Seat sensor delay program problem

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);
    }
    
  }
  
}

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

    SwitchState = !digitalRead(SwitchPin);

    if (SwitchState == HIGH)

If so then why have you made the logic so convoluted ?

Why not just

    SwitchState = digitalRead(SwitchPin);

    if (SwitchState == 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

: )

Well, @UKHeliBob ,

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.

hal

Hah @xfpd,

fortunately or perhaps, unfortunately, in this case the owner and carpenter are the same person. :slight_smile:

hal

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

Thanks @UKHeliBob,

No question, I'm confusing myself.

Thanks for your comments.

ha

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?

hal

No because the switching on is delayed again

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

WOW! @StefanL38,

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.

thank you.

hal

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.