I'm using a BME280 to get Temperature and Humidity and most of the time it works. But as you can see on the graph, sometimes I get a zero degree C reading. while temperature is about 23 degrees.
Is there something wrong with the sensor or the code?
I guess I could make a function that tests if it gets 0 multiple times and only accept the reading of zero if it repeats, otherwise do a new reading. I would like it if this was not necessary though.
Such events happen with many sensors. There can be communication errors, timing errors, etc.
Your code could recognize and reject clear outliers. Some sensors respond with NAN (not a number) but if not, one approach is to reject a measurement that clearly deviates from the trend of the last few previous measurements. Or, also take the next measurement into consideration.
I typically use a low pass filter (an "exponential filter") to calculate a moving average, and some predetermined threshold value (e.g. three standard deviations from the mean) to reject outliers.
No, not at all, and that code won't compile without many fatal errors. It looks like you are making code up with little to no idea what it does.
One serious problem is that variables must be defined such that they can either be seen by all functions, or values passed between the functions.
You need to start at the beginning and learn more about the coding language. A reasonable place to start would be to carefully study the simple examples that come with Arduino, and on line language tutorials. There are many of those, and some are really good.
I kinda can read code, just not very good at writing new stuff, lol
I find it challenging to learn too, so it's a bit annoying.
Keep forgetting simple things.
What should fabs and threshold be?
I did create the sensor post code by myself and compiled on first try without errors, but it's a while ago. Got to relearn everything, lol.
One thing to note is that it's always a zero value reading when it's not working, so I guess reading again if value is 0 is a good enough solution?
Ok! Yes I know it does not do anything useful, I'm just trying to think how to use that as an example. I have a code that is working and not using if (true), isn't that just for running the loop without conditions? I can post the full code tomorrow, but I've not added the stuff from this topic yet. I didn't feel it was needed. Just wanted some code examples.
Addittionally i suggest that you check the cables with a multimeter. Alot of times they look okay but in fact present the circuit with unresonable resistance due to poor connection.
Ok! I feel a bit silly posting this code, since I have it in another topic too, but here we go:
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <credentials.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
WiFiClient wifiClient;
const char ssid[] = WIFI_SSID;
const char password[] = WIFI_PASSWD;
//Your Domain name with URL path or IP address with path
String serverName = "https://www.mysite.com/write_data.php";
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTime = 0;
unsigned long timerDelay = 60000;
unsigned short wifiFail = 0;
void setup() {
unsigned short count = 0;
Wire.begin();
Serial.begin(115200);
while(!Serial); // time to get serial running
Serial.println(F("BME280 test"));
unsigned status;
// default settings
status = bme.begin(0x76);
// You can also pass in a Wire library object like &Wire2
//status = bme.begin(0x76, &Wire2)
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16);
Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n");
Serial.print(" ID of 0x60 represents a BME 280.\n");
Serial.print(" ID of 0x61 represents a BME 680.\n");
while (1) delay(10);
}
Serial.println("BME280 Test Complete");
WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
count++;
if (count >= 30) {
count = 0;
wifiRestart();
}
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 1 minute (timerDelay variable), it will take 1 minute before publishing the first reading.");
}
void wifiRestart() {
int tryCount = 0;
while(WiFi.status() != WL_CONNECTED) {
tryCount++;
wifiFail++;
WiFi.disconnect();
WiFi.begin(ssid, password);
vTaskDelay(5000);
if(tryCount >= 10) {
ESP.restart();
}
}
}
void runClear() {
if(wifiFail >= 20000) {
wifiFail = 0;
Serial.println("Too many fails, counter reset");
}
}
void loop() {
//Send an HTTP POST request every 10 minutes
if((millis() - lastTime) > timerDelay) {
//Check WiFi connection status
if((wifiClient.connected()) && (WiFi.status() == WL_CONNECTED)) {
// if(WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String serverPath = serverName + "?temp=" + bme.readTemperature() + "&humi=" + bme.readHumidity() + "&pres=" + (bme.readPressure() / 100.0F) + "&rssi=" + WiFi.RSSI();
// Your Domain name with URL path or IP address with path
http.begin(serverPath.c_str());
// Send HTTP GET request
int httpResponseCode = http.GET();
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
printValues();
}
else {
Serial.println("WiFi Disconnected");
wifiRestart();
}
Serial.print("Send Time = ");
Serial.println(lastTime);
runClear();
lastTime = millis();
}
}
void printValues() {
Serial.print("Test Time = ");
Serial.println(lastTime);
Serial.print("Temperature = ");
Serial.print(bme.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");
Serial.print("Approx. Altitude = ");
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Serial.print("Humidity = ");
Serial.print(bme.readHumidity());
Serial.println(" %");
Serial.print("Signal strength (RSSI) = ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
Serial.print("Test Time = ");
Serial.println(lastTime);
Serial.print("WiFi failed ");
Serial.print(wifiFail);
Serial.println(" times.");
Serial.println();
}
I'm looking for ways to improve the code, but for now the topic here is the sensor reading a zero value at rare occasions and I want to remove that, also an average of several readings in a short time-frame would be a more correct reading for the posting every minute. Any and all code examples are welcome. I'm not an experienced programmer. Though I did make most of this code myself as it was almost impossible to find something similar on the internet. Explaining https and GET request to post data. I made the website too, using PHP, SQL and Java Script.
Here is some WiFi art (removed all readings with 0 as a value manually in the database)!
I guess the moving_average has to be set to the new_value before the abs function, or it will never go through, lol. And how will I know that the function don't start when the value is reading the wrong value, and using that as a reference?
I have a different sensor and periodically receive readings with very large errors. In all cases I've logged only single readings had this issue. My setup is pretty simple with no noise generating circuits nearby.
My solution was to test for huge jumps and delete them. For an average I have (in another sensor installation) performed the following steps.
Read 9 readings into an array.
Sort the array
Average the middle 5 readings.
This effectively deletes the lowest and highest 2 readings.
You can do variations,
15 readings, average the middle n readings.