How to fade all 20 pins in and out ...

I got inspired by the recent post from someone who wanted to copy an input bit to an output. So I thought "why not use that to fade all 20 pins?".

This sketch is the result. It's based on the Fade example, but by adding in a pin change interrupt, we detect when the pin (pin 9) is pulsed and make all the other pins mirror it. Thus, all 20 pins fade in and out together.

int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

const byte pwmPin = 9;
const byte maxPin = 19;

ISR (PCINT0_vect)
 {
static byte val = 0;

 val = !val;
 for (byte i = 0; i <= maxPin; i++)
   if (i != pwmPin)
     digitalWrite (i, val);
 }
 
void setup() 
  { 
  for (byte i = 0; i <= maxPin; i++)
    pinMode (i, OUTPUT);

  // pin change interrupt
  PCMSK0 = _BV (PCINT1);  // only want pin 9
  PCIFR  = _BV (PCIF0);   // clear any outstanding interrupts
  PCICR |= _BV (PCIE0);   // enable pin change interrupts for PCINT7..0
  }   // end of setup

void loop()  
  { 
  // set the brightness of pin 9:
  analogWrite(pwmPin, brightness);    

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade: 
  if (brightness == 0 || brightness == 255) 
    fadeAmount = -fadeAmount ; 

  // wait for 30 milliseconds to see the dimming effect    
  delay(30);                            
}  // end of loop

Okay, now arrange the 20 pins in a circle, and work the fade up & down around the circle ...

Let me get my hammer and saw ...

It's a bit silly, I know, because you could just make a loop anyway that did it. But still it shows how you can mirror what is on one pin to be on another one if you need to.

Nice for learning but it shows a significant amount of flicker. Most probably due to the slow digitalWrites. I would implement it along the lines of my knight rider Knight Rider Without Flicker | Blinkenlight or heartbeat Heartbeat | Blinkenlight examples.

 for (byte i = 0; i <= maxPin; i++)
   if (i != pwmPin)
     digitalWrite (i, val);

use direct port manipulations?

Yes you could do that, but it obscures the basic idea, that you can react to a pin changing. It isn't fabulously practical as such (there would be easier ways of fading 20 LEDs).

Actually what would be interesting would be to try to make a ripple effect, and make use of the delay (eg. pin 1 causes pin 2 to change which causes pin 3 to change and so on).

robtillaart:
use direct port manipulations?

OK, if you replace the ISR with:

ISR (PCINT0_vect)
 {
 if (PINB & _BV (1))   // D9
   PORTB = PORTC = PORTD = 0xFF;
 else
   PORTB = PORTC = PORTD = 0;
 }

Then it is smoother.

Done! And I tested with your Blinkenlight Shield, Udo.