/*
Forum: https://forum.arduino.cc/t/rgb-led-randomization-when-button-clicked/1239702
Wokwi: https://wokwi.com/projects/393342544046703617
Matrix keyboard for 4 rows x 4 columns = 16 keys
requires one Pin per row and one per column = 8 pins in this case
And a 15 pixel Neopixel ring
Press the red key to start a game
Press the button that corresponds to the blue pixel (changes the color to green)
If a "black pixel" button was pressed the black pixel changes to red
If all blue pixels have been changed to green the game ends and
can be restarted with the red button
2024/03/25 by ec2021
*/
#include <Adafruit_NeoPixel.h>
#define PIN_NEO_PIXEL 8 // Arduino pin that connects to NeoPixel
#define NUM_PIXELS 15 // The number of LEDs (pixels) on NeoPixel
Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);
byte pixelColReference[NUM_PIXELS];
const byte clBlack = 0;
const byte clBlue = 1;
const byte clGreen = 2;
const byte clRed = 3;
const byte NUM_BLUE = 8;
// key matrix
int row[] = {2, 3, 4, 5};
int column[] = {13, 12, 11, 10};
int col_scan;
int last_scan = -1;
constexpr int noOfRows = sizeof(row) / sizeof(row[0]);
constexpr int noOfColumns = sizeof(column) / sizeof(column[0]);
boolean blueModus = false;
int greenPixels = 0;
int redPixels = 0;
void setup()
{
Serial.begin(115200);
NeoPixel.begin();
NeoPixel.clear();
for (int i = 0; i < noOfRows; i++)
{
//Initialization of row pins
pinMode(row[i], OUTPUT);
}
for (int i = 0; i < noOfColumns; i++)
{
//Initialization of column pins
pinMode(column[i], INPUT);
digitalWrite(column[i], HIGH);
}
setAllTo(clBlue);
delay(1000);
setAllTo(clGreen);
delay(1000);
setAllTo(clBlack);
}
int aRow;
int aColumn;
void loop()
{
if (buttonPressed(aRow, aColumn)) {
action(aRow, aColumn);
}
}
void setAllTo(byte aColor) {
for (int i = 0; i < NUM_PIXELS; i++) {
pixelColReference[i] = aColor;
}
updateNeoPixels();
}
void updateNeoPixels() {
for (int pixel = 0; pixel < NUM_PIXELS; pixel++) {
switch (pixelColReference[pixel]) {
case clBlack: NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 0, 0));
break;
case clBlue: NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 0, 255));
break;
case clGreen : NeoPixel.setPixelColor(pixel, NeoPixel.Color(0, 255, 0));
break;
case clRed: NeoPixel.setPixelColor(pixel, NeoPixel.Color(255, 0, 0));
break;
}
}
NeoPixel.show();
}
void randomBlue() {
randomSeed(millis());
setAllTo(clBlack);
int i = 0;
while (i < NUM_BLUE) {
int index = random(NUM_PIXELS);
if (pixelColReference[index] == clBlack) {
pixelColReference[index] = clBlue;
i++;
}
}
updateNeoPixels();
blueModus = true;
greenPixels = 0;
redPixels = 0;
}
boolean buttonPressed(int &aRow, int &aColumn) {
//Check for pressed buttons
static boolean pressed = false;
static unsigned long lastPressTime = 0;
if (pressed && millis() - lastPressTime < 300) { // The 300 ms avoid bouncing and
// quick key repetitions
return false;
}
pressed = false;
for (int i = 0; i < noOfRows; i++)
{
if (pressed) break;
for (int j = 0; j < noOfRows; j++) {
digitalWrite(row[j], HIGH);
}
digitalWrite(row[i], LOW);
for (int j = 0; j < noOfColumns; j++)
{
col_scan = digitalRead(column[j]);
if (col_scan == LOW)
{
lastPressTime = millis();
pressed = true;
aRow = i;
aColumn = j;
break;
}
}
}
return pressed;
}
void action(int i, int j)
{
int keyNo = i * noOfColumns + j + 1;
switch (keyNo) {
case 1 ... NUM_PIXELS :
changeColor(keyNo - 1);
break;
case 16 : // Action for key 16
randomBlue();
break;
default: // and all others here ...
Serial.println("No action implemented yet ....");
}
}
void changeColor(byte pixel) {
if (!blueModus) {
return;
}
byte color = pixelColReference[pixel];
switch (color) {
case clBlue: color = clGreen;
greenPixels++;
break;
case clBlack: color = clRed;
redPixels++;
break;
}
pixelColReference[pixel] = color;
updateNeoPixels();
if (greenPixels == NUM_BLUE) {
blueDone();
}
}
void blueDone() {
blueModus = false;
Serial.print("Wrong Keys ");
Serial.println(redPixels);
delay(2000);
setAllTo(clGreen);
delay(1000);
setAllTo(clBlue);
delay(1000);
setAllTo(clRed);
delay(1000);
setAllTo(clBlack);
}