I have the following code running on a Wemos D1 (ESP8266 dev board) which is supposed to read the HMC5883 magnetic field sensor every 100 milliseconds. As you can see I'm using the Adafruit library for the HMC5883
However my sketch locks up 10-15 times a day. If I comment out the line that reads the I2C data "mag.getEvent(&event);" the sketch will run all day without a hiccup so its definitely this library.
I've implemented the workaround at Watchdog managed by sketch only · Issue #1532 · esp8266/Arduino · GitHub but maybe there is a better way?
The issue is discussed here method for recovering I2C bus · Issue #1025 · esp8266/Arduino · GitHub and the impression I get was that a patch was applied back in May (long before i downloaded the ESP libraries) although I could be reading it wrong?
Anyone have good experience with I2C on the ESP8266?
/* Magsense defines */
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
#define N 3 //average 3 readings
/* Wemos defines */
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#define USE_SERIAL Serial
#solution to lockups as per https://github.com/esp8266/Arduino/issues/1532
#include <Ticker.h>
Ticker tickerOSWatch;
#define OSWATCH_RESET_TIME 30
static unsigned long last_loop;
void ICACHE_RAM_ATTR osWatch(void) {
unsigned long t = millis();
unsigned long last_run = abs(t - last_loop);
if(last_run >= (OSWATCH_RESET_TIME * 1000)) {
// save the hit here to eeprom or to rtc memory if needed
ESP.restart(); // normal reboot
//ESP.reset(); // hard reset
}
}
ESP8266WiFiMulti WiFiMulti;
/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
void displaySensorDetails(void)
{
sensor_t sensor;
mag.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" uT");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" uT");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" uT");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(D5,INPUT);
USE_SERIAL.begin(115200);
// USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for (uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFiMulti.addAP("SSID", "password");
Serial.println("Connecting Wifi...");
if (WiFiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
/* Initialise the mag sensor */
if (!mag.begin())
{
/* There was a problem detecting the HMC5883 ... check your connections */
Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
while (1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
pinMode(LED_BUILTIN, OUTPUT);
//start the watchdog routine
last_loop = millis();
tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), osWatch);
}
void loop(void)
{
sensors_event_t event;
static double x[3];
static double xmin[3]={9999,9999,9999},xmax[3]={-9999,-9999,-9999};
int n;
static unsigned long int next_upload = 10000, next_mag = 0, next_blink=2000;
static long int counter1=0;
int ldr;
unsigned long int now = millis();
last_loop = now;
ldr=digitalRead(D5);
if ( now >= next_mag) {
next_mag += 100;
/* Get a new sensor event */
mag.getEvent(&event);
x[0] = event.magnetic.x;
x[1] = event.magnetic.y;
x[2] = event.magnetic.z;
for (n=0;n<3;n++) {
if (x[n]>xmax[n]) {
xmax[n]=x[n];
}
if (x[n]<xmin[n]) {
xmin[n]=x[n];
}
}
};
if (now>=next_blink) {
next_blink+=2000;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
// wait for WiFi connection
if (now >= next_upload) {
String vars="";
for (n=0;n<3;n++) {
vars+="&field"+String(n*2+2)+"="+String(xmax[n])+"&field"+String(n*2+3)+"="+String(xmin[n]);
Serial.print(xmax[n]); Serial.print(",");
Serial.print(xmin[n]); Serial.print(",");
xmax[n]=-9999; xmin[n]=9999;
};
Serial.println();
//USE_SERIAL.println(counter1);
next_upload += 16000;
if ((WiFiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
//USE_SERIAL.print("[HTTP] begin...\n");
String url = "http://api.thingspeak.com/update?api_key=API_KEY&field1=";
//counter1=ESP.getFreeHeap();
counter1+=1;
USE_SERIAL.println(url+counter1+vars);
http.begin(url +counter1+vars ); //HTTP
//http.begin(url +counter1);
//USE_SERIAL.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);
String payload = http.getString();
USE_SERIAL.println(payload);
} else {
USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
}
}