Extended and smooth fading time ( 20 minutes or more)

Hi All,
I am new to Arduino world :o
I am looking for the code to slow fading an LED for extended time more than 20 Minutes.

The analogWrite() has 255 increments.
On the low end, that's not really a lot of smoothing.

If you want more, try using 2 or three analogWrite() pins, with 10k, 1k, and .1k resisters on each going to the LED. You can make it more smooth.

Jack wp is correct to say that 255 steps provided by analogWrite() will not be enough to give a smooth fade over such a long period.

There is a way to get 65,000 steps on pins 9 & 10 with this code:

/* Configure digital pins 9 and 10 as 16-bit PWM outputs. */
void setupPWM16() {
    DDRB |= _BV(PB1) | _BV(PB2);        /* set pins as outputs */
    TCCR1A = _BV(COM1A1) | _BV(COM1B1)  /* non-inverting PWM */
        | _BV(WGM11);                   /* mode 14: fast PWM, TOP=ICR1 */
    TCCR1B = _BV(WGM13) | _BV(WGM12)
        | _BV(CS10);                    /* no prescaling */
    ICR1 = 0xffff;                      /* TOP counter value */
}

/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
    switch (pin) {
        case  9: OCR1A = val; break;
        case 10: OCR1B = val; break;
    }
}

(I did not create this, I found it here)

Paul

thanks PaulRB & Jack wp.
I appreciate your help.
so, if I want to have longer fade time I just need to put a delay before each incrementation ?

Yes, but there can be problems using the delay() function. What else does the Arduino need to do during the fade? Monitor pushbuttons or other sensors?

"so, if I want to have longer fade time I just need to put a delay before each incrementation ?"

If that process is the only one you want to run on that arduino, then, yes, you can add delay(s) . But if you want that arduino to preform multiple tasks, you will need to use "soft delays".

Hi guys,
Thank you so much for your help I really appreciate it.
I am not planning to do anything else during the fade duration.
Actually I want to build a small system that fade in when a switch is activated and stay full brightness until the switch is open and then fade out slowly to zero.

Ok, so during the fade, the Arduino will have to monitor the switch for changes. Otherwise it will not notice if the switch has changed for up to 20 minutes. This means that your sketch must either not use delay() or only use delay() for short periods, so that the switch can be checked frequently. Also for() and while() loops cannot be used unless they also last only for very short periods.

Can you confirm that the switch will be a toggle switch and not a momentary push switch?

Hi Paul,
It's just a toggle switch am using. And for now I am monitoring anything else.
The sequence is switched closed start fading in (0 to max brightness) and stay bright. When the switch is open then fade out to 0 and stay there until the switch is closed again.

Hi Paul,
It's just a toggle switch am using. And for now I am monitoring anything else.
The sequence is switched closed start fading in (0 to max brightness) and stay bright. When the switch is open then fade out to 0 and stay there until the switch is closed again.

If you don't want to test the switch during the fade in (or fade out), then you can use delays ok.
Once the fade in is completed, then you can look at the switch again.
Once the fade out is completed, then you can look at the switch again.
Is that your plan?

Here is some example code I wrote for someone else to fade over 65535 steps. It currently fades pin 13 on the UNO (the on board LED) but is not limited to a particular pin or pins.
It uses Timer1 so you cannot use normal (analogWrite) PWM on pins 9,10.

// 16 bit PWM on any pin
// Example uses built in LED on pin 13 (PORTB bit 5)

void setup(){
  pinMode(13, OUTPUT);
  
  cli();                                // Disable all interrupts
  TCCR1A = 0;                           // Clear all flags in control register A
  TCCR1B = 0;                           // Clear all flags in control register B
  TCNT1 = 0;                            // Zero timer 1 count
  
  OCR1A = 32768;                        // Preload compare match register (50% duty cycle)
  
   // No prescaler   
  //TCCR1B |= _BV(CS12);    
  //TCCR1B |= _BV(CS11);    
  TCCR1B |= _BV(CS10);    
  
  TIMSK1 |= _BV(OCIE1A);                // Enable timer compare interrupt
  TIMSK1 |= _BV(TOIE1);                 // Enable timer overflow interrupt

  sei();                                // enable all interrupts
}

void loop(){
  for(unsigned int x = 1; x < 65535; x++){
    //cli();
    OCR1A = x;
    //sei();
    delayMicroseconds(50);
  }
}

ISR(TIMER1_OVF_vect){                   // Timer1 overflow interrupt service routine
  PORTB |= _BV(PORTB5);                 // Turn LED (pin 13) on
}

ISR(TIMER1_COMPA_vect){                 // Timer1 compare interrupt service routine
  PORTB &= ~_BV(PORTB5);                // Turn LED off
}

How does that work, Riva? I thought pwm on pins 9 & 10 used timer 1. I would have expected your code to interfere with pwm on pins 9 & 10.

PaulRB:
How does that work, Riva? I thought pwm on pins 9 & 10 used timer 1. I would have expected your code to interfere with pwm on pins 9 & 10.

Yes it will effect the use of PWM on pins 9 & 10 hence the warning.

It uses Timer1 so you cannot use normal (analogWrite) PWM on pins 9,10.

but it will work on any pin or pins (using direct port manipulation). It hijacks the timer 1 overflow and compare ISR's The pin(s) turned on when timer 1 overflows and get turned off when it matches the compare value.

Sorry, I misread your earlier post and thought you were saying pwm on pins 9 & 10 could be used as normal.

how can I have the fading for 20 minutes duration ?

How many intervals did you decide to work with?
What is your script like now? Please post your script, and we can give advice based on how you are proceeding.

derdhih:
how can I have the fading for 20 minutes duration ?

Change

    delayMicroseconds(50);

to

    delay(18);

Hi All,
This is my code.
I want the LED to stay full bright when riched the hi level, until the swith is open (low)
how can I do that

int inPin = 2;         // the number of the input pin
int outPin = 13;       // the number of the output pin
int reading;           // the current reading from the input pin

void setup()
{
cli();                                // Disable all interrupts
TCCR1A = 0;                           // Clear all flags in control register A
TCCR1B = 0;                           // Clear all flags in control register B
TCNT1 = 0;                            // Zero timer 1 count

OCR1A = 32768;                        // Preload compare match register (50% duty cycle)

// No prescaler   
//TCCR1B |= _BV(CS12);   
//TCCR1B |= _BV(CS11);   
TCCR1B |= _BV(CS10);   

TIMSK1 |= _BV(OCIE1A);                // Enable timer compare interrupt
TIMSK1 |= _BV(TOIE1);                 // Enable timer overflow interrupt

sei();                                // enable all interrupts

pinMode(inPin, INPUT);
pinMode(outPin, OUTPUT);
}

void loop()
{
reading = digitalRead(inPin);
if (reading == HIGH ) {
  for(unsigned int x = 65535; x > 1; x--)
//cli();
OCR1A = x;
//sei();
delayMicroseconds(50);}
else 
for(unsigned int x = 1; x > 65535; x++){
//cli();
OCR1A = x;
//sei();
delayMicroseconds(50);}

}

Diming.ino (1.68 KB)

for(unsigned int x = 1; x > 65535; x++){

How many times would you expect this for() to execute ?

Please put your code inside code tags. It will make it lots easier for us to read.