Okay, got some things working again. At least the device doesn't crash anymore :-) The sensors need some work to give correct readings in the new setup. It looks like I'm initializing them twice or so. Fix will follow in the next commit.

This commit is contained in:
Maurice Makaay 2020-07-14 15:28:20 +02:00
parent 49115a0545
commit 19f754b577
16 changed files with 84 additions and 86 deletions

View File

@ -10,7 +10,10 @@ namespace Dough
App::App() : config(), App::App() : config(),
wifi(), wifi(),
mqtt(&wifi, mqttOnConnect, mqttOnMessage), mqtt(
&wifi,
mqttOnConnectCallback,
mqttOnMessageCallback),
temperatureSensor( temperatureSensor(
&mqtt, &mqtt,
"temperature", "temperature",
@ -31,9 +34,8 @@ namespace Dough
DistanceSensor::Instance(), DistanceSensor::Instance(),
DISTANCE_AVERAGE_STORAGE, DISTANCE_AVERAGE_STORAGE,
DISTANCE_MEASURE_INTERVAL, DISTANCE_MEASURE_INTERVAL,
MINIMUM_PUBLISH_INTERVAL) MINIMUM_PUBLISH_INTERVAL),
{ _logger("APP") {}
}
void App::setup() void App::setup()
{ {
@ -62,14 +64,16 @@ namespace Dough
} }
} // namespace Dough } // namespace Dough
void mqttOnConnect(Dough::MQTT *mqtt) Dough::Logger callbackLogger("CALLBACK");
void mqttOnConnectCallback(Dough::MQTT *mqtt)
{ {
Serial.println("Subscribe to required incoming MQTT topics"); callbackLogger.log("s", "MQTT connection establish, subscribing to topics");
mqtt->subscribe("container_height"); mqtt->subscribe("container_height");
mqtt->subscribe("temperature_offset"); mqtt->subscribe("temperature_offset");
} }
void mqttOnMessage(String &topic, String &payload) void mqttOnMessageCallback(String &topic, String &payload)
{ {
Serial.println("Handle message"); callbackLogger.log("s", "MQTT message received");
} }

View File

@ -28,11 +28,12 @@ namespace Dough
private: private:
App(); App();
Logger _logger;
}; };
} }
// Callback functions that need to live in the global namespace. // Callback functions that need to live in the global namespace.
void mqttOnConnect(Dough::MQTT*); void mqttOnConnectCallback(Dough::MQTT* mqtt);
void mqttOnMessage(String &topic, String &payload); void mqttOnMessageCallback(String &topic, String &payload);
#endif #endif

View File

@ -36,7 +36,7 @@ namespace Dough
// } // }
// else // else
// { // {
// App::Instance()->config._logger.log("sS", "ERROR - Unhandled MQTT message, key = ", key); // App::Instance()->config._logger.log("ss", "ERROR - Unhandled MQTT message, key = ", key.c_str());
// } // }
// } // }

View File

