OMG!!
Really sorry.. That was not the full code.. I just posted the part we discussed to make sure I am doing it right. Below is the full code
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;
int setvalue;
int actualvalue;
int timer;
int duration;
int timermode;
int ontime = 5000;
const byte CheckMode = 10;
const byte CheckValue = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;
byte MyStateVariable;
void setup () {
Serial.begin(115200);
WiFiManager wifiManager;
wifiManager.autoConnect("Device");
Serial.println("Connected to WiFi");
pinMode(device1_pin, OUTPUT);
pinMode(device2_pin, OUTPUT);
pinMode(device3_pin, OUTPUT);
pinMode(device4_pin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
switch(MyStateVariable)
{
case CheckMode:
// code
if (timer == 0){
MyStateVariable = CheckValue;
}
if (timer == 1){
MyStateVariable = OnOffTiming;
}
break;
case CheckValue:
if (setvalue > actualvalue){
MyStateVariable = AutoModeSwitchOn;
break;
}
case AutoModeSwitchOn:
digitalWrite(device1_pin, HIGH);
Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
SwitchOnTimeStamp = currentMillis;
MyStateVariable = WaitForAutoModeOnTimeToEnd;
break;
case WaitForAutoModeOnTimeToEnd:
if (currentMillis - SwitchOnTimeStamp >= ontime){
Serial.println("Switch Turned Off After Set Duration in AUTO mode");
MyStateVariable = CheckMode;
break;
}
case OnOffTiming:
digitalWrite(device1_pin, HIGH);
TimerModeOnTimeStamp = currentMillis;
Serial.println("Switch ON in TIMER mode");
MyStateVariable = WaitForTimerONTime_End;
break;
case WaitForTimerONTime_End:
if (currentMillis - TimerModeOnTimeStamp > duration){
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = Timer_Start_OFF_Period;
break;
}
case Timer_Start_OFF_Period:
OFFPeriodStartsTimestamp = currentMillis;
MyStateVariable = WaitForTimerOFF_PeriodToEnd;
break;
case WaitForTimerOFF_PeriodToEnd:
if (currentMillis - OFFPeriodStartsTimestamp > timer){
Serial.println("Switch ON in TIMER mode After Set Timer Period");
MyStateVariable = CheckMode;
break;
}
}
}
You still did not use autoformat by pressing Ctrl-T in in the Arduino-IDE.
This autoformat does all the indentions to right place.
The indentions help to identify missing or too much inserted curly brackets "{" "}"
OK so what is missing is the initialisation of the statevariable
inside setup add a
MyStateVariable = CheckMode;
and as an addition pre-caution add a "default-case" to the switch-case-structure
default:
Serial.println("switch-case-variable did not have any valid value");
Serial.println("setting switch-case-variable to value of symbol CheckMode ");
MyStateVariable = CheckMode;
break;
best regards Stefan
Sorry, no luck..
Below is the changes code (now formatted usint Cntrl + T)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;
int setvalue;
int actualvalue;
int timer;
int duration;
int timermode;
int ontime = 5000;
const byte CheckMode = 10;
const byte CheckValue = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;
byte MyStateVariable;
void setup () {
Serial.begin(115200);
WiFiManager wifiManager;
wifiManager.autoConnect("Device");
Serial.println("Connected to WiFi");
pinMode(device1_pin, OUTPUT);
pinMode(device2_pin, OUTPUT);
pinMode(device3_pin, OUTPUT);
pinMode(device4_pin, OUTPUT);
MyStateVariable = CheckMode;
}
void loop() {
unsigned long currentMillis = millis();
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
switch (MyStateVariable)
{
default:
Serial.println("switch-case-variable did not have any valid value");
Serial.println("setting switch-case-variable to value of symbol CheckMode ");
MyStateVariable = CheckMode;
break;
case CheckMode:
// code
if (timer == 0) {
MyStateVariable = CheckValue;
}
if (timer == 1) {
MyStateVariable = OnOffTiming;
}
break;
case CheckValue:
if (setvalue > actualvalue) {
MyStateVariable = AutoModeSwitchOn;
}
break;
case AutoModeSwitchOn:
digitalWrite(device1_pin, HIGH);
Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
SwitchOnTimeStamp = currentMillis;
MyStateVariable = WaitForAutoModeOnTimeToEnd;
break;
case WaitForAutoModeOnTimeToEnd:
if (currentMillis - SwitchOnTimeStamp >= ontime) {
Serial.println("Switch Turned Off After Set Duration in AUTO mode");
MyStateVariable = CheckMode;
}
break;
case OnOffTiming:
digitalWrite(device1_pin, HIGH);
TimerModeOnTimeStamp = currentMillis;
Serial.println("Switch ON in TIMER mode");
MyStateVariable = WaitForTimerONTime_End;
break;
case WaitForTimerONTime_End:
if (currentMillis - TimerModeOnTimeStamp > duration) {
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = Timer_Start_OFF_Period;
}
break;
case Timer_Start_OFF_Period:
OFFPeriodStartsTimestamp = currentMillis;
MyStateVariable = WaitForTimerOFF_PeriodToEnd;
break;
case WaitForTimerOFF_PeriodToEnd:
if (currentMillis - OFFPeriodStartsTimestamp > timer) {
Serial.println("Switch ON in TIMER mode After Set Timer Period");
MyStateVariable = CheckMode;
}
}
}
All what I see in my Serial Monitor is below
12:50:44.593 -> Set Moisture=23
12:50:44.802 -> Actual Moisture=20
12:50:44.970 -> Set Timer=15
12:50:45.210 -> Set Duration=10
12:50:45.401 -> Timer Mode=1
if duration has value 10 this means 10 milliseconds = 0,01 seconds
if timer has value 15 this means 15 milliseconds = 0,015 seconds
I guess you mean 10 seconds = 10000 milliseconds and 15 seconds = 15000 milliseconds
I added some helper-functions to your code
making the onboard-led blink and a function that shows the state every 0,5 seconds with its symbol-name
this will it make much easier to track what your code is really doing.
It is intended in this way Your loop is running through 10-thousands times per second the ShowActualState-function shows the state everay 0,5 seconds
this means transitional states that do one action and then switch MyStateVariable to the next state will not show up.
But these states have their own serial.prints
If they shall show up you can slow-down the loop by uncommenting
the comment delay(500);
I don't have your libraries installed so I'm unable to test if this compiles
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;
int setvalue;
int actualvalue;
int timer;
int duration;
int timermode;
int ontime = 5000;
const byte CheckMode = 10;
const byte CheckValue = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;
byte MyStateVariable;
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
const byte = 10;
const byte = 15;
const byte = 20;
const byte = 30;
const byte = 35;
const byte = 40;
const byte = 45;
const byte = 50;
const byte = 55;
const byte = 60;
void ShowActualState() {
Serial.print("MyStateVariable is on value: ");
if (MyStateVariable == CheckMode) {
Serial.print("CheckMode (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == CheckValue) {
Serial.print("CheckValue (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == AutoModeSwitchOn) {
Serial.print("AutoModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == TimerModeSwitchOn) {
Serial.print("TimerModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == OnOffTiming) {
Serial.print("OnOffTiming (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == switchOn) {
Serial.print("switchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForAutoModeOnTimeToEnd) {
Serial.print("WaitForAutoModeOnTimeToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerONTime_End) {
Serial.print("WaitForTimerONTime_End (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == Timer_Start_OFF_Period) {
Serial.print("Timer_Start_OFF_Period (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerOFF_PeriodToEnd) {
Serial.print("WaitForTimerOFF_PeriodToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
}
void setup () {
Serial.begin(115200);
WiFiManager wifiManager;
wifiManager.autoConnect("Device");
Serial.println("Connected to WiFi");
pinMode(device1_pin, OUTPUT);
pinMode(device2_pin, OUTPUT);
pinMode(device3_pin, OUTPUT);
pinMode(device4_pin, OUTPUT);
MyStateVariable = CheckMode;
}
void loop() {
// visual feedback with the help of the onboard-led if loop is running
BlinkHeartBeatLED(OnBoard_LED,500);
unsigned long currentMillis = millis();
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http; //Declare an object of class HTTPClient
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http:/...."); //Specify request destination
int httpCode1 = http.GET(); //Send the request
if (httpCode1 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
setvalue = payload.toInt();
Serial.print("Set Moisture=");
Serial.print(setvalue); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode2 = http.GET(); //Send the request
if (httpCode2 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
actualvalue = payload.toInt();
Serial.print("Actual Moisture=");
Serial.print(actualvalue); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode3 = http.GET(); //Send the request
if (httpCode3 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
timer = payload.toInt();
Serial.print("Set Timer=");
Serial.print(timer); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode4 = http.GET(); //Send the request
if (httpCode4 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
duration = payload.toInt();
Serial.print("Set Duration=");
Serial.print(duration); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode5 = http.GET(); //Send the request
if (httpCode5 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
timermode = payload.toInt();
Serial.print("Timer Mode=");
Serial.print(timermode); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println("-------------------------------------------------------------------------------------");
http.end(); //Close connection
}
// alternatively use delay(500);
if ( TimePeriodIsOver(MyTestTimer,500) ) {
ShowActualState();
}
switch (MyStateVariable) {
case CheckMode:
if (timer == 0) {
MyStateVariable = CheckValue;
}
if (timer == 1) {
MyStateVariable = OnOffTiming;
}
break;
case CheckValue:
if (setvalue > actualvalue) {
MyStateVariable = AutoModeSwitchOn;
}
break;
case AutoModeSwitchOn:
digitalWrite(device1_pin, HIGH);
Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
SwitchOnTimeStamp = currentMillis;
MyStateVariable = WaitForAutoModeOnTimeToEnd;
break;
case WaitForAutoModeOnTimeToEnd:
if (currentMillis - SwitchOnTimeStamp >= ontime) {
Serial.println("Switch Turned Off After Set Duration in AUTO mode");
MyStateVariable = CheckMode;
}
break;
case OnOffTiming:
digitalWrite(device1_pin, HIGH);
TimerModeOnTimeStamp = currentMillis;
Serial.println("Switch ON in TIMER mode");
MyStateVariable = WaitForTimerONTime_End;
break;
case WaitForTimerONTime_End:
if (currentMillis - TimerModeOnTimeStamp > duration) {
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = Timer_Start_OFF_Period;
}
break;
case Timer_Start_OFF_Period:
OFFPeriodStartsTimestamp = currentMillis;
MyStateVariable = WaitForTimerOFF_PeriodToEnd;
break;
case WaitForTimerOFF_PeriodToEnd:
if (currentMillis - OFFPeriodStartsTimestamp > timer) {
Serial.println("Switch ON in TIMER mode After Set Timer Period");
MyStateVariable = CheckMode;
}
default:
Serial.println("switch-case-variable did not have any valid value");
Serial.println("setting switch-case-variable to value of symbol CheckMode ");
MyStateVariable = CheckMode;
break;
}
}
best regards Stefan
additionally
keep the serial monito open.
You can upload with the serial monitor opened.
Start the upload and switch to the serial monitor
The serial monitor has to be opened before starting the upload
the serial monitor just gets grayed out.
click on clear output while upload is in progress
and then watch all the output
to see really everything
If you want to see it again press the resetbutton on your ESP8266
best regards Stefan
I am getting the below error while compiling
exit status 1
expected unqualified-id before '=' token
In the line
const byte = 60;
Sorry my bad. forgot to delete some lines I used for cut & paste.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;
int setvalue;
int actualvalue;
int timer;
int duration;
int timermode;
int ontime = 5000;
const byte CheckMode = 10;
const byte CheckValue = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;
byte MyStateVariable;
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
void ShowActualState() {
Serial.print("MyStateVariable is on value: ");
if (MyStateVariable == CheckMode) {
Serial.print("CheckMode (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == CheckValue) {
Serial.print("CheckValue (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == AutoModeSwitchOn) {
Serial.print("AutoModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == TimerModeSwitchOn) {
Serial.print("TimerModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == OnOffTiming) {
Serial.print("OnOffTiming (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == switchOn) {
Serial.print("switchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForAutoModeOnTimeToEnd) {
Serial.print("WaitForAutoModeOnTimeToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerONTime_End) {
Serial.print("WaitForTimerONTime_End (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == Timer_Start_OFF_Period) {
Serial.print("Timer_Start_OFF_Period (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerOFF_PeriodToEnd) {
Serial.print("WaitForTimerOFF_PeriodToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
}
void setup () {
Serial.begin(115200);
WiFiManager wifiManager;
wifiManager.autoConnect("Device");
Serial.println("Connected to WiFi");
pinMode(device1_pin, OUTPUT);
pinMode(device2_pin, OUTPUT);
pinMode(device3_pin, OUTPUT);
pinMode(device4_pin, OUTPUT);
MyStateVariable = CheckMode;
}
void loop() {
// visual feedback with the help of the onboard-led if loop is running
BlinkHeartBeatLED(OnBoard_LED,500);
unsigned long currentMillis = millis();
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http; //Declare an object of class HTTPClient
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http:/...."); //Specify request destination
int httpCode1 = http.GET(); //Send the request
if (httpCode1 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
setvalue = payload.toInt();
Serial.print("Set Moisture=");
Serial.print(setvalue); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode2 = http.GET(); //Send the request
if (httpCode2 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
actualvalue = payload.toInt();
Serial.print("Actual Moisture=");
Serial.print(actualvalue); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode3 = http.GET(); //Send the request
if (httpCode3 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
timer = payload.toInt();
Serial.print("Set Timer=");
Serial.print(timer); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode4 = http.GET(); //Send the request
if (httpCode4 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
duration = payload.toInt();
Serial.print("Set Duration=");
Serial.print(duration); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://...."); //Specify request destination
int httpCode5 = http.GET(); //Send the request
if (httpCode5 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
timermode = payload.toInt();
Serial.print("Timer Mode=");
Serial.print(timermode); //Print the response payload
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.println("-------------------------------------------------------------------------------------");
http.end(); //Close connection
}
// alternatively use delay(500);
if ( TimePeriodIsOver(MyTestTimer,500) ) {
ShowActualState();
}
switch (MyStateVariable) {
case CheckMode:
if (timer == 0) {
MyStateVariable = CheckValue;
}
if (timer == 1) {
MyStateVariable = OnOffTiming;
}
break;
case CheckValue:
if (setvalue > actualvalue) {
MyStateVariable = AutoModeSwitchOn;
}
break;
case AutoModeSwitchOn:
digitalWrite(device1_pin, HIGH);
Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
SwitchOnTimeStamp = currentMillis;
MyStateVariable = WaitForAutoModeOnTimeToEnd;
break;
case WaitForAutoModeOnTimeToEnd:
if (currentMillis - SwitchOnTimeStamp >= ontime) {
Serial.println("Switch Turned Off After Set Duration in AUTO mode");
MyStateVariable = CheckMode;
}
break;
case OnOffTiming:
digitalWrite(device1_pin, HIGH);
TimerModeOnTimeStamp = currentMillis;
Serial.println("Switch ON in TIMER mode");
MyStateVariable = WaitForTimerONTime_End;
break;
case WaitForTimerONTime_End:
if (currentMillis - TimerModeOnTimeStamp > duration) {
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = Timer_Start_OFF_Period;
}
break;
case Timer_Start_OFF_Period:
OFFPeriodStartsTimestamp = currentMillis;
MyStateVariable = WaitForTimerOFF_PeriodToEnd;
break;
case WaitForTimerOFF_PeriodToEnd:
if (currentMillis - OFFPeriodStartsTimestamp > timer) {
Serial.println("Switch ON in TIMER mode After Set Timer Period");
MyStateVariable = CheckMode;
}
default:
Serial.println("switch-case-variable did not have any valid value");
Serial.println("setting switch-case-variable to value of symbol CheckMode ");
MyStateVariable = CheckMode;
break;
}
}
Below is what my serial monitor outputs. I updated the values in the website so it returns 15000 when I enter 15 in the website.
14:03:03.789 -> MyStateVariable is on value: CheckMode (10)
14:03:04.150 -> Set Moisture=23
14:03:04.348 -> Actual Moisture=20
14:03:04.548 -> Set Timer=15000
14:03:04.739 -> Set Duration=10000
14:03:04.940 -> Timer Mode=1
14:03:04.940 -> -------------------------------------------------------------------------------------
14:03:04.940 -> MyStateVariable is on value: CheckMode (10)
14:03:05.310 -> Set Moisture=23
14:03:05.509 -> Actual Moisture=20
14:03:05.709 -> Set Timer=15000
14:03:05.909 -> Set Duration=10000
14:03:06.189 -> Timer Mode=1
14:03:06.189 -> ------------------------------------------------------------
What is the exact name of your WifiManager?
If you lookup the library-manager which one is installed?
When I use the searchfunction of the Arduino-IDE with keyword "Wifimanager"
I get about 10 entries matching the name of the library "WiFiManager".
That is one downside of opensource without quality-management
using too common names to identify. I suggest that each and everybody adds at least 4 letters to his library-name that try to be globally-unique
best regards Stefan
So start analysing why does your code stay inside state CheckMode ?
My bad.. its atypo.. recitifed that. I typed "timer" instead of "timermode"
Now it is as below..
Trying the troubleshoot the below
14:11:33.711 -> MyStateVariable is on value: WaitForTimerONTime_End (50)
14:11:34.122 -> Set Moisture=23
14:11:34.352 -> Actual Moisture=20
14:11:34.552 -> Set Timer=15000
14:11:34.752 -> Set Duration=10000
14:11:34.913 -> Timer Mode=1
your variablename "timer" is way too generalised to explain what the purpose of this variable is. And this leads to a wrong usage of the variable.
and for finding the places where variable "timer" is used has a lot of wrong
hits like
int timermode;
WaitForTimerOFF_PeriodToEnd
etc. etc. etc.
So think about what the exact purpose of variable "timer" is
and find a name that uses between 10 and 20 letters that do selfexplain this purpose.
best regards Stefan
I use doubleclick Ctrl-C on such longer names to quickly get the name into the clipboard and then paste it where I have to write it again.
This ensures right spelling of each letter and is quick
best regards Stefan
all variables that are used in if-condition with millis() or variables of type unsigned long should by of the same type unsigned long too.
variables that get assigned values from millis() must be of type unsigend long
In an if-condition like
if (currentMillis - TimerModeOnTimeStamp > duration) {
all variables should be of type unsigned long
this means change
int timer;
int duration;
int ontime = 5000;
to
unsigned long timer;
unsigned long duration;
unsigned long ontime = 5000;
as a minimum.
But what is "duration" ? duration of what?
what is "ontime" what is "ON"?
same thing with
int setvalue;
int actualvalue;
what "value"? This "value" has a meaning.
And it is not the number of Whisky-bottles dump has drunk after loosing ;-))
And to make your code easier to understand
change the variable names to something that is much more selfdescriptive
there are two ways of investing time in finishing a project
1st way:
trying to save time by quick and dirty programming using quick & dirty names for everything leaving out testing.
and then loosing the saved time on debugging of a huge area of possible reasons caused by the quick & dirty programming at the start
2nd way: investing time to carefully thinking about selfexplaining names
doing debugging step by step with - most of the time - finding bugs quickly because the area where the bug can be is much much smaller.
best regards Stefan
Hello,
I cleaned up the code as per your recommendation. Now it looks cleaner and more understandable.
I uploaded the code and the functions are kind of working.
BUT, my initial problem is still not resolved.
I mean, the issue was that, when I change to Auto mode when the Timer period is still running, it waits till that period ends before switching to Auto.
Now I ran the code in my device with Timer duration of 30 seconds. After around 10 seconds, I changed the mode to Auto. But it waited for the 30 seconds to complete before changing to Auto mode.
Below is the code after the cleanup which I did
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;
int SetValueInWebPage;
int ActualSensorValueInWebPage;
int timermode;
unsigned long TimerPeriodSetInWebsite;
unsigned long SwitchOnDurationInTimerMode;
unsigned long SwitchOnDurationInAutoMode = 5000;
const byte CheckMode = 10;
const byte CheckValue = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
const byte WaitForTimerDurationToEnd = 65;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;
byte MyStateVariable;
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
void ShowActualState() {
Serial.print("MyStateVariable is on value: ");
if (MyStateVariable == CheckMode) {
Serial.print("CheckMode (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == CheckValue) {
Serial.print("CheckValue (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == AutoModeSwitchOn) {
Serial.print("AutoModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == TimerModeSwitchOn) {
Serial.print("TimerModeSwitchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == OnOffTiming) {
Serial.print("OnOffTiming (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == switchOn) {
Serial.print("switchOn (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForAutoModeOnTimeToEnd) {
Serial.print("WaitForAutoModeOnTimeToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerONTime_End) {
Serial.print("WaitForTimerONTime_End (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == Timer_Start_OFF_Period) {
Serial.print("Timer_Start_OFF_Period (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForTimerOFF_PeriodToEnd) {
Serial.print("WaitForTimerOFF_PeriodToEnd (");
Serial.print(MyStateVariable);
Serial.println(")");
}
}
void setup () {
Serial.begin(115200);
WiFiManager wifiManager;
wifiManager.autoConnect("Device");
Serial.println("Connected to WiFi");
pinMode(device1_pin, OUTPUT);
pinMode(device2_pin, OUTPUT);
pinMode(device3_pin, OUTPUT);
pinMode(device4_pin, OUTPUT);
MyStateVariable = CheckMode;
}
void loop() {
// visual feedback with the help of the onboard-led if loop is running
BlinkHeartBeatLED(OnBoard_LED, 500);
unsigned long currentMillis = millis();
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
// alternatively use delay(500);
if ( TimePeriodIsOver(MyTestTimer, 500) ) {
ShowActualState();
}
switch (MyStateVariable) {
case CheckMode:
if (timermode == 0) {
MyStateVariable = CheckValue;
}
if (timermode == 1) {
MyStateVariable = OnOffTiming;
}
break;
case CheckValue:
if (SetValueInWebPage > ActualSensorValueInWebPage) {
MyStateVariable = AutoModeSwitchOn;
}
break;
case AutoModeSwitchOn:
digitalWrite(device1_pin, HIGH);
Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
SwitchOnTimeStamp = currentMillis;
MyStateVariable = WaitForAutoModeOnTimeToEnd;
break;
case WaitForAutoModeOnTimeToEnd:
if (currentMillis - SwitchOnTimeStamp >= SwitchOnDurationInAutoMode) {
digitalWrite(device1_pin, LOW);
Serial.println("Switch Turned Off After Set Duration in AUTO mode");
MyStateVariable = CheckMode;
}
break;
case OnOffTiming:
digitalWrite(device1_pin, HIGH);
TimerModeOnTimeStamp = currentMillis;
Serial.println("Switch ON in TIMER mode");
MyStateVariable = WaitForTimerONTime_End;
break;
case WaitForTimerONTime_End:
if (currentMillis - TimerModeOnTimeStamp >= SwitchOnDurationInTimerMode) {
digitalWrite(device1_pin, LOW);
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = Timer_Start_OFF_Period;
}
break;
case Timer_Start_OFF_Period:
OFFPeriodStartsTimestamp = currentMillis;
MyStateVariable = WaitForTimerOFF_PeriodToEnd;
break;
case WaitForTimerOFF_PeriodToEnd:
if (currentMillis - OFFPeriodStartsTimestamp >= TimerPeriodSetInWebsite) {
digitalWrite(device1_pin, HIGH);
Serial.println("Switch ON in TIMER mode After Set Timer Period");
MyStateVariable = WaitForTimerDurationToEnd;
}
break;
case WaitForTimerDurationToEnd:
if (currentMillis - TimerModeOnTimeStamp >= SwitchOnDurationInTimerMode) {
digitalWrite(device1_pin, LOW);
Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
MyStateVariable = CheckMode;
}
break;
default:
Serial.println("switch-case-variable did not have any valid value");
Serial.println("setting switch-case-variable to value of symbol CheckMode ");
MyStateVariable = CheckMode;
break;
}
}
OK. So if your code is still in state
WaitForTimerOFF_PeriodToEnd
or in state WaitForTimerONTime_End
you add an if-condition that checks if mode was changed to Auto
and if this condition results in true
you change the state-variable.
As the timing is done non-blocking
your loop runs at high speed.
The state WaitForTimerOFF_PeriodToEnd is entered thousands of times
each time checking
if (currentMillis - TimerModeOnTimeStamp >= SwitchOnDurationInTimerMode) {
and only when MyStateVariable changes to a new state the code inside this state gets executed
So you add
if (timermode == 0) {
MyStateVariable = CheckValue;
}
inside the
case WaitForTimerONTime_End:
and inside the
case WaitForTimerOFF_PeriodToEnd:
If you want to have this behaviour from switching from automode to timermode too you add the appropriate conditions their too
Your code is a very good example how state-machines "simplify" things
compared to add more and more if-conditions and boolean variables
"simplifly" in double-hyphens as this programming-technique is somehow advanced.
best regards Stefan
Voilà !!
That did the job!!
I can't believe this and whatever you taught me is priceless!!
Thanks a lot for your time and efforts..
I am left out with just one concern, which of course is not about the code itself.
In fact there are lots of request going all the time to the website to fetch data. But its fine..
I enjoy this kind of supporting.
If you want to reduce the number of requests to the website think about what reaction-time to switch any parameter is still fast enough that you say yes it is fast enough.
And then you write another timer where you can use my TimePeriodIsOver-function
unsigned long MyHTTPrequestTimer = 0; // variables MUST be of type unsigned long
//lets say your the interval for a new request shall be 3 seconds
if ( TimePeriodIsOver(MyHTTPrequestTimer, 3000) ) {
// your requesting code here inside the if-condition
}
alternatively
and to give your code some more structure
put all the lines that do the requesting inside its own function
void MakeHTTP_Request() {
// your requesting code here
}
and then the code looks like
if ( TimePeriodIsOver(MyHTTPrequestTimer, 3000) ) {
MakeHTTP_Request();
}
best regards Stefan
Wow.. Thanks for that tip..

Hello,
Sorry to bother you once again..
I tried to use the state-machines method you told me for one of my sensors, which uploads data to my website.
There is a CAL switch online, and I am looking to send the readings every 2 seconds when the switch is ON and send every 60 seconds when the switch is OFF. Below is the code I wrote. But it is not changing the time irrespective of the switch position. Could you please have a look and advise?
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
const int numReadings = 20;
//static const uint8_t D5 = 14;
const char* host = "......";
const int sensor_pin = A0; /* Connect Soil moisture analog sensor pin to A0 of NodeMCU */
//int device1_pin=D5;
//int value ;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int inputPin = A0;
int cal_status;
int cal_low;
int cal_high;
unsigned long cal_on = 2000;
unsigned long cal_off = 60000;
unsigned long time_now = 0;
unsigned long MyHTTPrequestTimer = 0;
const byte CheckCalibrationMode = 10;
const byte CalibrationModeON = 20;
const byte CalibrationModeOFF = 30;
const byte WaitForCalONTimeToEnd = 40;
const byte WaitForCalOFFTimeToEnd = 50;
unsigned long CalOnTimeStamp;
unsigned long CalOffTimeStamp;
byte MyStateVariable;
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0;
void ShowActualState() {
Serial.print("MyStateVariable is on value: ");
if (MyStateVariable == CheckCalibrationMode) {
Serial.print("Calibration Mode (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == CalibrationModeON) {
Serial.print("Calibration is ON (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == CalibrationModeOFF) {
Serial.print("Calibration is OFF (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForCalONTimeToEnd) {
Serial.print("Calibration ON Wait Time Over (");
Serial.print(MyStateVariable);
Serial.println(")");
}
if (MyStateVariable == WaitForCalOFFTimeToEnd) {
Serial.print("Calibration OFF Wait Time Over (");
Serial.print(MyStateVariable);
Serial.println(")");
}
}
void setup() {
// pinMode(device1_pin,OUTPUT);
Serial.begin(9600); /* Define baud rate for serial communication */
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
WiFiManager wifiManager;
if (WiFi.SSID() != "") wifiManager.setConfigPortalTimeout(60); //If no access point name has been previously entered disable timeout. Else timeout 60s
Serial.print("Connecting to ");
wifiManager.autoConnect("Device");
Serial.print("."); //UNCOMMENT FOR TESTING IF REQUIRED
Serial.println("connected..."); //UNCOMMENT FOR TESTING IF REQUIRED
MyStateVariable = CheckCalibrationMode;
}
void loop() {
unsigned long currentMillis = millis();
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(inputPin);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;
// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}
// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
//Serial.println(average);
if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
HTTPClient http; //Declare an object of class HTTPClient
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://......."); //Specify request destination
int httpCode1 = http.GET(); //Send the request
if (httpCode1 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
cal_status = payload.toInt();
Serial.println();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://....."); //Specify request destination
int httpCode2 = http.GET(); //Send the request
if (httpCode2 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
cal_low = payload.toInt();
Serial.print("Cal Low Value=");
Serial.print(cal_low); //Print the response payload
Serial.println();
}/////////////////////////////////////////////////////////////////////////////////////////////////////////////
http.begin("http://....."); //Specify request destination
int httpCode3 = http.GET(); //Send the request
if (httpCode3 > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
cal_high = payload.toInt();
Serial.print("Cal High Value=");
Serial.print(cal_high); //Print the response payload
Serial.println();
}
//if (cal_low == cal_high) { //if both values are equal, there is stack error in serial monitor
//cal_low = cal_high + 1;
//}
//digitalWrite(device1_pin,HIGH);
//delay (500);
int percentageHumididy = map(average, cal_low, cal_high, 0, 100);
Serial.print("Moisture Percentage = ");
Serial.print(percentageHumididy);
Serial.println("%");
Serial.print("Raw Sensor value = ");
Serial.println(average);
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
ESP.reset();
return;
}
String url = ".....";
client.print(String("GET ") + url + " HTTP / 1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
//delay(500);
while (client.available()) {
String line = client.readStringUntil('\r');
//Serial.print(line);
}
//digitalWrite(device1_pin,LOW);
if ( TimePeriodIsOver(MyTestTimer, 500) ) {
ShowActualState();
}
switch (MyStateVariable) {
case CheckCalibrationMode:
if (cal_status == 1) {
MyStateVariable = CalibrationModeON;
}
if (cal_status == 0) {
MyStateVariable = CalibrationModeOFF;
}
break;
case CalibrationModeON:
Serial.println("Calibration Mode is ON");
CalOnTimeStamp = currentMillis;
MyStateVariable = WaitForCalONTimeToEnd;
break;
case WaitForCalONTimeToEnd:
if (currentMillis - CalOnTimeStamp >= cal_on) {
Serial.println("Cal ON Wait Time Is Over");
MyStateVariable = CheckCalibrationMode;
}
break;
case CalibrationModeOFF:
Serial.println("Calibration Mode is OFF");
CalOffTimeStamp = currentMillis;
MyStateVariable = WaitForCalOFFTimeToEnd;
break;
case WaitForCalOFFTimeToEnd:
if (currentMillis - CalOffTimeStamp >= cal_off) {
Serial.println("Cal OFF Wait Time Is Over");
MyStateVariable = CheckCalibrationMode;
}
break;
}
}
}