The showcase of this post is calculating the conversion of a number to a pip pattern, making it scalable for larger projects.
The trivial part of this post is lighting the WS2812 in a dice roll pattern. A "roll" would take one line, a lookup table would take one array, and a button press would take one line.
-
if (debug)printing enable/disable to see values
sketch.ino
// DICE FOR WS2812 3x7 MATRIX xfpd
bool debug = 1; // "1" for serial monitor output
/*
PIXEL INDEXING FOR DICE PIPS
DIE MULTIPLIER (d) 0 * 4 1 * 4
ROW MULTIPLIER (r) 0 * 7 | 00 .. 02 | 03 | 04 .. 06 |
ROW MULTIPLIER (r) 1 * 7 | 07 08 09 | 10 | 11 12 13 |
ROW MULTIPLIER (r) 2 * 7 | 14 .. 16 | 17 | 18 .. 20 |
COLUMN INDEX (c) +0 +1 +2 +4 +5 +6
*/
#include <Adafruit_NeoPixel.h> // https://github.com/adafruit/Adafruit_NeoPixel
#define PIN 4 // Neopixel pin
#define PIX 21 // Number of Neopixels
Adafruit_NeoPixel led = Adafruit_NeoPixel(PIX, PIN, NEO_GRB + NEO_KHZ800);
byte buttonPin = 2;
byte die[2]; // two dice
byte dieface[] = { // binary value for each row of pips
0, 2, 0, // 1 000 010 000
1, 0, 4, // 2 001 000 100
1, 2, 4, // 3 001 010 100
5, 0, 5, // 4 101 000 101
5, 2, 5, // 5 101 010 101
5, 5, 5 // 6 101 101 101
};
#define ORG 255, 128, 0
#define PIP 0, 255, 0
#define COLOR ORG
void setup() {
if (debug) Serial.begin(115200); // initialize serial communications
randomSeed(analogRead(A0)); // initialize pseudorandomness
pinMode(buttonPin, INPUT_PULLUP); // button to roll dice
led.begin(); // initialize Neopixel object/instance
led.clear(); // clear pixel buffer
divider(); // show dice divider
led.show(); // display pixel buffer
}
void loop() {
while (digitalRead(buttonPin)); // press button to roll dice
delay(150); // debounce button
led.clear(); // clear matrix
divider(); // show dice divider
roll(); // roll the dice
led.show(); // display dice and divider
}
void divider() { // color middle column
for (int i = 0; i < 3; i++) { // three LEDs
led.setPixelColor(i * 7 + 3, led.Color(COLOR)); // any color
}
}
void roll() { // d = die multiplier, r = row multiplier, c = column/bit index
if (debug) Serial.println(); // separate rolls
for (int d = 0; d < 2; d++) { // roll two dice
die[d] = random(0, 6); // face value of each die from 1 to 6
for (int r = 0; r < 3; r++) { // three binary value rows per face
if (debug) if (d) Serial.print(" "); // offset second die
for (int c = 0; c < 3; c++) { // three bits per row
bool pip = bitRead(dieface[die[d] * 3 + r], 2 - c); // each bit, MSB first
if (debug) Serial.print(pip); // print pips
if (pip) // if bit is set...
led.setPixelColor(d * 4 + r * 7 + c, led.Color(PIP)); // ...color pixel (PIXEL INDEXING)
}
if (debug) Serial.println(); // separate each die
}
}
}
diagram.json for wokwi.com
{
"version": 1,
"author": "foreignpigdog x",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-nano", "id": "nano", "top": -4.8, "left": -0.5, "attrs": {} },
{
"type": "wokwi-neopixel-matrix",
"id": "ring1",
"top": -125.64,
"left": 3.09,
"attrs": { "pixleate": "1", "rows": "3", "cols": "7" }
},
{ "type": "wokwi-vcc", "id": "vcc1", "top": -95.24, "left": -19.2, "attrs": {} },
{ "type": "wokwi-gnd", "id": "gnd1", "top": 0, "left": -19.8, "attrs": {} },
{
"type": "wokwi-resistor",
"id": "r1",
"top": -24.55,
"left": 8.2,
"rotate": 180,
"attrs": { "value": "470" }
},
{ "type": "wokwi-text", "id": "text1", "top": -48, "left": 192, "attrs": { "text": "ROLL" } },
{
"type": "wokwi-gate-and-2",
"id": "and1",
"top": -47.6,
"left": -105.6,
"rotate": 180,
"attrs": {}
},
{
"type": "wokwi-text",
"id": "text3",
"top": -38.4,
"left": -67.2,
"attrs": { "text": "E-cap" }
},
{
"type": "wokwi-text",
"id": "text2",
"top": -48,
"left": -76.8,
"attrs": { "text": "1000uF" }
},
{
"type": "wokwi-pushbutton",
"id": "btn2",
"top": -51.4,
"left": 124.8,
"attrs": { "color": "yellow", "xray": "1" }
}
],
"connections": [
[ "gnd1:GND", "ring1:GND", "black", [ "v-9.6", "h-105.6" ] ],
[ "vcc1:VCC", "ring1:VCC", "red", [ "v19.2", "h-96" ] ],
[ "nano:4", "r1:1", "blue", [ "v0" ] ],
[ "ring1:DIN", "r1:2", "blue", [ "v19.2", "h-95.8" ] ],
[ "vcc1:VCC", "and1:B", "red", [ "v0" ] ],
[ "gnd1:GND", "and1:A", "black", [ "v0" ] ],
[ "nano:GND.2", "btn2:2.l", "black", [ "v0" ] ],
[ "nano:2", "btn2:1.l", "yellow", [ "v0" ] ]
],
"dependencies": {}
}
