// Derby Race game Nano feasibiity per
// https://forum.arduino.cc/t/help-with-race-car-derby-racing-game-with-addressable-leds/1248176/10
// https://wokwi.com/projects/395283077096057857
// more complicated button-handling within pinball machines could
// be done with a separate controllers for each pinball machine
// confidureg to deliver pulses to this display controller
// See https://wokwi.com/projects/395389818314203137 for an example.
#include <FastLED.h>
const size_t numSections = 16;
const size_t ledsPerSection = 27;
const size_t ledCount = numSections * ledsPerSection;
const uint8_t ledPin = 2;
const byte InPins[numSections] = {3, 4, 5, 6, 7, 8, 10, 11, 12, 13, A0, A1, A2, A3, A4, A5};
byte lastPinState[numSections] = {};
uint32_t lastPinMs[numSections] = {};
byte position[numSections] = {};
const int ACTIVE = LOW;
uint32_t now = 0;
// hat tip https://forum.arduino.cc/t/multiple-animation-zones-on-1-pixel-strip-with-fastled/1073391/16
CRGB leds[ledCount];
// See https://fastled.io/docs/class_c_pixel_view.html
CPixelView<CRGB> sections[numSections] = {
CPixelView<CRGB>(leds, 0 * ledsPerSection, 1 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 1 * ledsPerSection, 2 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 2 * ledsPerSection, 3 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 3 * ledsPerSection, 4 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 4 * ledsPerSection, 5 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 5 * ledsPerSection, 6 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 6 * ledsPerSection, 7 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 7 * ledsPerSection, 8 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 8 * ledsPerSection, 9 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 9 * ledsPerSection, 10 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 10 * ledsPerSection, 11 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 11 * ledsPerSection, 12 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 12 * ledsPerSection, 13 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 13 * ledsPerSection, 14 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 14 * ledsPerSection, 15 * ledsPerSection - 1),
CPixelView<CRGB>(leds, 15 * ledsPerSection, 16 * ledsPerSection - 1)
};
void setup() {
Serial.begin(115200);
FastLED.addLeds<WS2812B, ledPin, GRB>(leds, ledCount);
lampTest();
randomRainbowTest();
for (auto &pin : InPins ) {
pinMode(pin, INPUT_PULLUP);
}
Serial.println("Ready. Set. Ding!");
}
void loop() {
now = millis();
scanButtons();
//swapColors();
}
void scanButtons(void) {
for (int ii = 0; ii < numSections; ++ii) {
int buttonState = digitalRead(InPins[ii]);
if (buttonState != lastPinState[ii] && now - lastPinMs[ii] > 100) {
lastPinState[ii] = buttonState;
lastPinMs[ii] = now;
Serial.print(ii); Serial.print(" ");
if (buttonState == ACTIVE) {
sections[ii][position[ii]] = CRGB::Black;
++position[ii];
if (position[ii] > ledsPerSection - 1) { // winner
Serial.print("Winner!");
position[ii] = ledsPerSection - 1;
}
sections[ii][position[ii]] = CRGB::CRGB::Yellow;
FastLED.show();
}
}
}
}
void swapColors(void) {
static uint32_t last = 0;
static int flip = 1;
if (millis() - last < 1000) return;
last = millis();
for (int idx = 0; idx < ledCount; ++idx) {
leds[idx] = (idx + flip) & 0b1 ? CRGB(74, 126, 54) : CRGB::Coral ;
}
flip = flip > 0 ? 0 : 1;
Serial.print(".");
FastLED.show();
}
void lampTest(void) {
// test leds
Serial.print("test all the leds in leds()...");
for (int idx = 0; idx < ledCount; ++idx) {
leds[idx] = idx & 0b1 ? CRGB::Aqua : CRGB::Coral ;
}
FastLED.show();
Serial.println("done.");
delay(2000);
}
void randomRainbowTest(void) {
Serial.println("test each strand in sections[]...");
for (int ii ; ii < numSections; ++ii) {
Serial.print("sections[");
Serial.print(ii);
Serial.print("].size()=");
Serial.print(sections[ii].size());
Serial.print(" ");
randomSeed(random() + analogRead(A7) + micros());
sections[ii].fill_rainbow(random(255), 3);
FastLED.show();
delay(377);
}
Serial.println("...done.");
delay(1000);
}
Derby Race -- Hit the buttons to advance the lights.