-
-
Save SimonMerrett/ae4fad1020020ef2e58c03b3475a48a1 to your computer and use it in GitHub Desktop.
current state of thermometer menu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Actions library for thermometer | |
@created: 2020-05-16 | |
@author: Simon Merrett | |
@version: 0.1 | |
Source code link: #TODO: complete link when published | |
For changelog see actions.h | |
*/ | |
#include "actions.h" | |
#include "numbersIn.h" | |
void actions::digits() | |
{ | |
Serial.print(F("DISPLAY Current Temp = ")); | |
printTemperatureDiv10(currentTempx10); | |
char u = getUnitSymbol(unit); | |
Serial.println(u); | |
if (button1Pressed) | |
{ | |
menuState = Option::graph; | |
} | |
if (button2Pressed) | |
{ | |
menuState = Option::units; | |
} | |
} | |
void actions::graph() | |
{ | |
Serial.println(F("DISPLAY Graph")); | |
if (button1Pressed) | |
{ | |
menuState = (coolDownState) ? Option::countdown : Option::digits; | |
} | |
if (button2Pressed) | |
{ | |
menuState = Option::units; | |
} | |
} | |
void actions::countdown() | |
{ | |
Serial.print(F("DISPLAY Count down remaining = ")); | |
Serial.println(countDownRemaining); | |
if (button1Pressed) | |
{ | |
menuState = Option::digits; | |
} | |
if (button2Pressed) | |
{ | |
menuState = Option::units; | |
} | |
} | |
void actions::units() | |
{ | |
// show the current setting | |
Serial.print(F("MENU Units: ")); | |
Serial.println(printout = (static_cast<bool>(unit)) ? "Celsius" : "Farenheit"); | |
if (button2Pressed) | |
{ //TODO: deal with toggling bool | |
unit = static_cast<TempUnit>(1 - static_cast<bool>(unit));//!temperatureUnits; // toggle the variable | |
} | |
if (button1Pressed) | |
{ | |
menuState = Option::alarmOnOff; | |
} | |
} | |
void actions::alarmOnOff() | |
{ | |
// show the current setting | |
Serial.print(F("MENU Alarm: ")); | |
showOnOff(alarmState); | |
if (button2Pressed) | |
{ | |
alarmState = !alarmState; // toggle the setting | |
} | |
if (button1Pressed) | |
{ | |
menuState = (alarmState) ? Option::alarmLowLimit : Option::coolDownOnOff; | |
} | |
} | |
void actions::alarmLowLimit() | |
{ | |
lowerLimitAlarmInput.render(); | |
if (button2Pressed) | |
lowerLimitAlarmInput.incrementDigit(); | |
if (button1Pressed) | |
{ | |
auto previous = lowerLimitAlarmInput.getDigit(); | |
lowerLimitAlarmInput.cycleDigit(); | |
auto current = lowerLimitAlarmInput.getDigit(); | |
if((previous == Digit::Tenths) && (current == Digit::Tens)) | |
menuState = Option::alarmHighLimit; | |
} | |
} | |
void actions::alarmHighLimit() | |
{ | |
higherLimitAlarmInput.render(); | |
if (button2Pressed) | |
higherLimitAlarmInput.incrementDigit(); | |
if (button1Pressed) | |
{ | |
auto previous = higherLimitAlarmInput.getDigit(); | |
higherLimitAlarmInput.cycleDigit(); | |
auto current = higherLimitAlarmInput.getDigit(); | |
if((previous == Digit::Tenths) && (current == Digit::Tens)) | |
menuState = Option::coolDownOnOff; | |
} | |
} | |
void actions::coolDownOnOff() | |
{ | |
Serial.print(F("MENU Cooldown counter: ")); // show the current setting | |
showOnOff(coolDownState); | |
if (button2Pressed) | |
{ | |
coolDownState = !coolDownState; // toggle the setting | |
} | |
if (button1Pressed) | |
{ | |
menuState = (coolDownState) ? Option::coolDownTarget : Option::digits ; | |
} | |
} | |
void actions::coolDownTarget() | |
{ | |
coolDownTargetInput.render(); | |
if (button2Pressed) | |
coolDownTargetInput.incrementDigit(); | |
if (button1Pressed) | |
{ | |
auto previous = coolDownTargetInput.getDigit(); | |
coolDownTargetInput.cycleDigit(); | |
auto current = coolDownTargetInput.getDigit(); | |
if((previous == Digit::Tenths) && (current == Digit::Tens)) | |
menuState = Option::digits; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Actions library for thermometer | |
@created: 2020-05-16 | |
@author: Simon Merrett | |
@version: 0.1 | |
Credits: thanks to @Pharap who provided many of the elements of this code and coached Simon Merrett hugely | |
Source code link: #TODO: complete link when published | |
Changelog: | |
- V0.1 initial drafting, after moving to platformio | |
*/ | |
#ifndef ACTIONS_H | |
#define ACTIONS_H | |
#include <Arduino.h> // required for uint8_t to be recognised as a type | |
class NumberInputSystem; // declare the class which is initialised elsewhere (numbersIn.h) | |
enum class Option : uint8_t | |
{ | |
digits, | |
graph, | |
countdown, | |
units, | |
alarmOnOff, | |
alarmLowLimit, | |
alarmHighLimit, | |
coolDownOnOff, | |
coolDownTarget, | |
}; | |
enum class TempUnit : uint8_t | |
{ | |
farenheit, | |
celsius | |
}; | |
extern uint16_t currentTempx10; // dummy number for displaying digits | |
extern void printTemperatureDiv10(uint16_t tempx10); | |
extern char getUnitSymbol(TempUnit unit); | |
extern void showOnOff(bool var); | |
extern Option menuState; | |
extern TempUnit unit; | |
extern bool button1Pressed; | |
extern bool button2Pressed; | |
extern bool alarmState; // initialises that the alarm is off | |
extern bool coolDownState; // initialises to not showing or activating the countdown | |
extern uint8_t countDownRemaining; // dummy countdown variable | |
extern uint16_t alarmLowLimit; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
extern uint16_t alarmHighLimit; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
extern uint16_t coolingTarget; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
extern const char* printout; // declare to hold values for printing later | |
extern NumberInputSystem lowerLimitAlarmInput; // declare instances that we want to use of the NumberInputSystem class | |
extern NumberInputSystem higherLimitAlarmInput;// declare instances that we want to use of the NumberInputSystem class | |
extern NumberInputSystem coolDownTargetInput; // declare instances that we want to use of the NumberInputSystem class | |
class actions | |
{ | |
public: | |
void digits(); | |
void graph(); | |
void countdown(); | |
void units(); | |
void alarmOnOff(); | |
void alarmLowLimit(); | |
void alarmHighLimit(); | |
void coolDownOnOff(); | |
void coolDownTarget(); | |
} ; | |
#endif // ACTIONS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Menu Test for memory-limited microcontrollers | |
This aims to see how much memory is required to implement different techniques of providing a menu system | |
Credits: thanks to @Pharap who provided many of the elements of this code and coached Simon Merrett hugely | |
Changelog: | |
- V06 moves more of the main file into header files for readability (and one day, maintainability) | |
- V05 is purely a transition to platformio (change to .cpp etc) | |
- V04 fixes some issues that Pharap pointed out (assignment inside an expression) and moves towards separate files | |
- V03 moves from one single enum class to two enum classes, moves functions out of cases, uses the ternary operator, removes the floats (saving 1700B!) | |
- V02 adds some simulated behaviour, such as a (constant) current temperature value and adds menu state change functionality | |
- V01 changes some names for better readability and removes conditional compilation | |
*/ | |
#include <Arduino.h> | |
#include "actions.h" | |
#include "numbersIn.h" | |
bool button1Pressed = false; // button state | |
bool button2Pressed = false; // button state | |
uint16_t currentTempx10 = 443; // dummy number for displaying digits | |
bool alarmState = false; // default that the alarm is off | |
bool coolDownState = false; // default to not showing or activating the countdown | |
uint8_t countDownRemaining = 255; // dummy countdown variable | |
uint16_t alarmLowLimit = 200; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
uint16_t alarmHighLimit = 210; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
uint16_t coolingTarget = 200; // equivalent to 10 * temperature, so 200 = 20.0 degrees Centigrade | |
const char* printout; // declare to hold values for printing later | |
// Initialise Arduino pin numbers | |
constexpr uint8_t button1 = 2; | |
constexpr uint8_t button2 = 3; | |
constexpr uint8_t led1 = 4; | |
constexpr uint8_t led2 = 5; | |
void showOnOff(bool var); | |
uint16_t incrementTens(uint16_t tensToIncrease); | |
uint16_t incrementOnes(uint16_t onesToIncrease); | |
uint16_t incrementTenths(uint16_t tenthsToIncrease); | |
void printTemperatureDiv10(uint16_t tempx10); | |
void displayUpdate(); | |
void buttonCheck(); | |
void Blink(uint8_t led); | |
char getUnitSymbol(TempUnit unit); | |
Option menuState = Option::digits; // initialise the first state | |
TempUnit unit = TempUnit::celsius; // initialise the first unit | |
actions act; // initialise an instance of the class `actions`, called `act` | |
NumberInputSystem lowerLimitAlarmInput { /*F("MENU Alarm lower limit: "), */ alarmLowLimit/*, Digit::Tens*/ }; // initialise an instance of the class `NumberInputSystem`, called `lowerLimitAlarmInput` | |
NumberInputSystem higherLimitAlarmInput {/* F("MENU Alarm upper limit: "),*/ alarmHighLimit/*, Digit::Tens*/ }; | |
NumberInputSystem coolDownTargetInput { /*F("MENU Cooldown target: "),*/ coolingTarget/*, Digit::Tens */}; | |
void setup() { | |
// set up serial monitor for output and user input | |
Serial.begin(115200); | |
// set up real buttons and state LEDs | |
pinMode(2, INPUT_PULLUP); | |
pinMode(3, INPUT_PULLUP); | |
pinMode(4, OUTPUT); | |
pinMode(5, OUTPUT); | |
// set the messages for the input prompts | |
lowerLimitAlarmInput.setMessage(F("MENU Alarm lower limit: ")); | |
higherLimitAlarmInput.setMessage(F("MENU Alarm upper limit: ")); | |
coolDownTargetInput.setMessage(F("MENU Cooldown target: ")); | |
} | |
void loop() { | |
switch (menuState) | |
{ | |
case Option::digits: // code to display current reading in digits | |
act.digits(); // test that the function is run | |
break; | |
case Option::graph: // code to display graph of current and past readings | |
act.graph(); // test that the function is run | |
break; | |
case Option::countdown: // code to display countdown estimate to target temperature | |
act.countdown(); | |
break; | |
case Option::units: // code to toggle between Centigrade and Farenheit | |
act.units(); | |
break; | |
case Option::alarmOnOff: // code to toggle between on and off | |
act.alarmOnOff(); | |
break; | |
case Option::alarmLowLimit: | |
act.alarmLowLimit(); | |
break; | |
case Option::alarmHighLimit: | |
act.alarmHighLimit(); | |
break; | |
case Option::coolDownOnOff: // code to toggle between on and off | |
act.coolDownOnOff(); | |
break; | |
case Option::coolDownTarget: // code to increment and select the tens unit of cooling target temperature | |
act.coolDownTarget(); | |
break; | |
} | |
buttonCheck(); | |
delay(100); | |
} | |
void showOnOff(bool var) | |
{ | |
String p = (var) ? F("ON") : F("OFF"); | |
Serial.println(p); | |
} | |
uint16_t incrementTens(uint16_t tensToIncrease) | |
{ | |
tensToIncrease = (tensToIncrease + 100) % 1000; // remember that 100 represents 10 degrees. Modulo keeps tensToIncrease in range | |
return tensToIncrease; | |
} | |
uint16_t incrementOnes(uint16_t onesToIncrease) | |
{ | |
uint16_t strippedLimit = (onesToIncrease / 100) * 100 + onesToIncrease % 10; // take the 10's out of onesToIncrease, e.g 258 -> 208 | |
onesToIncrease = strippedLimit + 10 * ((1 + (onesToIncrease / 10) ) % 10); | |
return onesToIncrease; | |
} | |
uint16_t incrementTenths(uint16_t tenthsToIncrease) | |
{ | |
uint16_t strippedLimit = (tenthsToIncrease / 10) * 10; // take the 1's out of alarmLowLimit, e.g 258 -> 250 | |
tenthsToIncrease = strippedLimit + ((1 + tenthsToIncrease ) % 10); | |
return tenthsToIncrease; | |
} | |
void printTemperatureDiv10(uint16_t tempx10) | |
{ | |
Serial.print(tempx10 / 10); | |
Serial.print(F(".")); | |
Serial.print(tempx10 % 10); | |
} | |
void displayUpdate() | |
{ | |
// TODO: insert code to see if the screen needs to be changed | |
} | |
void buttonCheck() | |
{ | |
button1Pressed = 0; // reset so serial input can be used | |
button2Pressed = 0; // reset so serial input can be used | |
if ( Serial.available() ) | |
{ | |
char c = Serial.read(); | |
if ( c == '1') | |
{ | |
button1Pressed = 1; | |
Serial.println(F("Button 1 pressed")); | |
} | |
else if (c == '2') | |
{ | |
button2Pressed = 2; | |
Serial.println(F("Button 2 pressed")); | |
} | |
} | |
else // read hardware buttons | |
{ | |
button1Pressed = digitalRead(button1) == 0; | |
button2Pressed = digitalRead(button2) == 0; | |
} | |
if (button1Pressed) | |
{ | |
Blink(led1); | |
Serial.println(F("Button 1 pressed")); | |
} | |
if (button2Pressed) | |
{ | |
Blink(led2); | |
Serial.println(F("Button 2 pressed")); | |
} | |
} | |
void Blink(uint8_t led) | |
{ | |
digitalWrite(led, HIGH); | |
delay(100); | |
digitalWrite(led, LOW); | |
} | |
char getUnitSymbol(TempUnit unit) | |
{ | |
switch(unit) | |
{ | |
case TempUnit::farenheit: | |
return 'F'; | |
case TempUnit::celsius: | |
return 'C'; | |
default: | |
return '?'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Value editing library for the thermometer. | |
Handles the incrementing of digits in variables by using the buttons | |
@created: 2020-05-18 | |
@author: Simon Merrett | |
@version: 0.1 | |
Credits: thanks to @Pharap who provided many of the elements of this code and coached Simon Merrett hugely | |
Source code link: #TODO: complete link when published | |
Changelog: | |
- V0.1 initial drafting, after moving to platformio | |
*/ | |
#ifndef NUMBERSIN_H | |
#define NUMBERSIN_H | |
#include <Arduino.h> // required for uint8_t to be recognised as a type | |
#include "actions.h" | |
// declare external variables and functions | |
extern uint16_t currentTempx10; // dummy number for displaying digits | |
extern void printTemperatureDiv10(uint16_t tempx10); | |
extern char getUnitSymbol(TempUnit unit); | |
extern Option menuState; | |
extern TempUnit unit; | |
extern bool button1Pressed; | |
extern bool button2Pressed; | |
extern uint16_t incrementTens(uint16_t tensToIncrease); | |
extern uint16_t incrementOnes(uint16_t onesToIncrease); | |
extern uint16_t incrementTenths(uint16_t tenthsToIncrease); | |
enum class Digit : uint8_t { | |
Tens, | |
Ones, | |
Tenths, | |
}; | |
class NumberInputSystem | |
{ | |
private: | |
const __FlashStringHelper * message; | |
uint16_t & value; | |
Digit digit; | |
public: | |
NumberInputSystem(/*const __FlashStringHelper * message,*/ uint16_t & value) : /*message(message),*/ value(value), digit(Digit::Tens) {} | |
void setMessage(const __FlashStringHelper * m) | |
{ | |
message = m; | |
} | |
Digit getDigit() | |
{ | |
return this->digit; | |
} | |
void render() | |
{ | |
Serial.print(message); | |
printTemperatureDiv10(this->value); | |
Serial.println(); | |
} | |
void incrementDigit() | |
{ | |
switch(this->digit) | |
{ | |
case Digit::Tens: | |
this->value = incrementTens(this->value); | |
break; | |
case Digit::Ones: | |
this->value = incrementOnes(this->value); | |
break; | |
case Digit::Tenths: | |
this->value = incrementTenths(this->value); | |
break; | |
} | |
} | |
void cycleDigit() | |
{ | |
switch(this->digit) | |
{ | |
case Digit::Tens: | |
this->digit = Digit::Ones; | |
break; | |
case Digit::Ones: | |
this->digit = Digit::Tenths; | |
break; | |
case Digit::Tenths: | |
this->digit = Digit::Tens; | |
break; | |
} | |
} | |
}; | |
#endif // NUMBERSIN_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment