Erriez / ErriezBMX280

BMP280 / BME280 temperature/pressure/humidity sensor library for Arduino
https://github.com/Erriez/ErriezArduinoLibrariesAndSketches
MIT License
7 stars 4 forks source link

Abnormal values after some time #1

Closed FBMinis closed 1 year ago

FBMinis commented 1 year ago

First of all, thank your very much for sharing your work.

I would like to return the values from the BME280 when I issue a command in a Telegram chat. I am not sure if I need to update those values every 1 second in the loop() function, then send them to me when I issued the command. I tried capturing the values from the sensor only when the command is issued but after leaving the module unattended for some minutes, the values were not correct anymore (like 623.39 hPa instead of 1020.71 hPa).

My project is comprised of a Wemos D1, a PIR and a BME238 sensor, powered by USB. The PIR triggers and interrupt and a message is sent to a Telegram channel; the BME238 captures temperature, humidity, pressure and altitude and these values are sent to me when I type "/status". It is a basic surveillance/weather station that is placed in my backyard. My only doubt is how to correctly retrieve the values from the BME238.

I would appreciate your feedback on how to improve my code : )

/*******************************************************************
  Wemos D1 Mini
  HC-SR501 PIR output to D7: send message to Telegram channel upon interrupt
  BME280 to D1 D2: sends weather data to Telegram chat upon request with "/status"
  TODO: send periodically to Thingspeak

  Using library ESP8266WiFi at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266WiFi
  Using library UniversalTelegramBot at version 1.3.0 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\UniversalTelegramBot
  Using library ArduinoJson at version 6.19.4 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\ArduinoJson
  Using library BME280 at version 3.0.0 in folder: E:\arduino-1.8.13\portable\sketchbook\libraries\BME280
  Using library Wire at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire
  Using library SPI at version 1.0 in folder: E:\arduino-1.8.13\portable\packages\esp8266\hardware\esp8266\3.0.2\libraries\SPI
 *******************************************************************/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Wifi network station credentials
#define WIFI_SSID "blablabla"
#define WIFI_PASSWORD "blablabla"
#define BOT_TOKEN "blablabla" // Telegram BOT Token (Get from Botfather)

const unsigned long BOT_MTBS = 1000; // mean time between scan messages

X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOT_TOKEN, secured_client);
unsigned long bot_lasttime; // last time messages' scan has been done

#define CHANNEL_ID "blablabla"
const int motionSensor = 13; //D7
boolean motion = false;
boolean pir_active = false;

#include <Wire.h>
#include <ErriezBMX280.h>

// Adjust sea level for altitude calculation
#define SEA_LEVEL_PRESSURE_HPA      1026.25

// Create BMX280 object I2C address 0x76 or 0x77
ErriezBMX280 bmx280 = ErriezBMX280(0x76);

float temperature, humidity, pressure, altitude;

unsigned long previousMillis = 0;

void IRAM_ATTR detectsMovement() {
  Serial.println("movement detected");
  motion = true;
}

void handleNewMessages(int numNewMessages)
{
  Serial.print("handleNewMessages ");
  Serial.println(numNewMessages);

  for (int i = 0; i < numNewMessages; i++)
  {
    String chat_id = bot.messages[i].chat_id;
    String text = bot.messages[i].text;

    String from_name = bot.messages[i].from_name;
    if (from_name == "")
      from_name = "Guest";

    if (text == "/enpir")
    {
      pir_active = true;
      bot.sendMessage(chat_id, "PIR activated", "");
    }

    if (text == "/dispir")
    {
      pir_active = false;
      bot.sendMessage(chat_id, "PIR deactivated", "");
    }

    if (text == "/status")
    {
      String stat = "Rssi: " + String(WiFi.RSSI());
      stat += "\nPIR: " + String(pir_active);
      stat += "\nTemp: " + String(temperature) + " C";
      stat += "\nHum: " + String(humidity) + " %";
      stat += "\nPres: " + String(pressure) + " hPa";
      stat += "\nAlt: " + String(altitude) + " m";
      bot.sendMessage(chat_id, stat, "Markdown");
    }

    if (text == "/start")
    {
      String welcome = "Welcome, " + from_name + ".\n";
      welcome += "Commands list:\n\n";
      welcome += "/enpir : to switch the pir ON\n";
      welcome += "/dispir : to switch the pir OFF\n";
      welcome += "/status : Returns current status of pir\n";
      bot.sendMessage(chat_id, welcome, "Markdown");
    }
  }
}

