Troubleshooting a BMP280 sensor with wrong readings

Hi,

I set an Arduino Uno with a BMP 280 sensor to act as a weather station. After a few hours operating smoothly, the BMP280 starts to operate erratically, presenting strange values, and coincidentally always freeze at the same values of temperature (-137.76 .C), altitude (-767.71 m) and pressure (1108.92 hPa). When I restart the board, the operation go back to normal, only to freeze again after a while in an intermittent time interval, anywhere between few minutes to one time a day or a week.

Naturally, I tested some hypothesis, but I was not successful at all:
a) I checked the connections, replaced the breadboard jumper wires, resoldered the PCB pin connector;
b) Checked the voltages (3.3VDC for sensor);
c) I replaced the USB charger, the USB cable and even connected directly to the computer USB port to eliminate voltage fluctuations from the AC power source;
d) Tried both I2C address (0x76 and 0x77);
e) Changed the Arduino Uno board and connected the BMP280 to a Weimos ESP32 dev board;
f) The serial output to the Arduino IDE, a LCD display or remote communication to a Blynk server keep working, only the sensor reading remains at the same values cited above.

So, apparently, the problem is neither software nor the boards because the system is not freezing.

My last attempt will be to solder the sensor to the board instead of using jumpers to eliminate some kind of bad contact, or use some sort of shielding, but frankly, I'm not confident that this will solve anything.

Am I missing something here? Is there any way to test the sensor or debug to find out what happens in this situation? Or I shouldn't even waste time, give up and buy another sensor?

Connections:
VCC = 3.3V
GND = GND
SCL = GPIO22 (for ESP32) / A5 (Arduino)
SDA = GPIO21 (for ESP32) / A4 (Arduino)
CSB = Not used
SDO = Disconnected - (0x76) for LOW level / connected in 3.3V (0x77) for HIGH level

Code:

// Programa : Sensor de temperatura e pressao BMP280
// Autor : Baseado no código de FILIPEFLOP - https://www.filipeflop.com/blog/temperatura-pressao-bmp180-arduino/
 
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <LiquidCrystal.h>
 
LiquidCrystal lcd(2,3, 4, 5, 6, 7);
 
Adafruit_BMP280 bmp280;
 
int mostrador = 0;
   
void setup() 
{
  Serial.begin(9600);
  lcd.begin(20,4);
  if (!bmp280.begin(0x77)) // Conectado em interface I2C, pino SDO em nível alto
  {
    Serial.println("Sensor nao encontrado !!");
    while (1) {}
  }
}
   
void loop() 
{   
   lcd.setCursor(0, 1);
   lcd.print("Temp. :  ");
   Serial.print("Temperatura : ");
   if ( bmp280.readTemperature() < 10)
   {
     lcd.print(" "); 
     lcd.print(bmp280.readTemperature());
     Serial.print(bmp280.readTemperature());
     Serial.println(" C");
   }
   else
   {
     lcd.print(bmp280.readTemperature(),2);
     Serial.print(bmp280.readTemperature(),2);
     Serial.println(" C");
   }
   lcd.print(" ");
   lcd.print((char)223); 
   lcd.print("C   ");
       
   if (mostrador == 0)
   {
     lcd.setCursor(0, 2);
     lcd.print("                ");
     lcd.setCursor(0, 2);
     lcd.print("Altit.: ");
     Serial.print("Altitude : ");
     lcd.print(bmp280.readAltitude());
     Serial.print(bmp280.readAltitude());
     Serial.println(" m");
     lcd.print(" m");  
    }
   if (mostrador == 1)
   {
     lcd.setCursor(0, 3);
     lcd.print("                ");
     lcd.setCursor(0, 3);
     lcd.print("Press.: ");
     Serial.print("Pressao : ");
     lcd.print(bmp280.readPressure()/100);  
     Serial.print(bmp280.readPressure()/100);  
     Serial.println(" hPa");
     lcd.print(" hPa");
   }
    
   delay(3000);
   mostrador = !mostrador;
}

Might not be totally relevant to your problem but I sometimes get NaN (Not A Number) values back from my BME280 sensors so I inserted some extra code to check for this and perform a BME280 reset that cures the problem without having to cycle the power on the whole device.

