The project turns a reading light on when a seat is occupied and off when not. Works perfectly, until I messed with the program. I wanted to add a delay so that wiggling in the seat wouldn't turn the light off each time a person adjusted themselves. I thought my 2 second delay would wait to determine if the light should really turn off or stay on. But instead, it doesn't turn on until a person is seated for 2 seconds instead of turning on immediately when seated and then waiting for a person to truly leave the seat.
Here's the sketch.
// final Seat Occupancy Switch project, i.e. reading lamp
// uses 5v buck converter attached to 12v input from 12v ad/dc converter to power Nano at 5v and LED light panel at 12 volts
// and MOSFET attached to car seat pressure switch to trigger on/off lights when chair is occupied
const int SwitchPin = 3; // now just a momentary switch that'll be replaced with the seat occupany sensor
const int LedReadingLightPin = A0; // This triggers the Mosfet to turn on the reading light
const int NanoLed = 13; // this is the builtin LED on the Arduino Nano board
int SwitchState; // a variable to tell whether the switch is on or off (HIGH or LOW)
// the setup functipn runs once when you press reset or power the board
void setup() {
// initialize the pins as input or output
pinMode(SwitchPin, INPUT_PULLUP);
pinMode(LedReadingLightPin,OUTPUT);
pinMode(NanoLed,OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
SwitchState = !digitalRead(SwitchPin);
if (SwitchState == HIGH) {
//turn led on
digitalWrite (LedReadingLightPin, HIGH);
digitalWrite (NanoLed, HIGH);
} else {
// delay to allow for occupant wiggling on seat
delay(2000);
// read switch again to see if still not pressed befoe turning light off
SwitchState = !digitalRead(SwitchPin);
// if button still not pressed, turn the light off
if (SwitchState == LOW) {
// turn LED off:
digitalWrite(LedReadingLightPin, LOW);
}
}
}
Owner: How much does it cost?
Carpenter: $100
Owner: How much if I watch?
Carpenter: $150
Owner: How much if I help?
Carpenter: $200
Owner: I tried fixing it.
Carpenter: $500
You've got me rethinking this. Someone else helped with the original code when started the project and was having intermittent results. The INPUT_PULLUP solved that problem. The suggested "SwitchState = !digitalRead(SwitchPin);" seemed to line up with my mind thinking HIGH in this case means the seat is occupied. And LOW meaning not occupied.
As you have used INPUT_PULLUP in pinMode() I assume that you have wired the switch to take the input pin LOW when the seat is occupied
I didn't know the switch wiring had a low or high wiring consideration. It didn't seem to matter which switch leg went where One leg to ground, the other to the input pin. The original sketch works good except when periodically adjusting to get more comforable in the seat. Then it's slighly annoying to have the light flicker on and off.
The resulting HIGH and LOW just seemed to line up better with my mindset. HIGH means on, LOW means off. But I have to admit, when thinking through this again, and trying to "improve" it, I'm getting myself all tangled up.
FWIW - I haven't loaded the "improved" version to the device yet. I tried it in Tinkercad and saw that it wasn't producing the result I imagined.
It does not matter which pin of the switch goes to the input pin and which goes to GND. What is important is that INPUT_PULLUP keeps the input pin normally HIGH and that by wiring the switch to take the input pin LOW when the switch is closed you can detect that LOW state and know that the switch is, indeed, closed
It is a very human thing to think of HIGH as active, on, working etc and for LOW to mean inactive, off, not working etc but the processor does not care.
You can certainly use the ! operator to invert the result of reading the pin state but in my experience that only serves to confuse things
Maybe I need to set a flag when first the light is turned on?. Then the delay and subsequent turn off only happens when the flag is on. Reset the flag off when the delay and turn off happens.
something like this:
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// variables will change:
int SwitchRead; // variable to store value of the Seat Occupancy Switch
int buttonState = 0; // variable for reading the pushbutton status
int flag; // variable to keep track of when the light is first turned on
// so that the delay and lights off doesn't happen before that
// flag is set back to zero (off) when the seat is not occupied
// this is meant to prevent the light from flickering on and off
// when someone is wiggling to get comfortable
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
flag = 0;
}
void loop() {
// read the state of the pushbutton value:
buttonState = !digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
flag = 1; // set flag on to indicate this turning on the lights
// is
}
else {
// delay to allow for occupant wiggling on seat
delay(3000);
// read switch again to see if still not pressed befoe turning light off
buttonState = !digitalRead(buttonPin);
// if button still not pressed, turn the light off
if (buttonState == LOW && (flag == 1)) {
// turn LED off and set flag to OFF
digitalWrite(ledPin, LOW);
flag == 0;
}
}
}
Seems to work in TinkerCad. But am I just making this way too complicated?
If you use self-explaining names for everythning the code becomes easier to understand and easier t maintain and you don't need any additional comments because the code explains itself
these constants say what their purpose is
const byte seatOccupied = LOW;
const byte seatFree = HIGH;
const byte OFF = LOW;
const byte ON = HIGH;
In addition with if you use non-blocking timing based on function millis()
everything works as expected
// final Seat Occupancy Switch project, i.e. reading lamp
// uses 5v buck converter attached to 12v input from 12v ad/dc converter to power Nano at 5v and LED light panel at 12 volts
// and MOSFET attached to car seat pressure switch to trigger on/off lights when chair is occupied
const byte SwitchPin = 3; // now just a momentary switch that'll be replaced with the seat occupany sensor
const byte LedReadingLightPin = A0; // This triggers the Mosfet to turn on the reading light
const int NanoLed = 13; // this is the builtin LED on the Arduino Nano board
const byte seatOccupied = LOW;
const byte seatFree = HIGH;
const byte OFF = LOW;
const byte ON = HIGH;
unsigned long firstClosing = 0;
byte SwitchState = seatFree; // variable for reading the pushbutton status
void setup() {
pinMode(LedReadingLightPin, OUTPUT);
pinMode(SwitchPin, INPUT_PULLUP);
}
void loop() {
SwitchState = digitalRead(SwitchPin);
if (SwitchState == seatOccupied) {
if (firstClosing == 0) { // if no time is stored yet indicated through value 0
firstClosing = millis(); // store snapshot of time in the moment of first close
}
digitalWrite(LedReadingLightPin, ON);
}
// check if more than 3 seconds have passed by since the moment
// the contact was closed for the first time
if (millis() - firstClosing > 3000) {
if (SwitchState == seatFree) {
digitalWrite(LedReadingLightPin, OFF);
firstClosing = 0; // reset timing variable to zero
}
}
}
tinkercad requires registration.
WOKWI is free and does not require a registration
so here is the code and hardware as a WOWKI-Simulation
That is so efficient. And thank you for that great tip about self-explaining names. Perfect.
Wowki - I'm heading there to play with it. Thanks for not only that lead, but also for taking the time to build the simulation there. It works just as I want.