intensity-fade conflict

I’m trying to use fade to mimic sunrise/sunset and control intensity with pots. The intensity sketch works well when it’s in it’s own sketch, but when I added it to the sunrise-sunset sketch it became inoperable, as if I’d never added it. It’s the first four lines after void loop(). Any ideas how to get intensity control working? Here’s the schematic I’m using.

   //Fade part of sketch Created 1 Nov 2008 By David A. Mellis
 //modified 30 Aug 2011 By Tom Igoe

  long secondsInMs(int s){ 
  return s*1000L; //values will be expressed in seconds
 
  
} 
  
  int nemLED = 3; 
  int nemPOT = A1;
  int rightrockLED = 5;
  int rightrockPOT = A2;
  int leftrockLED = 6;
  int leftrockPOT = A3;
  int purpLED = 9;
  int purpPOT = A4;
  int fans = 4;
 
 void setup() {
  pinMode(nemPOT, INPUT);
  pinMode(nemLED, OUTPUT);                             
  pinMode(rightrockPOT, INPUT);
  pinMode(rightrockLED, OUTPUT);
  pinMode(leftrockPOT, INPUT);
  pinMode(leftrockLED, OUTPUT);
  pinMode(purpPOT, INPUT);
  pinMode(purpLED, OUTPUT);
  pinMode(fans, OUTPUT); 
} 

void loop()
{
   analogWrite(nemLED, (analogRead(nemPOT)));             //adjust intensity of LED with potentiometer
   analogWrite(rightrockLED, (analogRead(rightrockPOT))); //adjust intensity of LED with potentiometer
   analogWrite(leftrockLED, (analogRead(leftrockPOT)));   //adjust intensity of LED with potentiometer
   analogWrite(purpLED, (analogRead(purpPOT)));           //adjust intensity of LED with potentiometer
   
   digitalWrite(fans, HIGH);
   
   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(purpLED, fadeValue);
     delay(30);}
     
   delay(500);
     
   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(rightrockLED, fadeValue);
     delay(30);}

   delay(500);

   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(leftrockLED, fadeValue);
     delay(30);}

   delay(500);

   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(nemLED, fadeValue);
     delay(30);}

   delay(secondsInMs(15));    //temporary delay represents daytime
    
   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {   
     // sets the value (range from 0 to 255):d
     analogWrite(nemLED, fadeValue);
     delay(30);}

     delay(500);
     
   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(rightrockLED, fadeValue);
     delay(30);}

     delay(500);

   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(leftrockLED, fadeValue);
     delay(30);}

   delay(500);

   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(purpLED, fadeValue);
     delay(30);}

   digitalWrite(fans, LOW);

   delay(secondsInMs(15));  //temporary delay represents night time
}

sunrises-sunset.pdf (544 KB)

Hi,

 analogWrite(nemLED, (analogRead(nemPOT)));             //adjust intensity of LED with potentiometer
   analogWrite(rightrockLED, (analogRead(rightrockPOT))); //adjust intensity of LED with potentiometer
   analogWrite(leftrockLED, (analogRead(leftrockPOT)));   //adjust intensity of LED with potentiometer
   analogWrite(purpLED, (analogRead(purpPOT)));           //adjust intensity of LED with potentiometer

Are these the lines you added. analogRead ranges from 0 to 1023 analogWrite ranges from 0 to 255

You need to divide analogRead by 4 then analogWrite or use map function

Tom.. :)

Hi,
OPs diag.
fader1.jpg
Tom… :slight_smile:

  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   

// sets the value (range from 0 to 255):
    analogWrite(purpLED, fadeValue);
    delay(30);}

This is what’s called “blocking”. The for loop must count up to 255 and finish before it can go on to the rest of your code. The code is spending all its time in these loops and not regularly executing the code in the top of the loop().

For everything which must fade simultaneously, you will need to keep a separate fadeValue and the time that you last changed the fade level for that. Then the main loop needs to check the millis() timer to see if it’s time to change any of the faders.

If you want it to look sequential but still respond to the other inputs, then you can use a “state machine”. For example, you need to know that you’re in the middle of fading the purple LED and when that reaches 255, switch to fading the next one. Alternatively, add a ‘start time’ to every separate fader so that you can time it to start fading the ‘next’ one 7.65 seconds after the beginning of the sketch.
[/code]

Hi,
Looking at your code, what do you want to pots to do?
At the moment they set the brightness at the start of the loop, then you adjust them, then at the top of the loop you reset them to the pot settings
How fast do you want the fading, and do you want the pots to set the maximum brightness?

Can you explain the process of your code please?

Tom… :slight_smile:

This project is for my sunlit fish tank.

I have the LEDs coming on one after the other to more gradually light the tank. I was going change that 500 ms delay to a minute for the finished sketch. That part seems to work as planned.