@ -3,11 +3,11 @@
namespace Dough namespace Dough
{ {
MQTT::MQTT( MQTT::MQTT(
WiFi *network, WiFi *wifi,
MQTTConnectHandler onConnect, MQTTConnectHandler onConnect,
MQTTMessageHandler onMessage) : _logger("MQTT") MQTTMessageHandler onMessage) : _logger("MQTT")
{ {
_wifi = network; _wifi = wifi;
_onConnect = onConnect; _onConnect = onConnect;
_onMessage = onMessage; _onMessage = onMessage;
} }

View File

@ -20,7 +20,7 @@ namespace Dough
class MQTT class MQTT
{ {
public: public:
MQTT(WiFi *network, MQTTConnectHandler onConnect, MQTTMessageHandler onMessage); MQTT(WiFi *wifi, MQTTConnectHandler onConnect, MQTTMessageHandler onMessage);
void setup(); void setup();
bool isConnected(); bool isConnected();
bool connect(); bool connect();

View File

@ -58,7 +58,10 @@ namespace Dough
// Check if the connection attempt was successful. // Check if the connection attempt was successful.
if (status == WL_CONNECTED) if (status == WL_CONNECTED)
{ {
_logger.log("sa", "IP-Address = ", ::WiFi.localIP()); char buf[50]; // this will also fit IPv6 addresses
auto printer = StringPrinter(buf, 50);
printer.print(::WiFi.localIP());
_logger.log("ss", "IP-Address = ", buf);
_logger.log("sis", "Signal strength = ", ::WiFi.RSSI(), " dBm"); _logger.log("sis", "Signal strength = ", ::WiFi.RSSI(), " dBm");
return true; return true;
} }

View File

@ -2,10 +2,6 @@
namespace Dough namespace Dough
{ {
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
DistanceSensor *DistanceSensor::Instance() DistanceSensor *DistanceSensor::Instance()
{ {
static DistanceSensor *_instance = new DistanceSensor(); static DistanceSensor *_instance = new DistanceSensor();
@ -17,10 +13,6 @@ namespace Dough
_hcsr04 = new SensorHCSR04(HCSR04_TRIG_PIN, HCSR04_ECHO_PIN); _hcsr04 = new SensorHCSR04(HCSR04_TRIG_PIN, HCSR04_ECHO_PIN);
} }
// ----------------------------------------------------------------------
// setup
// ----------------------------------------------------------------------
void DistanceSensor::setup() void DistanceSensor::setup()
{ {
_hcsr04->setup(); _hcsr04->setup();
@ -36,10 +28,6 @@ namespace Dough
_hcsr04->setHumidity(humidity); _hcsr04->setHumidity(humidity);
} }
// ----------------------------------------------------------------------
// loop
// ----------------------------------------------------------------------
Measurement DistanceSensor::read() Measurement DistanceSensor::read()
{ {
int d = _hcsr04->readDistance(); int d = _hcsr04->readDistance();

View File

@ -2,10 +2,6 @@
namespace Dough namespace Dough
{ {
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
HumiditySensor *HumiditySensor::Instance() HumiditySensor *HumiditySensor::Instance()
{ {
static HumiditySensor *_instance = new HumiditySensor(); static HumiditySensor *_instance = new HumiditySensor();
@ -14,19 +10,11 @@ namespace Dough
HumiditySensor::HumiditySensor() : _logger("HUMIDITY") {} HumiditySensor::HumiditySensor() : _logger("HUMIDITY") {}
// ----------------------------------------------------------------------
// setup
// ----------------------------------------------------------------------
void HumiditySensor::setup() void HumiditySensor::setup()
{ {
SensorDHT11::Instance()->begin(); SensorDHT11::Instance()->begin();
} }
// ----------------------------------------------------------------------
// loop
// ----------------------------------------------------------------------
Measurement HumiditySensor::read() Measurement HumiditySensor::read()
{ {
float t = SensorDHT11::Instance()->readHumidity(); float t = SensorDHT11::Instance()->readHumidity();

View File

@ -2,10 +2,6 @@
namespace Dough namespace Dough
{ {
// ----------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------
TemperatureSensor *TemperatureSensor::Instance() TemperatureSensor *TemperatureSensor::Instance()
{ {
static TemperatureSensor *_instance = new TemperatureSensor(); static TemperatureSensor *_instance = new TemperatureSensor();
@ -14,10 +10,6 @@ namespace Dough
TemperatureSensor::TemperatureSensor() : _logger("TEMPERATURE") {} TemperatureSensor::TemperatureSensor() : _logger("TEMPERATURE") {}
// ----------------------------------------------------------------------
// setup
// ----------------------------------------------------------------------
void TemperatureSensor::setup() void TemperatureSensor::setup()
{ {
SensorDHT11::Instance()->begin(); SensorDHT11::Instance()->begin();

View File

@ -144,4 +144,4 @@ namespace Dough
_state = UP_AFTER_LONG; _state = UP_AFTER_LONG;
} }
} }
} } // namespace Dough

View File

@ -173,4 +173,4 @@ namespace Dough
{ {
return _pinState == LOW; return _pinState == LOW;
} }
} } // namespace Dough

View File

@ -55,26 +55,17 @@ namespace Dough
float f = va_arg(args, double); float f = va_arg(args, double);
Serial.print(f); Serial.print(f);
} }
else if (*fmt == 'a')
{
IPAddress a = va_arg(args, IPAddress);
Serial.print(a);
}
else if (*fmt == 's') else if (*fmt == 's')
{ {
const char *s = va_arg(args, const char *); const char *s = va_arg(args, const char *);
Serial.print(s); Serial.print(s);
} }
else if (*fmt == 'S')
{
String S = va_arg(args, String);
Serial.print(S);
}
else else
{ {
Serial.print("<log(): invalid format char '"); Serial.print("<log(): invalid format char '");
Serial.print(*fmt); Serial.print(*fmt);
Serial.print("'>"); Serial.println("'>");
return;
} }
fmt++; fmt++;
} }

View File

@ -26,6 +26,40 @@ namespace Dough
const char *_section; const char *_section;
bool _suspended = false; bool _suspended = false;
}; };
// This class allows printing to a char*, so we can leverage standard
// Printable support for classes. It's up to the caller to provide a
// buffer that is large enough to hold the results. When the printed
// output is larger than the provided buffer, the overflow is silently
// ignored.
class StringPrinter : public Print
{
public:
StringPrinter(char *buffer, int buflen) : _buf(buffer), _pos(0), _len(buflen)
{
if (_len > 0)
{
_buf[0] = '\0';
}
}
virtual size_t write(uint8_t c)
{
// Silently ignore buffer overflows.
if ((_pos + 1) < _len)
{
_buf[_pos] = c;
_pos++;
_buf[_pos] = '\0';
}
return 1;
}
private:
char *_buf;
size_t _pos;
size_t _len;
};
} }
#endif #endif

View File

@ -47,7 +47,7 @@ namespace Dough
// This allows for example to have a flashing LED, during the // This allows for example to have a flashing LED, during the
// wifi connection setup. // wifi connection setup.
_setupTimerInterrupt(); _setupTimerInterrupt();
// Notify the user that we're on a roll! // Notify the user that we're on a roll!
_flash_all_leds(); _flash_all_leds();
@ -95,7 +95,8 @@ namespace Dough
TC_CTRLA_ENABLE; // Enable TC4 TC_CTRLA_ENABLE; // Enable TC4
REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 overflow (OVF) interrupts REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 overflow (OVF) interrupts
REG_TC4_COUNT8_CC0 = 1; // Set the CC0 as the TOP value for MFRQ (1 => 50ms per pulse) REG_TC4_COUNT8_CC0 = 1; // Set the CC0 as the TOP value for MFRQ (1 => 50ms per pulse)
while (TC4->COUNT8.STATUS.bit.SYNCBUSY); // Wait for synchronization while (TC4->COUNT8.STATUS.bit.SYNCBUSY)
; // Wait for synchronization
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -160,7 +161,7 @@ namespace Dough
delay(100); delay(100);
led3.off(); led3.off();
} }
} } // namespace Dough
// This callback is called when the TC4 timer hits an overflow interrupt. // This callback is called when the TC4 timer hits an overflow interrupt.
// Defined outside the Dough namespace, because TC4_Handler is a hard-coded // Defined outside the Dough namespace, because TC4_Handler is a hard-coded
@ -170,4 +171,3 @@ void TC4_Handler()
Dough::UI::Instance()->updatedLEDs(); Dough::UI::Instance()->updatedLEDs();
REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag. REG_TC4_INTFLAG = TC_INTFLAG_OVF; // Clear the OVF interrupt flag.
} }

