sensor esp8266 with arduino wont loop anymore - arduino-esp8266

Do forgive me as i am new to programming.
I used a sample code I found online for dht22 and have added other sensors in my esp8266. However, when i added the code necessary for the latest sensor (waterproof temp sensor), it doesn't activate the loop. the serial monitor prints out one sensor reading but it stops there
12:03:50.208 -> WiFi connected - ESP IP address: ****
12:03:50.208 -> Attempting MQTT connection...connected
12:03:55.499 -> { "temperature": " 23.72", "humidity" : " 56.70", "soilmoisture" : "99", "soiltemperature" : " 22.00"}
I looked around and deleted the code for the temp sensor one by one and i have discovered that when i changed the
char data[80] to char data[100]
the code starts working again but now it is looping every milisecond or something instead of 10s that i have assigned
// Loading the ESP8266WiFi library and the PubSubClient library
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
// Uncomment one of the lines bellow for whatever DHT sensor type you're using!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//For capacitive soil sensor
const int AirValue = 865; //you need to replace this value with Value_1
const int WaterValue = 590; //you need to replace this value with Value_2
int soilMoistureValue = 0;
int soilmoisturepercent= 0;
// GPIO where the DS18B20 (soil temperature) is connected to
const int oneWireBus = D3;
// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "****";
const char* password = "****";
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "****";
// Initializes the espClient
WiFiClient espClient;
PubSubClient client(espClient);
// DHT Sensor
const int DHTPin = 5;
// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Timers auxiliar variables
long now = millis();
long lastMeasure = 0;
char data[100];
// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());
}
// This functions is executed when some device publishes a message to a topic that your ESP8266 is subscribed to
// Change the function below to add logic to your program, so when a device publishes a message to a topic that
// your ESP8266 is subscribed you can actually do something
void callback(String topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
}
// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
/*
YOU NEED TO CHANGE THIS NEXT LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
To change the ESP device ID, you will have to give a unique name to the ESP8266.
Here's how it looks like now:
if (client.connect("ESP8266Client")) {
If you want more devices connected to the MQTT broker, you can do it like this:
if (client.connect("ESPOffice")) {
Then, for the other ESP:
if (client.connect("ESPGarage")) {
That should solve your MQTT multiple connections problem
THE SECTION IN loop() function should match your device name
*/
if (client.connect("ESP8266Client")) {
Serial.println("connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics (to control more LEDs in this example)
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// The setup function sets your DHT sensor, starts the serial communication at a baud rate of 115200
// Sets your mqtt broker and sets the callback function
// The callback function is what receives messages and actually controls the LEDs
void setup() {
dht.begin();
// Start the DS18B20 sensor
sensors.begin();
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
// For this project, you don't need to change anything in the loop function.
// Basically it ensures that you ESP is connected to your broker
void loop() {
if (!client.connected()) {
reconnect();
}
if(!client.loop())
/*
YOU NEED TO CHANGE THIS NEXT LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
To change the ESP device ID, you will have to give a unique name to the ESP8266.
Here's how it looks like now:
client.connect("ESP8266Client");
If you want more devices connected to the MQTT broker, you can do it like this:
client.connect("ESPOffice");
Then, for the other ESP:
client.connect("ESPGarage");
That should solve your MQTT multiple connections problem
THE SECTION IN recionnect() function should match your device name
*/
client.connect("ESP8266Client");
now = millis();
// Publishes new temperature and humidity every 30 seconds
if (now - lastMeasure > 10000)
{
lastMeasure = now;
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
//put Sensor insert into soil
float sensorValue = analogRead(A0);
soilmoisturepercent = map(sensorValue, AirValue, WaterValue, 0, 100);
float s = soilmoisturepercent;
//sensor soil temperature code
sensors.requestTemperatures();
float temperatureC = sensors.getTempCByIndex(0);
//float temperatureF = sensors.getTempFByIndex(0);
// Check if any reads failed and exit early (to try again).
//
if (isnan(h) || isnan(t) || isnan(f) || isnan(soilmoisturepercent) || isnan(temperatureC))
{
Serial.println("Failed to read from sensors!");
return;
}
// Computes temperature values in Celsius
float hic = dht.computeHeatIndex(t, h, false);
static char temperatureTemp[7];
dtostrf(hic, 6, 2, temperatureTemp);
static char humidityTemp[7];
dtostrf(h, 6, 2, humidityTemp);
static char soilmoist[7];
dtostrf(soilmoisturepercent, 6, 2, soilmoist);
static char soiltemp[7];
dtostrf(temperatureC, 6, 2, soiltemp);
String dhtReadings = "{ \"temperature\": \"" + String(temperatureTemp) + "\", \"humidity\" : \"" + String(humidityTemp) + "\", \"soilmoisture\" : \"" + String(soilmoisturepercent) + "\", \"soiltemperature\" : \"" + String(soiltemp) + "\"}";
dhtReadings.toCharArray(data, (dhtReadings.length() + 1));
client.publish("room/temperature", temperatureTemp);
client.publish("room/humidity", humidityTemp);
client.publish("room/soilmoisture", soilmoist);
client.publish("room/soiltemperature", soiltemp);
// Publishes Temperature and Humidity values
client.publish("/esp8266/dhtreadings", data);
Serial.println(data);
}
}

Related

Display data on oled 1.3 inch screen after 5 seconds but update data on google sheet after every 15 minutes

I am working with DHT22 sensor and NodeMCU to get temperature and humidity values. I want to store values on google sheet and also display values on 1.3 inch oled display. I have used millis() to do multitasking but still not able to do multitask. Both task (display on oled and update on google sheet) take place after 1 minute interval. Please suggest what modifications can be done to code.
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include "DHT.h"
#include <OneWire.h>
#include <SPI.h>
#define DHTTYPE DHT22 // type of the temperature sensor
#include "SH1106Wire.h"
SH1106Wire display (0x3C, D1, D2);
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 4000; // interval at which to blink (milliseconds)
const int DHTPin = 14; //--> The pin used for the DHT11 sensor is Pin D1 = GPIO5
DHT dht(DHTPin, DHTTYPE); //--> Initialize DHT sensor, DHT dht(Pin_used, Type_of_DHT_Sensor);
#define ON_Board_LED 2 //--> Defining an On Board LED, used for indicators when the process of connecting to a wifi router
const char* ssid = "OPPO F11 Pro"; //--> Your wifi name or SSID.
//const char* ssid = "SWE-SEEIT";
const char* host = "script.google.com";
const int httpsPort = 443;
WiFiClientSecure client; //--> Create a WiFiClientSecure object.
String GAS_ID = "AKfycbxoDW-7HxrMx90MH7ggsM_0DOTz3gIj-Z06kWTGOwOaoFoaUxW4xfGn_8L7WJh6LX3o"; //--> spreadsheet script ID
void setup() {
dht.begin();
delay(500);
display.init();
display.flipScreenVertically();
Serial.begin(115200);
WiFi.begin(ssid, NULL); //--> Connect to your WiFi router
pinMode(ON_Board_LED,OUTPUT); //--> On Board LED port Direction output
digitalWrite(ON_Board_LED, HIGH); //--> Turn off Led On Board
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(ON_Board_LED, LOW);
delay(250);
digitalWrite(ON_Board_LED, HIGH);
delay(250);
}
digitalWrite(ON_Board_LED, HIGH); //--> Turn off the On Board LED when it is connected to the wifi router.
client.setInsecure();
}
void loop() {
int h = dht.readHumidity();
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor !");
delay(500);
return;
}
String Temp = "Temperature : " + String(t) + " °C";
String Humi = "Humidity : " + String(h) + " %";
Serial.println(Temp);
Serial.println(Humi);
servosweep();
sendData(t, h);
delay(60000) ;
}
void servosweep(){
int h = dht.readHumidity();
float t = dht.readTemperature();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
display.setFont(ArialMT_Plain_16);
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString (60,0,"Temperature (°C)");
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(60,16,String(t));
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(60,32,"Humidity (%)");
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(60,48,String(h));
display.display();
}
}
// Subroutine for sending data to Google Sheets
void sendData(float tem, int hum) {
//Serial.println("==========");
//Serial.print("connecting to ");
//Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}
//----------------------------------------Processing data and sending data
String string_temperature = String(tem);
String string_humidity = String(hum, DEC);
String url = "/macros/s/" + GAS_ID + "/exec?temperature=" + string_temperature + "&humidity=" + string_humidity;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");
//----------------------------------------Checking whether the data was sent successfully or not
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
//Serial.println("headers received");
break;
}
}
String line = client.readStringUntil('\n');
}