I want the pots to set max intensity. Every week during winter, I'll adjust intensity. I'll only need the supplemental light 4-5 month/year.

The fading part, I think I have. I'll change fadeValue from 5 to 1 to make the fade more gradual and change that delay from 30 ms to 14 seconds for about an hour fade. I have things sped up for bench testing.

Thanks guys-I'll work on it tonight.

TomGeorge: You need to divide analogRead by 4 then analogWrite or use map function

Tom.. :)

I divided by 4 like this, but it didn't seem to make any difference.

  analogWrite(nemLED, (analogRead(nemPOT)/4));         //adjust intensity of LED with potentiometer
   analogWrite(rightrockLED, (analogRead(rightrockPOT)/4));    //adjust intensity of LED with potentiometer
   analogWrite(leftrockLED, (analogRead(leftrockPOT)/4));       //adjust intensity of LED with potentiometer
   analogWrite(purpLED, (analogRead(purpPOT)/4));               //adjust intensity of LED with potentiometer

I wrote one line as this but got an error about too few arguments.

analogRead(purpPOT)/4, (analogWrite(purpLED));

MorganS: This is what's called "blocking". The for loop must count up to 255 and finish before it can go on to the rest of your code. The code is spending all its time in these loops and not regularly executing the code in the top of the loop().

For everything which must fade simultaneously, you will need to keep a separate fadeValue and the time that you last changed the fade level for that. Then the main loop needs to check the millis() timer to see if it's time to change any of the faders.

If you want it to look sequential but still respond to the other inputs, then you can use a "state machine". For example, you need to know that you're in the middle of fading the purple LED and when that reaches 255, switch to fading the next one. Alternatively, add a 'start time' to every separate fader so that you can time it to start fading the 'next' one 7.65 seconds after the beginning of the sketch. [/code]

Now I see why an hour fade is not a good idea the way it's set up blocking style.

I have a voltmeter on each pot to keep intensity between LEDs consistent. The pots adjust the voltage from 0.00 to 4.93, but the LEDs go to max brightness no matter what.

Hi, You are sending your pot value directly to the LEDs, how is that going to set the maximum brightness for the rest of the code. You need to read the pots and store them each as a separate variable. Then in your code where you fade up and down, you use the variable values as your maximum limits of your fade up.

  • Read Pot values and assign to nemLEDmax, rightrockLEDmax leftrockLEDmax and purpleLEDmax.
  • Fade each LED up to nemLEDmax and rightrockLEDmax etc...
  • Fade each LED down to zero from nemLEDmax and from rightrockLEDmax etc...

Hope this helps.. Tom.. :)

Thank you Tom. I think I see what you are saying, I'll work on getting there.

It seems odd that the intensity sketch works when it's all by itself, but gets stomped on by the fade sketch...

I very much appreciate your directions to get this thing working. Joe

saltyjoe: Thank you Tom. I think I see what you are saying, I'll work on getting there.

It seems odd that the intensity sketch works when it's all by itself, but gets stomped on by the fade sketch...

I very much appreciate your directions to get this thing working. Joe

Good, just start by coding for one LED string only, that way you will not have too many variables to work with. Tom... :)

I did this thinking I was following directions…The sketch compiles, but purpLED won’t turn on.

int purpLEDmax;

