NOOB here trouble with repeatability: LED Dimmer

Hi all, have been working on this for quite some time now to no avail. Basically I am programming an Arduino to control the interior lights of a car. The functions I want to be able to perform are as follows:

  • Door opens, dome light fades up over 3 seconds.

  • Door closes, dome lights stay on for 20 seconds then fade off over 3 seconds.

  • If the door is left open for more than 10 mins, i.e. the interior light is on for 10 mins the dome light turns off.

  • If the door is closed and the dome light is in the period of which it is waiting for 20 seconds to fade off and the ignition is turned on the dome light automatically fades out.

This is more or less what I want the code to be able to do. I am running the Arduino as a state machine as that seemed easier to read the code and have it function properly. However after writing most of the code to what I thought was correct, I was having all sorts of repeatability issues. So I thought I would start again and see if I could get some help as now not even my simplest code to fade the light on is not repeatable.

The current circumstance is that if Pin 4 goes LOW, the led fades up correctly. Then if Pin 4 goes HIGH, the led turns off. But as soon as I try and fade the led up again by making Pin 4 LOW nothing happens. This is a very simplified version of what I want to be able to do, but if I cant even get this to work properly then I cannot proceed to the rest of the code.

I am very new to programming, hardware I have had lots of experience with, so please go easy on my messy code. As a note I am performing all my tests on the online simulator as I do not have an Arduino board yet.

Thanks

Code:

//LED FADER//

unsigned long interval=12; // the time we need to wait
unsigned long previousMillis=0;// millis() returns an unsigned long.
const int ledPin1 = 5;//Led that will be faded up
static int fadeValueA = 0;


void setup() {
 pinMode(ledPin1, OUTPUT);
}
 
void loop() {

    doorOpenFadeUp();

    if (digitalRead(4) == HIGH){
       (digitalWrite(ledPin1, LOW));
       (fadeValueA = 0);
 }
}
  
  void doorOpenFadeUp() {
      if (digitalRead(4) == LOW) {
      unsigned long currentMillis = millis(); // grab current time
   	  // check if "interval" time has passed (12 milliseconds)
 	  if ((unsigned long)(currentMillis - previousMillis) >= interval) {
  	  //If interval time has passed i.e. statement is true, code progresses
      if (fadeValueA < 255) {
      // increment intensity
      fadeValueA++;
      // write LED intensity
      analogWrite(ledPin1, fadeValueA);
      previousMillis = millis();
   }
  }
 }
}

It looks to me as if the fade up is active only if pin 4 is LOW (not HIGH as you have said). How have you got the button wired and are you using a pullup/pull down resistor ?

This is wrong for an assignment. There should be only one '=' sign:

(fadeValueA == 0);

This was a typing error on my part. It is actually the other way around. Corrected first post.
Also your suggestion fixed my repeatability issues.

First thing I notice, the indentation is all over the place. This doesn't really help to see what's going on. Press Ctrl + T in the IDE and see how that looks.

Next up, don't use pin numbers, give them names. That makes it clearer to see what you actually do. So for example

const byte DoorSwitchPin = 4;

JSV1:
Corrected first post.

Nope it's not... And what's up whit all the () there?

Why is the led pin called ledPin1? Are you planning on connecting multiple? And if you want to, arrays. If you want to number things an array is almost always an easier option because that makes reusing code easy.

And maybe the biggest tip, grab my FadeLed library :wink: This handles all the fading and it even does it with gamma correction. That way it will look wayyy better (more gradually) then when you do it just linear.

Corrected first post.

Don't do that. You make people that have commented on the code that is no longer there look like fools.

Admit you screwed up, and post the corrected code in the same reply.

Thanks for all the replies , sorry to make anyone look like a fool. Very new to all of this. Septillion, I have seen your library and planned on using it except for the fact that currently I am programming everything using the online simulator of which your library is not compatible. However I will be purchasing a physical Arduino shortly so I will give your library a go when I get it.

JSV1:
However I will be purchasing a physical Arduino shortly so I will give your library a go when I get it.

Good idea! Simulators are just junk. Arduino is designed to use it hands on :slight_smile:

Arduino is designed to use it hands on

Even if you let the smoke out, it’s not the end of the world. Just order more smoke.

Ok so I’ve purchased an Arduino uno and I’m using Septillions library. Ill explain the scenario again as some things have changed. I have a NC momentary button connected to pin 2 and ground with the internal pull-up resistor on pin 2.

The problem I’m having which I’ve been having from the start is the delay Off section of the code. What I am trying to do is have the LED fade on when a pin goes HIGH. Once that pin then goes LOW I want to wait for 5000ms and then fade the LED off.

Its the fading off thats the issue, the fade off time is not consistent and I think its to do with where the code starts counting from (i.e. previousMillis?) because when the Arduino powers up the pin starts LOW, therefore the timer starts and mucks up the off delay. Ive tried using booleans so tat only once the LED is on and the Pin goes low does the delay timer start, but it doesn’t seem to work and i end up with a similar result.

#include <FadeLed.h>

unsigned long interval = 5000; // the time we need to wait
unsigned long previousMillis = 0;// millis() returns an unsigned long.
FadeLed testLED(9);

void setup() {

testLED.setTime(1800, true); //testLED is set to constant fade time, by setting second parameter to true
pinMode (2, INPUT_PULLUP);
}

