diff --git a/.gitignore b/.gitignore index 89cc49c..d3a58ed 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +data/homie/config.json diff --git a/lib/HomieNodes/DHT22Node.cpp b/lib/HomieNodes/DHT22Node.cpp new file mode 100644 index 0000000..15989e0 --- /dev/null +++ b/lib/HomieNodes/DHT22Node.cpp @@ -0,0 +1,105 @@ +/* + * DHT22Node.cpp + * Homie Node for DHT22 sensors using Adafruit DHT22 library. + * + * Version: 1.0 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#include "DHT22Node.hpp" + +#define DHTTYPE DHT22 + +DHT22Node::DHT22Node(const char *name, const int sensorPin, const int measurementInterval) + : SensorNode(name, "DHT22"), + _sensorPin(sensorPin), + _measurementInterval(measurementInterval), + _lastMeasurement(0) +{ + if (_sensorPin > DEFAULTPIN) + { + dht = new DHT(_sensorPin, DHTTYPE); + } + + advertise(cStatusTopic) + .setDatatype("enum") + .setFormat("error, ok"); + advertise(cTemperatureTopic) + .setDatatype("float") + .setFormat("-40:125") + .setUnit(cUnitDegrees); + advertise(cHumidityTopic) + .setDatatype("float") + .setFormat("0:100") + .setUnit(cUnitPercent); + advertise(cAbsHumidityTopic) + .setDatatype("float") + .setUnit(cUnitMgm3); +} + +void DHT22Node::printCaption() +{ + Homie.getLogger() << cCaption << " pin[" << _sensorPin << "]:" << endl; +} + +void DHT22Node::send() +{ + printCaption(); + + if (isnan(temperature) || isnan(humidity)) + { + Homie.getLogger() << cIndent << "Error reading from Sensor" << endl; + + if (Homie.isConnected()) + { + setProperty(cStatusTopic).send("error"); + } + } + else + { + float absHumidity = computeAbsoluteHumidity(temperature, humidity); + + Homie.getLogger() << cIndent << "Temperature: " << temperature << " °C" << endl; + Homie.getLogger() << cIndent << "Humidity: " << humidity << " %" << endl; + Homie.getLogger() << cIndent << "Abs humidity: " << absHumidity << " g/m³" << endl; + + if (Homie.isConnected()) + { + setProperty(cStatusTopic).send("ok"); + setProperty(cTemperatureTopic).send(String(temperature)); + setProperty(cHumidityTopic).send(String(humidity)); + setProperty(cAbsHumidityTopic).send(String(absHumidity)); + } + } +} + +void DHT22Node::loop() +{ + if (dht) + { + if ((millis() - _lastMeasurement >= _measurementInterval * 1000UL) || + (_lastMeasurement == 0)) + { + temperature = dht->readTemperature(); + humidity = dht->readHumidity(); + + fixRange(&temperature, cMinTemp, cMaxTemp); + fixRange(&humidity, cMinHumid, cMaxHumid); + + send(); + + _lastMeasurement = millis(); + } + } +} + +void DHT22Node::setup() +{ + printCaption(); + Homie.getLogger() << cIndent << "Reading interval: " << _measurementInterval << " s" << endl; + + if (dht) + { + dht->begin(); + } +} diff --git a/lib/HomieNodes/DHT22Node.hpp b/lib/HomieNodes/DHT22Node.hpp new file mode 100644 index 0000000..cc46def --- /dev/null +++ b/lib/HomieNodes/DHT22Node.hpp @@ -0,0 +1,50 @@ +/* + * DHT22Node.hpp + * Homie Node for DHT-22 sensors using Adafruit DHT library. + * + * Version: 1.0 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#pragma once + +#include +#include + +#include "SensorNode.hpp" +#include "constants.hpp" + +#define DEFAULTPIN -1 + +class DHT22Node : public SensorNode +{ +private: + const float cMinTemp = -40.0; + const float cMaxTemp = 125.0; + const char *cCaption = "• DHT22 sensor"; + const char *cIndent = " ◦ "; + + int _sensorPin; + unsigned long _measurementInterval; + unsigned long _lastMeasurement; + + float temperature = NAN; + float humidity = NAN; + + DHT *dht = NULL; + + void printCaption(); + void send(); + +protected: + virtual void setup() override; + virtual void loop() override; + +public: + explicit DHT22Node(const char *name, + const int sensorPin = DEFAULTPIN, + const int measurementInterval = MEASUREMENT_INTERVAL); + + float getHumidity() const { return humidity; } + float getTemperature() const { return temperature; } +}; diff --git a/lib/HomieNodes/PingNode.cpp b/lib/HomieNodes/PingNode.cpp new file mode 100644 index 0000000..c6caba2 --- /dev/null +++ b/lib/HomieNodes/PingNode.cpp @@ -0,0 +1,147 @@ +/* + * BME280Node.cpp + * Homie Node for BME280 sensors using Adafruit BME280 library. + * + * Version: 1.1 + * Author: Lübbe Onken (http://github.com/luebbe) + * Author: Markus Haack (http://github.com/mhaack) + */ + +#include "PingNode.hpp" +#include + +bool checkBounds(float value, float min, float max) { + return !isnan(value) && value >= min && value <= max; +} + +PingNode::PingNode(const char *name, const int triggerPin, const int echoPin, + const int measurementInterval, const int publishInterval) + : SensorNode(name, "RCW-0001"), + _triggerPin(triggerPin), _echoPin(echoPin),_lastMeasurement(0), _lastPublish(0) +{ + _measurementInterval = (measurementInterval > MIN_INTERVAL) ? measurementInterval : MIN_INTERVAL; + _publishInterval = (publishInterval > int(_measurementInterval)) ? publishInterval : _measurementInterval; + setMicrosecondsToMetersFactor(20); + + if (_triggerPin > DEFAULTPIN && _echoPin > DEFAULTPIN) { + sonar = new NewPing(_triggerPin,_echoPin,cMaxDistance*100.0); + } + + advertise(cDistanceTopic) + .setDatatype("float") + .setFormat("0:3") + .setUnit(cUnitMeter); + advertise(cPingTopic) + .setDatatype("float") + .setUnit(cUnitMicrosecond); + advertise(cStatusTopic) + .setDatatype("enum") + .setFormat("error, ok"); + advertise(cChangedTopic) + .setName("Obstacle changed") + .setDatatype("boolean"); +} + +void PingNode::printCaption() +{ + Homie.getLogger() << cCaption << " triggerpin[" << _triggerPin << "], echopin[" << _echoPin << "]:" << endl; +} + +void PingNode::send() +{ + printCaption(); + Homie.getLogger() << cIndent << "Ping: " << _ping_us << " " << cUnitMicrosecond << endl; + Homie.getLogger() << cIndent << "Distance: " << _distance << " " << cUnitMeter << endl; + bool valid = _distance > 0; + Homie.getLogger() << cIndent << "Status: " << (valid ? "ok" : "error") << endl; + bool changed = signalChange(_distance, _lastDistance); + Homie.getLogger() << cIndent << "Changed: " << (changed ? "true" : "false") << " " << endl; + if (Homie.isConnected()) + { + setProperty(cStatusTopic).send(valid ? "ok" : "error"); + if (valid) { + setProperty(cDistanceTopic).send(String(_distance)); + setProperty(cChangedTopic).send(changed ? "true": "false"); + } + } + if (changed) + { + _changeHandler(); + } + if (valid) { + _lastDistance = _distance; + _distance = -1; + } + +} + +void PingNode::loop() +{ + if (sonar) { + if (millis() - _lastMeasurement >= _measurementInterval * 1000UL || _lastMeasurement == 0) + { + float ping_us = sonar->ping_median(); + // Calculating the distance @ 10 °C from d = t_ping /2 * c => t_ping /2 * 337 [m/s] => t_ping_us / 1e-6 * 1/2 * 337 + float newDistance = ping_us*0.0001685; + fixRange(&newDistance, cMinDistance, cMaxDistance); + if (newDistance > 0) { + _ping_us = ping_us; + _distance = newDistance; + } + _lastMeasurement = millis(); + } + + if (millis() - _lastPublish >= _publishInterval * 1000UL || _lastPublish == 0) + if (_distance > 0) { + send(); + _lastPublish = millis(); + _distance = 0; + } + } +} + +void PingNode::onReadyToOperate() +{ + if (Homie.isConnected()) + { + setProperty(cStatusTopic).send("ok"); + } +}; + +void PingNode::setup() +{ + printCaption(); + Homie.getLogger() << cIndent << "Reading interval: " << _measurementInterval << " s" << endl; + Homie.getLogger() << cIndent << "Publish interval: " << _publishInterval << " s" << endl; +} + +void PingNode::setMicrosecondsToMetersFactor(float temperatureCelcius) +{ + //float soundSpeed = 337.0; // @ 10°C + float soundSpeed = 331.4 * 0.6*temperatureCelcius; + // Calculating the distance from d = t_ping /2 * c => t_ping /2 * 337 [m/s] => t_ping_us / 1e-6 * 1/2 * 337 + _microseconds2meter = 0.5e-6 * soundSpeed; +} + +float PingNode::getRawEchoTime() { + // Clears the trigPin + digitalWrite(_triggerPin, LOW); + delayMicroseconds(2); + + // Sets the trigPin on HIGH state for 10 micro seconds + digitalWrite(_triggerPin, HIGH); + delayMicroseconds(10); + digitalWrite(_triggerPin, LOW); + + // Reads the echoPin, returns the sound wave travel time in microseconds + return pulseIn(_echoPin, HIGH); +} + +bool PingNode::signalChange(float distance, float lastDistance) { + return fabs(distance - lastDistance) > cMinimumChange; +} + +PingNode& PingNode::setChangeHandler(const ChangeHandler& changeHandler) { + _changeHandler = changeHandler; + return *this; +} diff --git a/lib/HomieNodes/PingNode.hpp b/lib/HomieNodes/PingNode.hpp new file mode 100644 index 0000000..9241d49 --- /dev/null +++ b/lib/HomieNodes/PingNode.hpp @@ -0,0 +1,71 @@ +/* + * BME280Node.h + * Homie Node for BME280 sensors using Adafruit BME280 library. + * + * Version: 1.1 + * Author: Lübbe Onken (http://github.com/luebbe) + * Author: Markus Haack (http://github.com/mhaack) + */ + +#pragma once + +#include "NewPing.h" + +#include "SensorNode.hpp" +#include "constants.hpp" + +#define DEFAULTPIN -1 + +class PingNode : public SensorNode +{ +public: + typedef std::function ChangeHandler; +private: + const float cMinDistance = 0.0; + const float cMaxDistance = 3.0; + const float cMinimumChange = 0.2; + + static const int MIN_INTERVAL = 1; // in seconds + const char *cCaption = "• RCW-0001 sensor"; + const char *cIndent = " ◦ "; + + int _triggerPin; + int _echoPin; + float _microseconds2meter; + + unsigned long _measurementInterval; + unsigned long _lastMeasurement; + unsigned long _publishInterval; + unsigned long _lastPublish; + + NewPing* sonar; + float _distance = NAN; + int _ping_us = NAN; + float _lastDistance = 0; + ChangeHandler _changeHandler = [](){}; + + float getRawEchoTime(); + void setMicrosecondsToMetersFactor(float temperatureCelcius); + bool signalChange(float distance, float lastDistance); + void printCaption(); + void send(); + +protected: + virtual void setup() override; + virtual void loop() override; + virtual void onReadyToOperate() override; + static const int DEFAULT_MEASUREMENT_INTERVAL = 1; + static const int DEFAULT_PUBLISH_INTERVAL = 5; + + +public: + explicit PingNode(const char *name, + const int triggerPin = DEFAULTPIN, + const int echoPin = DEFAULTPIN, + const int measurementInterval = DEFAULT_MEASUREMENT_INTERVAL, + const int publishInterval = DEFAULT_PUBLISH_INTERVAL); + + float getDistance() const { return _distance; } + void setTemperature(float temperatureCelcius) { setMicrosecondsToMetersFactor(temperatureCelcius); } + PingNode& setChangeHandler(const ChangeHandler& changeHandler); +}; diff --git a/lib/HomieNodes/RelayNode.cpp b/lib/HomieNodes/RelayNode.cpp new file mode 100644 index 0000000..4a04b57 --- /dev/null +++ b/lib/HomieNodes/RelayNode.cpp @@ -0,0 +1,179 @@ +/* + * RelayNode.cpp + * Homie Node for a Relay with optional status indicator LED + * + * Version: 1.1 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#include "RelayNode.hpp" + +RelayNode::RelayNode(const char *name, const int relayPin, const int ledPin, const bool reverseSignal) + : HomieNode(name, "RelayNode", "actor") +{ + _relayPin = relayPin; + _ledPin = ledPin; + if (reverseSignal) + { + _relayOnValue = LOW; + _relayOffValue = HIGH; + } + else + { + _relayOnValue = HIGH; + _relayOffValue = LOW; + } + advertise("on") + .setDatatype("boolean") + .settable(); + + advertise("timeout") + .setDatatype("integer") + .settable(); +} + +HomieInternals::Uptime relayUptime; + +bool RelayNode::handleOnOff(const String &value) +{ + if (value == "true" || value == "false") + { + setRelay(value == "true"); + return true; + } + else + { + return false; + } +} + +#define IS_INTEGER(s) (s == String(s.toInt())) + +bool RelayNode::handleTimeout(const String &value) +{ + if (IS_INTEGER(value)) + { + long timeout = value.toInt(); + if (timeout > 0) + { + setRelay(true, timeout); + return true; + } + } + return false; +} + +bool RelayNode::handleInput(const HomieRange &range, const String &property, const String &value) +{ + Homie.getLogger() << "Message: " << property << " " << value << endl; + + if (property.equals("on")) + { + return handleOnOff(value); + } + else if (property.equals("timeout")) + { + return handleTimeout(value); + } + else + { + return false; + } +} + +void RelayNode::printCaption() +{ + Homie.getLogger() << cCaption << endl; +} + +void RelayNode::setLed(bool on) +{ + if (_ledPin > DEFAULTPIN) + { + digitalWrite(_ledPin, on ? LOW : HIGH); // LOW = LED on + } +} + +void RelayNode::setRelay(bool on, long timeoutSecs) +{ + printCaption(); + + if (_relayPin > DEFAULTPIN) + { + setRelayState(on); + if (on && timeoutSecs > 0) + { + _timeout = relayUptime.getSeconds() + timeoutSecs; + } + else + { + _timeout = 0; + } + sendState(); + } + else + { + Homie.getLogger() << cIndent << "No Relay Pin!" << endl; + } + setLed(on); +} + +void RelayNode::sendState() +{ + bool on = getRelayState(); + Homie.getLogger() << cIndent << "Relay is " << (on ? "on" : "off") << endl; + if (Homie.isConnected()) + { + setProperty("on").send(on ? "true" : "false"); + setProperty("timeout").send(String(long(_timeout))); + } +} + +void RelayNode::setRelayState(bool on) +{ + digitalWrite(_relayPin, on ? _relayOnValue : _relayOffValue); +} + +bool RelayNode::getRelayState() +{ + return digitalRead(_relayPin) == _relayOnValue; +} + +void RelayNode::toggleRelay() +{ + setRelay(!getRelayState()); +} + +void RelayNode::setupRelay() +{ + pinMode(_relayPin, OUTPUT); +} + +void RelayNode::setup() +{ + printCaption(); + + Homie.getLogger() << cIndent << "Relay Pin: " << _relayPin << endl + << cIndent << "Led Pin : " << _ledPin << endl; + + if (_ledPin > DEFAULTPIN) + { + pinMode(_ledPin, OUTPUT); + setLed(false); + } + + if (_relayPin > DEFAULTPIN) + { + setupRelay(); + setRelay(false); + } +} + +void RelayNode::loop() +{ + relayUptime.update(); + if ((_timeout > 0) && getRelayState() && (_timeout < relayUptime.getSeconds())) + { + setRelay(false); + } +} diff --git a/lib/HomieNodes/RelayNode.hpp b/lib/HomieNodes/RelayNode.hpp new file mode 100644 index 0000000..43feb03 --- /dev/null +++ b/lib/HomieNodes/RelayNode.hpp @@ -0,0 +1,49 @@ +/* + * RelayNode.hpp + * Homie Node for a Relay with optional status indicator LED + * + * Version: 1.0 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#pragma once + +#include + +#define DEFAULTPIN -1 + +class RelayNode : public HomieNode +{ +private: + const char *cCaption = "• Relay:"; + const char *cIndent = " ◦ "; + + int _relayPin; + int _ledPin; + + uint8_t _relayOnValue; + uint8_t _relayOffValue; + uint64_t _timeout; + + bool handleOnOff(const String &value); + bool handleTimeout(const String &value); + + void printCaption(); + void sendState(); + + void setupRelay(); + bool getRelayState(); + void setRelayState(bool on); + + void setLed(bool on); + +protected: + virtual bool handleInput(const HomieRange &range, const String &property, const String &value) override; + virtual void setup() override; + virtual void loop() override; + +public: + explicit RelayNode(const char *name, const int relayPin = DEFAULTPIN, const int ledPin = DEFAULTPIN, const bool reverseSignal = false); + void setRelay(bool on, long timeoutSecs = 0); + void toggleRelay(); +}; diff --git a/lib/HomieNodes/SensorNode.cpp b/lib/HomieNodes/SensorNode.cpp new file mode 100644 index 0000000..bb630cd --- /dev/null +++ b/lib/HomieNodes/SensorNode.cpp @@ -0,0 +1,48 @@ +/* + * SensorNode.hpp + * Homie Node for genric sensors. + * Provides a limit method for measurement values + * + * Version: 1.0 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#include "SensorNode.hpp" + +SensorNode::SensorNode(const char *name, const char *type) + : HomieNode(name, type, "sensor") +{ +} + +float SensorNode::computeAbsoluteHumidity(float temperature, float percentHumidity) { + // Calculate the absolute humidity in g/m³ + // https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/ + + float absHumidity; + float absTemperature; + absTemperature = temperature + 273.15; + + absHumidity = 6.112; + absHumidity *= exp((17.67 * temperature) / (243.5 + temperature)); + absHumidity *= percentHumidity; + absHumidity *= 2.1674; + absHumidity /= absTemperature; + + return absHumidity; +} + +void SensorNode::fixRange(float *value, float min, float max) +{ + if (isnan(*value)) + { + return; + } + else if (*value < min) + { + *value = min; + } + else if (*value > max) + { + *value = max; + }; +} diff --git a/lib/HomieNodes/SensorNode.hpp b/lib/HomieNodes/SensorNode.hpp new file mode 100644 index 0000000..05de251 --- /dev/null +++ b/lib/HomieNodes/SensorNode.hpp @@ -0,0 +1,26 @@ +/* + * SensorNode.hpp + * Homie Node for genric sensors. + * Provides a limit method for measurement values + * + * Version: 1.0 + * Author: Lübbe Onken (http://github.com/luebbe) + */ + +#pragma once + +#include + +class SensorNode : public HomieNode +{ +protected: + const float cMinHumid = 0.0; + const float cMaxHumid = 100.0; + static const int MEASUREMENT_INTERVAL = 300; + + float computeAbsoluteHumidity(float temperature, float percentHumidity); + void fixRange(float *value, float min, float max); + +public: + explicit SensorNode(const char *name, const char *type); +}; diff --git a/lib/HomieNodes/constants.hpp b/lib/HomieNodes/constants.hpp new file mode 100644 index 0000000..dec01d5 --- /dev/null +++ b/lib/HomieNodes/constants.hpp @@ -0,0 +1,25 @@ +// Units +#define cUnitDegrees "°C" +#define cUnitHpa "hPa" +#define cUnitMgm3 "g/m³" +#define cUnitPercent "%" +#define cUnitVolt "V" +#define cUnitMeter "m" +#define cUnitMicrosecond "μs" + +// Topics +#define cStatusTopic "status" +#define cUnitTopic "unit" +#define cTemperatureTopic "temperature" +#define cTemperatureUnitTopic cTemperatureTopic "/" cUnitTopic +#define cHumidityTopic "humidity" +#define cPressureTopic "pressure" +#define cAbsHumidityTopic "abshumidity" +#define cVoltageTopic "voltage" +#define cBatteryLevelTopic "batterylevel" +#define cDistanceTopic "distance" +#define cPingTopic "ping" +#define cChangedTopic "changed" +#define cValidTopic "valid" + + diff --git a/platformio.ini b/platformio.ini index b487207..8b7fc79 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,4 +17,5 @@ monitor_speed = 115200 lib_deps = NewPing Homie - + DHT sensor library + Adafruit Unified Sensor diff --git a/src/main.cpp b/src/main.cpp index b7c71a4..12e40d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,28 +1,38 @@ -#include #include +#include "PingNode.hpp" +#include "RelayNode.hpp" +#include "DHT22Node.hpp" + #define TURN_ON LOW #define TURN_OFF HIGH -const int trigPin = D1; //D1 -const int echoPin = D2; //D2 +const int trigPin = D1; +const int echoPin = D2; +const int relayPin = 14; // D5 +const int dhtPin = D7; ; const int ledPin = LED_BUILTIN; -const float minDistance = 0.01; -const float maxDistance = 4.0; -const float minimumChange = 0.2; -#define MEASURE_INTERVAL 1000 // ms -#define PUBLISH_INTERVAL 5000 // ms +unsigned long HEARTBEAT_INTERVAL = 5; +unsigned long lastHeartbeat = 0; -NewPing sonar(trigPin,echoPin,maxDistance*100.0); -HomieNode obstacleNode("obstacle", "Obstacle", "object"); +PingNode obstacleNode("obstacle",trigPin,echoPin); +DHT22Node airNode("air",dhtPin,20); +RelayNode relayNode("relay",relayPin,ledPin); -void signal_led(bool ons = true); +void signal_led(bool on = true); void heartbeat_led(int times = 2); -void longbeat_led(); -void loopHandler(); -void setupHandler(); -float readDistance(); + +void changeHandler() { + signal_led(); +} + +void loopHandler() { + if (millis() - lastHeartbeat > HEARTBEAT_INTERVAL * 1000UL || lastHeartbeat == 0) { + heartbeat_led(); + lastHeartbeat = millis(); + } +} void setup() { Serial.begin(115200); @@ -31,14 +41,9 @@ void setup() { pinMode(ledPin, OUTPUT); Homie_setBrand("EtxeanIoT"); - Homie_setFirmware("etxean-distancesensor", "1.0.4"); + Homie_setFirmware("etxean-garagesensor", "1.0.5"); Homie.setLoopFunction(loopHandler); - obstacleNode - .advertise("distance").setName("Distance").setDatatype("float").setUnit("m"); - obstacleNode - .advertise("valid").setName("Valid measurement").setDatatype("boolean"); - obstacleNode - .advertise("changed").setName("Obstacle changed").setDatatype("boolean"); + obstacleNode.setChangeHandler(changeHandler); Homie.setup(); } @@ -46,86 +51,9 @@ void loop() { Homie.loop(); } -long lastPublish = 0; -long lastMeasurement = 0; -float lastDistance = 0.0; -float validDistance = -1; - -bool checkBounds(float value, float min, float max) { - return !isnan(value) && value >= min && value <= max; -} - -bool signalChange(float distance, float lastDistance) { - return fabs(distance - lastDistance) > minimumChange; -} - -String toPayload(bool value) -{ - return value ? "true" : "false"; -} - -void loopHandler() { - if (millis() - lastMeasurement >= MEASURE_INTERVAL) { - float distance = readDistance(); - //float distance = random(5,400)/100.0; - Homie.getLogger() << "Distance: " << distance << " m"; - bool valid = checkBounds(distance,minDistance,maxDistance); - Homie.getLogger() << ", valid = " << toPayload(valid) << endl; - if (valid) - validDistance = distance; - lastMeasurement = millis(); - } - if (millis() - lastPublish >= PUBLISH_INTERVAL) { - heartbeat_led(); - - bool valid = validDistance > 0; - obstacleNode.setProperty("valid").send(toPayload(valid)); - if (valid) - { - Homie.getLogger() << "Publish distance: " << validDistance << " m"; - obstacleNode.setProperty("distance").send(String(validDistance)); - bool changed = signalChange(validDistance, lastDistance); - obstacleNode.setProperty("changed").send(toPayload(changed)); - if (changed) - { - signal_led(); - Homie.getLogger() << ", changed" << endl; - } - lastDistance = validDistance; - validDistance = -1; - } - lastPublish = millis(); - } -} - -float getEchoTime() { - // Clears the trigPin - digitalWrite(trigPin, LOW); - delayMicroseconds(2); - - // Sets the trigPin on HIGH state for 10 micro seconds - digitalWrite(trigPin, HIGH); - delayMicroseconds(10); - digitalWrite(trigPin, LOW); - - // Reads the echoPin, returns the sound wave travel time in microseconds - return pulseIn(echoPin, HIGH); -} - -float readDistance() { - //auto ping_us = getEchoTime(); - auto ping_us = sonar.ping_median(); - // Calculating the distance @ 10 °C from d = t_ping /2 * c => t_ping /2 * 337 [m/s] => t_ping_us / 1e-6 * 1/2 * 337 - auto computedDistance = ping_us*0.0001685; - return computedDistance; -} - void signal_led(bool on) { - if (on) - digitalWrite(ledPin, TURN_ON); - else - digitalWrite(ledPin, TURN_OFF); + digitalWrite(ledPin, on ? TURN_ON : TURN_OFF); } void heartbeat_led(int times)