int dataPin = 0; // physical pin 5 int clockPin = 1; // physical pin 6 int registerPin = 2; // physical pin 7 int buttonPin = 4; // physical pin 3 int debouncer = 0; // timer for debouncing boolean buttonState = LOW; // debounced button state boolean oldButtonState = LOW; // this helps to determine if the buttons was just recently pressed, or held down unsigned long buttonHeld = 0; // microseconds button was held for, for randomization purposes unsigned long timer = 0; // this counts milliseconds to go with sequenceDelay below int sequenceDelay = 300; // milliseconds between display changes; change this to adjust speed int sequenceNumber = 0; // which pattern is currently playing int sequenceProgress = 0; // which step of the pattern we're on int sequenceTotal = 6; // total number of patterns int sequenceLengths[6] = {1, 2, 14, 28, 16, 1}; // number of steps in each pattern and below are the sequence arrays themselves unsigned int sequenceZero[1] = {(B11111111 + (B11111111 << 8))}; // bytes that have been shifted left("<< 8") will be shifted out first, to the register whose serial input isn't directly connected to the microcontroller unsigned int sequenceOne[2] = {(B11111111 + (B11111111 << 8)), 0}; unsigned int sequenceTwo[14] = {(B00010000 << 8), (B00001000 << 8), (B00000100 << 8), (B00000010 << 8), (B10000000), (B01000000), (B00100000), (B00010000), (B00001000), (B00000100), (B00000010), (B10000000 << 8), (B01000000 << 8), (B00100000 << 8)}; unsigned int sequenceThree[28] = {B00010000, B00011000, B00011100, B00011110, (B00011110 + (B10000000 << 8)), (B00011110 + (B11000000 << 8)), (B00011110 + (B11100000 << 8)), (B00011110 + (B11110000 << 8)), (B00011110 + (B11111000 << 8)), (B00011110 + (B11111100 << 8)), (B00011110 + (B11111110 << 8)), (B10011110 + (B11111110 << 8)), (B11011110 + (B11111110 << 8)), (B11111110 + (B11111110 << 8)), (B11101110 + (B11111110 << 8)), (B11100110 + (B11111110 << 8)), (B11100010 + (B11111110 << 8)), (B11100000 + (B11111110 << 8)), (B11100000 + (B01111110 << 8)), (B11100000 + (B00111110 << 8)), (B11100000 + (B00011110 << 8)), (B11100000 + (B00001110 << 8)), (B11100000 + (B00000110 << 8)), (B11100000 + (B00000010 << 8)), B11100000, B01100000, B00100000, 0}; unsigned int sequenceFour[16] = {(B11111110 + (B11111110 << 8)), (B11101110 + (B11111110 << 8)), (B11010110 + (B11111110 << 8)), (B10111010 + (B11111110 << 8)), (B01111100 + (B11111110 << 8)), (B11111110 + (B01111100 << 8)), (B11111110 + (B10111010 << 8)), (B11111110 + (B11010110 << 8)), (B11111110 + (B11101110 << 8)), (B11111110 + (B11010110 << 8)), (B11111110 + (B10111010 << 8)), (B11111110 + (B01111100 << 8)), (B01111100 + (B11111110 << 8)), (B10111010 + (B11111110 << 8)), (B11010110 + (B11111110 << 8)), (B11101110 + (B11111110 << 8))}; // sequenceFive does not exist, as a call to findAndWriteStep(5, x) simply generates a random frame; a place for it in sequenceTotal and sequenceLengths keeps the code manageable void writeStep(int toBeShifted) // does the actual display changes { digitalWrite(registerPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, (toBeShifted >> 8)); shiftOut(dataPin, clockPin, MSBFIRST, (toBeShifted)); digitalWrite(registerPin, HIGH); } void findAndWriteStep(int sequence, int progression) // converts pattern number to a named array; a multidimensional array may have been better here, but meh { int passData = 65535; switch(sequence) { case 0: passData = sequenceZero[progression]; break; case 1: passData = sequenceOne[progression]; break; case 2: passData = sequenceTwo[progression]; break; case 3: passData = sequenceThree[progression]; break; case 4: passData = sequenceFour[progression]; break; case 5: passData = random(65535); break; } writeStep(passData); } void setup() { pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(registerPin, OUTPUT); pinMode(buttonPin, INPUT); digitalWrite(registerPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, 0); // clear high byte shiftOut(dataPin, clockPin, MSBFIRST, 0); // clear low byte digitalWrite(registerPin, HIGH); timer = millis(); // initialize timer } void loop() { if(digitalRead(buttonPin) == HIGH) { debouncer = 0; buttonState = LOW; buttonHeld = micros() - buttonHeld; // store difference in microseconds between button pushed and released randomSeed(buttonHeld); // regenerate random numbers only when they'll change } else { if(debouncer < 10) { debouncer += 1; } } if(debouncer >= 10) { oldButtonState = buttonState; buttonState = HIGH; } if(oldButtonState == LOW && buttonState == HIGH) // if button barely changed state; prevents repeated switching from holding the button down { // code here for button press digitalWrite(3, HIGH); delay(100); digitalWrite(3, LOW); sequenceNumber += 1; // increment sequence number, reset to zero if too high if(sequenceNumber >= sequenceTotal) { sequenceNumber = 0; } sequenceProgress = 0; // when button pressed, reset counter buttonHeld = micros(); // store current time in microseconds } if(millis() - sequenceDelay >= timer) // if enough time has passed since last update { findAndWriteStep(sequenceNumber, sequenceProgress); sequenceProgress += 1; // increment sequence step, reset to zero if too high timer = millis(); } if(sequenceProgress >= sequenceLengths[sequenceNumber]) { sequenceProgress = 0; } }