View File

@ -6,7 +6,7 @@
// serial messages to appear in the serial monitor. // serial messages to appear in the serial monitor.
// Without this, some of the initial serial messages might // Without this, some of the initial serial messages might
// be missing from the output. // be missing from the output.
#undef LOG_WAIT_SERIAL //#define LOG_WAIT_SERIAL
// The digital pins to which the push buttons are connected. // The digital pins to which the push buttons are connected.
#define ONOFF_BUTTON_PIN 2 #define ONOFF_BUTTON_PIN 2

View File

@ -1,14 +1,10 @@
#include "main.h" #include "main.h"
// TODO: move code to Dough namespace
// TODO: move config to a separate class
// TODO: see if I can give each sensor its own built-in loop schedule for sampling, the DoughData class might be overkill in the latest setup.
// TOOD: implement the calibration logic // TOOD: implement the calibration logic
// TODO: see what more stuff can be moved to the UI code. Maybe state to UI state translation ought to be there as well // TODO: see what more stuff can be moved to the UI code. Maybe state to UI state translation ought to be there as well
// TODO: make significantChange part of sensor class?
DoughBoyState state = CONFIGURING; DoughBoyState state = CONFIGURING;
auto logger = Dough::Logger("MAIN"); Dough::Logger logger("MAIN");
void setup() void setup()
{ {
@ -25,7 +21,6 @@ void setup()
void loop() void loop()
{ {
auto app = Dough::App::Instance(); auto app = Dough::App::Instance();
auto mqtt = app->mqtt;
auto ui = Dough::UI::Instance(); auto ui = Dough::UI::Instance();
ui->processButtonEvents(); ui->processButtonEvents();
@ -34,12 +29,15 @@ void loop()
{ {
return; return;
} }
mqtt.procesIncomingsMessages(); app->mqtt.procesIncomingsMessages();
if (state == CONFIGURING && app->config.isOk()) if (state == CONFIGURING)
{ {
setStateToMeasuring(); if (app->config.isOk())
{
setStateToMeasuring();
}
} }
else if (state == MEASURING && !app->config.isOk()) else if (state == MEASURING && !app->config.isOk())
{ {
@ -69,10 +67,8 @@ bool setupNetworkConnection()
auto app = Dough::App::Instance(); auto app = Dough::App::Instance();
auto ui = Dough::UI::Instance(); auto ui = Dough::UI::Instance();
auto network = app->wifi;
auto mqtt = app->mqtt;
if (!network.isConnected()) if (!app->wifi.isConnected())
{ {
if (connectionState == CONNECTED) if (connectionState == CONNECTED)
{ {
@ -86,9 +82,9 @@ bool setupNetworkConnection()
ui->led1.blink()->slow(); ui->led1.blink()->slow();
ui->led2.off(); ui->led2.off();
ui->led3.off(); ui->led3.off();
network.connect(); app->wifi.connect();
} }
if (network.isConnected() && !mqtt.isConnected()) if (app->wifi.isConnected() && !app->mqtt.isConnected())
{ {
if (connectionState == CONNECTED) if (connectionState == CONNECTED)
{ {
@ -99,12 +95,13 @@ bool setupNetworkConnection()
logger.log("s", "Connecting to the MQTT broker ..."); logger.log("s", "Connecting to the MQTT broker ...");
} }
connectionState = CONNECTING_MQTT; connectionState = CONNECTING_MQTT;
ui->led1.on(); ui->led1.blink()->fast();
ui->led2.blink()->slow(); ui->led2.off();
ui->led3.off(); ui->led3.off();
mqtt.connect(); app->mqtt.connect();
delay(1000); // purely costmetic, to make the faster LED blinking noticable
} }
if (network.isConnected() && mqtt.isConnected()) if (app->wifi.isConnected() && app->mqtt.isConnected())
{ {
if (connectionState != CONNECTED) if (connectionState != CONNECTED)
{ {