Here comes a non-blocking version anyway
I have changed baudrate to 115200 which is the new standard-baudrate
the main thing is to have 4 different modes of operation
const byte sm_Idling = 0;
const byte sm_Laser10ms_On = 1;
const byte sm_Laser90ms_Off = 2;
const byte sm_Wait1SecOff = 3;
idling waiting for
if (switchState_Feeder == HIGH)
then starts the laser pulsing on/off/on/off pause 1 second
repeat this until 60 seconds have passed by
This means void loop is as short as
void loop() {
LaserPulseStateMachine();
}
because everything is happening inside function LaserPulseStateMachine()
The code has macros for serial debug-output which must be on top of the file to make it work
I gave your IO-pins self-explaining names
This code uses my version of a non-blocking timer-function which I claim is more intuitive as the standard blink without understanding example of the arduino-IDE
non-blocking timing allows that the code is always responsive to user-input as
stopping the pulsing at any time with another button or updating a display
etc.
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope
#define dbgi(myFixedText, variableName,timeInterval) \
do { \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
} while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
// print only once when value has changed
#define dbgc(myFixedText, variableName) \
do { \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
} while (false);
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
byte switchState_Feeder = 0;
byte switchState_Pellet = 0;
long sessiontime;
long sessiontimestart;
long sessiontimestop;
long totalsessiontime;
unsigned long pulseTimer;
unsigned long mySessionTimer;
unsigned long Active1SecTimer;
unsigned long Pause1SecTimer;
const unsigned long LaserOnTime = 10;
const unsigned long LaserOffTime = 90;
const byte sm_Idling = 0;
const byte sm_Laser10ms_On = 1;
const byte sm_Laser90ms_Off = 2;
const byte sm_Wait1SecOff = 3;
byte myState = sm_Idling ;
long Millis_start = 0;
long Millis_stop = 0;
const byte Feeder_input_Pin = 10;
const byte Pellet_input_Pin = 6;
const byte Laser_output_Pin = 3;
const byte LED_output_Pin = 2;
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void setup() {
pinMode(Feeder_input_Pin, INPUT);
pinMode(Pellet_input_Pin, INPUT);
pinMode(Laser_output_Pin, OUTPUT);
pinMode(LED_output_Pin, OUTPUT);
digitalWrite(Laser_output_Pin, LOW);
sessiontime = 60000;
Serial.begin(115200);
PrintFileNameDateTime();
digitalWrite(LED_output_Pin, HIGH);
delay(2000);
digitalWrite(LED_output_Pin, LOW);
}
void LaserPulseStateMachine() {
dbgc("L:", myState);
switch (myState) {
case sm_Idling:
switchState_Feeder = digitalRead(Feeder_input_Pin);
dbgi("idling", switchState_Feeder, 1000);
if (switchState_Feeder == HIGH) {
//digitalWrite(LED_output_Pin, HIGH);
mySessionTimer = millis(); // store snapshot of time into timer-variable
Active1SecTimer = millis(); // store snapshot of time into timer-variable
sessiontimestart = millis();
myState = sm_Laser10ms_On;
pulseTimer = millis(); // store snapshot of time into timer-variable
}
break; // immidiately jump down to End-of-Switch
case sm_Laser10ms_On:
digitalWrite(Laser_output_Pin, HIGH); // 10hz laser ON for 1 second according to loop
if ( TimePeriodIsOver(pulseTimer, LaserOnTime) ) {
pulseTimer = millis(); // store snapshot of time into timer-variable
dbg("jump to Off", 0);
myState = sm_Laser90ms_Off;
}
// check if 60 seconds have passed by
if (TimePeriodIsOver(mySessionTimer, sessiontime) ) {
digitalWrite(Laser_output_Pin, LOW);
sessiontimestop = millis();
totalsessiontime = sessiontimestop - sessiontimestart;
Serial.print("Total Session Time...");
Serial.println(totalsessiontime);
myState = sm_Idling;
break; // immidiately jump down to End-of-Switch
}
break; // immidiately jump down to End-of-Switch
case sm_Laser90ms_Off:
digitalWrite(Laser_output_Pin, LOW);
if ( TimePeriodIsOver(pulseTimer, LaserOffTime) ) {
pulseTimer = millis(); // store snapshot of time into timer-variable
dbg("jump to On", 0);
myState = sm_Laser10ms_On;
}
// check if one second has passed by
if ( TimePeriodIsOver(Active1SecTimer, 1000) ) {
Pause1SecTimer = millis(); // store snapshot of time into timer-variable
dbg("90ms off jump to pause ", 0);
myState = sm_Wait1SecOff;
}
break; // immidiately jump down to End-of-Switch
case sm_Wait1SecOff:
digitalWrite(Laser_output_Pin, LOW);
// check if one second has passed by
if ( TimePeriodIsOver(Pause1SecTimer, 1000) ) {
Active1SecTimer = millis();
dbg("jump to active 10ms on", 0);
myState = sm_Laser10ms_On;
pulseTimer = millis();
}
break; // immidiately jump down to End-of-Switch
} // End-of-Switch
}
void loop() {
LaserPulseStateMachine();
}
best regards Stefan