Files
garagesensor/lib/HomieNodes/PingNode.cpp
2020-03-08 22:49:22 +01:00

153 lines
4.6 KiB
C++

/*
* 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 <Homie.h>
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(cPingTopic).send(String(_ping_us));
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*_microseconds2meter;
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;
printCaption();
Homie.getLogger() << cIndent
<< "SpeedOfSound: " << soundSpeed << " " << cUnitMetersPerSecond
<< " at " << temperatureCelcius << " " << cUnitDegrees << endl;
// 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;
}