mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-15 04:37:07 +01:00
Migrate DS18B20 and counter to new sensor module
This commit is contained in:
@@ -758,11 +758,13 @@ PROGMEM const char* const custom_reset_string[] = {
|
||||
#define SENSOR_TEMPERATURE_DECIMALS 1
|
||||
#define SENSOR_HUMIDITY_DECIMALS 0
|
||||
#define SENSOR_ANALOG_DECIMALS 0
|
||||
#define SENSOR_EVENTS_DECIMALS 0
|
||||
|
||||
#define SENSOR_UNKNOWN_TOPIC "unknown"
|
||||
#define SENSOR_TEMPERATURE_TOPIC "temperature"
|
||||
#define SENSOR_HUMIDITY_TOPIC "humidity"
|
||||
#define SENSOR_ANALOG_TOPIC "analog"
|
||||
#define SENSOR_EVENTS_TOPIC "events"
|
||||
|
||||
#define SENSOR_TEMPERATURE_UNITS TMP_CELSIUS // Temperature units (TMP_CELSIUS | TMP_FAHRENHEIT)
|
||||
#define SENSOR_TEMPERATURE_CORRECTION 0.0 // Offset correction
|
||||
|
||||
@@ -75,6 +75,7 @@ template<typename T> bool idbSend(const char * topic, unsigned char id, T payloa
|
||||
// Sensors
|
||||
// -----------------------------------------------------------------------------
|
||||
#include "sensors/BaseSensor.h"
|
||||
#include <DallasTemperature.h> // WTF!
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utils
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
#ifndef DHT_SUPPORT
|
||||
#define DHT_SUPPORT 1
|
||||
#define DHT_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#ifndef DHT_PIN
|
||||
@@ -92,7 +92,7 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
#ifndef COUNTER_SUPPORT
|
||||
#define COUNTER_SUPPORT 0 // Do not build with counter support by default
|
||||
#define COUNTER_SUPPORT 1 // Do not build with counter support by default
|
||||
#endif
|
||||
|
||||
#ifndef COUNTER_PIN
|
||||
@@ -121,11 +121,11 @@
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
#ifndef DS18B20_SUPPORT
|
||||
#define DS18B20_SUPPORT 0
|
||||
#define DS18B20_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#ifndef DS18B20_PIN
|
||||
#define DS18B20_PIN 14
|
||||
#define DS18B20_PIN 13
|
||||
#endif
|
||||
|
||||
#ifndef DS18B20_PULLUP
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
|
||||
COUNTER MODULE
|
||||
|
||||
Copyright (C) 2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
*/
|
||||
|
||||
#if COUNTER_SUPPORT
|
||||
|
||||
volatile unsigned long _counterCurrent = 0;
|
||||
volatile unsigned long _counterLast = 0;
|
||||
|
||||
unsigned long _counterBuffer[COUNTER_REPORT_EVERY] = {0};
|
||||
unsigned char _counterBufferPointer = 0;
|
||||
unsigned long _counterValue = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// COUNTER
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ICACHE_RAM_ATTR _counterISR() {
|
||||
if (millis() - _counterLast > COUNTER_DEBOUNCE) {
|
||||
++_counterCurrent;
|
||||
_counterLast = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void _counterWebSocketOnSend(JsonObject& root) {
|
||||
root["counterVisible"] = 1;
|
||||
root["counterValue"] = getCounter();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
unsigned long getCounter() {
|
||||
return _counterValue;
|
||||
}
|
||||
|
||||
void counterSetup() {
|
||||
|
||||
pinMode(COUNTER_PIN, COUNTER_PIN_MODE);
|
||||
attachInterrupt(COUNTER_PIN, _counterISR, COUNTER_INTERRUPT_MODE);
|
||||
|
||||
#if WEB_SUPPORT
|
||||
|
||||
// Websockets
|
||||
wsOnSendRegister(_counterWebSocketOnSend);
|
||||
|
||||
// API
|
||||
apiRegister(COUNTER_TOPIC, COUNTER_TOPIC, [](char * buffer, size_t len) {
|
||||
snprintf_P(buffer, len, PSTR("%d"), getCounter());
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
DEBUG_MSG_P(PSTR("[COUNTER] Counter on GPIO %d\n"), COUNTER_PIN);
|
||||
|
||||
}
|
||||
|
||||
void counterLoop() {
|
||||
|
||||
// Check if we should read new data
|
||||
static unsigned long last_update = 0;
|
||||
if ((millis() - last_update) < COUNTER_UPDATE_INTERVAL) return;
|
||||
last_update = millis();
|
||||
|
||||
// Update buffer counts
|
||||
_counterValue = _counterValue - _counterBuffer[_counterBufferPointer] + _counterCurrent;
|
||||
_counterBuffer[_counterBufferPointer] = _counterCurrent;
|
||||
_counterCurrent = 0;
|
||||
_counterBufferPointer = (_counterBufferPointer + 1) % COUNTER_REPORT_EVERY;
|
||||
|
||||
DEBUG_MSG_P(PSTR("[COUNTER] Value: %d\n"), _counterValue);
|
||||
|
||||
// Update websocket clients
|
||||
#if WEB_SUPPORT
|
||||
wsSend(_counterWebSocketOnSend);
|
||||
#endif
|
||||
|
||||
// Do we have to report?
|
||||
if (_counterBufferPointer == 0) {
|
||||
|
||||
// Send MQTT messages
|
||||
#if MQTT_SUPPORT
|
||||
mqttSend(getSetting("counterTopic", COUNTER_TOPIC).c_str(), String(_counterValue).c_str());
|
||||
#endif
|
||||
|
||||
// Send to Domoticz
|
||||
#if DOMOTICZ_SUPPORT
|
||||
domoticzSend("dczCountIdx", 0, String(_counterValue).c_str());
|
||||
#endif
|
||||
|
||||
// Send to InfluxDB
|
||||
#if INFLUXDB_SUPPORT
|
||||
idbSend(COUNTER_TOPIC, _counterValue);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // COUNTER_SUPPORT
|
||||
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
|
||||
DHT MODULE
|
||||
|
||||
Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
*/
|
||||
|
||||
#if DHT_SUPPORT
|
||||
|
||||
double _dhtTemperature = 0;
|
||||
unsigned int _dhtHumidity = 0;
|
||||
bool _dhtIsConnected = false;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// HAL
|
||||
// https://github.com/gosouth/DHT22/blob/master/main/DHT22.c
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define DHT_MAX_DATA 5
|
||||
#define DHT_MAX_ERRORS 5
|
||||
#define DHT_MIN_INTERVAL 2000
|
||||
#define DHT_OK 0
|
||||
#define DHT_CHECKSUM_ERROR -1
|
||||
#define DHT_TIMEOUT_ERROR -2
|
||||
|
||||
#define DHT11 11
|
||||
#define DHT22 22
|
||||
#define DHT21 21
|
||||
#define AM2301 21
|
||||
|
||||
unsigned long _getSignalLevel(unsigned char gpio, int usTimeOut, bool state) {
|
||||
unsigned long uSec = 1;
|
||||
while (digitalRead(gpio) == state) {
|
||||
if (++uSec > usTimeOut) return 0;
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
return uSec;
|
||||
}
|
||||
|
||||
int readDHT(unsigned char gpio, unsigned char type) {
|
||||
|
||||
static unsigned long last_ok = 0;
|
||||
if ((last_ok > 0) && (millis() - last_ok < DHT_MIN_INTERVAL)) return DHT_OK;
|
||||
|
||||
unsigned long low = 0;
|
||||
unsigned long high = 0;
|
||||
|
||||
static unsigned char errors = 0;
|
||||
uint8_t dhtData[DHT_MAX_DATA] = {0};
|
||||
uint8_t byteInx = 0;
|
||||
uint8_t bitInx = 7;
|
||||
|
||||
// Send start signal to DHT sensor
|
||||
if (++errors > DHT_MAX_ERRORS) {
|
||||
errors = 0;
|
||||
digitalWrite(gpio, HIGH);
|
||||
delay(250);
|
||||
}
|
||||
pinMode(gpio, OUTPUT);
|
||||
noInterrupts();
|
||||
digitalWrite(gpio, LOW);
|
||||
delayMicroseconds(500);
|
||||
digitalWrite(gpio, HIGH);
|
||||
delayMicroseconds(40);
|
||||
pinMode(gpio, INPUT_PULLUP);
|
||||
|
||||
// No errors, read the 40 data bits
|
||||
for( int k = 0; k < 41; k++ ) {
|
||||
|
||||
// Starts new data transmission with >50us low signal
|
||||
low = _getSignalLevel(gpio, 56, LOW);
|
||||
if (low==0) return DHT_TIMEOUT_ERROR;
|
||||
|
||||
// Check to see if after >70us rx data is a 0 or a 1
|
||||
high = _getSignalLevel(gpio, 75, HIGH);
|
||||
if (high==0) return DHT_TIMEOUT_ERROR;
|
||||
|
||||
// Skip the first bit
|
||||
if (k==0) continue;
|
||||
|
||||
// add the current read to the output data
|
||||
// since all dhtData array where set to 0 at the start,
|
||||
// only look for "1" (>28us us)
|
||||
if (high > low) dhtData[byteInx] |= (1 << bitInx);
|
||||
|
||||
// index to next byte
|
||||
if (bitInx == 0) {
|
||||
bitInx = 7;
|
||||
++byteInx;
|
||||
} else {
|
||||
--bitInx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interrupts();
|
||||
|
||||
// Verify checksum
|
||||
if (dhtData[4] != ((dhtData[0] + dhtData[1] + dhtData[2] + dhtData[3]) & 0xFF)) {
|
||||
return DHT_CHECKSUM_ERROR;
|
||||
}
|
||||
|
||||
// Get humidity from Data[0] and Data[1]
|
||||
if (type == DHT11) {
|
||||
_dhtHumidity = dhtData[0];
|
||||
} else {
|
||||
_dhtHumidity = dhtData[0] * 256 + dhtData[1];
|
||||
_dhtHumidity /= 10;
|
||||
}
|
||||
|
||||
// Get temp from Data[2] and Data[3]
|
||||
if (type == DHT11) {
|
||||
_dhtTemperature = dhtData[2];
|
||||
} else {
|
||||
_dhtTemperature = (dhtData[2] & 0x7F) * 256 + dhtData[3];
|
||||
_dhtTemperature /= 10;
|
||||
if (dhtData[2] & 0x80) _dhtTemperature *= -1;
|
||||
}
|
||||
|
||||
last_ok = millis();
|
||||
errors = 0;
|
||||
return DHT_OK;
|
||||
|
||||
}
|
||||
|
||||
int readDHT() {
|
||||
return readDHT(DHT_PIN, DHT_TYPE);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Private
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void _dhtWebSocketOnSend(JsonObject& root) {
|
||||
root["dhtVisible"] = 1;
|
||||
root["dhtConnected"] = getDHTIsConnected();
|
||||
if (getDHTIsConnected()) {
|
||||
root["dhtTmp"] = getDHTTemperature();
|
||||
root["dhtHum"] = getDHTHumidity();
|
||||
}
|
||||
root["tmpUnits"] = getSetting("tmpUnits", SENSOR_TEMPERATURE_UNITS).toInt();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Values
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool getDHTIsConnected() {
|
||||
return _dhtIsConnected;
|
||||
}
|
||||
|
||||
double getDHTTemperature(bool celsius) {
|
||||
double value = celsius ? _dhtTemperature : _dhtTemperature * 1.8 + 32;
|
||||
double correction = getSetting("tmpCorrection", SENSOR_TEMPERATURE_CORRECTION).toFloat();
|
||||
return roundTo(value + correction, TEMPERATURE_DECIMALS);
|
||||
}
|
||||
|
||||
double getDHTTemperature() {
|
||||
bool celsius = getSetting("tmpUnits", SENSOR_TEMPERATURE_UNITS).toInt() == TMP_CELSIUS;
|
||||
return getDHTTemperature(celsius);
|
||||
}
|
||||
|
||||
unsigned int getDHTHumidity() {
|
||||
return _dhtHumidity;
|
||||
}
|
||||
|
||||
void dhtSetup() {
|
||||
|
||||
#if DHT_PULLUP
|
||||
pinMode(DHT_PIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
#if WEB_SUPPORT
|
||||
|
||||
// Websockets
|
||||
wsOnSendRegister(_dhtWebSocketOnSend);
|
||||
|
||||
apiRegister(DHT_TEMPERATURE_TOPIC, DHT_TEMPERATURE_TOPIC, [](char * buffer, size_t len) {
|
||||
dtostrf(getDHTTemperature(), 1-len, 1, buffer);
|
||||
});
|
||||
apiRegister(DHT_HUMIDITY_TOPIC, DHT_HUMIDITY_TOPIC, [](char * buffer, size_t len) {
|
||||
snprintf_P(buffer, len, PSTR("%d"), getDHTHumidity());
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void dhtLoop() {
|
||||
|
||||
static unsigned long last_update = 0;
|
||||
static double last_temperature = 0.0;
|
||||
static unsigned int last_humidity = 0;
|
||||
|
||||
// Check if we should read new data
|
||||
if ((millis() - last_update > DHT_UPDATE_INTERVAL) || (last_update == 0)) {
|
||||
last_update = millis();
|
||||
|
||||
// Read sensor data
|
||||
int response = readDHT(DHT_PIN, DHT_TYPE);
|
||||
if (response != DHT_OK) {
|
||||
DEBUG_MSG_P(PSTR("[DHT] Error: %d\n"), response);
|
||||
return;
|
||||
}
|
||||
_dhtIsConnected = true;
|
||||
|
||||
// Get values
|
||||
bool celsius = getSetting("tmpUnits", SENSOR_TEMPERATURE_UNITS).toInt() == TMP_CELSIUS;
|
||||
double t = getDHTTemperature(celsius);
|
||||
unsigned int h = getDHTHumidity();
|
||||
|
||||
// Build strings
|
||||
char temperature[6];
|
||||
char humidity[6];
|
||||
dtostrf(t, 1-sizeof(temperature), 1, temperature);
|
||||
itoa((unsigned int) h, humidity, 10);
|
||||
|
||||
// Debug
|
||||
DEBUG_MSG_P(PSTR("[DHT] Temperature: %s%s\n"), temperature, celsius ? "ºC" : "ºF");
|
||||
DEBUG_MSG_P(PSTR("[DHT] Humidity: %s\n"), humidity);
|
||||
|
||||
// If the new temperature & humidity are different from the last
|
||||
if ((fabs(t - last_temperature) >= TEMPERATURE_MIN_CHANGE)
|
||||
|| (abs(h - last_humidity) >= HUMIDITY_MIN_CHANGE)) {
|
||||
|
||||
last_temperature = t;
|
||||
last_humidity = h;
|
||||
|
||||
// Send MQTT messages
|
||||
#if MQTT_SUPPORT
|
||||
mqttSend(getSetting("dhtTmpTopic", DHT_TEMPERATURE_TOPIC).c_str(), temperature);
|
||||
mqttSend(getSetting("dhtHumTopic", DHT_HUMIDITY_TOPIC).c_str(), humidity);
|
||||
#endif
|
||||
|
||||
// Send to Domoticz
|
||||
#if DOMOTICZ_SUPPORT
|
||||
{
|
||||
domoticzSend("dczTmpIdx", 0, temperature);
|
||||
int status;
|
||||
if (h > 70) {
|
||||
status = HUMIDITY_WET;
|
||||
} else if (h > 45) {
|
||||
status = HUMIDITY_COMFORTABLE;
|
||||
} else if (h > 30) {
|
||||
status = HUMIDITY_NORMAL;
|
||||
} else {
|
||||
status = HUMIDITY_DRY;
|
||||
}
|
||||
char buffer[2];
|
||||
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), status);
|
||||
domoticzSend("dczHumIdx", humidity, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if INFLUXDB_SUPPORT
|
||||
idbSend(getSetting("dhtTmpTopic", DHT_TEMPERATURE_TOPIC).c_str(), temperature);
|
||||
idbSend(getSetting("dhtHumTopic", DHT_HUMIDITY_TOPIC).c_str(), humidity);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Update websocket clients
|
||||
#if WEB_SUPPORT
|
||||
wsSend(_dhtWebSocketOnSend);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
|
||||
DS18B20 MODULE
|
||||
|
||||
Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
*/
|
||||
|
||||
#if DS18B20_SUPPORT
|
||||
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
OneWire oneWire(DS18B20_PIN);
|
||||
DallasTemperature ds18b20(&oneWire);
|
||||
|
||||
bool _dsIsConnected = false;
|
||||
double _dsTemperature = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Private
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void _dsWebSocketOnSend(JsonObject& root) {
|
||||
root["dsVisible"] = 1;
|
||||
root["dsConnected"] = getDSIsConnected();
|
||||
if (getDSIsConnected()) {
|
||||
root["dsTmp"] = getDSTemperature();
|
||||
}
|
||||
root["tmpUnits"] = getSetting("tmpUnits", TMP_UNITS).toInt();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DS18B20
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool getDSIsConnected() {
|
||||
return _dsIsConnected;
|
||||
}
|
||||
|
||||
double getDSTemperature(bool celsius) {
|
||||
double value = celsius ? _dsTemperature : _dsTemperature * 1.8 + 32;
|
||||
double correction = getSetting("tmpCorrection", TEMPERATURE_CORRECTION).toFloat();
|
||||
return roundTo(value + correction, TEMPERATURE_DECIMALS);
|
||||
}
|
||||
|
||||
double getDSTemperature() {
|
||||
bool celsius = getSetting("tmpUnits", TMP_UNITS).toInt() == TMP_CELSIUS;
|
||||
return getDSTemperature(celsius);
|
||||
}
|
||||
|
||||
void dsSetup() {
|
||||
|
||||
#if DS18B20_PULLUP
|
||||
pinMode(DS18B20_PIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
ds18b20.begin();
|
||||
ds18b20.setWaitForConversion(false);
|
||||
|
||||
#if WEB_SUPPORT
|
||||
|
||||
wsOnSendRegister(_dsWebSocketOnSend);
|
||||
|
||||
apiRegister(DS18B20_TEMPERATURE_TOPIC, DS18B20_TEMPERATURE_TOPIC, [](char * buffer, size_t len) {
|
||||
dtostrf(getDSTemperature(), 1-len, 1, buffer);
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void dsLoop() {
|
||||
|
||||
static unsigned long last_update = 0;
|
||||
static double last_temperature = 0.0;
|
||||
static bool requested = false;
|
||||
|
||||
if ((millis() - last_update > DS18B20_UPDATE_INTERVAL) || (last_update == 0)) {
|
||||
|
||||
if (!requested) {
|
||||
ds18b20.requestTemperatures();
|
||||
requested = true;
|
||||
// Requesting takes time, so data will probably not be available in this round
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if requested data is already available
|
||||
if (!ds18b20.isConversionComplete()) return;
|
||||
requested = false;
|
||||
last_update = millis();
|
||||
|
||||
// Read sensor data
|
||||
double t = ds18b20.getTempCByIndex(0);
|
||||
|
||||
// Check returned value
|
||||
if (t == DEVICE_DISCONNECTED_C) {
|
||||
_dsIsConnected = false;
|
||||
DEBUG_MSG_P(PSTR("[DS18B20] Not connected\n"));
|
||||
return;
|
||||
} else {
|
||||
_dsIsConnected = true;
|
||||
}
|
||||
|
||||
// Save & convert
|
||||
_dsTemperature = t;
|
||||
bool celsius = getSetting("tmpUnits", TMP_UNITS).toInt() == TMP_CELSIUS;
|
||||
t = getDSTemperature(celsius);
|
||||
|
||||
// Build string
|
||||
char temperature[6];
|
||||
dtostrf(getDSTemperature(celsius), 1-sizeof(temperature), 1, temperature);
|
||||
|
||||
// Debug
|
||||
DEBUG_MSG_P(PSTR("[DS18B20] Temperature: %s%s\n"), temperature, celsius ? "ºC" : "ºF");
|
||||
|
||||
// If the new temperature is different from the last
|
||||
if (fabs(_dsTemperature - last_temperature) >= TEMPERATURE_MIN_CHANGE) {
|
||||
|
||||
last_temperature = _dsTemperature;
|
||||
|
||||
// Send MQTT messages
|
||||
#if MQTT_SUPPORT
|
||||
mqttSend(getSetting("dsTmpTopic", DS18B20_TEMPERATURE_TOPIC).c_str(), temperature);
|
||||
#endif
|
||||
|
||||
// Send to Domoticz
|
||||
#if DOMOTICZ_SUPPORT
|
||||
domoticzSend("dczTmpIdx", 0, temperature);
|
||||
#endif
|
||||
|
||||
#if INFLUXDB_SUPPORT
|
||||
idbSend(getSetting("dsTmpTopic", DS18B20_TEMPERATURE_TOPIC).c_str(), temperature);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Update websocket clients
|
||||
#if WEB_SUPPORT
|
||||
wsSend(_dsWebSocketOnSend);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -314,12 +314,6 @@ void setup() {
|
||||
#if INFLUXDB_SUPPORT
|
||||
idbSetup();
|
||||
#endif
|
||||
#if DS18B20_SUPPORT
|
||||
dsSetup();
|
||||
#endif
|
||||
#if COUNTER_SUPPORT
|
||||
counterSetup();
|
||||
#endif
|
||||
#if RF_SUPPORT
|
||||
rfSetup();
|
||||
#endif
|
||||
@@ -380,12 +374,6 @@ void loop() {
|
||||
#if NOFUSS_SUPPORT
|
||||
nofussLoop();
|
||||
#endif
|
||||
#if DS18B20_SUPPORT
|
||||
dsLoop();
|
||||
#endif
|
||||
#if COUNTER_SUPPORT
|
||||
counterLoop();
|
||||
#endif
|
||||
#if RF_SUPPORT
|
||||
rfLoop();
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@ unsigned char _counts[MAGNITUDE_MAX];
|
||||
bool _sensor_realtime = API_REAL_TIME_VALUES;
|
||||
unsigned char _sensor_temperature_units = SENSOR_TEMPERATURE_UNITS;
|
||||
double _sensor_temperature_correction = SENSOR_TEMPERATURE_CORRECTION;
|
||||
unsigned char _sensor_isr = 0xFF;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Private
|
||||
@@ -40,6 +41,8 @@ String _sensorTopic(magnitude_t type) {
|
||||
return String(SENSOR_HUMIDITY_TOPIC);
|
||||
} else if (type == MAGNITUDE_ANALOG) {
|
||||
return String(SENSOR_ANALOG_TOPIC);
|
||||
} else if (type == MAGNITUDE_EVENTS) {
|
||||
return String(SENSOR_EVENTS_TOPIC);
|
||||
}
|
||||
return String(SENSOR_UNKNOWN_TOPIC);
|
||||
}
|
||||
@@ -51,6 +54,8 @@ unsigned char _sensorDecimals(magnitude_t type) {
|
||||
return SENSOR_HUMIDITY_DECIMALS;
|
||||
} else if (type == MAGNITUDE_ANALOG) {
|
||||
return SENSOR_ANALOG_DECIMALS;
|
||||
} else if (type == MAGNITUDE_EVENTS) {
|
||||
return SENSOR_EVENTS_DECIMALS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -64,6 +69,8 @@ String _sensorUnits(magnitude_t type) {
|
||||
}
|
||||
} else if (type == MAGNITUDE_HUMIDITY) {
|
||||
return String("%");
|
||||
} else if (type == MAGNITUDE_EVENTS) {
|
||||
return String("/m");
|
||||
}
|
||||
return String();
|
||||
}
|
||||
@@ -138,22 +145,56 @@ void _sensorAPISetup() {
|
||||
// Values
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void sensorISR() {
|
||||
_sensors[_sensor_isr]->InterruptHandler();
|
||||
}
|
||||
|
||||
void sensorRegister(BaseSensor * sensor) {
|
||||
_sensors.push_back(sensor);
|
||||
}
|
||||
|
||||
unsigned char sensorCount() {
|
||||
return _sensors.size();
|
||||
}
|
||||
|
||||
void sensorInterrupt(unsigned char sensor_id, unsigned char gpio, int mode) {
|
||||
_sensor_isr = sensor_id;
|
||||
attachInterrupt(gpio, sensorISR, mode);
|
||||
}
|
||||
|
||||
void sensorInit() {
|
||||
|
||||
#if DHT_SUPPORT
|
||||
#include "sensors/DHTSensor.h"
|
||||
sensorRegister(new DHTSensor(DHT_PIN, DHT_TYPE, DHT_PULLUP));
|
||||
#endif
|
||||
|
||||
#if DS18B20_SUPPORT
|
||||
#include "sensors/DS18B20Sensor.h"
|
||||
sensorRegister(new DS18B20Sensor(DS18B20_PIN, DS18B20_PULLUP));
|
||||
#endif
|
||||
|
||||
#if ANALOG_SUPPORT
|
||||
#include "sensors/AnalogSensor.h"
|
||||
sensorRegister(new AnalogSensor(ANALOG_PIN));
|
||||
#endif
|
||||
|
||||
#if COUNTER_SUPPORT
|
||||
if (_sensor_isr == 0xFF) {
|
||||
#include "sensors/EventSensor.h"
|
||||
sensorRegister(new EventSensor(COUNTER_PIN, COUNTER_PIN_MODE, COUNTER_DEBOUNCE));
|
||||
sensorInterrupt(sensorCount()-1, COUNTER_PIN, COUNTER_INTERRUPT_MODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void sensorSetup() {
|
||||
|
||||
// Load sensors
|
||||
#if DHT_SUPPORT
|
||||
#include "sensors/DHTSensor.h"
|
||||
_sensors.push_back(new DHTSensor(DHT_PIN, DHT_TYPE));
|
||||
#if DHT_PULLUP
|
||||
pinMode(DHT_PIN, INPUT_PULLUP);
|
||||
#endif
|
||||
#endif
|
||||
#if ANALOG_SUPPORT
|
||||
#include "sensors/AnalogSensor.h"
|
||||
_sensors.push_back(new AnalogSensor(ANALOG_PIN));
|
||||
#endif
|
||||
sensorInit();
|
||||
|
||||
// Read magnitudes
|
||||
// Load magnitudes
|
||||
for (unsigned char i=0; i<_sensors.size(); i++) {
|
||||
|
||||
BaseSensor * sensor = _sensors[i];
|
||||
@@ -234,6 +275,10 @@ void sensorLoop() {
|
||||
|
||||
value = magnitude.sensor->value(magnitude.local);
|
||||
magnitude.filter->add(value);
|
||||
|
||||
// Special case
|
||||
if (magnitude.type == MAGNITUDE_EVENTS) value = magnitude.filter->result();
|
||||
|
||||
value = _sensorProcess(magnitude.type, value);
|
||||
_magnitudes[i].current = value;
|
||||
|
||||
@@ -252,7 +297,9 @@ void sensorLoop() {
|
||||
|
||||
if (report_count == 0) {
|
||||
|
||||
double value = magnitude.filter->result();
|
||||
// TODO: option to report only if it has change (configurable amount)
|
||||
|
||||
value = magnitude.filter->result();
|
||||
value = _sensorProcess(magnitude.type, value);
|
||||
_magnitudes[i].filtered = value;
|
||||
magnitude.filter->reset();
|
||||
|
||||
@@ -13,27 +13,7 @@ class AnalogSensor : public BaseSensor {
|
||||
|
||||
AnalogSensor(unsigned char gpio): BaseSensor() {
|
||||
_gpio = gpio;
|
||||
}
|
||||
|
||||
// Pre-read hook (usually to populate registers with up-to-date data)
|
||||
void pre() {}
|
||||
|
||||
// Post-read hook (usually to reset things)
|
||||
void post() {}
|
||||
|
||||
// Return sensor status (true for ready)
|
||||
bool status() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return sensor last internal error
|
||||
int error() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Number of available slots
|
||||
unsigned char count() {
|
||||
return 1;
|
||||
_count = 1;
|
||||
}
|
||||
|
||||
// Descriptive name of the sensor
|
||||
@@ -61,7 +41,7 @@ class AnalogSensor : public BaseSensor {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
unsigned char _gpio;
|
||||
|
||||
|
||||
@@ -31,26 +31,29 @@ class BaseSensor {
|
||||
|
||||
public:
|
||||
|
||||
BaseSensor() {
|
||||
}
|
||||
// Constructor
|
||||
BaseSensor() {}
|
||||
|
||||
~BaseSensor() {
|
||||
}
|
||||
// Destructor
|
||||
~BaseSensor() {}
|
||||
|
||||
// General interrupt handler
|
||||
void InterruptHandler() {}
|
||||
|
||||
// Pre-read hook (usually to populate registers with up-to-date data)
|
||||
virtual void pre();
|
||||
void pre() {}
|
||||
|
||||
// Post-read hook (usually to reset things)
|
||||
virtual void post();
|
||||
void post() {}
|
||||
|
||||
// Return sensor status (true for ready)
|
||||
virtual bool status();
|
||||
bool status() { return _error == 0; }
|
||||
|
||||
// Return sensor last internal error
|
||||
virtual int error();
|
||||
int error() { return _error; }
|
||||
|
||||
// Number of available slots
|
||||
virtual unsigned char count();
|
||||
unsigned char count() { return _count; }
|
||||
|
||||
// Descriptive name of the sensor
|
||||
virtual String name();
|
||||
@@ -65,6 +68,10 @@ class BaseSensor {
|
||||
virtual double value(unsigned char index);
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
int _error = 0;
|
||||
unsigned char _count = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -23,9 +23,11 @@ class DHTSensor : public BaseSensor {
|
||||
|
||||
public:
|
||||
|
||||
DHTSensor(unsigned char gpio, unsigned char type): BaseSensor() {
|
||||
DHTSensor(unsigned char gpio, unsigned char type, bool pull_up = false): BaseSensor() {
|
||||
_gpio = gpio;
|
||||
_type = type;
|
||||
if (pull_up) pinMode(_gpio, INPUT_PULLUP);
|
||||
_count = 2;
|
||||
}
|
||||
|
||||
// Pre-read hook (usually to populate registers with up-to-date data)
|
||||
@@ -123,29 +125,9 @@ class DHTSensor : public BaseSensor {
|
||||
|
||||
}
|
||||
|
||||
// Post-read hook (usually to reset things)
|
||||
void post() {
|
||||
|
||||
}
|
||||
|
||||
// Return sensor status (true for ready)
|
||||
bool status() {
|
||||
return (_last_ok > 0) & (_error == 0);
|
||||
}
|
||||
|
||||
// Return sensor last internal error
|
||||
int error() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
// Number of available slots
|
||||
unsigned char count() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Descriptive name of the sensor
|
||||
String name() {
|
||||
char buffer[64];
|
||||
char buffer[20];
|
||||
snprintf(buffer, sizeof(buffer), "DHT%d @ GPIO%d", _type, _gpio);
|
||||
return String(buffer);
|
||||
}
|
||||
@@ -170,7 +152,7 @@ class DHTSensor : public BaseSensor {
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
unsigned long _signal(int usTimeOut, bool state) {
|
||||
unsigned long uSec = 1;
|
||||
@@ -183,7 +165,6 @@ class DHTSensor : public BaseSensor {
|
||||
|
||||
unsigned char _gpio;
|
||||
unsigned char _type;
|
||||
int _error;
|
||||
|
||||
unsigned long _last_ok = 0;
|
||||
unsigned char _errors = 0;
|
||||
|
||||
105
code/espurna/sensors/DS18B20Sensor.h
Normal file
105
code/espurna/sensors/DS18B20Sensor.h
Normal file
@@ -0,0 +1,105 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// DHT Sensor
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "BaseSensor.h"
|
||||
#include <OneWire.h>
|
||||
#include <DallasTemperature.h>
|
||||
|
||||
#define DS18B20_OK 0
|
||||
#define DS18B20_NOT_FOUND 1
|
||||
#define DS18B20_OUT_OF_RANGE 2
|
||||
#define DS18B20_CONVERSION_ERROR 3
|
||||
|
||||
class DS18B20Sensor : public BaseSensor {
|
||||
|
||||
public:
|
||||
|
||||
DS18B20Sensor(unsigned char gpio, bool pull_up = false): BaseSensor() {
|
||||
_gpio = gpio;
|
||||
if (pull_up) pinMode(_gpio, INPUT_PULLUP);
|
||||
init();
|
||||
}
|
||||
|
||||
// Pre-read hook (usually to populate registers with up-to-date data)
|
||||
void pre() {
|
||||
|
||||
_device->requestTemperatures();
|
||||
|
||||
// TODO: enable?
|
||||
/*
|
||||
while (!_device->isConversionComplete()) {
|
||||
delay(1);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// Descriptive name of the sensor
|
||||
String name() {
|
||||
char buffer[20];
|
||||
snprintf(buffer, sizeof(buffer), "DS18B20 %s@ GPIO%d",
|
||||
_device->isParasitePowerMode() ? "(P) " : "",
|
||||
_gpio
|
||||
);
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
// Descriptive name of the slot # index
|
||||
String slot(unsigned char index) {
|
||||
if (index < _count) {
|
||||
DeviceAddress address;
|
||||
_device->getAddress(address, index);
|
||||
char buffer[40];
|
||||
snprintf(buffer, sizeof(buffer), "%02X%02X%02X%02X%02X%02X%02X%02X @ %s",
|
||||
address[0], address[1], address[2], address[3],
|
||||
address[4], address[5], address[6], address[7],
|
||||
name().c_str()
|
||||
);
|
||||
return String(buffer);
|
||||
}
|
||||
_error = DS18B20_OUT_OF_RANGE;
|
||||
return String();
|
||||
}
|
||||
|
||||
// Type for slot # index
|
||||
magnitude_t type(unsigned char index) {
|
||||
if (index < _count) return MAGNITUDE_TEMPERATURE;
|
||||
_error = DS18B20_OUT_OF_RANGE;
|
||||
return MAGNITUDE_NONE;
|
||||
}
|
||||
|
||||
// Current value for slot # index
|
||||
double value(unsigned char index) {
|
||||
if (index < _count) {
|
||||
double t = _device->getTempCByIndex(index);
|
||||
if (t != DEVICE_DISCONNECTED_C) {
|
||||
_error = DS18B20_OK;
|
||||
return t;
|
||||
}
|
||||
_error = DS18B20_CONVERSION_ERROR;
|
||||
}
|
||||
_error = DS18B20_OUT_OF_RANGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void init() {
|
||||
OneWire * wire = new OneWire(_gpio);
|
||||
_device = new DallasTemperature(wire);
|
||||
_device->begin();
|
||||
_device->setWaitForConversion(false);
|
||||
_count = _device->getDeviceCount();
|
||||
if (_count == 0) _error = DS18B20_NOT_FOUND;
|
||||
}
|
||||
|
||||
unsigned char _gpio;
|
||||
|
||||
DallasTemperature * _device;
|
||||
|
||||
|
||||
};
|
||||
64
code/espurna/sensors/EventSensor.h
Normal file
64
code/espurna/sensors/EventSensor.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// DHT Sensor
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "BaseSensor.h"
|
||||
|
||||
class EventSensor : public BaseSensor {
|
||||
|
||||
public:
|
||||
|
||||
void InterruptHandler() {
|
||||
static unsigned long last = 0;
|
||||
if (millis() - last > _debounce) {
|
||||
_events = _events + 1;
|
||||
last = millis();
|
||||
}
|
||||
}
|
||||
|
||||
EventSensor(unsigned char gpio, int pin_mode, unsigned long debounce): BaseSensor() {
|
||||
_gpio = gpio;
|
||||
_count = 1;
|
||||
_debounce = debounce;
|
||||
pinMode(_gpio, pin_mode);
|
||||
}
|
||||
|
||||
// Descriptive name of the sensor
|
||||
String name() {
|
||||
char buffer[20];
|
||||
snprintf(buffer, sizeof(buffer), "EVENT @ GPIO%d", _gpio);
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
// Descriptive name of the slot # index
|
||||
String slot(unsigned char index) {
|
||||
return name();
|
||||
}
|
||||
|
||||
// Type for slot # index
|
||||
magnitude_t type(unsigned char index) {
|
||||
if (index == 0) return MAGNITUDE_EVENTS;
|
||||
return MAGNITUDE_NONE;
|
||||
}
|
||||
|
||||
// Current value for slot # index
|
||||
double value(unsigned char index) {
|
||||
double value = 0;
|
||||
if (index == 0) {
|
||||
value = _events;
|
||||
_events = 0;
|
||||
};
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
volatile unsigned long _events = 0;
|
||||
unsigned long _debounce = 0;
|
||||
unsigned char _gpio;
|
||||
|
||||
};
|
||||
@@ -31,6 +31,7 @@ function sensorType(type) {
|
||||
if (type == 1) return "Temperature";
|
||||
if (type == 2) return "Humidity";
|
||||
if (type == 11) return "Analog";
|
||||
if (type == 12) return "Events";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user