From 8564a6b56fdaceae85b91e5ba6a6430a72deee34 Mon Sep 17 00:00:00 2001 From: Alexander Entinger <cto@lxrobotics.com> Date: Tue, 19 Jul 2022 10:25:34 +0200 Subject: [PATCH 1/2] Thermostat example demonstrate advantages of source/sink vs shared in certain applications. --- .../Thermostat/SharedVariables.h | 0 .../TemperatureControl_LivingRoom.inot | 59 +++++++++++++++++++ .../TemperatureControl_SleepingRoom.inot | 59 +++++++++++++++++++ .../Thermostat/TemperatureSensor.inot | 19 ++++++ .../Thermostat/TemperatureSensorReporter.inot | 19 ++++++ .../Thermostat/Thermostat.ino | 37 ++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 examples/Threading_Basics/Thermostat/SharedVariables.h create mode 100644 examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot create mode 100644 examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot create mode 100644 examples/Threading_Basics/Thermostat/TemperatureSensor.inot create mode 100644 examples/Threading_Basics/Thermostat/TemperatureSensorReporter.inot create mode 100644 examples/Threading_Basics/Thermostat/Thermostat.ino diff --git a/examples/Threading_Basics/Thermostat/SharedVariables.h b/examples/Threading_Basics/Thermostat/SharedVariables.h new file mode 100644 index 0000000..e69de29 diff --git a/examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot b/examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot new file mode 100644 index 0000000..f771ce9 --- /dev/null +++ b/examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot @@ -0,0 +1,59 @@ +/* Define a data sink named 'temperature' of type 'float'. */ +SINK(temperature, float, 10); + +static String living_room_message_prefix(String const & /* msg */) +{ + return String("[Living Room] "); +} + +void setup() +{ + Serial.begin(9600); + Serial.prefix(living_room_message_prefix); + while (!Serial) { } +} + +bool is_heating_on = false; + +void loop() +{ + float current_temperature_deg = temperature.pop(); + + /* Check if the temperature reported by the thermostat is above + * or below 22.0 °C. If the temperature is below 22.0 °C, turn + * on the heating. + */ + bool turn_heating_on = false, + turn_heating_off = false; + + if (current_temperature_deg < 22.0f) + turn_heating_on = true; + else + turn_heating_off = true; + + /* Only perform a simulated turning on of + * the heating if the heating is currently + * turned off. + */ + if (is_heating_on && turn_heating_off) + { + is_heating_on = false; + + Serial.block(); + Serial.print("Heating OFF ("); + Serial.print(current_temperature_deg); + Serial.println(" °C)"); + Serial.unblock(); + } + + if (!is_heating_on && turn_heating_on) + { + is_heating_on = true; + + Serial.block(); + Serial.print("Heating ON ("); + Serial.print(current_temperature_deg); + Serial.println(" °C)"); + Serial.unblock(); + } +} diff --git a/examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot b/examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot new file mode 100644 index 0000000..cf86f23 --- /dev/null +++ b/examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot @@ -0,0 +1,59 @@ +/* Define a data sink named 'temperature' of type 'float'. */ +SINK(temperature, float, 10); + +static String sleeping_room_message_prefix(String const & /* msg */) +{ + return String("[Sleeping Room] "); +} + +void setup() +{ + Serial.begin(9600); + Serial.prefix(sleeping_room_message_prefix); + while (!Serial) { } +} + +bool is_ac_on = false; + +void loop() +{ + float current_temperature_deg = temperature.pop(); + + /* Check if the temperature reported by the thermostat is above + * or below 20.0 °C. If the temperature is above 20.0 °C, turn + * on the AC. + */ + bool turn_ac_on = false, + turn_ac_off = false; + + if (current_temperature_deg > 20.0f) + turn_ac_on = true; + else + turn_ac_off = true; + + /* Only perform a simulated turning on of + * the air conditioner if the heating is + * air conditioner is currently turned off. + */ + if (is_ac_on && turn_ac_off) + { + is_ac_on = false; + + Serial.block(); + Serial.print("AC OFF ("); + Serial.print(current_temperature_deg); + Serial.println(" °C)"); + Serial.unblock(); + } + + if (!is_ac_on && turn_ac_on) + { + is_ac_on = true; + + Serial.block(); + Serial.print("AC ON ("); + Serial.print(current_temperature_deg); + Serial.println(" °C)"); + Serial.unblock(); + } +} diff --git a/examples/Threading_Basics/Thermostat/TemperatureSensor.inot b/examples/Threading_Basics/Thermostat/TemperatureSensor.inot new file mode 100644 index 0000000..8d7c3b1 --- /dev/null +++ b/examples/Threading_Basics/Thermostat/TemperatureSensor.inot @@ -0,0 +1,19 @@ +/* Define a data source named 'temperature' of type 'float'. */ +SOURCE(temperature, float); + +void setup() +{ + +} + +void loop() +{ + /* Read temperature - since this is just a simulation + * so we take a random value between 15 and 25 °C. + */ + float const temperature_deg = (rand() % 16) + 10; + /* Store in temperature source variable. */ + temperature.push(temperature_deg); + /* Do only one temperature sensore measurement per second. */ + delay(5000); +} diff --git a/examples/Threading_Basics/Thermostat/TemperatureSensorReporter.inot b/examples/Threading_Basics/Thermostat/TemperatureSensorReporter.inot new file mode 100644 index 0000000..c6ceb10 --- /dev/null +++ b/examples/Threading_Basics/Thermostat/TemperatureSensorReporter.inot @@ -0,0 +1,19 @@ +/* Define a data sink named 'temperature' of type 'float'. */ +SINK(temperature, float); + +void setup() +{ + Serial.begin(9600); + while (!Serial) { } +} + +void loop() +{ + float const current_temperature_deg = temperature.pop(); + + Serial.block(); + Serial.print("Temperature = "); + Serial.print(current_temperature_deg); + Serial.println(" °C"); + Serial.unblock(); +} diff --git a/examples/Threading_Basics/Thermostat/Thermostat.ino b/examples/Threading_Basics/Thermostat/Thermostat.ino new file mode 100644 index 0000000..a655e96 --- /dev/null +++ b/examples/Threading_Basics/Thermostat/Thermostat.ino @@ -0,0 +1,37 @@ +/* This example emulates a thermostat system which consists of + * a single temperature sensore and multiple heating devices + * or air-conditioners. The temperature sensor provides periodic + * temperature sensor measurements and acts as a temperature source. + * This temperature is consumed by various TemperatureControl_ threads + * which perform the act of actual room temperature control. + * + * Note: While there is only a single temperature "source" there are + * multiple temperature "sinks". The source/sink paradigm is constructed + * in such a way, that each sink is guaranteed to see every value provided + * by a source. This is something that can not be modeled using the shared + * variable abstraction. + */ + +void setup() +{ + /* Connect the TemperatureSensor thread providing temperature readings + * with the various TemperatureControl_* threads. + */ + TemperatureSensor.temperature.connectTo(TemperatureControl_LivingRoom.temperature); + TemperatureSensor.temperature.connectTo(TemperatureControl_SleepingRoom.temperature); + TemperatureSensor.temperature.connectTo(TemperatureSensorReporter.temperature); + + /* Start the individual threads for sensing the temperature + * and controlling heating/air-conditioning based on the sensed + * temperature on a per-room basis. + */ + TemperatureSensor.start(); + TemperatureControl_LivingRoom.start(); + TemperatureControl_SleepingRoom.start(); + TemperatureSensorReporter.start(); +} + +void loop() +{ + +} From 1e5a95a9ecb40d2a2b36c6ce00bd2c0be252c6d5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger <cto@lxrobotics.com> Date: Fri, 22 Jul 2022 08:26:45 +0200 Subject: [PATCH 2/2] Simplify example. --- ..._SleepingRoom.inot => AirConditionerControl.inot} | 10 ++-------- ...reControl_LivingRoom.inot => HeatingControl.inot} | 6 ------ .../Thermostat/TemperatureSensor.inot | 4 ++-- examples/Threading_Basics/Thermostat/Thermostat.ino | 12 ++++++------ 4 files changed, 10 insertions(+), 22 deletions(-) rename examples/Threading_Basics/Thermostat/{TemperatureControl_SleepingRoom.inot => AirConditionerControl.inot} (79%) rename examples/Threading_Basics/Thermostat/{TemperatureControl_LivingRoom.inot => HeatingControl.inot} (88%) diff --git a/examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot b/examples/Threading_Basics/Thermostat/AirConditionerControl.inot similarity index 79% rename from examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot rename to examples/Threading_Basics/Thermostat/AirConditionerControl.inot index cf86f23..59dc16e 100644 --- a/examples/Threading_Basics/Thermostat/TemperatureControl_SleepingRoom.inot +++ b/examples/Threading_Basics/Thermostat/AirConditionerControl.inot @@ -1,15 +1,9 @@ /* Define a data sink named 'temperature' of type 'float'. */ SINK(temperature, float, 10); -static String sleeping_room_message_prefix(String const & /* msg */) -{ - return String("[Sleeping Room] "); -} - void setup() { Serial.begin(9600); - Serial.prefix(sleeping_room_message_prefix); while (!Serial) { } } @@ -20,13 +14,13 @@ void loop() float current_temperature_deg = temperature.pop(); /* Check if the temperature reported by the thermostat is above - * or below 20.0 °C. If the temperature is above 20.0 °C, turn + * or below 26.0 °C. If the temperature is above 26.0 °C, turn * on the AC. */ bool turn_ac_on = false, turn_ac_off = false; - if (current_temperature_deg > 20.0f) + if (current_temperature_deg > 26.0f) turn_ac_on = true; else turn_ac_off = true; diff --git a/examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot b/examples/Threading_Basics/Thermostat/HeatingControl.inot similarity index 88% rename from examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot rename to examples/Threading_Basics/Thermostat/HeatingControl.inot index f771ce9..5fcaf82 100644 --- a/examples/Threading_Basics/Thermostat/TemperatureControl_LivingRoom.inot +++ b/examples/Threading_Basics/Thermostat/HeatingControl.inot @@ -1,15 +1,9 @@ /* Define a data sink named 'temperature' of type 'float'. */ SINK(temperature, float, 10); -static String living_room_message_prefix(String const & /* msg */) -{ - return String("[Living Room] "); -} - void setup() { Serial.begin(9600); - Serial.prefix(living_room_message_prefix); while (!Serial) { } } diff --git a/examples/Threading_Basics/Thermostat/TemperatureSensor.inot b/examples/Threading_Basics/Thermostat/TemperatureSensor.inot index 8d7c3b1..d763ca4 100644 --- a/examples/Threading_Basics/Thermostat/TemperatureSensor.inot +++ b/examples/Threading_Basics/Thermostat/TemperatureSensor.inot @@ -9,9 +9,9 @@ void setup() void loop() { /* Read temperature - since this is just a simulation - * so we take a random value between 15 and 25 °C. + * so we take a random value between 15 and 30 °C. */ - float const temperature_deg = (rand() % 16) + 10; + float const temperature_deg = (rand() % 16) + 15; /* Store in temperature source variable. */ temperature.push(temperature_deg); /* Do only one temperature sensore measurement per second. */ diff --git a/examples/Threading_Basics/Thermostat/Thermostat.ino b/examples/Threading_Basics/Thermostat/Thermostat.ino index a655e96..7fdfd17 100644 --- a/examples/Threading_Basics/Thermostat/Thermostat.ino +++ b/examples/Threading_Basics/Thermostat/Thermostat.ino @@ -14,11 +14,11 @@ void setup() { - /* Connect the TemperatureSensor thread providing temperature readings - * with the various TemperatureControl_* threads. + /* Connect the temperature sensor thread providing temperature readings + * with the various temperature control unit threads. */ - TemperatureSensor.temperature.connectTo(TemperatureControl_LivingRoom.temperature); - TemperatureSensor.temperature.connectTo(TemperatureControl_SleepingRoom.temperature); + TemperatureSensor.temperature.connectTo(HeatingControl.temperature); + TemperatureSensor.temperature.connectTo(AirConditionerControl.temperature); TemperatureSensor.temperature.connectTo(TemperatureSensorReporter.temperature); /* Start the individual threads for sensing the temperature @@ -26,8 +26,8 @@ void setup() * temperature on a per-room basis. */ TemperatureSensor.start(); - TemperatureControl_LivingRoom.start(); - TemperatureControl_SleepingRoom.start(); + HeatingControl.start(); + AirConditionerControl.start(); TemperatureSensorReporter.start(); }