void setup()
{
  delay(500);
  Serial.begin(115200);
  Serial.println();

  // Initialize I2C bus
  Wire.begin();
  Wire.setClock(400000);

  // Initialize sensor
  while (!bmx280.begin()) {
    Serial.println(F("Error: Could not detect sensor"));
    delay(3000);
  }

  // Print sensor type
  Serial.print(F("\nSensor type: "));
  switch (bmx280.getChipID()) {
    case CHIP_ID_BMP280:
      Serial.println(F("BMP280\n"));
      break;
    case CHIP_ID_BME280:
      Serial.println(F("BME280\n"));
      break;
    default:
      Serial.println(F("Unknown\n"));
      break;
  }

  // Set sampling - Recommended modes of operation
  //
  // Weather
  //  - forced mode, 1 sample / minute
  //  - pressure ×1, temperature ×1, humidity ×1
  //  - filter off
  //
  // Humidity sensing
  //  - forced mode, 1 sample / second
  //  - pressure ×0, temperature ×1, humidity ×1
  //  - filter off
  //
  // Indoor navigation
  //  - normal mode, t standby = 0.5 ms
  //  - pressure ×16, temperature ×2, humidity ×1
  //  - filter coefficient 16
  //
  // Gaming
  //  - forced mode, t standby = 0.5 ms
  //  - pressure ×1, temperature ×1, humidity ×1
  //  - filter off
  bmx280.setSampling(BMX280_MODE_NORMAL,    // SLEEP, FORCED, NORMAL
                     BMX280_SAMPLING_X16,   // Temp:  NONE, X1, X2, X4, X8, X16
                     BMX280_SAMPLING_X16,   // Press: NONE, X1, X2, X4, X8, X16
                     BMX280_SAMPLING_X16,   // Hum:   NONE, X1, X2, X4, X8, X16 (BME280)
                     BMX280_FILTER_X16,     // OFF, X2, X4, X8, X16
                     BMX280_STANDBY_MS_500);// 0_5, 10, 20, 62_5, 125, 250, 500, 1000

  // PIR Motion Sensor
  pinMode(motionSensor, INPUT);
  // Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

  // attempt to connect to Wifi network:
  configTime(0, 0, "pool.ntp.org");      // get UTC time via NTP
  secured_client.setTrustAnchors(&cert); // Add root certificate for api.telegram.org
  Serial.print("Connecting to Wifi SSID ");
  Serial.print(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.print("\nWiFi connected. IP address: ");
  Serial.println(WiFi.localIP());

  // Check NTP/Time, usually it is instantaneous and you can delete the code below.
  Serial.print("Retrieving time: ");
  time_t now = time(nullptr);
  while (now < 24 * 3600)
  {
    Serial.print(".");
    delay(100);
    now = time(nullptr);
  }
  Serial.println(now);

  //  bot.sendMessage(chat_id, "/start", "");
}

void loop()
{

  // Check for Telegram messages
  if (millis() - bot_lasttime > BOT_MTBS)
  {
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);

    while (numNewMessages)
    {
      Serial.println("got response");
      handleNewMessages(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }

    bot_lasttime = millis();
  }

  // When interrupt is triggered by motion, don't send message if PIR is set as inactive
  if (motion && pir_active) {
    bot.sendMessage(CHANNEL_ID, "/photo", "");
    motion = false;
  } else {
    motion = false;
  }

// Update BME280 values every 1 seconds
  if (millis() - previousMillis >= 1000) {

    previousMillis = millis();

    temperature = bmx280.readTemperature();
    Serial.print(F("Temperature: "));
    Serial.print(temperature);
    Serial.println(" C");

    if (bmx280.getChipID() == CHIP_ID_BME280) {
      humidity = bmx280.readHumidity();
      Serial.print(F("Humidity:    "));
      Serial.print(humidity);
      Serial.println(" %");
    }

    pressure = bmx280.readPressure() / 100.0F;
    Serial.print(F("Pressure:    "));
    Serial.print(pressure);
    Serial.println(" hPa");

    altitude = bmx280.readAltitude(SEA_LEVEL_PRESSURE_HPA);
    Serial.print(F("Altitude:    "));
    Serial.print(altitude);
    Serial.println(" m");
  }
}
Erriez commented 1 year ago

Thanks for using this library. Just some suggestions:

  1. Did you encounter any issues with the original examples on the Wemos D1?
  2. Can you add the volatile keyword for variables shared between the main loop and interrupt handler?

Please notice that the scope of helping with issues is limited to this ErriezBMX280 library and maintain this in spare time. Integration with libraries can influence the behavior and I can only provide some suggestions.

Success!

FBMinis commented 1 year ago
  1. I tested if briefly inside and the values were as expected. When I tested it outside the values became abnormal after some readings;
  2. I have done so, thank you.

Do I need to change the sampling and mode of operation if I used the sensor outside, compared to the values in the example?

Thank you

Erriez commented 1 year ago

The sampling mode of operation is handled inside the sensor hardware and configures the accuracy of the sensor values. The library contains an interface setSampling() for setting this mode.

The commented weather mode is recommended for outdoor which is less accurate (sufficient for weather conditions) and is also for low-power battery devices. In your posted example, the highest accuracy with highest power consumption is specified and probably not required for your application, but up to you.

A second mode is important and configured correctly once at startup in setup():

For more modes of operation information, please refer to section 3.5 Recommended modes of operation.

FBMinis commented 1 year ago

Thank you very much for your time to help me and for your libraries :)

Erriez commented 1 year ago

You're welcome. I'll close this issue.