That effect looks awesome. Since I still had the 20 LED array set up I had a play. Here's a completely underwhelming 20 LED approximation...
// each block of 4 LEDs in the array is groupled by a common anode (+, long leg)
// for simplicity of wiring on breadboard, using a colour code
#define GREEN 0
#define ORANGE 1
#define WHITE 2
#define BLUE 3
#define YELLOW 4
// pin definitions {GREEN, ORANGE, WHITE, BLUE, YELLOW}
const int charliePin[5] = {
3, 4, 0, 1, 2};
// Charlieplexed LED definitions (current flowing from-to pairs)
const int LED[20][2] = {
{ORANGE, GREEN}, // 0 (GREEN GROUP)
{WHITE, GREEN}, // 1
{BLUE, GREEN}, // 2
{YELLOW, GREEN}, // 3
{GREEN, ORANGE}, // 4 (ORANGE GROUP)
{WHITE, ORANGE}, // 5
{BLUE, ORANGE}, // 6
{YELLOW, ORANGE}, // 7
{GREEN, WHITE}, // 8 (WHITE GROUP)
{ORANGE, WHITE}, // 9
{BLUE, WHITE}, // 10
{YELLOW, WHITE}, // 11
{GREEN, BLUE}, // 12 (BLUE GROUP)
{ORANGE, BLUE}, // 13
{WHITE, BLUE}, // 14
{YELLOW, BLUE}, // 15
{GREEN, YELLOW}, // 16 (YELLOW GROUP)
{ORANGE, YELLOW}, // 17
{WHITE, YELLOW}, // 18
{BLUE, YELLOW} // 19
};
// other
int current = 0; // LED in array with current focus
int previous = 0; // previous LED that was lit
const unsigned long displayTime = 15; // milliseconds to spend at each focus LED in descent
const int lineLength = 10; // how many LEDs to light maximum
void setup() {
}
void loop() {
unsigned long timeNow = millis(); //
while(millis()- timeNow < displayTime) { // animation slows toward end
for(int thisLED = current; thisLED > current - lineLength; thisLED--) {
if (thisLED >= 0 && thisLED <= 19) charlieON(thisLED);
}
}
current++;
if(current==19+lineLength) { // start over
current = 0;
charlieOFF(19); // turn off the remaining (possibly) lit LED
delay(1200); // and then rinse, repeat...after a short pause
}
}
// --------------------------------------------------------------------------------
// turns on LED #thisLED. Turns off all LEDs if the value passed is out of range
//
void charlieON(int thisLED) {
// turn off previous (reduces overhead, only switch 2 pins rather than 5)
digitalWrite(charliePin[LED[previous][1]], LOW); // ensure internal pull-ups aren't engaged on INPUT mode
pinMode(charliePin[LED[previous][0]], INPUT);
pinMode(charliePin[LED[previous][1]], INPUT);
// turn on the one that's in focus
if(thisLED >= 0 && thisLED <= 19) {
pinMode(charliePin[LED[thisLED][0]], OUTPUT);
pinMode(charliePin[LED[thisLED][1]], OUTPUT);
digitalWrite(charliePin[LED[thisLED][0]], LOW);
digitalWrite(charliePin[LED[thisLED][1]], HIGH);
}
previous = thisLED;
}
// --------------------------------------------------------------------------------
// turns off LED #thisLED.
//
void charlieOFF(int thisLED) {
digitalWrite(charliePin[LED[thisLED][1]], LOW); // ensure internal pull-ups aren't engaged on INPUT mode
pinMode(charliePin[LED[thisLED][0]], INPUT);
pinMode(charliePin[LED[thisLED][1]], INPUT);
}
It just moves a block of lineLength LEDs down the array repeatedly. If nothing else it proves more than 20 LEDs and an ATTiny85 were used in your video
Geoff