Added luminosity sensor, more acurate temperature end debounced rainfall meter

This commit is contained in:
marcel
2025-01-14 17:19:12 +01:00
parent aaec2a02ad
commit 92956c2707
7 changed files with 259 additions and 39 deletions

View File

@@ -10,7 +10,7 @@
* BLINK : I2C ERROR
* FLASH : Heartbeat
*
* Copyright (C) 2023, 2024 M.T. Konstapel https://meezenest.nl/mees
* Copyright (C) 2023-2025 M.T. Konstapel https://meezenest.nl/mees
*
* This file is part of weather_station
*
@@ -32,12 +32,23 @@
* - Changed some variables to the propper standard (uint8_t, uint16_t, etc.)
* - SparkFun wind interrupt now calculates over 3 seconds in stead of 1 second (KNMI standard)
*
* 2-24-05-02: - Removed cope for si7021
* 2024-05-02: - Removed code for si7021
* - Added code for HYT221 humidity sensor
*
* 2025-01-13: - Cleanup of code
* - Debounce rainfall meter from 100ms to 250mms
* - Debug messages can be switched on and off with the _DEBUG_ variable
* - Main temperature and backup temperature registers switched: the sensor on the HYT221 heats up by
* the circuitry and is therefore about 1.5 degrees above ambient temperature. The BMP280 does not heat up.
* - Added SEN0562 luminosity sensor
*
* See CHANGELOG.md
*
**********************************************************************************/
// When set to 1 debug messages are send to the serial port, set it to 0 for production code!
#define _DEBUG_ 0
#include <ModbusSerial.h>
#include "SparkFun_Weather_Meter_Kit_Arduino_Library.h"
@@ -48,10 +59,13 @@
//Temperature and humidity sensor
#define HYT_ADDR 0x28 // I2C address of the HYT 221, 271, 371 and most likely the rest of the family
// Light meter
#define SEN0562_ADDR 0x23 //I2C address of Gravity SEN0562 light meter
// Pressure sensor
#include "i2c_BMP280.h"
BMP280 bmp280;
float PRESSURE_OFFSET = 210; // Calibration of BMP280: offset in Pascal
float PRESSURE_OFFSET = -100; // Calibration of BMP280: offset in Pascal
/**************************/
/* Configurable variables */
@@ -106,8 +120,7 @@ const int SensorStatusBitsIreg = 14;
* Coils
* 0 = Heater algorithm (0 = disable, 1 = enable)
*/
const int HeaterCoil = 0;
float HUMIDITY_THRESHOLD = 92.0;
const int HeaterCoil = 0; // Legacy register, not used anymore.
// RS-485 serial port
#define MySerial Serial // define serial port used, Serial most of the time, or Serial1, Serial2 ... if available
@@ -143,13 +156,13 @@ struct MeasuredData {
uint16_t RainLast24;
uint16_t SensorRainSinceMidnight;
uint16_t Pressure;
uint16_t Luminosity;
uint16_t StatusBits = 0;
uint16_t RainfallCounter = 0;
float Temperature;
float TemperatureHygrometer;
float Humidity;
float TemperatureBackup;
float TemperatureBarometer;
float Luminosity;
bool HeaterStatus = 0;
} MeasuredData;
@@ -188,17 +201,55 @@ void ReadHYT221 (void)
temperature = 165.0 / pow(2,14) * rawTemperature - 40;
// Scale for more decimal positions when converted to integer value for ModBus
MeasuredData.Temperature = 100 * temperature;
MeasuredData.TemperatureHygrometer = 100 * temperature;
//Serial.print(MeasuredData.Humidity);
//Serial.print("% - Temperature: ");
//Serial.println(MeasuredData.Temperature);
if (_DEBUG_) {
Serial.print("HYT221 humidity: ");
Serial.print(MeasuredData.Humidity/100);
Serial.print("% - Temperature: ");
Serial.println(MeasuredData.TemperatureHygrometer/100);
}
}
else {
Serial.println("Not enough bytes available on wire.");
}
}
uint8_t ReadSEN0562_register(uint8_t reg, const void* pBuf)
{
if (pBuf == NULL) {
Serial.println("pBuf ERROR!! : null pointer");
}
uint8_t * _pBuf = (uint8_t *)pBuf;
Wire.beginTransmission(SEN0562_ADDR);
Wire.write(&reg, 1);
if ( Wire.endTransmission() != 0) {
return 0;
}
delay(20);
Wire.requestFrom(SEN0562_ADDR, 2);
for (uint16_t i = 0; i < 2; i++) {
_pBuf[i] = Wire.read();
}
return 2;
}
void ReadSEN0562()
{
uint8_t buf[4] = {0};
uint16_t data, data1;
ReadSEN0562_register(0x10, buf); //Register address 0x10
data = buf[0] << 8 | buf[1];
MeasuredData.Luminosity = (((float)data )/1.2)*100;
if (_DEBUG_) {
Serial.print("SEN0562 light intensity: ");
Serial.print(MeasuredData.Luminosity/100);
Serial.println(" Lux");
}
}
// Read BMP280
void ReadBMP280 (void)
{
@@ -209,12 +260,18 @@ void ReadBMP280 (void)
pascal = (pascal - PRESSURE_OFFSET) / 10; // Convert to hPa
MeasuredData.Pressure = pascal;
bmp280.getTemperature(MeasuredData.TemperatureBackup);
bmp280.getTemperature(MeasuredData.TemperatureBarometer);
// Scale for more decimal positions when converted to integer value for ModBus
MeasuredData.TemperatureBackup *= 100;
MeasuredData.TemperatureBarometer *= 100;
bmp280.triggerMeasurement();
if (_DEBUG_) {
Serial.print("BMP280 pressure: ");
Serial.print(MeasuredData.Pressure);
Serial.print("hPa - Temperature: ");
Serial.println(MeasuredData.TemperatureBarometer/100);
}
}
int MaxOfArray (int array[], uint16_t length)
@@ -382,19 +439,11 @@ void setup() {
mb.Ireg (SensorRainSinceMidnightIreg, 0);
mb.Ireg (SensorSnowFallIreg, 0);
Serial.println(F("Weather station v0.3.0"));
Serial.println(F("(C)2024 M.T. Konstapel"));
Serial.println(F("Weather station v0.3.1"));
Serial.println(F("(C)2024-2025 M.T. Konstapel"));
Serial.println(F("This project is free and open source"));
Serial.println(F("More details: https://meezenest.nl/mees/"));
// The standard library of the Si7021 sets the heater element to the default 3.1mA, but we want the full power
// We could alter the library, but than we break compatibility. So for this one time we do a raw-write to the
// heater register.
const uint8_t SI7021_I2C_ADDRESS =(0x40);
const uint8_t SI7021_CMD_WRITE_HEATER_CONTROL_REG =(0x51);
const uint8_t SI7021_HEATER_FULL_BLAST =(0x0F); // Set heater to 94mA
i2c.writeByte(SI7021_I2C_ADDRESS, SI7021_CMD_WRITE_HEATER_CONTROL_REG, SI7021_HEATER_FULL_BLAST);
// Initialize BMP280 pressure sensor
Serial.print(F("Pressure sensor BMP280 "));
if (bmp280.initialize())
@@ -462,7 +511,7 @@ void setup() {
// The rainfall detector switch can sometimes bounce, causing multiple extra
// triggers. This input is debounced by ignoring extra triggers within a
// time window, which defaults to 100ms
calibrationParams.minMillisPerRainfall = 100;
calibrationParams.minMillisPerRainfall = 250;
// The anemometer contains a switch that opens and closes as it spins. The
// rate at which the switch closes depends on the wind speed. The datasheet
@@ -503,6 +552,8 @@ void loop() {
// Read temperature and humidity
ReadHYT221();
ReadSEN0562();
// Read pressure and temperature
ReadBMP280();
@@ -515,19 +566,15 @@ void loop() {
mb.Ireg (SensorWindGustIreg, MeasuredData.WindGust);
mb.Ireg (SensorRainIreg, MeasuredData.Rain);
mb.Ireg (SensorRainLast24Ireg, MeasuredData.RainLast24);
mb.Ireg (SensorTemperatureIreg, MeasuredData.Temperature);
mb.Ireg (SensorTemperatureIreg, MeasuredData.TemperatureBarometer);
mb.Ireg (SensorHumidityIreg, MeasuredData.Humidity);
mb.Ireg (SensorPressureIreg, MeasuredData.Pressure);
mb.Ireg (SensorTemperatureBackupIreg, MeasuredData.TemperatureBackup);
mb.Ireg (SensorTemperatureBackupIreg, MeasuredData.TemperatureHygrometer);
mb.Ireg (SensorLuminosityIreg, MeasuredData.Luminosity);
mb.Ireg (SensorRainfallRawIreg, MeasuredData.RainfallCounter);
mb.Ireg (SensorStatusBitsIreg, MeasuredData.StatusBits);
// Debug wind vane
//Serial.print(F("\n Measured ADC: "));
//Serial.print(analogRead(windDirectionPin));
// enable or disable smart heater
// enable or disable smart heater (legacy code, does not do anything except setting the status bit)
if (mb.Coil (HeaterCoil)) {
MeasuredData.StatusBits |= 0x04; // Set bit
} else {