Hello there,
This is my first post, and trying to comply to the guidelines and best practices, but I may miss something, apologies in advance if so!
The Problem
I am trying to run a very simple loop that reads the values of these two sensors. The BME280 is being read every 15s and the GY-302 ligt sensor, is being read (in single sample mode) every minute. Everything starts normal and successful, but after aprrximately one hour, arduino hangs. I know it hagngs cause I have set a led to blink every second.
Attempts to solve
I have read so many post about arduinos hanging or crashing. No one seems to point me in the direcction of the real cause of my problem. As you will see in the code. I am not using std libreary strings, just plain C-Strings. The code is very simple. I am sampling at very low rates (15s, and 60s) . I2c cable to the devices is just about 10cm long, so no cable impadance issues. Baud rate is low enough (9600) so to prevent high freq noise? I have added pull-up resistors 2kOhm as this is being sugested in many places. Nothing seems to work. The only clue I can provide is that, if I remove the light sensor, the program can run forever no problem (sampling the pressure temp sensor only) . So problems come if I run both or even if I run the light sensor only. I am a Software guy so HW is not my strength, please feel free to correct me if i said something silly.
The code
/*--------------------------------------------------------
* Sensors platform
--------------------------------------------------------*/
#include <Arduino.h> // arduino types and defs
#include <Adafruit_Sensor.h> // Generic sensor lib
#include <Adafruit_BME280.h> // static air data drivers
#include <BH1750.h> // light sensor driver... Christph Laws
#include <Wire.h>
//--- Serial
static const unsigned SERIAL_BAUDRATE = 9600; // 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800, 115200, 230400, 250000[baud]
static const byte BUFFER_SIZE = 255;
static const byte LED_PIN = 2;
//--- tasks schedulling
static byte count60s = 0;
static byte count15s = 0;
static int led_status = HIGH;
static unsigned long count1s = 0;
static char output_buffer[BUFFER_SIZE];
static char straux[25];
//--- light sensor
static BH1750 lt_sensor;
static float lux = ZERO;
//--- baro sensor
//{
static Adafruit_BME280 bme280; // I2C add 0x76 (118)
static float press = 1013.25f;
static float temp = 15.f, rel_hum = 50.f;
//}
//--- prototypes
static bool validate_value(const float min, const float max, const float update, float &value);
static const char *format_to_float(char *str, float const x);
//-------------------------------------------------------------------
// Initialisations
//-------------------------------------------------------------------
void setup()
{
delay(1000);
byte count = 0;
//--- Serial setup
while(count < 150)
{
Serial.begin(SERIAL_BAUDRATE);
if(Serial) break;
count++;
}
Serial.println("Initialising");
//--- Pins I/O configuration
pinMode(LED_PIN , OUTPUT);
digitalWrite(LED_PIN , HIGH);
//---- I2C
Serial.println("Init Wire");
Wire.begin();
delay(1000);
//--- pressure sensor BME280 inits
Serial.println("Init BME280 sensor");
if(bme280.begin(0x76, &Wire) == 0)
Serial.println("BME280 Fault!");
//--- Light Sensor
Serial.println("Init light sensor");
lt_sensor.begin(BH1750::ONE_TIME_HIGH_RES_MODE);
delay(500);
}
//-------------------------------------------------------------------
// Main loop
//-------------------------------------------------------------------
void loop()
{
//--- 1s base sampling
if(millis() < count1s) return;
//--- 1s tasks
led_status = (led_status == HIGH)? LOW : HIGH;
digitalWrite(LED_PIN, led_status);
//--- 15s tasks
//. Sample BME280 sensor
//. Broadcast to PMCU: press, temp, RH, lux
if(count15s >= 15)
{
count15s = 1;
float aux = press;
//--- NAN filter
validate_value(-15.f , 50.f , bme280.readTemperature(), temp); // [C] greenhouse temperature
validate_value(89000.f, 110000.f, bme280.readPressure(), aux); // [Pa] static pressure
validate_value(0.f , 100.f , bme280.readHumidity(), rel_hum); // [%] uncalibrated greenhouse relative humidity
press = aux;
char *wr_pt = output_buffer;
format_to_float(straux, press * 0.01f);
snprintf(wr_pt, BUFFER_SIZE, "$%s", straux); // press
byte len = strlen(output_buffer);
wr_pt = output_buffer + len;
format_to_float(straux, temp);
snprintf(wr_pt, BUFFER_SIZE, ",%s", straux); // temp
len = strlen(output_buffer);
wr_pt = output_buffer + len;
format_to_float(straux, rel_hum);
snprintf(wr_pt, BUFFER_SIZE, ",%s", straux); // RH
len = strlen(output_buffer);
wr_pt = output_buffer + len;
format_to_float(straux, lux);
snprintf(wr_pt, BUFFER_SIZE, ",%s\n", straux); // lux
Serial.print(output_buffer); // data stream
}
else
count15s++;
//---1min tasks
//. Sample light sensor
if(count60s >= 60)
{
count60s = 1;
//--- Light sensor - Xistoph Laws library version
if(lt_sensor.measurementReady(true))
{
float lumens = lt_sensor.readLightLevel();
//--- self calibration as per library example)
bool ltsen_error = false;
if (lumens > 40000.f) // reduce measurement time - needed in direct sun light
ltsen_error = !lt_sensor.setMTreg(32);
else
{
if (lumens > 10.f) // typical light environment
ltsen_error = !lt_sensor.setMTreg(69);
else
ltsen_error = !lt_sensor.setMTreg(138);
}
// perform some fault handling using ltsen_error
// TODO
//--- sample
lt_sensor.configure(BH1750::ONE_TIME_HIGH_RES_MODE);
ltsen_error = !validate_value(0., 100000.f, lumens, lux); //E: read the result
if(ltsen_error)
Serial.println("Invalid Light Sample");
}
}
else
count60s++;
count1s = millis() + 1000;
}
////////////////////////////////////////////////////////////////////////////
static const char *format_to_float(char *str, float const x)
{
int intg = (int)x,
cent = abs((int)((x - intg)* 100.f));
sprintf(str, "%d.%d", intg, cent);
return str;
}
//------------------------------------------
// Valid number checker
//------------------------------------------
static bool validate_value(const float min,const float max, const float update, float &value)
{
if(isnan(update)) return false;
if((update < min) || (update > max)) return false;
value = update;
return true;
}