My setup: arduino leonardo + yun shield
What I'm trying to accomplish:
Display a temperature via one-wire on html served by yun. Allow user to set goal temperature via slider bar on yun html page and have that set the value of a variable in the function "goaltemp".
Here is my html:
<!DOCTYPE html>
<html>
<head>
<title>AngularJS / Arduino</title>
<meta name="viewport" content="width=device-width">
<script type="text/javascript" src="zepto.min.js"></script>
<script type="text/javascript">
function refresh() {
$('#content').load('/arduino/temperature');
}
var value;
function sendVal() {
$.get('/arduino/goaltemp' + value, function(){
}
);
}
function updateVal(val) {
value = val;
$("#val").text(value);
sendVal();
}
</script>
</head>
<body onload="setInterval(refresh, 2000);">
<span id="content">0</span>
<p>Goal Temperature:
<input type="range" min="0" max="230" onchange="updateVal(this.value);">
<p id="val">0</p>
</p>
</body>
</html>
Here is my arduino sketch:
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <SevSeg.h>
#include <OneWire.h>
#include <DallasTemperature.h>
//*****Temp Read
//code from http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library
//Orange Stripe is PWR: 3-5V,
//White Stripe is GND
//Blue Stripe is data.
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
//Powerswitch Tail
const int powerPin = A0;
boolean powerOn = false;
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Listen on default port 5555, the webserver on the Yún
// will forward there all the HTTP requests for us.
YunServer server;
String startString;
long hits = 0;
void setup() {
//Serial.begin(9600);
// Bridge startup
Bridge.begin();
// Listen for incoming connection only from localhost
// no one from the external network could connect
server.listenOnLocalhost();
server.begin();
// get the time that this sketch started:
Process startTime;
startTime.runShellCommand("date");
while (startTime.available()) {
char c = startTime.read();
startString += c;
}
}
void loop() {
int temp = (sensors.getTempFByIndex(0));
sensors.requestTemperatures(); // Send the command to get temperatures
// Get clients coming from server
YunClient client = server.accept();
// There is a new client?
if (client) {
// read the command
String command = client.readString();
command.trim(); //kill whitespace
Serial.println(command);
// is "temperature" command?
if (command == "temperature") {
// get the time from the server:
Process time;
time.runShellCommand("date");
String timeString = "";
while (time.available()) {
char c = time.read();
timeString += c;
}
Serial.println(timeString);
int sensorValue = analogRead(A1);
// convert the reading to millivolts:
// convert the millivolts to temperature celsius:
// print the temperature:
//client.print("Current time on the Yún: ");
//client.println(timeString);
client.print("<br>Current temperature: ");
client.print(temp);
client.print(" °F");
//client.print("<br>This sketch has been running since ");
//client.print(startString);
client.print("<br>Hits so far: ");
client.print(hits);
}
if (command == "goaltemp") {
int value = client.parseInt();
client.print("<br>The Goal Temperature is ");
client.print(value);
client.print(" °F");
}
// Close connection and free resources.
client.stop();
hits++;
}
delay(50); // Poll every 50ms
}
The temperature reporting currently works great. I cannot, however, figure out how to pass the value of the slider in my html to arduino. Any advice or help would be greatly appreciated!
Have you checked out the example code and documentation here: https://www.arduino.cc/en/Guide/ArduinoYun#toc20? The sample code there covers what you are attempting to do.
Specifically, pay attention to how the code author breaks down the processing of the URL arguments using different functions as so:
void process(YunClient client) {
String command = client.readStringUntil('/');
if (command == "digital") {
digitalCommand(client);
}
if (command == "analog") {
analogCommand(client);
}
if (command == "mode") {
modeCommand(client);
}
}
In each processing function, you can simply do a client.readStringUntil('/') to parse down the tree. Eventually, you will get your goaltemp value.
Hint, you may want to format your URL as /arduino/goaltemp/20 - that will make parsing easier.
Good luck!
Related
I have the following code:
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
static void log(String message) {
Serial.println(message);
}
const char* deviceName = "BLEScanner";
BLEScan* pBLEScan;
void setup() {
Serial.begin(115200);
log("Setup!");
BLEDevice::init(deviceName);
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
log("Listing BLE Sensors");
BLEScanResults foundSensors = pBLEScan->start(30, false);
int count = foundSensors.getCount();
for (int i = 0; i < count; i++) {
BLEAdvertisedDevice bleSensor = foundSensors.getDevice(i);
String sensorName = bleSensor.getName().c_str();
String address = bleSensor.getAddress().toString().c_str();
log(address + " " + sensorName);
}
log("Sleeping");
sleep(10);
}
And when running it I get the following output:
Setup!
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89 LM0845
c4:7c:8d:6a:36:cf Flower care
c4:7c:8d:6a:45:6b Flower care
c4:7c:8d:6a:46:2c Flower care
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
dc4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
Sleeping
Listing BLE Sensors
00:09:b0:09:e7:ca
41:59:8f:07:ec:96
ac:5d:5c:e1:72:89
c4:7c:8d:6a:36:cf
dc4:7c:8d:6a:45:6b
dc4:7c:8d:6a:46:2c
de:d5:2a:8e:1e:fd Tile
... and so on
For some reason I only get the names of some of the devices the first time, is this a known error and what can be done about it?
I have tried to put a pBLEScan->clearResults(); before I start a scan but that did not help.
I'm using an ESP32 Adafruit feather.
The only solution I have found is to put the BLEDevice::init(deviceName); inside the loop and then run BLEDevice::deinit(); before sleep!
Can someone help me with this Sigfox setup?
What have I done wrong? :-)
The only thing I wanted to achieve was to post the internal temperature and the status to the sigfox backend.
Each 15min, the data would be posted.
A configured an email from the service showing the temperature in degrees Celcius.
Posting to the backend is working.
However the email message and the data seems not to correspond.
When running the code in debug mode. The temperature is showing correctly in degrees Celcius.
Is there a manual available?
Code Arduino MKR FOX 1200
Temp.ino
#include <ArduinoLowPower.h>
#include <SigFox.h>
#include "conversions.h"
// Set oneshot to false to trigger continuous mode when you finisched setting up the whole flow
int oneshot = false;
#define STATUS_OK 0
/*
ATTENTION - the structure we are going to send MUST
be declared "packed" otherwise we'll get padding mismatch
on the sent data - see http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding
for more details
*/
typedef struct __attribute__ ((packed)) sigfox_message {
int16_t moduleTemperature;
uint8_t lastMessageStatus;
} SigfoxMessage;
// stub for message which will be sent
SigfoxMessage msg;
void setup() {
if (oneshot == true) {
// Wait for the serial
Serial.begin(115200);
while (!Serial) {}
}
if (!SigFox.begin()) {
// Something is really wrong, try rebooting
// Reboot is useful if we are powering the board using an unreliable power source
// (eg. solar panels or other energy harvesting methods)
reboot();
}
//Send module to standby until we need to send a message
SigFox.end();
if (oneshot == true) {
// Enable debug prints and LED indication if we are testing
SigFox.debug();
}
}
void loop() {
// Every 15 minutes, read all the sensor and send the data
// Let's try to optimize the data format
// Only use floats as intermediate representaion, don't send them directly
//sensors_event_t event;
// Start the module
SigFox.begin();
// Wait at least 30ms after first configuration (100ms before)
delay(100);
// We can only read the module temperature before SigFox.end()
float temperature = SigFox.internalTemperature();
msg.moduleTemperature = convertoFloatToInt16(temperature, 60, -60);
if (oneshot == true) {
Serial.println("Internal temp: " + String(temperature));
}
// Clears all pending interrupts
SigFox.status();
delay(1);
SigFox.beginPacket();
SigFox.write((uint8_t*)&msg, 12);
msg.lastMessageStatus = SigFox.endPacket();
if (oneshot == true) {
Serial.println("Status: " + String(msg.lastMessageStatus));
}
SigFox.end();
if (oneshot == true) {
// spin forever, so we can test that the backend is behaving correctly
while (1) {}
}
//Sleep for 15 minutes
LowPower.sleep(1 * 60 * 1000);
}
void reboot() {
NVIC_SystemReset();
while (1);
}
Conversion.h
#define UINT16_t_MAX 65536
#define INT16_t_MAX UINT16_t_MAX/2
int16_t convertoFloatToInt16(float value, long max, long min) {
float conversionFactor = (float) (INT16_t_MAX) / (float)(max - min);
return (int16_t)(value * conversionFactor);
}
uint16_t convertoFloatToUInt16(float value, long max, long min = 0) {
float conversionFactor = (float) (UINT16_t_MAX) / (float)(max - min);
return (uint16_t)(value * conversionFactor);
}
Settings Sigfox Backend - email Callbacks
With the current convertoFloatToInt16, it will not be possible to display the real temperature in an email directly from Sigfox Backend.
You either need to use a callback from Sigfox Backend to a server that implements convertoFloatToUInt16 and then sends the email, or send the temperature in a format that the Sigfox Backend can decode natively (32-bit float is probably the most suitable).
I've been trying to get the BME680 to work and for the most part it seems to be working great. I do have one issue and that is with the gas sensor.
I write all the contents of the BME680 out to a webpage and all of the other values remain consistent.
Temperature: 77.29 *F
Humidity: 59.12 %
Pressure: 1010.45 millibars
Air Quality: 3.24 KOhms
On every refresh of the page the values for Temperature, Humidity, and Pressure all remain close to their values. They correct for a little while and show the minor fluctuations correctly. When it starts to rain the pressure goes down, the humidity goes up, etc... The issue is the Gas Sensor. On ever refresh the value keeps increasing. Regardless of whether I refresh it once per minute or per hour it keeps increasing. I'm clearly doing something wrong.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <WiFi101.h>
#include <WiFiUdp.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(80);
#define SEALEVELPRESSURE_HPA (1023.03)
Adafruit_BME680 bme; // I2C
void setup() {
//Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT); // set the LED pin mode
bme.begin();
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
//Serial.println("WiFi shield not present");
while (true); // don't continue
}
// attempt to connect to WiFi network:
while ( status != WL_CONNECTED) {
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin(); // start the web server on port 80
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
//Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
//Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
if (! bme.performReading()) {
client.print("Failed to perform reading :(<br>");
return;
}
// the current weather condidtions
client.print("Temperature: ");
client.print((bme.temperature * 9/5) + 32);
client.print(" *F<br>");
client.print("Humidity: ");
client.print(bme.humidity);
client.print(" %<br>");
client.print("Pressure: ");
client.print(bme.pressure / 100.0);
client.print(" millibars<br>");
client.print("Air Quality: ");
client.print(bme.gas_resistance / 1000.0);
client.print(" KOhms<br>");
delay(2000);
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
//Serial.println("client disonnected");
}
}
I see two important points. Two for the beginning. Missing the ambient temperature and the sea-level.
Default ambient is: 25deg.C
Default sea-level is: 500 meter
Add this with correct values to your code. Then you have todo some automatic calibrations after burn in time. My own experience is that 2 weeks 24/7 is needed to get the sensor much old as needed. Next step look in the BOSCH original library and example code. Then start over again. Currently i'm rewriting the driver for the BME and BMP series for Tasmota (github). Lot's of work believe me. And i'm from the physics and chemical side. So some research helps always.
I'm trying to get the current local time with an API. I am using a WEMOS D1 Mini and the get method with blynk to return JSON from the API and store it.
I use this code
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <BlynkSimpleEsp8266.h>
String json;
char auth[] = "";
char ssid[] = "YourNetworkName";
char pass[] = "YourPassword";
BLYNK_WRITE(V0) {
json = param.asStr();
}
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
}
void loop() {
Blynk.run();
Blynk.virtualWrite(V0, "https://api.bot-dev.org/time/");
JsonObject& root = jsonBuffer.parseObject(json);
long time = root[String("ENtime")];
}
But i cant receive time in long time variable.
You can do that in simpler way.
You need to add WebHook widget to your app. In the webhoook widget you need to put https://api.bot-dev.org/time/ url. And assign this widget to the virtual pin, let's say V0. Webhook widget will return response to your hardware after it was triggered. So your code should look like that:
BLYNK_WRITE(V0) {
//here you'll get response from the webhook
json = param.asStr();
}
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
}
void loop() {
Blynk.run();
//trigger the webhook
Blynk.virtualWrite(V0, 1); //you can send any value to trigger webhook
}
Have in mind that you need also to move out Blynk.virtualWrite from main loop in order to avoid flooding.
Here is more details regarding the webhook widget.
Added a temperature and humidity sensor (DHT11) to the standard Cosm Arduino sensor client example. Works for a short while then data streams flat line.
Any idea what could be causing the problem?
Many thanks
Staza
/**
* Cosm Arduino sensor client example.
*
`` * This sketch demonstrates connecting an Arduino to Cosm (https://cosm.com),
* using the new Arduino library to send and receive data.
/**
DHT11 temp and humidity sensor added to the COSM example code
**/
#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
#include <Cosm.h>
#include <dht11.h>
//DHT11*********************************************************************
dht11 DHT11;
#define DHT11PIN 7//pin DHT11 sensor is connected to
//DHT11*********************************************************************
#define API_KEY "xxxxxx" // your Cosm API key
#define FEED_ID xxxxx // your Cosm feed ID
// MAC address for your Ethernet shield
byte mac[] = {xxxx, xxxx, xxxx, xxxx, xxxx, xxxx};
// Analog pin which we're monitoring (0 and 1 are used by the Ethernet shield)
int sensorPin = 2;
unsigned long lastConnectionTime = 0; // last time we connected to Cosm
const unsigned long connectionInterval = 15000; // delay between connecting to Cosm in milliseconds
// Initialize the Cosm library
// Define the string for our datastream ID
char sensorId[] = "sensor_reading";
char sensorId2[] = "DHT11_humidity_sensor_reading";
char sensorId3[] = "DHT11_temperature_sensor_reading";
CosmDatastream datastreams[] = {
CosmDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
CosmDatastream(sensorId2, strlen(sensorId2), DATASTREAM_FLOAT),
CosmDatastream(sensorId3, strlen(sensorId3), DATASTREAM_FLOAT),
};
// Wrap the datastream into a feed
CosmFeed feed(FEED_ID, datastreams, 3 /* number of datastreams */);
EthernetClient client;
CosmClient cosmclient(client);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Cosm Sensor Client Example");
Serial.println("==========================");
Serial.println("Initializing network");
while (Ethernet.begin(mac) != 1) {
Serial.println("Error getting IP address via DHCP, trying again...");
delay(15000);
}
Serial.println("Network initialized");
Serial.println();
}
void loop() {
// main program loop
if (millis() - lastConnectionTime > connectionInterval) {
//check DHT11 sensor is working OK
int chk = DHT11.read(DHT11PIN);
Serial.print("Read DHT11 sensor: ");
switch (chk)
{
case 0: Serial.println("OK"); break;
case -1: Serial.println("Checksum error"); break;
case -2: Serial.println("Time out error"); break;
default: Serial.println("Unknown error"); break;
}
sendData(); // send data to Cosm
getData(); // read the datastream back from Cosm
lastConnectionTime = millis(); // update connection time so we wait before connecting again
}
}
// send the supplied values to Cosm, printing some debug information as we go
void sendData() {
int sensorValue = analogRead(sensorPin);
int humidityDHT11 = ((float)DHT11.humidity);
int tempDHT11 = ((float)DHT11.temperature);
datastreams[0].setFloat(sensorValue);
datastreams[1].setFloat(humidityDHT11); //DHT11 humidity value*******
datastreams[2].setFloat(tempDHT11); //DHT11 temp value********
Serial.print("Read sensor value ");
Serial.println(datastreams[0].getFloat());
Serial.print("Read DHT11 humidity sensor value ");
Serial.println(datastreams[1].getFloat());
Serial.print("Read DHT11 temperature sensor value ");
Serial.println(datastreams[2].getFloat());
Serial.println("Uploading to Cosm");
int ret = cosmclient.put(feed, API_KEY);
Serial.print("PUT return code: ");
Serial.println(ret);
Serial.println();
}
// get the value of the datastream from Cosm, printing out the value we received
void getData() {
Serial.println("Reading data from Cosm");
int ret = cosmclient.get(feed, API_KEY);
Serial.print("GET return code: ");
Serial.println(ret);
if (ret > 0) {
Serial.print("Datastream is: ");
Serial.println(feed[0]);
Serial.print("Sensor value is: ");
Serial.println(feed[0].getFloat());
Serial.print("Datastream is: ");
Serial.println(feed[1]);
Serial.print("Sensor value is: ");
Serial.println(feed[1].getFloat());
Serial.print("Datastream is: ");
Serial.println(feed[2]);
Serial.print("Sensor value is: ");
Serial.println(feed[2].getFloat());
}
Serial.println();
}
Cosm has a debug page which might give you a clue as to what's going wrong.
This is currently located at: https://cosm.com/users/YOURUSERNAME/debug and it lists all incoming requests in real time as they come through. If your device works initially, you should see it start making requests successfully, and depending on how long it takes till it flatlines you might be able to keep this page open and hopefully see when it starts failing.
Do you see anything in the Arduino serial output when it seems to stop working, or does it seem like the Arduino is still happily sending data?
The other thing you could try is using Wireshark to inspect network traffic over the wire. Setting this up is slightly more involved however, so I'd suggest trying the other approaches first.
If none of this seems feasible I'd suggest mailing Cosm support with your feed details and have them look into it.
Seconding smulube's suggestion to monitor the serial output. Additionally, eliminate the variable of the COSM code & Ethernet: start debugging the issue with a sketch that is just taking readings from the DHT11 and monitor what's going on in the Arduino's serial output on your computer (in the Tools dropdown menu).
I just received my DHT22 (RHT03) from Sparkfun last night and tried several samples that wouldn't compile (my fault, I'm sure). The sample that worked "out of the box" for me with my Arduino Uno came from Tom Boyd's page (be sure to scroll to the bottom for the most recent code): DHT11 / Aosong AM2302 humidity and temperature sensor
I'm curious: how long did it take for your sensor to flatline? I integrated the code from Tom with the Cosm code and it's been running without interruption for me for an hour now.
Cheers,
Reeves