/* * 9ledseq1.ino * G. Forrest Cook, www.solorb.com * rev: Feb 13, 2026 * Released under the GPLV3 license * * Arduino Nano sketch * Interrupt triggered 9 LED light sequencer for use with a musical * beat detector circuit. * the display consists of eight differently colored LEDs in a circle * and a white LED in the middle. * Pick a random pattern, step through a random number of times (1-3) and * turn the white LED on or off randomly each time through the pattern. * If the beat detector is idle for a few seconds, step through the patterns * at a random speed. * * I/O Connections: * The colored LEDs are pulled down (on) via a ULN2803A darlington array and a * series resistor, the resistors are chosen for equal brightness of the * various LEDs. * The white LED is pulled down (on) through a series resistor and a * 2N3904 transistor, the base of the transistor connects to port B4 * through a 4.7K resistor. * The LED colors are: deep red, orange, amber, yellow-green, true green, * aqua, blue, violet and white. * Colored LEDs 1-4 are driven by Port D5 through D7, * Colored LEDs 5-8 are driven by port B0 through B3. * A low-going step signal from the beat detector connects to port D2/INT0. * A short 1 inch "antenna" connects to analog port A0 for generating a * random number generator seed. */ // Constants const long IdleTout = 5000; // inactivity timeout (mSec) // Global variables unsigned long Mstime; // running milliseconds counter volatile byte IntSemaphore = 0; // irq semaphore // Light pattern arrays, the first byte is the length. // pattern 1: 00000001 rotation static byte LedSeq1[] = {8, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; // pattern 2: 00000011 rotation static byte LedSeq2[] = {8, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x81}; // pattern 3: 00000101 rotation static byte LedSeq3[] = {8, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x41, 0x82}; // pattern 4: 1,11,111,1111,11111... static byte LedSeq4[] = {16, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x07F, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00}; // pattern 5: 11,111,110,1110,1100... (2,3 bit step) static byte LedSeq5[] = {16, 0x03, 0x07, 0x06, 0x0E, 0x0C, 0x18, 0x38, 0x30, 0x70, 0x60, 0xE0, 0xC0, 0xC1, 0x81, 0x83}; // pattern 6: 00011001 00110001 alternate, rotate static byte LedSeq6[] = {16, 0x19, 0x31, 0x32, 0x62, 0x64, 0xC4, 0xC8, 0x89, 0x91, 0x13, 0x23, 0x26, 0x46, 0x4C, 0x08, 0x98}; // pattern 7: 00100101,00101001 rotation static byte LedSeq7[] = {16, 0x25, 0x29, 0x4A, 0x52, 0x94, 0xA4, 0x29, 0x49, 0x52, 0x92, 0xA4, 0x25, 0x49, 0x4A, 0x92, 0x94}; // pattern 8: 00010001 00100001 alternate step rotate static byte LedSeq8[] = {16, 0x11, 0x21, 0x22, 0x42, 0x44, 0x84, 0x88, 0x09, 0x11, 0x12, 0x22, 0x24, 0x44, 0x48, 0x88, 0x90}; void setup() { DDRB = 0x1F; // set portB output pins DDRD = 0xF0; // set portD output pins PORTB = 0x00; // LEDs 5-9 on PB0-4, LED9 is white PORTD = 0x00; // LEDs 1-4 on PD4-7 attachInterrupt(0, timerint, FALLING); // Int 0 runs timerint() randomSeed(analogRead(A0)); // Get a random seed from an analog input Serial.begin (19200); // Initialize serial port, set the baud rate Serial.println (); Serial.println (F("9 LED Light Sequencer")); Serial.println (F("LED Test")); ledsout (0xFF, 1); // All LEDs on delay (2000); ledsout (0x00, 0); // All LEDs off Mstime = millis(); // mark the real time } void loop() { int patnum, loops, direction; char *pattern; patnum = random(0,8); // pick a random pattern direction = random (0,2); // pick a random direction loops = random(1,4); // pick random loop count from 1 to 3 switch (patnum) // pick a random pattern { case 0: pattern = LedSeq1; break; case 1: pattern = LedSeq2; break; case 2: pattern = LedSeq3; break; case 3: pattern = LedSeq4; break; case 4: pattern = LedSeq5; break; case 5: pattern = LedSeq6; break; case 6: pattern = LedSeq7; break; case 7: pattern = LedSeq8; break; } // Serial.print (F("pat:")); // Serial.print (patnum); // Serial.print (F(" dir:")); // Serial.print (direction); // Serial.print (F(" loop:")); // Serial.println (loops); oneseq (pattern, direction, loops); // display a sequence } // Step through a sequence forward or backwards count times. void oneseq (char *seq, byte dir, int count) { byte white; int i, j, idlestep; idlestep = random(100,501); // random step time when idle for (j=0; j=1; i--) { irqwait (idlestep); ledsout (seq[i], white); } } } } // Output the 9 LED bits. // Turn low 4 color bits into high 4 bits for output on port D // turn high 4 color bits to low 4 bits plus white for output on port B void ledsout (byte colors, byte white) { PORTD = colors << 4; if (white) PORTB = (colors >> 4) + 16; else PORTB = (colors >> 4); } // Wait until an interrupt occurs or exit after a long period of inactivity. void irqwait (int dtime) { while (IntSemaphore == 0) // hold until interrupt { if (millis() - Mstime >= IdleTout) // check for idle timeout { delay (dtime); // delay then exit the function return; } } Mstime = millis(); // reset the idle timeout noInterrupts(); IntSemaphore = 0; // reset the irq semaphore interrupts(); } // Set the interrupt semaphore if int0 is pulled low. void timerint() { IntSemaphore = 1; }