Skip to content

Instantly share code, notes, and snippets.

@usr-ein
Created August 24, 2020 15:06
Show Gist options
  • Save usr-ein/900af6e13bcdfbd8de4e030b3cba1e98 to your computer and use it in GitHub Desktop.
Save usr-ein/900af6e13bcdfbd8de4e030b3cba1e98 to your computer and use it in GitHub Desktop.
Position flipflop switch with timeout
/*
* Author: Samuel Prevost <samuel.prevost@pm.me>
* Date: 2020-08-24
*
* WIRING:
* A two way switch is wired onto pin SWITCH_PIN:
* - either pin SWITCH_PIN is linked to ground (default position)
* - or pin SWITCH_PIN is linked to VCC (pressed switch position)
* If pin SWITCH_PIN is connected to neither, it's an anomaly and will result in random behaviour.
*
* A relay board's IN1 is wired to the pin RELAY_PIN, its VCC to 5.5V and its GND to ground.
* Then, you connect your appliance to the relay such that current doesn't flow in the
* default state (i.e. default switch position).
*
* EXPECTED BEHAVIOUR:
* When the switch is being pressed (continuously), a countdown of
* MAX_TIMER milliseconds is running. During that time, the appliance's
* current will flow through the relay.
* If the switch is released before the countdown's end, the countdown is reseted
* and the appliance's current is switched off.
* If the switch is pressed longer than the countdown. The countdown is reseted
* and the appliance's current is switched off.
*
* USE CASE:
* You want a fan to work only for ten minutes after the door is closed
* and stop working after that, but also stop it automatically if the door is openned before
* it finishes, and restart automatically from zero if the door is openned and closed back
* in the middle of the countdown.
*
* N.B.: You can avoid resetting the countdown upon "interruptions" by
* setting the RESET_TIMER flag to false.
*/
const int RELAY_PIN = 6;
const int SWITCH_PIN = 7;
const long MAX_TIMER = 15*60; // seconds, 15 minutes is the usual desinfection cycle for hospitals
const int DELAY_STEP = 100; // ms
const bool RESET_TIMER = false; // Resets the timer value when interrupting countdown
bool triggered = false;
bool doorClose = false;
int timerValue = MAX_TIMER;
int tmpMillisecTimerValue = 0;
void setup() {
pinMode(RELAY_PIN, OUTPUT);
pinMode(SWITCH_PIN, INPUT);
Serial.begin(9600);
}
void relay_on() {
// The default position (without power) of the relay board
// is equivalent to RELAY_PIN set to HIGH.
// RELAY_PIN is only set to LOW when the GND and the IN1 are connected,
// i.e. that the relay is indeed well wired and everything works.
// TL;DR this is a failsafe measure
digitalWrite(RELAY_PIN, LOW);
}
void relay_off() {
digitalWrite(RELAY_PIN, HIGH);
}
void increment_timer(){
// Workaround the "15 minutes is a lot of milliseconds"-problem
tmpMillisecTimerValue += DELAY_STEP;
if (tmpMillisecTimerValue > 1000){
tmpMillisecTimerValue -= 1000;
timerValue--;
}
}
void reset_timer(){
timerValue = MAX_TIMER;
tmpMillisecTimerValue = 0;
}
void loop() {
doorClose = digitalRead(SWITCH_PIN) == HIGH;
if(!triggered && doorClose && timerValue > 0){
relay_on();
increment_timer();
} else if(doorClose) { // Countdown expired
triggered = true;
reset_timer();
relay_off();
} else { // Door has been opened before the countdown's end
triggered = false;
if (RESET_TIMER){
reset_timer();
}
relay_off();
}
delay(DELAY_STEP);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment