- Always start your projects by making a proposed schematic.
example:
-
As mentioned, tabs are an important tool to keep code organized, however, they make it more difficult to share code with us.
-
I start with a pre formatted skeleton sketch.
//================================================^================================================
//
// URL
//
// Name
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 24/05/25 Started writing this sketch
//
//
//
//#include <Wire.h>
//================================================
#define LEDon HIGH //PIN---[220R]---A[LED]K---GND
#define LEDoff LOW
#define PRESSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define RELEASED HIGH
#define CLOSED LOW //+5V---[Internal 50k]---PIN---[Switch]---GND
#define OPENED HIGH
//================================================^================================================
// millis() / micros() B a s e d T I M E R S
//================================================^================================================
//To keep the sketch tidy, you can put this structure in a different tab in the IDE
//
//These TIMER objects are non-blocking
struct makeTIMER
{
#define MILLIS 1
#define MICROS 1000 //we can use this value to divide into a variable to get milliseconds
#define ENABLED true
#define DISABLED false
#define YES true
#define NO false
#define STILLtiming 0
#define EXPIRED 1
#define TIMERdisabled 2
//these are the bare minimum "members" needed when defining a TIMER
int TimerType; //what kind of TIMER is this? MILLIS/MICROS
unsigned long Time; //when the TIMER started
unsigned long Interval; //delay time which we are looking for
bool TimerFlag; //is the TIMER enabled ? ENABLED/DISABLED
bool Restart; //do we restart this TIMER ? YES/NO
//================================================
//condition returned: STILLtiming (0), EXPIRED (1) or TIMERdisabled (2)
//function to check the state of our TIMER ex: if(myTimer.checkTIMER() == EXPIRED);
byte checkTIMER()
{
//========================
//is this TIMER enabled ?
if (TimerFlag == ENABLED)
{
//========================
//has this TIMER expired ?
if (getTime() - Time >= Interval)
{
//========================
//should this TIMER restart again?
if (Restart == YES)
{
//restart this TIMER
Time = getTime();
}
//this TIMER has expired
return EXPIRED;
}
//========================
else
{
//this TIMER has not expired
return STILLtiming;
}
} //END of if (TimerFlag == ENABLED)
//========================
else
{
//this TIMER is disabled
return TIMERdisabled;
}
} //END of checkTime()
//================================================
//function to enable and restart this TIMER ex: myTimer.enableRestartTIMER();
void enableRestartTIMER()
{
TimerFlag = ENABLED;
//restart this TIMER
Time = getTime();
} //END of enableRestartTIMER()
//================================================
//function to disable this TIMER ex: myTimer.disableTIMER();
void disableTIMER()
{
TimerFlag = DISABLED;
} //END of disableTIMER()
//================================================
//function to restart this TIMER ex: myTimer.restartTIMER();
void restartTIMER()
{
Time = getTime();
} //END of restartTIMER()
//================================================
//function to force this TIMER to expire ex: myTimer.expireTimer();
void expireTimer()
{
//force this TIMER to expire
Time = getTime() - Interval;
} //END of expireTimer()
//================================================
//function to set the Interval for this TIMER ex: myTimer.setInterval(100);
void setInterval(unsigned long value)
{
//set the Interval
Interval = value;
} //END of setInterval()
//================================================
//function to return the current time
unsigned long getTime()
{
//return the time i.e. millis() or micros()
//========================
if (TimerType == MILLIS)
{
return millis();
}
//========================
else
{
return micros();
}
} //END of getTime()
}; //END of struct makeTIMER
// D e f i n e a l l a r e T I M E R S
//================================================^================================================
/*example
//========================
makeTIMER toggleLED =
{
MILLIS/MICROS, 0, 500ul, ENABLED/DISABLED, YES/NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
Function examples:
toggleLED.checkTIMER();
toggleLED.enableRestartTIMER();
toggleLED.disableTIMER();
toggleLED.expireTimer();
toggleLED.setInterval(100ul);
*/
//========================
makeTIMER heartbeatTIMER =
{
MILLIS, 0, 500ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER switchesTIMER =
{
MILLIS, 0, 5ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER machineTIMER =
{
MICROS, 0, 1000ul, ENABLED, YES //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
//========================
makeTIMER commonTIMER =
{
MILLIS, 0, 1000ul, DISABLED, NO //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};
// S t a t e M a c h i n e
//================================================^================================================
//the States in our machine (use better names that mean something to you)
enum STATES : byte
{
STARTUP, STATE1, STATE2, STATE3, STATE4, FINISHED
};
STATES mState = STARTUP;
// G P I O s
//================================================^================================================
//
//structure to define input objects
struct makeInput
{
const byte pin; //the digital input pin number
unsigned long switchTime; //the time the switch was closed
byte lastState; //the state the input was last in
byte counter; //a counter used to valididate a switch change in state
}; //END of struct makeInput
//Digital Inputs
//===================================
//define this input which is connected to a PB switch
makeInput mySwitch =
{
2, 0, OPENED, 0 //pin, switchTime, lastState, counter
};
byte filter = 10;
//TIMER "switches" runs every 5ms.
//5ms * 10 = 50ms is needed to validate a switch change in state.
//A switch change in state is valid "only after" 10 identical changes is detected.
//used to filter out EMI noise in the system
//OUTPUTS
//===================================
const byte testLED = 12;
const byte heartbeatLED = 13;
//VARIABLES
//===================================
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
//Serial.begin(9600);
//use INPUT_PULLUP so the pin dose not float which can cause faulty readings
pinMode(mySwitch.pin, INPUT_PULLUP);
pinMode(heartbeatLED, OUTPUT);
digitalWrite(testLED, LEDoff);
pinMode(testLED, OUTPUT);
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//======================================================================== T I M E R heartbeatLED
//is it time to toggle the heartbeat LED ?
if (heartbeatTIMER.checkTIMER() == EXPIRED)
{
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R switches
//is it time to check our switches ?
if (switchesTIMER.checkTIMER() == EXPIRED)
{
checkSwitches();
}
//======================================================================== T I M E R machine
//is it time to service our State Machine ?
if (machineTIMER.checkTIMER() == EXPIRED)
{
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
}
break;
//========================
case STATE1:
{
//condition returned: STILLtiming, EXPIRED or TIMERdisabled
if (commonTIMER.checkTIMER() == EXPIRED)
{
digitalWrite(testLED, LEDoff);
//we are finished with this TIMER
commonTIMER.disableTIMER();
//next state
mState = STATE2;
}
}
break;
//========================
case STATE2:
{
//Do something
}
break;
//========================
case STATE3:
{
//Do something
}
break;
//========================
case STATE4:
{
//Do something
}
break;
//========================
case FINISHED:
{
//Do something
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte pinState;
//======================================================================== mySwitch.pin
pinState = digitalRead(mySwitch.pin);
//===================================
//has this switch changed state ?
if (mySwitch.lastState != pinState)
{
mySwitch.counter++;
//is this change in state stable ?
if (mySwitch.counter >= filter)
{
//get ready for the next sequence
mySwitch.counter = 0;
//update to this new state
mySwitch.lastState = pinState;
//========================
//did this switch go closed ?
if (pinState == CLOSED)
{
//the time this switch closed
mySwitch.switchTime = millis();
digitalWrite(testLED, LEDon);
//set interval to 2 seconds
commonTIMER.setInterval(2000ul);
commonTIMER.enableRestartTIMER();
//next state
mState = STATE1;
}
//========================
//did this switch go opened ?
else if (pinState == OPENED)
{
Serial.print("The time the switch was closed = ");
Serial.println(millis() - mySwitch.switchTime);
}
}
}
//===================================
//a valid switch change has not been confirmed
else
{
mySwitch.counter = 0;
}
//END of mySwitch.pin
//======================================================================== Next Switch
} //END of checkSwitches()
//================================================^================================================