// https://wokwi.com/projects/372380727802934273
// https://forum.arduino.cc/t/make-an-output-pin-behave-like-a-monostable-multivibrator/1155428/12
// this is meant to be the state diagram in post #12
// the PIR delayTime is set to 2 seconds in the *.json file
# define IR_Pin 2
# define LED_Pin 13
// blink heartbeat-led just to see that we are looping.
# define heartBeatLED_Pin 12
enum {IDLE = 0, LED_ON, LED_OFF, WAIT,};
unsigned long snapshot_PIR_HIGH_detected;
unsigned long snapshot_PIR_went_LOW;
# define LED_ON_TIME 5000
# define NO_OBSTAKLE_WAIT_TIME 2000
void setup() {
Serial.begin(115200);
Serial.println("Hello World!\n");
pinMode(IR_Pin, INPUT);
pinMode(LED_Pin, OUTPUT);
pinMode(heartBeatLED_Pin, OUTPUT);
}
byte state = IDLE;
bool PIR_Sensor_HIGH;
unsigned long milliseconds_right_now;
bool ledOn;
void loop() {
delay(50);
digitalWrite(heartBeatLED_Pin, (millis() & 512) ? HIGH : LOW);
// I-P-O-model I)nputs-P)rocess-O)utput
// I. INPUTS to the model - time and motion activity
milliseconds_right_now = millis();
// when digitalRead(IR_Pin) delivers HIGH
// (digitalRead(IR_Pin) == HIGH) results in true
// HIGH == HIGH is true
// when digitalRead(IR_Pin) delivers LOW
// (digitalRead(IR_Pin) == HIGH) results in false
// LOW == HIGH is false
PIR_Sensor_HIGH = (digitalRead(IR_Pin) == HIGH);
// P. PROCESS the inputs given the current state and inputs
theFSM();
// RIGHT-BELOW-FSM
// O. OUTPUTS use the process to set the outputs.
if (ledOn == true) {
digitalWrite(LED_Pin, HIGH);
}
else {
digitalWrite(LED_Pin, LOW);
}
// shortest way to code the above if-else:
// digitalWrite(LED_Pin, ledOn ? HIGH : LOW);
}
void theFSM() {
unsigned long time_sincePIR_went_HIGH = 0;
unsigned long time_sincePIR_went_LOW = 0;
switch (state) {
// if variable "state" has value represented by the name "IDLE"
// mutually exclusive execute code below case IDLE:
case IDLE :
if (PIR_Sensor_HIGH) {
snapshot_PIR_HIGH_detected = milliseconds_right_now;
Serial.println("A. motion turns LED on");
state = LED_ON;
}
break; // IMMITIATELY jump down to END-OF-SWITCH
case LED_ON :
ledOn = true;
time_sincePIR_went_HIGH = milliseconds_right_now - snapshot_PIR_HIGH_detected;
if (time_sincePIR_went_HIGH >= LED_ON_TIME) {
Serial.println("B. time turns LED off");
ledOn = false;
state = LED_OFF;
}
break; // IMMITIATELY jump down to END-OF-SWITCH
case LED_OFF :
if (!PIR_Sensor_HIGH) {
Serial.println("C. IR signal gone, so");
snapshot_PIR_went_LOW = milliseconds_right_now;
state = WAIT;
}
break; // IMMITIATELY jump down to END-OF-SWITCH
case WAIT :
time_sincePIR_went_LOW = milliseconds_right_now - snapshot_PIR_went_LOW;
if (PIR_Sensor_HIGH) {
Serial.println("D. IR signal still or again, so");
time_sincePIR_went_LOW = milliseconds_right_now;
state = WAIT;
}
else if (time_sincePIR_went_LOW >= NO_OBSTAKLE_WAIT_TIME) {
Serial.println("E. after a bit more time, we reset");
//timer = milliseconds_right_now;
state = IDLE;
}
break; // IMMITIATELY jump down to END-OF-SWITCH
} // END-OF-SWITCH
// after a break; code-execution goes on here
// ==> jump back to RIGHT-BELOW-FSM
}
Heartbeat
The LED
PIR OUTPUT