ESP crashing at MQTT stage of IOT program
Posted: Mon Apr 03, 2017 8:25 am
Hi folks,
I'm working on a group project and we're having the following problem with our ESP(s):
Both ESP8266 (One is an adafruit feather, one is a very basic breakout board) connect to the WiFi no problem, both ESPs get data from our DHT22 sensors (and we can view this on the serial port), but when they attempt to publish to adafruit IO, they crash.
They're running virtually identical code, as follows:
(I changed the WiFi and adafruit login info to generic things just for posting, they are correct in our code)
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Ticker.h>
#include <DHT.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define WIFI_SSID "ADDRESS" // insert ssd
#define WIFI_PASSWORD "password" // insert password
#define MAX_LOOP_TIME_MS 10000 // this is the max time that the loop will run before going to sleep
#define DHTPIN 14 // dht digital pin
#define DHTTYPE DHT22 // type of dht sensor
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME "username" // plug in you adafruit username account
#define AIO_KEY "123key" // enter key for your adafruit account
/************ Global States ******************/
// DHT sensor
DHT dht(DHTPIN, DHTTYPE);
WiFiClient client;
// Store the MQTT server, username, and password in flash memory.
// This is required for using the Adafruit MQTT library.
const char MQTT_SERVER[] PROGMEM = AIO_SERVER;
const char MQTT_USERNAME[] PROGMEM = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM = AIO_KEY;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
/****************************** Feeds ***************************************/
// Setup feeds for sensors
const char TEMPERATURE_FEED[] PROGMEM = AIO_USERNAME "/feeds/DHT22_temp_outdoor"; // this is the portion of the code that actually sends the data to adafruit
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, TEMPERATURE_FEED);
const char HUMIDITY_FEED[] PROGMEM = AIO_USERNAME "/feeds/DHT22_humidity_outdoor";
Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, HUMIDITY_FEED);
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
Ticker sleepTicker; // ticker function to count time
unsigned long startTime; // place to store the start time
//this is the portion of the code that tells the esp to go to sleep when it is called.
void sleepyTime() {
const int elapsed = millis() - startTime; // display the total loop time
Serial.printf("Sleeping. Loop took %d ms\n", elapsed);
// If this sleep happened because of timeout, clear the
// Wifi state.
if (elapsed >= MAX_LOOP_TIME_MS) {
WiFi.disconnect();
}
ESP.deepSleep(15 * 1000000, WAKE_RF_DEFAULT);
// It can take a while for the ESP to actually go to sleep.
// When it wakes up we start again in setup().
delay(5000);
}
void waitForWifi() { // wifi function to connect to wifi
Serial.print("Connecting to WiFi.");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println(" Done");
Serial.println("ESP8266 Weather Sensor");
Serial.printf("Connected to %s\n", WIFI_SSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void setup(void)
{
startTime = millis(); // start ticker to begin counting time
sleepTicker.once_ms(12000, &sleepyTime); // not sure what this is.. you can esily look it up on google
Serial.begin(115200); // baud rate
dht.begin(); // tell dht library to begin
pinMode(13, OUTPUT); // set up led for visual affects of data being sent
digitalWrite(13, HIGH);
Serial.println();
Serial.println("Using saved SSID: " + WiFi.SSID()); // this portion of the code attempts to connect to the last ssid
if (WiFi.SSID() != WIFI_SSID) {
Serial.println("Configuring persistent wifi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.persistent(true);
WiFi.setAutoConnect(true);
WiFi.setAutoReconnect(true);
} else {
Serial.println("Using saved wifi info...");
}
}
bool isValidHumidity(const float humidity) { // these are new functions I added so that we can test if the dht is giving us the proper reading.. returns true unless either one of those conditions are false
return (!isnan(humidity) && humidity >= 0 && humidity <= 100);
}
bool isValidTemp(const float temp) {
return (!isnan(temp) && temp >= -100 && temp <= 212);
}
void loop(void)
{
float humidity_data = (float)dht.readHumidity(); // grabs temp & humidity reading form temp sensor
float temperature_data = (float)dht.readTemperature();
while (!(isValidTemp(temperature_data) && isValidHumidity(humidity_data))) { // delays if false if data returned from the check function is false
delay(100);
}
const int sensorTime = millis() - startTime; // displays time it took to grab data
Serial.printf("snesor read took %d ms\n", sensorTime);
waitForWifi(); // wait for wifi connect function to connect before sending the data to MQTT
const int wifiTime = millis() - (startTime + sensorTime);
Serial.printf("WiFi init took an additional %d ms\n", wifiTime);
MQTT_connect(); // Connect to MQTT
// Publish data
if (! temperature.publish(temperature_data)); // pulblish data to MQTT
if (! humidity.publish(humidity_data));
sleepyTime(); // go to sleep
}
void MQTT_connect() { // mqtt connect function, which is required for the mqtt library
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
uint8_t retries = 7;
while ((ret = mqtt.connect()) != 0)
{ // connect will return 0 for connected
mqtt.disconnect();
delay(2); // wait 2 seconds
retries--;
if (retries == 0)
{
// go back to sleep
sleepyTime();
}
}
}
If you have a suggestion of an alternative that's more reliable, something we're messing up in the code, a link to a tutorial on MQTT, anything that might be of help, I would greatly appreciate it.
I'm working on a group project and we're having the following problem with our ESP(s):
Both ESP8266 (One is an adafruit feather, one is a very basic breakout board) connect to the WiFi no problem, both ESPs get data from our DHT22 sensors (and we can view this on the serial port), but when they attempt to publish to adafruit IO, they crash.
They're running virtually identical code, as follows:
(I changed the WiFi and adafruit login info to generic things just for posting, they are correct in our code)
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Ticker.h>
#include <DHT.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define WIFI_SSID "ADDRESS" // insert ssd
#define WIFI_PASSWORD "password" // insert password
#define MAX_LOOP_TIME_MS 10000 // this is the max time that the loop will run before going to sleep
#define DHTPIN 14 // dht digital pin
#define DHTTYPE DHT22 // type of dht sensor
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME "username" // plug in you adafruit username account
#define AIO_KEY "123key" // enter key for your adafruit account
/************ Global States ******************/
// DHT sensor
DHT dht(DHTPIN, DHTTYPE);
WiFiClient client;
// Store the MQTT server, username, and password in flash memory.
// This is required for using the Adafruit MQTT library.
const char MQTT_SERVER[] PROGMEM = AIO_SERVER;
const char MQTT_USERNAME[] PROGMEM = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM = AIO_KEY;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
/****************************** Feeds ***************************************/
// Setup feeds for sensors
const char TEMPERATURE_FEED[] PROGMEM = AIO_USERNAME "/feeds/DHT22_temp_outdoor"; // this is the portion of the code that actually sends the data to adafruit
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, TEMPERATURE_FEED);
const char HUMIDITY_FEED[] PROGMEM = AIO_USERNAME "/feeds/DHT22_humidity_outdoor";
Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, HUMIDITY_FEED);
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
Ticker sleepTicker; // ticker function to count time
unsigned long startTime; // place to store the start time
//this is the portion of the code that tells the esp to go to sleep when it is called.
void sleepyTime() {
const int elapsed = millis() - startTime; // display the total loop time
Serial.printf("Sleeping. Loop took %d ms\n", elapsed);
// If this sleep happened because of timeout, clear the
// Wifi state.
if (elapsed >= MAX_LOOP_TIME_MS) {
WiFi.disconnect();
}
ESP.deepSleep(15 * 1000000, WAKE_RF_DEFAULT);
// It can take a while for the ESP to actually go to sleep.
// When it wakes up we start again in setup().
delay(5000);
}
void waitForWifi() { // wifi function to connect to wifi
Serial.print("Connecting to WiFi.");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println(" Done");
Serial.println("ESP8266 Weather Sensor");
Serial.printf("Connected to %s\n", WIFI_SSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void setup(void)
{
startTime = millis(); // start ticker to begin counting time
sleepTicker.once_ms(12000, &sleepyTime); // not sure what this is.. you can esily look it up on google
Serial.begin(115200); // baud rate
dht.begin(); // tell dht library to begin
pinMode(13, OUTPUT); // set up led for visual affects of data being sent
digitalWrite(13, HIGH);
Serial.println();
Serial.println("Using saved SSID: " + WiFi.SSID()); // this portion of the code attempts to connect to the last ssid
if (WiFi.SSID() != WIFI_SSID) {
Serial.println("Configuring persistent wifi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.persistent(true);
WiFi.setAutoConnect(true);
WiFi.setAutoReconnect(true);
} else {
Serial.println("Using saved wifi info...");
}
}
bool isValidHumidity(const float humidity) { // these are new functions I added so that we can test if the dht is giving us the proper reading.. returns true unless either one of those conditions are false
return (!isnan(humidity) && humidity >= 0 && humidity <= 100);
}
bool isValidTemp(const float temp) {
return (!isnan(temp) && temp >= -100 && temp <= 212);
}
void loop(void)
{
float humidity_data = (float)dht.readHumidity(); // grabs temp & humidity reading form temp sensor
float temperature_data = (float)dht.readTemperature();
while (!(isValidTemp(temperature_data) && isValidHumidity(humidity_data))) { // delays if false if data returned from the check function is false
delay(100);
}
const int sensorTime = millis() - startTime; // displays time it took to grab data
Serial.printf("snesor read took %d ms\n", sensorTime);
waitForWifi(); // wait for wifi connect function to connect before sending the data to MQTT
const int wifiTime = millis() - (startTime + sensorTime);
Serial.printf("WiFi init took an additional %d ms\n", wifiTime);
MQTT_connect(); // Connect to MQTT
// Publish data
if (! temperature.publish(temperature_data)); // pulblish data to MQTT
if (! humidity.publish(humidity_data));
sleepyTime(); // go to sleep
}
void MQTT_connect() { // mqtt connect function, which is required for the mqtt library
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
uint8_t retries = 7;
while ((ret = mqtt.connect()) != 0)
{ // connect will return 0 for connected
mqtt.disconnect();
delay(2); // wait 2 seconds
retries--;
if (retries == 0)
{
// go back to sleep
sleepyTime();
}
}
}
If you have a suggestion of an alternative that's more reliable, something we're messing up in the code, a link to a tutorial on MQTT, anything that might be of help, I would greatly appreciate it.