I’m relatively new to the Arduino ecosystem. I am prototyping a “sensor box” based off an ESP8266 Thing Dev board. Currently, I have a SAM-M8Q breakout board and a GY-521 (accel, gyro sensor) daisy-chained to the ESP8266 via I2C. I also have a DHT11 (Temp and Humidity sensor) and an SMD RGB LED connected to the thing on other pins.
The code I wrote sends the information via an HTTP POST request to an API I built, and stores the data in a database.
Everything works as expected. However, after about 10 hours, I stop getting GPS coordinates (see screenshot). Twice now, I have left the device plugged in to power and just let it sit overnight. Both times, GPS stopped for no obvious reason. Simply toggling the power switch on the ESP8266 board fixed the problem. It’s worth noting this happened once before I added in the second sensor on the I2C bus and the accompanying code.
I don’t really have an idea of where I should begin troubleshooting this issue. Does anyone have any suggestions?
Thanks!
(It seems my browser is failing to upload pictures, so I will add some in a reply shortly)
#include <SparkFun_Ublox_Arduino_Library.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <DHTesp.h>
#include <Wire.h>
//Initialize DHTesp object called dht
DHTesp dht;
SFE_UBLOX_GPS myGPS;
//TODO: Make it try home wifi then phone wifi
/* Set these to your desired credentials. */
const char *ssid1 = "*****";
const char *password1 = "*****";
const char *ssid2 = "*****";
const char *password2 = "*****";
//Web/Server address to read/write from
const char *host = "********";
//const char *host ="badhost.int.lmp";
const int httpsPort = 443; //HTTPS= 443 and HTTP = 80
//SHA1 finger print of certificate use web browser to view and copy
//You need to visit the site you are POSTing to, view certificate, copy SHA1 fingerprint below
//Replace colons with spaces, example BA:CB turns into BA CB
const char fingerprint[] PROGMEM = "**********";
//The following is for JSON code
const size_t capacity = JSON_OBJECT_SIZE(6);
DynamicJsonDocument doc(capacity);
//RGB Module
const int redpin = 4;
const int greenpin = 0;
const int bluepin = 5;
//MPU_Setup
const int MPU_ADDR = 0x68;
int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data
char tmp_str[7]; // temporary variable used in convert function
char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
sprintf(tmp_str, "%6d", i);
return tmp_str;
}
void setRgbRed() {
analogWrite(bluepin, 0);
analogWrite(redpin, 255);
analogWrite(greenpin, 0);
}
void setRgbBlue() {
analogWrite(bluepin, 255);
analogWrite(redpin, 0);
analogWrite(greenpin, 0);
}
void setRgbGreen() {
analogWrite(bluepin, 0);
analogWrite(redpin, 0);
analogWrite(greenpin, 255);
}
void setRgbOff() {
analogWrite(bluepin, 0);
analogWrite(redpin, 0);
analogWrite(greenpin, 0);
}
void blinkRgb() {
setRgbRed();
delay(500);
setRgbOff();
delay(500);
}
void showRgbError() {
while (true) {
setRgbRed();
delay(100);
setRgbOff();
delay(100);
}
}
void setRgb(int r, int g, int b) {
analogWrite(bluepin, b);
analogWrite(redpin, r);
analogWrite(greenpin, g);
}
void setup() {
//Always good to have a delay
delay(1000);
Wire.begin();
Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
//Begin serial communication, might remove once pushing to web
Serial.begin(115200);
//Configure dht object for pin 14 and tell program it's a DHT11 (vs a DHT22)
dht.setup(12, DHTesp::DHT11);
//RGB Pins
pinMode(redpin, OUTPUT);
pinMode(bluepin, OUTPUT);
pinMode(greenpin, OUTPUT);
//Prevents reconnection issue (taking too long to connect)
WiFi.mode(WIFI_OFF);
delay(1000);
//Only Station No AP, This line hides the viewing of ESP as wifi hotspot
WiFi.mode(WIFI_STA);
//Connect to your WiFi router
//WiFi.begin(ssid, password);
//Serial.println("");
//Try network 1
WiFi.begin(ssid1, password1);
for (int i = 0; i < 5; i++) {
if (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Trying network 1");
}
}
//Try network 2 if not connected
if (WiFi.status() != WL_CONNECTED) {
WiFi.mode(WIFI_OFF);
delay(1000);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid2, password2);
for (int i = 0; i < 5; i++) {
if (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Trying network 2");
}
}
}
Serial.print("Connecting");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
setRgb(127, 0, 127);
delay(500);
setRgbOff();
delay(500);
Serial.print(".");
}
//If connection successful show IP address in serial monitor
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid2);
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
}
void loop() {
//Gyro/Accelerometer code
//TODO: Post to api and make useful
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
Wire.requestFrom(MPU_ADDR, 7 * 2, true); // request a total of 7*2=14 registers
// "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
accelerometer_x = Wire.read() << 8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
accelerometer_y = Wire.read() << 8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
accelerometer_z = Wire.read() << 8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
temperature = Wire.read() << 8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
gyro_x = Wire.read() << 8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
gyro_y = Wire.read() << 8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
gyro_z = Wire.read() << 8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
// print out data
Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
// the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
Serial.print(" | tmp = "); Serial.print(temperature / 340.00 + 36.53);
Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
Serial.println();
// delay
delay(1000);
////////RGB///////
setRgbOff();
delay(100);
setRgbBlue();
////////GPS///////
if (myGPS.begin() == false) {
myGPS.setI2COutput(COM_TYPE_UBX);
myGPS.saveConfiguration();
}
// Get and prepare latitude
float latitude = myGPS.getLatitude();
latitude = latitude / 10000000;
// Get and prepare longitude
float longitude = myGPS.getLongitude();
longitude = longitude / 10000000;
// Get and prepare speed
float speedMMperS = myGPS.getGroundSpeed();
float speedMPH = speedMMperS / 447.00;
// Get and prepare sattelite count
int numSats = myGPS.getSIV();
//Delay loop for as long as minimum sampling period of DHT11
delay(dht.getMinimumSamplingPeriod());
//Record humidity, temperature C, and temperaure F
float humidity = dht.getHumidity();
float temperature = dht.getTemperature();
float temperature_f = dht.toFahrenheit(temperature);
//Repot to serial, remove this once all set up
Serial.print(dht.getStatusString());
Serial.print("\t");
Serial.print("HUM: ");
Serial.print(humidity, 1);
Serial.print("\t\t");
Serial.print("TempF: ");
Serial.print(temperature_f, 1);
Serial.print("\t\t");
Serial.print("Heat Index F: ");
Serial.println(dht.computeHeatIndex(dht.toFahrenheit(temperature), humidity, true), 1);
delay(1000);
////////
//Declare object of class WiFiClient
WiFiClientSecure httpsClient;
//Print the host you are connecting to, as defined above
Serial.println(host);
//Print the fingerprint of the site's cert
Serial.printf("Using fingerprint '%s'\n", fingerprint);
httpsClient.setFingerprint(fingerprint);
httpsClient.setTimeout(15000); // 15 Seconds
delay(1000);
Serial.print("HTTPS Connecting");
int r = 0; //retry counter
while ((!httpsClient.connect(host, httpsPort)) && (r < 10)) {
delay(100);
Serial.print(".");
r++;
}
if (r == 10) {
Serial.println("Connection failed");
showRgbError();
}
else {
Serial.println("Connected to web");
}
String getData, Link;
//POST Data
//I believe this is the URI of where you want to send the post
Link = "/api/sensorreading";
Serial.print("requesting URL: ");
Serial.println(host);
///////JSON CODE//////
doc["tempF"] = temperature_f;
doc["humidity"] = humidity;
doc["longitude"] = longitude;
doc["latitude"] = latitude;
doc["speed"] = speedMPH;
doc["satelliteCount"] = numSats;
serializeJson(doc, Serial);
String jsonOutput;
serializeJson(doc, jsonOutput);
int clength;
clength = measureJson(doc);
/////////////////////
//Construct a valid POST header
//Pay attention to Content-Length, it must match your content
httpsClient.print(String("POST " + Link + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/json" + "\r\n" +
"Content-Length: " + clength + "\r\n\r\n" +
jsonOutput + "\r\n\r\n"));
Serial.println(" ");
Serial.println("-------------------");
Serial.println(String("POST " + Link + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/json" + "\r\n" +
"Content-Length: " + clength + "\r\n\r\n" +
jsonOutput + "\r\n\r\n"));
Serial.println("request sent");
while (httpsClient.connected()) {
String line = httpsClient.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
setRgbGreen();
break;
}
}
Serial.println("reply was:");
Serial.println("==========");
String line;
while (httpsClient.available()) {
line = httpsClient.readStringUntil('\n'); //Read Line by Line
Serial.println(line); //Print response
}
Serial.println("==========");
Serial.println("closing connection");
delay(1000); //POST Data at every 2 seconds
}
//=======================================================================