void loop(){
FadeLed::update(); //updates all FadeLed objects

if (digitalRead(2) == HIGH) {
  testLED.on();
}
if (digitalRead(2) == LOW) {
  unsigned long currentMillis = millis(); // grab current time
if (currentMillis - previousMillis >= interval) { // check if "interval" time has passed (5000 milliseconds)
  testLED.off();
  previousMillis = millis();
}
}
}

Again sorry if this appears messy, I’m still quite new.

JSV1:
Again sorry if this appears messy, I’m still quite new.

That’s why the IDE tries really hard (and you apparently fight back quite a bit) to make it look nice. But you can help again by pressing Ctrl+T :wink:

And you can also help by using names that describe what they do (in the real situation).

But what you want is state change detection. You don’t want to do stuff IF the button is pressed/released but you want to do stuff when the button BECOMES pressed/released :wink: See the state change example in the IDE. So you want to remember the moment the button becomes high again.

Or, grab a library like Bounce2. This also handles the button debouncing for you all in an easy to use library :wink:

With that I would say something like this should work (compiles but not tested):

#include <FadeLed.h>
#include <Bounce2.h>

//Pin variables
const byte LightPin = 9;
const byte DoorSwitchPin = 2;

//Other settings
const unsigned long OffDelay = 5000; // the time we need to wait to turn off after the door is closed (more comments ;)

//Global variables
unsigned long doorClosedMillis = 0;// When did the door closing happen? millis() returns an unsigned long.

//Button and FadeLed objects
FadeLed light(LightPin);
Bounce doorSwitch;

void setup() {
  light.setTime(1800, true); //testLED is set to constant fade time, by setting second parameter to true
  doorSwitch.attach(DoorSwitchPin, INPUT_PULLUP);
}

void loop() {
  FadeLed::update(); //updates all FadeLed objects
  doorSwitch.update();

  //Is the door opended (doorSwitch.rose()) AND light is off?
  //Checking if the light is off (!light.get()) is optional but will keep it fading up
  //even when you close and re-open the door while the light is still fading on.
  //Checking if the light is on (!light.get()) is optional but will keep it fading up
  //even when you close and re-open the door while the light is still fading on.
  if (doorSwitch.rose() && !light.get()){
    light.on();
  }
  //is the door closed?
  else if(doorSwitch.fell()){
    //remember the time the door became closed
    doorClosedMillis = millis();
  }

  //Now turning the light off is not dependent on the door BECOMING closed/open
  //so if door is closed (!doorSwitch.read())
  //AND light is not commanded to be off (light.get() return a value other then 0 aka on) 
  //AND time is up 
  if(!doorSwitch.read() && light.get() && millis() - doorClosedMillis > OffDelay){
    //then we turn off the light
    light.off();
  }
}

Septillion, You are quite the saint. :grin:

I have just started using the auto format function and it sure does help. As for the Debouncing library, that is an immense help. I actually had written a bunch of code to debounce and it was working well (was part of my repeatability problems), just had to figure out the delay off. Bounce2 though cleaned up the code very well and the code you provided worked perfectly first go!

Ill make a few tweaks to suit my needs but this is exactly what I needed to point me in the right direction. I had searched for a library to detect pin transitions but never came across the one Bounce2. Your library plus Bounce2 has made this much easier!

Many thanks! ;D ;D ;D ;D

You’re welcome :slight_smile:

One tweak I would make when I read it back now, put the fade time in a variable as well. Then you have all settings/parameters at the top of the sketch. Easy to edit and re-use.

#include <FadeLed.h>
#include <Bounce2.h>

//Pin variables
const byte LightPin = 9;
const byte DoorSwitchPin = 2;

//Other settings
const unsigned long OffDelay = 5000; // the time we need to wait to turn off after the door is closed (more comments ;)
const unsigned int FadeTime = 1800;

//Global variables
unsigned long doorClosedMillis = 0;// When did the door closing happen? millis() returns an unsigned long.

//Button and FadeLed objects
FadeLed light(LightPin);
Bounce doorSwitch;

void setup() {
  light.setTime(FadeTime, true); //testLED is set to constant fade time, by setting second parameter to true
  doorSwitch.attach(DoorSwitchPin, INPUT_PULLUP);
}

void loop() {
  FadeLed::update(); //updates all FadeLed objects
  doorSwitch.update();

  //Is the door opended (doorSwitch.rose()) AND light is off?
  //Checking if the light is off (!light.get()) is optional but will keep it fading up
  //even when you close and re-open the door while the light is still fading on.
  if (doorSwitch.rose() && !light.get()){
    light.on();
  }
  //is the door closed?
  else if(doorSwitch.fell()){
    //remember the time the door became closed
    doorClosedMillis = millis();
  }

  //Now turning the light off is not dependent on the door BECOMING closed/open
  //so if door is closed (!doorSwitch.read())
  //AND light is not commanded to be off (light.get() return a value other then 0 aka on)
  //AND time is up
  if(!doorSwitch.read() && light.get() && millis() - doorClosedMillis > OffDelay){
    //then we turn off the light
    light.off();
  }
}

Good thinking. Thanks again!

I have some more to do yet for a few other functions so ill get to it. :slight_smile: