Async temperature usermod (#1178)
* Change Temperature usermod to use async reading to avoid blocking * Fix comparison on wait time * Add * Simplify logic in the loop method * Optimize calls to minimize latency, inform user how long till first measurement * disable usermod if sensor not found * Added debug statements on init, update readme * fix spelling error of celsius
This commit is contained in:
parent
63d92381ee
commit
57421d2392
13
usermods/Temperature/platformio_override.ini
Normal file
13
usermods/Temperature/platformio_override.ini
Normal file
@ -0,0 +1,13 @@
|
||||
; Options
|
||||
; -------
|
||||
; USERMOD_DALLASTEMPERATURE - define this to have this user mod included wled00\usermods_list.cpp
|
||||
; USERMOD_DALLASTEMPERATURE_CELSIUS - define this to report temperatures in degrees celsius, otherwise fahrenheit will be reported
|
||||
; USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
|
||||
; USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
||||
;
|
||||
[env:d1_mini_usermod_dallas_temperature_C]
|
||||
extends = env:d1_mini
|
||||
build_flags = ${common.build_flags_esp8266} -D USERMOD_DALLASTEMPERATURE -D USERMOD_DALLASTEMPERATURE_CELSIUS
|
||||
lib_deps = ${env.lib_deps}
|
||||
milesburton/DallasTemperature@^3.9.0
|
||||
OneWire@~2.3.5
|
@ -5,11 +5,18 @@ This usermod will read from an attached DS18B20 temperature sensor (as available
|
||||
The temperature is displayed both in the Info section of the web UI as well as published to the `/temperature` MQTT topic if enabled.
|
||||
This usermod will be expanded with support for different sensor types in the future.
|
||||
|
||||
If temperature sensor is not detected during boot, this usermod will be disabled.
|
||||
|
||||
## Installation
|
||||
|
||||
Copy `usermod_temperature.h` to the wled00 directory.
|
||||
Uncomment the corresponding lines in `usermods_list.cpp` and compile!
|
||||
If this is the only v2 usermod you plan to use, you can alternatively replace `usermods_list.h` in wled00 with the one in this folder.
|
||||
Copy the example `platformio_override.ini` to the root directory. This file should be placed in the same directory as `platformio.ini`.
|
||||
|
||||
### Define Your Options
|
||||
|
||||
* `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp
|
||||
* `USERMOD_DALLASTEMPERATURE_CELSIUS` - define this to report temperatures in degrees celsious, otherwise fahrenheit will be reported
|
||||
* `USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL` - the number of milliseconds between measurements, defaults to 60 seconds
|
||||
* `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
||||
|
||||
## Project link
|
||||
|
||||
@ -17,7 +24,10 @@ If this is the only v2 usermod you plan to use, you can alternatively replace `u
|
||||
|
||||
### PlatformIO requirements
|
||||
|
||||
You might have to uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:d1_mini_usermod_dallas_temperature_C`.
|
||||
|
||||
|
||||
If you are not using `platformio_override.ini`, you might have to uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
|
||||
```ini
|
||||
# platformio.ini
|
||||
@ -38,3 +48,11 @@ lib_deps_external =
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
## Change Log
|
||||
|
||||
2020-09-12
|
||||
* Changed to use async, non-blocking implementation
|
||||
* Do not report low temperatures that indicate an error to mqtt
|
||||
* Disable plugin if temperature sensor not detected
|
||||
* Report the number of seconds until the first read in the info screen instead of sensor error
|
@ -11,61 +11,156 @@
|
||||
#define TEMPERATURE_PIN 14
|
||||
#endif
|
||||
|
||||
#define TEMP_CELSIUS // Comment out for Fahrenheit
|
||||
// the frequency to check temperature, 1 minute
|
||||
#ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL
|
||||
#define USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL 60000
|
||||
#endif
|
||||
|
||||
#define MEASUREMENT_INTERVAL 60000 //1 Minute
|
||||
// how many seconds after boot to take first measurement, 20 seconds
|
||||
#ifndef USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT
|
||||
#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000
|
||||
#endif
|
||||
|
||||
OneWire oneWire(TEMPERATURE_PIN);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
|
||||
class UsermodTemperature : public Usermod {
|
||||
private:
|
||||
//set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||
unsigned long lastMeasurement = UINT32_MAX - 40000;
|
||||
float temperature = 0.0f;
|
||||
public:
|
||||
void getReading() {
|
||||
sensor.requestTemperatures();
|
||||
#ifdef TEMP_CELSIUS
|
||||
temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
// The device's unique 64-bit serial code stored in on-board ROM.
|
||||
// Reading directly from the sensor device address is faster than
|
||||
// reading from index. When reading by index, DallasTemperature
|
||||
// must first look up the device address at the specified index.
|
||||
DeviceAddress sensorDeviceAddress;
|
||||
// set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT);
|
||||
// last time requestTemperatures was called
|
||||
// used to determine when we can read the sensors temperature
|
||||
// we have to wait at least 93.75 ms after requestTemperatures() is called
|
||||
unsigned long lastTemperaturesRequest;
|
||||
float temperature = -100; // default to -100, DS18B20 only goes down to -50C
|
||||
// indicates requestTemperatures has been called but the sensor measurement is not complete
|
||||
bool waitingForConversion = false;
|
||||
// flag to indicate we have finished the first getTemperature call
|
||||
// allows this library to report to the user how long until the first
|
||||
// measurement
|
||||
bool getTemperatureComplete = false;
|
||||
// flag set at startup if DS18B20 sensor not found, avoids trying to keep getting
|
||||
// temperature if flashed to a board without a sensor attached
|
||||
bool disabled = false;
|
||||
|
||||
void requestTemperatures() {
|
||||
// there is requestTemperaturesByAddress however it
|
||||
// appears to do more work,
|
||||
// TODO: measure exection time difference
|
||||
sensor.requestTemperatures();
|
||||
lastTemperaturesRequest = millis();
|
||||
waitingForConversion = true;
|
||||
}
|
||||
|
||||
void getTemperature() {
|
||||
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
|
||||
temperature = sensor.getTempC(sensorDeviceAddress);
|
||||
#else
|
||||
temperature = sensor.getTempF(sensorDeviceAddress);
|
||||
#endif
|
||||
|
||||
lastMeasurement = millis();
|
||||
waitingForConversion = false;
|
||||
getTemperatureComplete = true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void setup() {
|
||||
sensor.begin();
|
||||
sensor.setResolution(9);
|
||||
|
||||
// get the unique 64-bit serial code stored in on-board ROM
|
||||
// if getAddress returns false, the sensor was not found
|
||||
disabled = !sensor.getAddress(sensorDeviceAddress, 0);
|
||||
|
||||
if (!disabled) {
|
||||
DEBUG_PRINTLN("Dallas Temperature found");
|
||||
// set the resolution for this specific device
|
||||
sensor.setResolution(sensorDeviceAddress, 9, true);
|
||||
// do not block waiting for reading
|
||||
sensor.setWaitForConversion(false);
|
||||
} else {
|
||||
DEBUG_PRINTLN("Dallas Temperature not found");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (millis() - lastMeasurement > MEASUREMENT_INTERVAL)
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
// check to see if we are due for taking a measurement
|
||||
// lastMeasurement will not be updated until the conversion
|
||||
// is complete the the reading is finished
|
||||
if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL)
|
||||
{
|
||||
getReading();
|
||||
return;
|
||||
}
|
||||
|
||||
// we are due for a measurement, if we are not already waiting
|
||||
// for a conversion to complete, then make a new request for temps
|
||||
if (!waitingForConversion)
|
||||
{
|
||||
requestTemperatures();
|
||||
return;
|
||||
}
|
||||
|
||||
// we were waiting for a conversion to complete, have we waited log enough?
|
||||
if (now - lastTemperaturesRequest >= 94 /* 93.75ms per the datasheet */)
|
||||
{
|
||||
getTemperature();
|
||||
|
||||
if (WLED_MQTT_CONNECTED) {
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(temperature).c_str());
|
||||
if (-100 <= temperature) {
|
||||
// dont publish super low temperature as the graph will get messed up
|
||||
// the DallasTemperature library returns -127C or -196.6F when problem
|
||||
// reading the sensor
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(temperature).c_str());
|
||||
} else {
|
||||
// publish something else to indicate status?
|
||||
}
|
||||
}
|
||||
lastMeasurement = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void addToJsonInfo(JsonObject& root) {
|
||||
// dont add temperature to info if we are disabled
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray temp = user.createNestedArray("Temperature");
|
||||
if (temperature == DEVICE_DISCONNECTED_C) {
|
||||
|
||||
if (!getTemperatureComplete) {
|
||||
// if we haven't read the sensor yet, let the user know
|
||||
// that we are still waiting for the first measurement
|
||||
temp.add((USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
||||
temp.add(" sec until read");
|
||||
return;
|
||||
}
|
||||
|
||||
if (temperature <= -100) {
|
||||
temp.add(0);
|
||||
temp.add(" Sensor Error!");
|
||||
return;
|
||||
}
|
||||
|
||||
temp.add(temperature);
|
||||
#ifdef TEMP_CELSIUS
|
||||
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
|
||||
temp.add("°C");
|
||||
#else
|
||||
temp.add("°F");
|
||||
|
@ -9,7 +9,10 @@
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
#include "usermod_temperature.h"
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
#include "../usermods/Temperature/usermod_temperature.h"
|
||||
#endif
|
||||
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
void registerUsermods()
|
||||
@ -20,6 +23,9 @@ void registerUsermods()
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
usermods.add(new UsermodTemperature());
|
||||
#endif
|
||||
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
}
|
@ -10,7 +10,9 @@
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//#include "usermod_v2_example.h"
|
||||
//#include "usermod_temperature.h"
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
#include "../usermods/Temperature/usermod_temperature.h"
|
||||
#endif
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
void registerUsermods()
|
||||
@ -21,6 +23,8 @@ void registerUsermods()
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
//usermods.add(new UsermodTemperature());
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
usermods.add(new UsermodTemperature());
|
||||
#endif
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
}
|
Loading…
Reference in New Issue
Block a user