void loop()
{
 
 
    purpLEDmax = digitalRead(purpPOT);

for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {   
     // sets the value (range from 0 to 255):
     analogWrite(purpLEDmax, fadeValue);

saltyjoe:
I did this thinking I was following directions…The sketch compiles, but purpLED won’t turn on.

int purpLEDmax;

void loop()
{

purpLEDmax = digitalRead(purpPOT);

for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) { 
    // sets the value (range from 0 to 255):
    analogWrite(purpLEDmax, fadeValue);

That’s not a sketch, and it does not compile, but trying to do analogWrite to pin zero or pin one is never going to end well.

TomGeorge: Hi,

  • Read Pot values and assign to nemLEDmax, rightrockLEDmax leftrockLEDmax and purpleLEDmax.
  • Fade each LED up to nemLEDmax and rightrockLEDmax etc...
  • Fade each LED down to zero from nemLEDmax and from rightrockLEDmax etc...

Hope this helps.. Tom.. :)

This is in response to #1. purpLEDmax = digitalRead(purpPOT);

This is in response to #2. analogWrite(purpLEDmax, fadeValue);

Please tell me where I went wrong.

@ AWOL, I didn't mean that fragment of the sketch would compile. I just showed the changes to the sketch in my first post.

You broke which pin you are writing to. You need to analogWrite() to the correct pin.

Then you need to map() the 0-255 range of fadeValue to 0-purpLEDMax. Look up the use of the map() function.

Hi,
Look at this code and try it, it is setup for pot in A1 and leds in pin3.

int nemLED = 3;
int nemPOT = A1;
int nemPOTval;
int nemLEDmax;

void setup() {
  Serial.begin(9600);
  pinMode(nemPOT, INPUT);
  pinMode(nemLED, OUTPUT);

}

void loop()
{
  nemPOTval = analogRead(nemPOT);  //read pot, save value 0 to 1023 range
  nemLEDmax = map(nemPOTval, 0, 1023, 0, 255);  //convert value to 0 to 255 range

  for (int fadeValue = 0 ; fadeValue <= nemLEDmax; fadeValue += 5) // fade up to value set in nemLEDmax
  {
    analogWrite(nemLED, fadeValue);
    Serial.print("\tfadeup  ");
    Serial.print("\tnemLEDmax =");
    Serial.print(nemLEDmax);
    Serial.print("\tfadeValue =");
    Serial.println(fadeValue);
    delay(30);
  }

  delay(500);

  for (int fadeValue = nemLEDmax ; fadeValue >= 0; fadeValue -= 5) // fade down from value set in nemLEDmax
  {
    analogWrite(nemLED, fadeValue);
    Serial.print("\tfadedown");
    Serial.print("\tnemLEDmax =");
    Serial.print(nemLEDmax);
    Serial.print("\tfadeValue =");
    Serial.println(fadeValue);
    delay(30);
  }

  delay(500);

}

Your LED should fade up and down, the maximum set by the pot, also the lower the maximum the faster the fade up and down.
If you adjust the pot to change the maximum, it will not be read until after a fade down.
Open the IDE monitor and set it to 9600 and see the values
Tom… :slight_smile:

MorganS:
You broke which pin you are writing to. You need to analogWrite() to the correct pin.

Then you need to map() the 0-255 range of fadeValue to 0-purpLEDMax. Look up the use of the map() function.

Thanks, I fixed the broken pin and checked out the link for map.

TomGeorge:
Hi,
Look at this code and try it, it is setup for pot in A1 and leds in pin3.

Your LED should fade up and down, the maximum set by the pot, also the lower the maximum the faster the fade up and down.
If you adjust the pot to change the maximum, it will not be read until after a fade down.
Open the IDE monitor and set it to 9600 and see the values
Tom… :slight_smile:

Wow, that sketch works like a dream. That was very generous, I appreciate that a lot. Looking at how you used map in your sketch as I read that link on map will make it much easier to get. Thanks a million!

Hi, Good, I had it running here, before I sent it. You will see how using the max value is used to determine how far up the for loop counts and from where the down loop counts from.

The fad rate gets faster with lower max values because you are decreasing the number of steps to get from 0 to max and back.

Using that as your template you should be able to do all your LED channels.

Tom... :)

saltyjoe:
Now I see why an hour fade is not a good idea the way it’s set up blocking style.

Here’s an idea of what a non-blocking version might look like. It has more comment than code, but do ask about any lines you’re not sure of — when you’re ready for non-blocking style.

I made the fade steps big to limit the lines printed to serial monitor and put in a repeat count to stop the fade and printing to serial monitor just so the printed trace log can be scrolled through and checked against the code.

Sorry not tested but it compiles. It can be debugged quickly, I am sure, because it’s short, trivial code. I won’t claim that there’s no bugs… never tempt Murphy!

Set serial monitor to 250000 baud for this. Faster serial will clear the serial output buffer quicker, a GOOD thing.

#include "Arduino.h" 

byte nemLEDpin = 3;
byte nemPOTpin = A1;
int nemPOTval, nemLEDmax;

byte repeatFadeCycleXtimes = 2; // to limit monitor lines so you can scroll/copy them

// these are your process states
int doWhat; // 0=fade up, 1=wait to fade down, 2=fade down, 3=wait to fade up

int fadeValue;  // global variables default = 0
const int fadeChange = 50; // not smooth but makes fewer data lines on the monitor

unsigned long startTime, waitTime; // time variables should be unsigned
const unsigned long fadeWait = 200, dayWait = 1000, nightWait = 2000; // milliseconds

void setup() 
{
  Serial.begin( 250000 );  // fastest serial, set serial monitor to match
  pinMode( nemPOTpin, INPUT ); // not sure if needed for analog read
  pinMode( nemLEDpin, OUTPUT ); // not sure if needed for analog write
}

void loop()
{
  // -------------------------------- READ THE POT --------------------------
  // read the pot and set the limit, no trigger, this always happens
  nemPOTval = analogRead( nemPOTpin );  //read pot, save value 0 to 1023 range
  nemLEDmax = nemPOTval >> 2;  // VERY FAST divide by 4, converts value to 0 to 255

  // -------------------------------- TIMER --------------------------
  // fades and waits between fades only happen when their time is up
  // this is a time event trigger
  if ( millis() - startTime >= waitTime ) // non-blocking timer allows "instant" pot reads
  {
    // inside of the timer, what is done depends on the value of doWhat

    // -------------------------------- FADE UP --------------------------
    // this is a process state trigger
    // it runs until it's finished then sets up the next state and timer
    if ( doWhat == 0 )  // FADE UP only runs when it's supposed to
    {
      if ( fadeValue <= nemLEDmax )
      {
        analogWrite(nemLEDpin, fadeValue);
        Serial.print( F( "\tFADE UP  \tnemLEDmax = " ));
        Serial.print( nemLEDmax );
        Serial.print( F( "\tfadeValue = " ));
        Serial.println( fadeValue );

        fadeValue += fadeChange; // fade up to value set in nemLEDmax
      }
      if ( fadeValue >= nemLEDmax ) // no else here, fadeValue may change just above
      {
        Serial.println( F( "\tstart WAIT TO FADE DOWN" ));
        doWhat = 1; // next loop() run WAIT TO FADE DOWN after timer is done
        waitTime = dayWait; // set next timer wait to this long
      }
      startTime += fadeWait; // set start for the timer to correct "now"
    } // end of FADE UP

    // ------------------------ WAIT TO FADE DOWN --------------------------
    // this is a process state trigger
    // it sets up the next state and timer
    // the else is to force this to only happen after the timer finishes waiting
    else if ( doWhat == 1 ) // WAIT TO FADE DOWN only runs when it's supposed to
    {
      Serial.println( F( "\tWAIT TO FADE DOWN is over" ));
      doWhat = 2; // next loop(), run FADE DOWN after timer is done
      fadeValue = nemLEDmax; // fade down from nemLEDmax
      startTime += dayWait; // set start for the timer to correct "now"
      waitTime = fadeWait; // set next timer waits to this long
    } // end of WAIT TO FADE DOWN

    // -------------------------------- FADE DOWN --------------------------
    // this is a process state trigger
    // it runs until it's finished then sets up the next state and timer
    // the else is to force this to only happen after the timer finishes waiting
    else if ( doWhat == 2 )  // FADE DOWN only runs when it's supposed to
    {
      if ( fadeValue >= 0 )
      {
        analogWrite(nemLEDpin, fadeValue);
        Serial.print( F( "\tFADE DOWN\tnemLEDmax = " ));
        Serial.print( nemLEDmax );
        Serial.print( F( "\tfadeValue = " ));
        Serial.println( fadeValue );

        fadeValue -= fadeChange; // fade up to value set in nemLEDmax
      }
      if ( fadeValue < 0 ) // no else here, fadeValue may change just above
      {
        Serial.println( F( "\tstart WAIT TO FADE UP" ));
        doWhat = 3; // next loop(), run WAIT TO FADE UP after timer is done
        waitTime = nightWait; // set next timer wait to this long
      }
      startTime += fadeWait; // set start for the timer to correct "now"
    } // end of FADE DOWN

    // ------------------------ WAIT TO FADE UP --------------------------
    // this is a process state trigger
    // it sets up the next state and timer then runs the repeat count code
    // the else is to force this to only happen after the timer finishes waiting
    else if ( doWhat == 3 ) // WAIT TO FADE UP only runs when it's supposed to
    {
      Serial.println( F( "\tWAIT TO FADE UP is over" ));
      doWhat = 0; // next loop(), run FADE UP after timer is done
      fadeValue = 0; // fade up from 0
      startTime += nightWait; // set start for the timer to correct "now"
      waitTime = fadeWait; // set next timer waits to this long
      
      if ( repeatFadeCycleXtimes > 0 ) // so you can scroll monitor data
      {
        repeatFadeCycleXtimes--; // subtracts 1 from repeatFadeCycleXtimes
        if ( repeatFadeCycleXtimes == 0 ) // this is to stop output to monitor
        {
          doWhat = 100; // turn the fades off, stops serial prints
        }
      }
    } // end of WAIT TO FADE UP

  } // end of the non-blocking timer

  // you can add other triggers and/or inputs/outputs to this sketch
  // anything that changes can be used to trigger something else
  // as long as none takes long to run or messes with the pins used, all should run together

} // end of loop()

Thank you Tom George, I added the other three LEDs and it does work.

Thank you GoForSmoke, I'll try that sketch after work tomorrow.

Thanks so much, you guys.

Note: the best way to look at that code is to run it with serial monitor open and when it stops scrolling, then use that trace log to follow the code execution path in the IDE.

That pot read is the slowest thing there By Far at 105 micros. Really it should only be read inside of the timer too since only the state of the pot then makes any difference. There is fix #1 needed already.

It should notice the pot all the time but YOU only see it when the next fade happens.

That could change fadeValue and/or doWhat instantly with a bit more code.

Do you have a string or two of reds and maybe one of blue for high sun? You use any UV leds?