ESP32 Bench
Boards: ESP32, S2, S3, C3, C6
Flash and monitor: Web Serial
← All projects

Electronic dice

Press a button to roll two dice on an OLED, with a tumbling animation. The serial port keeps score, so you can check how fair the dice are.

Starter20 min115200 baud
Board
Fig. 1. Pins this project uses on the ESP32-DevKitC V4, 38 pin. USB connector at the bottom.

Wiring

FromTo boardNote
OLED VCC3V3
OLED GNDGND
OLED SDAGPIO 21
OLED SCLGPIO 22
ButtonGPIO 4Other side to GND. The internal pull-up does the rest

Tested on this board

Not run on this board yet. Treat the wiring and code as a first draft.

Firmware, Arduino sketch for ESP32 Dev Module

// Electronic dice on an SSD1306. Press the button to roll.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int BUTTON = 4;
const int DICE = 2;  // 1 or 2

Adafruit_SSD1306 display(128, 64, &Wire, -1);
int counts[13];  // how often each total came up
int rolls = 0;

void drawDie(int x, int y, int value) {
  const int S = 44, R = 4;
  display.drawRoundRect(x, y, S, S, 6, SSD1306_WHITE);
  int a = x + 11, b = x + S / 2, c = x + S - 11;  // pip columns
  int d = y + 11, e = y + S / 2, f = y + S - 11;  // pip rows
  if (value % 2 == 1) display.fillCircle(b, e, R, SSD1306_WHITE);
  if (value >= 2) {
    display.fillCircle(a, d, R, SSD1306_WHITE);
    display.fillCircle(c, f, R, SSD1306_WHITE);
  }
  if (value >= 4) {
    display.fillCircle(c, d, R, SSD1306_WHITE);
    display.fillCircle(a, f, R, SSD1306_WHITE);
  }
  if (value == 6) {
    display.fillCircle(a, e, R, SSD1306_WHITE);
    display.fillCircle(c, e, R, SSD1306_WHITE);
  }
}

void showDice(int one, int two) {
  display.clearDisplay();
  if (DICE == 1) {
    drawDie(42, 10, one);
  } else {
    drawDie(12, 10, one);
    drawDie(72, 10, two);
  }
  display.display();
}

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON, INPUT_PULLUP);
  Wire.begin(21, 22);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 not found at 0x3C");
    for (;;) delay(1000);
  }
  showDice(6, 6);
  Serial.println("Dice ready. Press the button to roll.");
}

void loop() {
  if (digitalRead(BUTTON) == HIGH) return;

  // Tumble: quick random faces that slow down, like a die settling.
  int one = 1, two = 1;
  for (int wait = 30; wait < 220; wait += 20) {
    one = 1 + esp_random() % 6;
    two = 1 + esp_random() % 6;
    showDice(one, two);
    delay(wait);
  }
  int total = DICE == 1 ? one : one + two;
  counts[total]++;
  rolls++;
  if (DICE == 1) Serial.printf("die1=%d\n", one);
  else Serial.printf("die1=%d die2=%d sum=%d\n", one, two, total);

  if (rolls % 12 == 0) {
    Serial.printf("after %d rolls:", rolls);
    for (int t = DICE; t <= DICE * 6; t++) Serial.printf(" %d:%d", t, counts[t]);
    Serial.println();
  }
  while (digitalRead(BUTTON) == LOW) delay(10);
  delay(50);
}

Parts

QuantityPartWhere to buy
1×ESP32 dev boardBuy at Amazon
1×0.96 inch SSD1306 OLED, I2C, address 0x3C
1×Push buttonBuy at Adafruit
6×Jumper wires

Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.

Libraries

Adafruit SSD1306, Adafruit GFX Library

Load it

  1. In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
  2. Install the libraries listed above from the Library Manager.
  3. Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
  4. Close the IDE's serial monitor, then open the bench here to watch the output.

Field notes

  • esp_random() uses the chip's hardware random number generator, which is truly random while the radio is on and plenty good for dice when it is off.
  • With two dice, 7 should come up most often: about one roll in six. The summary every 12 rolls lets you watch that happen.
  • Set DICE to 1 for a single die in the middle of the screen.

Not tested yet

  • Not tested on hardware yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.

Built it? Send a build report with your board and what the serial port printed. Working reports become the "Tested on this board" entries above.