Below is some excerpts of the reset code and the checks for NaN values. Hope this helps.

void BME280_Reset()
{
  if(DEBUG) Serial.println(F("BME280 Reset"));
  Wire.beginTransmission(BME280_I2C_ADDR);
  Wire.write((uint8_t)BME280_REGISTER_SOFTRESET);
  Wire.write((uint8_t)0xB6);
  Wire.endTransmission();
  delay(1000);
}

##########################################################

  // Start with temperature, as that data is needed for accurate compensation.
  // Reading the temperature updates the compensators of the other functions in the background.
  scratchfloat = bme.readTemperature();
  if(isnan(scratchfloat) || (scratchfloat == 0))
  {
    scratchfloat = temperature;                             // Just use last value instead to prevent perpetual NaN
    sendStatus(LoRaDevice " Temperature Reboot.");
    resetNeeded = true;
  }
  temperature += scratchfloat;
  temperature = temperature / 2;
  delay(1);
  
  scratchfloat = bme.readPressure() / 100.0F;
  if(isnan(scratchfloat) || (scratchfloat == 0))
  {
    scratchfloat = pressure;                                // Just use last value instead
    sendStatus(LoRaDevice " Pressure Reboot.");
    resetNeeded = true;
  }
  pressure += scratchfloat;
  pressure = pressure / 2;
  delay(1);
  
  scratchfloat = bme.readAltitude(SEALEVELPRESSURE_HPA);
  if(isnan(scratchfloat) || (scratchfloat == 0))
  {
    scratchfloat = altitude;                                // Just use last value instead
    sendStatus(LoRaDevice " Altitude Reboot.");
    resetNeeded = true;
  }
  altitude += scratchfloat;
  altitude = altitude / 2;
  delay(1);
  
  scratchfloat = bme.readHumidity();
  if(isnan(scratchfloat) || (scratchfloat == 0))
  {
    scratchfloat = humidity;                                // Just use last value instead
    sendStatus(LoRaDevice " Humidity Reboot.");
    resetNeeded = true;
  }
  humidity += scratchfloat;
  humidity = humidity / 2;
  
  if(resetNeeded)
  {
    BME280_Reset();
  }

Riva, thank you very much for the suggestion. I applied the code and tested it, but the problem happened again and the IF condition has not been triggered; in other words, it is not a NaN value.

I will adapt the IF condition to also trigger the reset when the temperature read is below -100 ºC as well, at least until I can find another explanation for this strange behavior.

Riva,

I tried the proposed solution and it didn't work. I circumvented the problem trying to use the ESP32 deep sleep function to force the sensor to reset every time the system sleeps, but I had very inconsistent results. Sometimes the ESP32 wakeup and keep reading values of temperature/pressure equal to zero, so would it means the sensor is not really resetting between deep sleep cycles. As the sensor is connected to the 3.3V output of the board, I'm wondering if even in deep sleep the BMP280 is really off. I found some references suggesting to write serial.end() before the deep sleep command (After ESP32 wakes up from deep sleep, i2c bus unusable · Issue #3363 · espressif/arduino-esp32 · GitHub), but I haven't tested it yet.

However, now I have encountered another problem, which is the ESP32 sometimes going into deep sleep and not coming back. Well, back to Google...if anyone has any suggestions on which way to go, I appreciate it.

To save battery life I power the BME280 from Arduino I/O pins so I can shut it down when not needed but still sometimes get the NaN problem that only goes away with power cycle or the BME280 reset command.

Just an update:

  1. I realized that sometimes the USB port of the ESP32 had little connection issues, maybe due to mechanical forces produced by the USB cable. I resoldered all the contacts again to reinforce the connector fixation before something serious could happen and the problems regarding deep sleep have been solved for now.

  2. I changed the VCC connection of the BMP280 to a GPIO, now I'm sure the sensor is turned off every cycle, so I don't need to worry about to reset the sensor if something goes wrong.

Thanks, Riva, for the help.

SOLVED, so if a moderator understand that this topic could be closed, feel free to do so.