ESP8266 / Arduino modbus RTU Buffer data conversion

I am using ESP8266 and ModbusMaster.h library to communicate with RS485 enabled power meter. Communication works fine but responses are the ones are confusing me and I can not get correct values. My power meter shows 1.49 kWh but response from Modbus is 16318. Here is my code:
#include <ArduinoOTA.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <ModbusMaster.h>
#include <ESP8266WiFi.h>
/*
Debug. Change to 0 when you are finished debugging.
*/
const int debug = 1;
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
int timerTask1, timerTask2, timerTask3;
float battBhargeCurrent, bvoltage, ctemp, btemp, bremaining, lpower, lcurrent, pvvoltage, pvcurrent, pvpower;
float stats_today_pv_volt_min, stats_today_pv_volt_max;
uint8_t result;
// this is to check if we can write since rs485 is half duplex
bool rs485DataReceived = true;
float data[100];
ModbusMaster node;
SimpleTimer timer;
// tracer requires no handshaking
void preTransmission() {}
void postTransmission() {}
// a list of the regisities to query in order
typedef void (*RegistryList[])();
RegistryList Registries = {
AddressRegistry_0001 // samo potrosnju
};
// keep log of where we are
uint8_t currentRegistryNumber = 0;
// function to switch to next registry
void nextRegistryNumber() {
currentRegistryNumber = (currentRegistryNumber + 1) % ARRAY_SIZE( Registries);
}
void setup()
{
// Serial.begin(115200);
Serial.begin(9600, SERIAL_8E1); //, SERIAL_8E1
// Modbus slave ID 1
node.begin(1, Serial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
// WiFi.mode(WIFI_STA);
while (Blynk.connect() == false) {}
ArduinoOTA.setHostname(OTA_HOSTNAME);
ArduinoOTA.begin();
timerTask1 = timer.setInterval(9000, updateBlynk);
timerTask2 = timer.setInterval(9000, doRegistryNumber);
timerTask3 = timer.setInterval(9000, nextRegistryNumber);
}
// --------------------------------------------------------------------------------
void doRegistryNumber() {
Registries[currentRegistryNumber]();
}
void AddressRegistry_0001() {
uint8_t j;
uint16_t dataval[2];
result = node.readHoldingRegisters(0x00, 2);
if (result == node.ku8MBSuccess)
{
for (j = 0; j < 2; j++) // set to 0,1 for two
datablocks
{
dataval[j] = node.getResponseBuffer(j);
}
terminal.println("---------- Show power---------");
terminal.println("kWh: ");
terminal.println(dataval[0]);
terminal.println("crc: ");
terminal.println(dataval[1]);
terminal.println("-----------------------");
terminal.flush();
node.clearResponseBuffer();
node.clearTransmitBuffer();
} else {
rs485DataReceived = false;
}
}
void loop()
{
Blynk.run();
// ArduinoOTA.handle();
timer.run();
}
I have tried similar thing but with Raspberry Pi and USB-RS485 and it works.
Sample of NodeJS code is below. It looks similar to Arduino code.
// create an empty modbus client
var ModbusRTU = require("modbus-serial");
var client = new ModbusRTU();
// open connection to a serial port
client.connectRTUBuffered("/dev/ttyUSB0", { baudRate: 9600, parity: 'even' }, read);
function write() {
client.setID(1);
// write the values 0, 0xffff to registers starting at address 5
// on device number 1.
client.writeRegisters(5, [0 , 0xffff])
.then(read);
}
function read() {
// read the 2 registers starting at address 5
// on device number 1.
console.log("Ocitavanje registra 0000: ");
client.readHoldingRegisters(0000, 12)
.then(function(d) {
var floatA = d.buffer.readFloatBE(0);
// var floatB = d.buffer.readFloatBE(4);
// var floatC = d.buffer.readFloatBE(8);
// console.log("Receive:", floatA, floatB, floatC); })
console.log("Potrosnja u kWh: ", floatA); })
.catch(function(e) {
console.log(e.message); })
.then(close);
}
function close() {
client.close();
}
This code displays 1.493748298302 in console.
How can I implement this var floatA = d.buffer.readFloatBE(0); in Arduino? Looks like that readFloatBE(0) does the trick, but available only in NodeJS / javascript.
Here i part of datasheet for my device
Here is what I am getting as result from original software that came with device:
If someone could point me in better direction I would be thenkfull.
UPDATE:
I found ShortBus Modbus Scanner software and tested readings.
Library read result as Unsigned integer, but need Floating Point and Word Order swapped. It is shown on image below.
Can someone tell how to set proper conversion please.
Right, so indeed the issue is with the part done by var floatA = d.buffer.readFloatBE(0);Modbus returns an array of bytes, and the client has to interpret those bytes, ideally done by the library you're using, but if not available on Arduino, you may try manually with byte decoding functions, with the following considerattions:
Modbus registers are 16 bit in length, so length 1 = 16 bits, length
2 = 32 bits, hence the data type noted on the docs as float32 means
"2 registers used for this value, interpret as float".
Therefore, on client.readHoldingRegisters(0000, 12)you're asking to read the register with address 00, and size 12... so this makes no sense, you only need 2 registers.
On your sample Node code, first you're writing
2 registers to address 5 in client.writeRegisters(5, [0 , 0xffff])
register 5 = 0, and register 6 = 0xFFFF, why? Then you go and read
from address 0, in read(), which is the address for Total KwH per
your docs.
So, you should get an array of bytes, and you need to
decode them as a float. Modbus is Big Endian for words and bytes, so
you need to use those in the decoding functions. I don't know exactly
what is available in Arduino, but hopefully you can figure it out
with this extra info.
I suppose that if you just send the buffer to print, you'll get an integer interpretation of the value, hence the problem

How to store string received with Serial.read() in Arduino?

I manage to send data from NodeJs runtime with serialport library.
The goal is storing a string received from Serial.read() in Arduino . What is correct:
int string = Serial.read()
or:
char string[20] = Serial.read()
There are many documentations on Internet and they are not the same
P/s: I send string from nodejs in buffer form but i dont think it matters because arduino still implement it as a string anyway.
From the Arduino documentation:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
https://www.arduino.cc/en/Serial/Read
.read():
Returns the first byte of incoming serial data available (or -1 if no
data is available) - int
FYI: I've used this code many times and it works on 100%.

Use Arduino for reading accelerometer data & save to raspi

I want to use Arduino to read data from ADXL345 accelerometer and use raspberry pi with Processing to save the data into a txt file in pi. I used the code from https://www.researchgate.net/post/How_can_I_save_data_directly_in_the_pc_using_an_Arduino_UNO
And my Arduino code is shown as follows:
#include <Wire.h>
#define DEVICE (0x53) //ADXL345 device address
#define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
char str[512]; //string buffer to transform data before sending it to the serial port
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void loop()
{
int regAddress = 0x32; //first axis-acceleration-data register on the ADXL345
int x, y, z;
readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
//each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
//thus we are converting both bytes in to one int
x = (((int)buff[1]) << 8) | buff[0];
y = (((int)buff[3])<< 8) | buff[2];
z = (((int)buff[5]) << 8) | buff[4];
//we send the x y z values as a string to the serial port
sprintf(str, "%d %d %d", x, y, z);
Serial.print(str);
Serial.write(10);
//It appears that delay is needed in order not to clog the port
delay(15);
}
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); //end transmission
}
void readFrom(int device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start transmission to device
Wire.write(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start transmission to device (initiate again)
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested (abnormal)
{
buff[i] = Wire.read(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
Processing code is shown as follows:
import processing.serial.*;
Serial mySerial;
PrintWriter output;
void setup() {
mySerial = new Serial( this, Serial.list()[0], 9600 );
output = createWriter( "/home/pi/data.txt" );
}
void draw() {
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
When only use serial monitor window to show x, y, z values, it looks well, but when using Processing to get data while Arduino serial monitor window is running, the data format changes, e.x. wrong format
Please help me.

Unexpected String when using BlueMix's Node-RED editor and MQTT->Debug Node

I'm following this tutorial,
http://energia.nu/creating-an-iot-connected-sensor-with-energia-mqtt/
I see the pushed data, but the Node-RED editor constantly prints 'Hello World #XX'. I don't see anything in the code that would suggest where its coming from:
#include <WiFi.h>
#include <PubSubClient.h>
#include <SPI.h> //only required if using an MCU LaunchPad + CC3100 BoosterPack. Not needed for CC3200 LaunchPad
WiFiClient wclient;
byte server[] = { 198, 41, 30, 241 }; // Public MQTT Brokers: http://mqtt.org/wiki/doku.php/public_brokers
byte ip[] = { 172, 16, 0, 100 };
char sensorRead[4];
#define WIFI_SSID "SSID"
#define WIFI_PWD "WIFIPASSWORD"
PubSubClient client(server, 1883, callback, wclient);
void callback(char* inTopic, byte* payload, unsigned int length){
// Handle callback here
}
void setup()
{
//Initialize serial and wait for port to open:
Serial.begin(115200);
Serial.println("Start WiFi");
WiFi.begin(WIFI_SSID, WIFI_PWD);
while(WiFi.localIP() == INADDR_NONE) {
Serial.print(".");
delay(300);
}
Serial.println("");
printWifiStatus();
}
void loop()
{
// read the input on analog pin:
int sensorValue = analogRead(24);
Serial.println(sensorValue);
// convert into to char array
String str = (String)sensorValue;
int str_len = str.length() + 1; // Length (with one extra character for the null terminator)
char char_array[str_len]; // Prepare the character array (the buffer)
str.toCharArray(char_array, str_len); // Copy it over
// publish data to MQTT broker
if (client.connect("LaunchPadClient")) {
client.publish("outTopic", char_array);
//client.subscribe("inTopic");
Serial.println("Publishing successful!");
client.disconnect();
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
}
Is this because this is a free/trial account? Incidentally, it shows I'm using 512MB/2GB, which seems high... does it include the data sent, or is 512MB just the application size?
You are using a MQTT broker that is public to the world, anybody can publish data to any topic on that broker. The messages are probably coming from somebody else doing similar experiments to yourself.
outTopic is the sort of topic name that many people could be using to test, try changing it to some random string in both the publishing code and the MQTT In node in Node-RED.
As for the size in Bluemix, this is how much memory is assigned to your application, it is unlikely to be actually using anything near that amount at the moment.

Resources