i made a weather station which is build on a ATmega2560 mini pro, Esp8266 module which communicate with atmega on serial1 which sends values to thingspeak, an TSL2561, 2.4 tft lcd, BMP180, DHT22 and a dust sensor module PMS5003 which is set on serial3 on mega2560. I made the wiring, program etc. the weather station is working fine for some days when it freezes. The problem is that thingspeak reports that it receive some data every 6 mins like i set it but the data received is blank. Not 0, or any other value, just blank data. I'm thinking it could be a problem with SRAM since it loses the values it reads. But why the loop is still working since it sends blank data to thingspeak ?
Atmega reads all values from sensors, then communicates with esp8266 by serial and using AT commands it sends the values read to thingspeak. So in my opinion it reads the values, but it won't stores them, then it sending blank data to thingspeak. If i reset the arduino it works fine for some days when suddenly it decides to stop working.
After compiling the program the arduino ide is reporting this:
Sketch uses 28,890 bytes (11%) of program storage space. Maximum is 253,952 bytes. Global variables use 1,800 bytes (21%) of dynamic memory, leaving 6,392 bytes for local variables. Maximum is 8,192 bytes.
So, my program it's not filling the SRAM. I'm a beginner in C++ so i tried to do my best with programming.
Link to thingspeak weather station: https://thingspeak.com/channels/116912
The code:
#include <SFE_BMP180.h>
#include <Wire.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <Adafruit_GFX.h> // Core graphics library
#include "SWTFT.h" // Hardware-specific library
#define DHTPIN 25 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define ALTITUDE 320.0 // Altitude in Grasse
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
SWTFT tft;
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino
SFE_BMP180 pressure;
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
//double bmptemp; //temp bmp rectificata cu 1.9 grade -
float hum; //Stores humidity value
float temp; //Stores temperature value
float lux; //Stores lux luminosity
char status; //used by bmp180
double T,P,p0; //p0 - sea-level compensated pressure in mb, T - temperature, P = absolute pressure in mb
#define IP "184.106.153.149" // thingspeak.com IP address; see their website for more detail
String GET = "GET /update?key=NWHWO6SLWNJP3HGQ"; // you channel will have unique code
int concentration=0;
//cod dust sensor
#define LENG 31 //0x42 + 31 bytes equal to 32 bytes
unsigned char buf[LENG];
int PM01Value=0; //define PM1.0 value of the air detector module
int PM2_5Value=0; //define PM2.5 value of the air detector module
int PM10Value=0; //define PM10 value of the air detector module
void setup() {
pinMode(17, OUTPUT); //pin pt esp - on /off
pinMode(16, OUTPUT); //pin buzzer
pinMode(31, OUTPUT); //pin on/off dust sensor
Serial.begin(9600); // this is to start serial monitoring with your Arduino IDE Serial monitor.
Serial1.begin(9600); // this is to start serial communication with the ESP via Software Serial.
Serial3.begin(9600); //serial dust sensor
Serial.println("Begin");
tft.reset();
uint16_t identifier = tft.readID();
tft.begin(identifier);
dht.begin();
if (!pressure.begin()) {
Serial.println("BMP180 init fail"); // Oops, something went wrong, this is usually a connection problem,
while(1); // Pause forever.
}
if(!tsl.begin()) {
/* There was a problem detecting the ADXL345 ... check your connections */
Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
while(1);
}
//tsl.setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */
//tsl.setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sensitivity */
tsl.enableAutoRange(true); /* Auto-gain ... switches automatically between 1x and 16x */
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but slowest conversions */
}
void loop() {
digitalWrite(31, LOW);
digitalWrite(17, LOW);
Serial.println("-----------------------");
dht22 ();
bmp120 ();
tsl2561();
dust();
Serial.println("-----------------------");
tft.fillScreen(BLACK);
tft.setRotation(1);
tft.setCursor(0, 0);
tft.setTextColor(GREEN);
tft.setTextSize(2);
tft.println("DHT22");
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Temperature = ");
tft.print(temp);
tft.println(" C");
tft.print("Humidite = ");
tft.print(hum);
tft.println(" %");
tft.println();
tft.setTextColor(GREEN);
tft.setTextSize(2);
tft.println("BMP180");
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Temperature = ");
tft.print(T);
tft.println(" C");
tft.print("Pression = ");
tft.print(p0);
tft.println(" mb");
tft.println();
tft.setTextColor(GREEN);
tft.setTextSize(2);
tft.println("TSL2561");
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("Luminosite = ");
tft.print(lux);
tft.println(" Lux");
tft.println();
tft.setTextColor(GREEN);
tft.setTextSize(2);
tft.println("Pollution aux particules");
tft.setTextColor(WHITE);
tft.setTextSize(2);
//tft.println("Concentration - ug/m3");
tft.print("PM1.0: ");
tft.print(PM01Value);
tft.println(" ug/m3");
tft.print("PM2.5: ");
tft.print(PM2_5Value);
tft.println(" ug/m3");
tft.print("PM10: ");
tft.print(PM10Value);
tft.println(" ug/m3");
//tft.println("Pcs/0.01cf");
String tempdht22 = String(temp);// turn integer to string
String humdht22 = String(hum);
String tempbmp180 = String(T);
String pressbmp180 = String(p0);
String lum = String(lux);
String pol01 = String(PM01Value);
String pol25 = String(PM2_5Value);
String pol10 = String(PM10Value);
esp8266(tempdht22, humdht22, tempbmp180, pressbmp180, lum, pol01, pol25, pol10);
Serial.println("Waiting..");
delay(300000);
}
void dht22 () {
//Read data and store it to variables hum and temp
hum = dht.readHumidity();
temp= dht.readTemperature();
//Print temp and humidity values to serial monitor
Serial.print("Humidity: ");
Serial.print(hum);
Serial.println(" % ");
Serial.print("Temp: ");
Serial.print(temp);
Serial.println(" C");
}
//cod pt dust sensor
void dust () {
digitalWrite(31, HIGH);
Serial.println("High Pms5003");
delay(5000);
for (int i=0; i <= 60; i++){
if(Serial3.find(0x42)){ //start to read when detect 0x42
Serial3.readBytes(buf,LENG);
if(buf[0] == 0x4d){
if(checkValue(buf,LENG)){
PM01Value=transmitPM01(buf); //count PM1.0 value of the air detector module
PM2_5Value=transmitPM2_5(buf);//count PM2.5 value of the air detector module
PM10Value=transmitPM10(buf); //count PM10 value of the air detector module
}
}
}
Serial.print("PM1.0: ");
Serial.print(PM01Value);
Serial.println(" ug/m3");
Serial.print("PM2.5: ");
Serial.print(PM2_5Value);
Serial.println(" ug/m3");
Serial.print("PM10: ");
Serial.print(PM10Value);
Serial.println(" ug/m3");
Serial.println();
delay(1000);
}
delay(1000);
Serial.println("Low Pms5003");
digitalWrite(31, LOW);
}
char checkValue(unsigned char *thebuf, char leng)
{
char receiveflag=0;
int receiveSum=0;
for(int i=0; i<(leng-2); i++){
receiveSum=receiveSum+thebuf[i];
}
receiveSum=receiveSum + 0x42;
if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1])) //check the serial data
{
receiveSum = 0;
receiveflag = 1;
}
return receiveflag;
}
int transmitPM01(unsigned char *thebuf)
{
int PM01Val;
PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module
return PM01Val;
}
//transmit PM Value to PC
int transmitPM2_5(unsigned char *thebuf)
{
int PM2_5Val;
PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
return PM2_5Val;
}
//transmit PM Value to PC
int transmitPM10(unsigned char *thebuf)
{
int PM10Val;
PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module
return PM10Val;
} //cod dust sensor
void bmp120 () {
status = pressure.startTemperature();
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable T.
// Function returns 1 if successful, 0 if failure.
status = pressure.getTemperature(T);
if (status != 0)
{
// Print out the measurement:
Serial.print("Temp2: ");
Serial.print(T);
Serial.println(" C ");
// Start a pressure measurement:
// The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
// If request is successful, the number of ms to wait is returned.
// If request is unsuccessful, 0 is returned.
status = pressure.startPressure(3);
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
// Retrieve the completed pressure measurement:
// Note that the measurement is stored in the variable P.
// Note also that the function requires the previous temperature measurement (T).
// (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
// Function returns 1 if successful, 0 if failure.
status = pressure.getPressure(P,T);
if (status != 0)
{
// The pressure sensor returns abolute pressure, which varies with altitude.
// To remove the effects of altitude, use the sealevel function and your current altitude.
// This number is commonly used in weather reports.
// Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
// Result: p0 = sea-level compensated pressure in mb
p0 = pressure.sealevel(P,ALTITUDE); // we're at 1655 meters (Boulder, CO)
Serial.print("Pressure: ");
Serial.print(p0);
Serial.println(" mb");
}
else Serial.println("error retrieving pressure measurement\n");
}
else Serial.println("error starting pressure measurement\n");
}
else Serial.println("error retrieving temperature measurement\n");
}
else Serial.println("error starting temperature measurement\n");
}
void tsl2561 () {
/* Get a new sensor event */
sensors_event_t event;
tsl.getEvent(&event);
/* Display the results (light is measured in lux) */
if (event.light)
{
Serial.print(event.light); Serial.println(" lux"); lux = event.light;
}
else
{
/* If event.light = 0 lux the sensor is probably saturated
and no reliable data could be generated! */
Serial.println("0 lux");
}
}
void esp8266( String temp1, String humm, String temp2, String pression, String luminosite, String pol001, String pol025, String pol010) {
//update value on thingspeak
digitalWrite(17, HIGH);
Serial.println("High ESP8266");
delay(4000);
Serial1.println("AT+RST"); // this resets the ESP8266.
Serial.println("AT+RST"); // this is just echoing the command to your serial monitor so you can follow what is going on
delay(2000);
Serial1.println("AT");
Serial.println("AT");
delay(5000);
if(Serial1.find("OK")){
Serial.println("OK");
Serial.println("Connected");
}
Serial.println("in the update loop");
//ESP8266.println("AT+RST"); // it seems that mine works better if I reset it everytime before I do CIPSTART
//Serial.println("AT+RST");
//delay(5000);
String cmd = "AT+CIPSTART=\"TCP\",\""; //standard code. see https://github.com/espressif/esp8266_at/wiki //
cmd += IP; // += is concatenating the previous cmd string with the content of IP
cmd += "\",80"; // same thing here it just keep adding stuff to the cmd string content
Serial1.println(cmd);//type in the string in cmd into the ESP8266
Serial.println(cmd);
delay(1000);
if(Serial1.find("Error")){
Serial.println("AT+CIPSTART Error");
digitalWrite(16, HIGH);
delay(250);
digitalWrite(16, LOW);
return;
}
cmd = GET + "&field1=" + temp1 + "&field2=" + humm + "&field3=" + temp2 + "&field4=" + pression + "&field5=" + luminosite + "&field6=" + pol001 + "&field7=" + pol025 + "&field8=" + pol010 + "\r\n\r\n";
Serial1.print("AT+CIPSEND=");
Serial1.println(cmd.length());
Serial.print("AT+CIPSEND=");
Serial.println(cmd.length());
delay(1000);
if(Serial1.find(">")){ // if ESP8266 return the > prompt back from the CIPSEND command, you are set, if not something is wrong
Serial1.print(cmd); //type in the GET command string and done
Serial.print(">");
Serial.println(cmd);
Serial.println("OK Sent");
}
else
{
Serial.println("AT+CIPSEND error");
digitalWrite(16, HIGH);
delay(250);
digitalWrite(16, LOW);
}
delay(1000);
digitalWrite(17, LOW);
Serial.println("Low ESP8266");
}
Here i uploaded the data file from thingspeak. You can see that until 2016-06-17 14:58:00 UTC it was working fine then thingspeak started receiving blank data. It received something but only blank data. The weather station is in another location so i don't have acces all time to reset it. http://www.filedropper.com/feeds8
[Shown below are some lines from the front, the transition point, and the end of the feeds (8).csv file at Andrei's filedropper link. – jw]
created_at,entry_id,field1,field2,field3,field4,field5,field6,field7,field8
2016-06-16 05:50:45 UTC,1,19.10,92.70,20.80,1003.02,1512.00,8,15,15
2016-06-16 05:55:07 UTC,2,19.00,94.00,20.91,1003.09,1659.00,41,54,61
2016-06-16 06:01:32 UTC,3,19.10,92.70,20.98,1003.11,2233.00,6,7,12
2016-06-16 06:07:57 UTC,4,19.00,92.90,21.16,1003.11,2620.00,6,7,11
2016-06-16 06:14:22 UTC,5,19.10,92.70,21.19,1002.97,2701.00,6,6,12
2016-06-16 06:20:48 UTC,6,19.10,92.20,21.44,1002.97,2973.00,220,291,327
2016-06-16 06:27:13 UTC,7,19.30,92.20,21.47,1002.99,3197.00,5,6,7
...
2016-06-17 14:19:30 UTC,305,22.70,50.50,23.43,1013.88,1956.00,1,1,1
2016-06-17 14:25:55 UTC,306,22.60,51.20,23.27,1013.88,1979.00,1,1,1
2016-06-17 14:32:20 UTC,307,22.70,50.10,23.18,1014.00,1962.00,1,1,1
2016-06-17 14:38:45 UTC,308,22.70,49.50,23.17,1014.03,1967.00,1,1,1
2016-06-17 14:45:10 UTC,309,22.50,50.90,23.55,1014.01,1856.00,2,2,2
2016-06-17 14:51:35 UTC,310,22.60,51.80,23.62,1013.99,1870.00,1,1,1
2016-06-17 14:58:00 UTC,311,22.60,50.80,23.21,1013.94,1987.00,1,2,2
2016-06-17 15:04:26 UTC,312,"",,,,,,,
2016-06-17 15:10:51 UTC,313,"",,,,,,,
2016-06-17 15:17:16 UTC,314,"",,,,,,,
2016-06-17 15:23:41 UTC,315,"",,,,,,,
2016-06-17 15:30:06 UTC,316,"",,,,,,,
2016-06-17 15:36:31 UTC,317,"",,,,,,,
2016-06-17 15:42:56 UTC,318,"",,,,,,,
...
2016-06-17 22:59:18 UTC,386,"",,,,,,,
2016-06-17 23:05:43 UTC,387,"",,,,,,,
2016-06-17 23:12:08 UTC,388,"",,,,,,,
2016-06-17 23:18:33 UTC,389,"",,,,,,,
2016-06-17 23:24:58 UTC,390,"",,,,,,,
2016-06-17 23:31:23 UTC,391,"",,,,,,,
2016-06-17 23:37:48 UTC,392,"",,,,,,,
2016-06-17 23:44:13 UTC,393,"",,,,,,,
I went and saw the station, it's more like an electrical problem imo because if i reset arduino nothing happens. The data readed by arduino on dht22 is nan and the rest of the sensors is working fine. The only way i could make dht22 reading again is to unplug the power and plug it back. So that's why i think it's more an electrical problem but can't figure why dht22 stops responding and need to switch off all power to bring it back to life. I will try putting an capacitor on wires to dht22 to see if it's better.