Skip to content

Digital Dice 🎲

My goal is to build myself a digital dice. I’m an exchange student from Czechia and I’m working on this kind of project for the first time. I’m going to try to designed a circuit for displaying the dice values on 7-segment display using Arduino Uno and Wemos D1 mini.

You can see my progress below!⬇️🤓

The first base of my digital dice.

If the user presses the first green button on the right, the numbers from 1 to 6 should be displayed. When the user presses the second green button on the left, the numbers from 0 to 9 should be displayed. If the button on the ir remote is pressed, the number is also displayed. Every time a number appears, the cube should make a sound. My goal was to have the 7 segment display show a number whenever the user presses a button. More information about the product design can be found in the section “Physical design”

In my case, my product is just called “Geacube”. I really like this official name, it’s not too long or too short. The first three letters are from the word gear.

There is nowhere specified what you start with when creating your project. I personally started with a database first. Now in retrospect, I realize it wasn’t the smartest idea.

The first step everyone should take when creating their project is to make a plan. Make a plan detailing what weeks you will be working on. Determine what your weaknesses are and what you are good at so you know what you can get stuck on, for example. In this, my first project, I skipped this step and also found out after a while that it was a big mistake. Because I was kind of doing all the parts at once, and that didn’t quite work for me.

I will describe the steps I followed (I determined these steps myself. Next time I would make a plan and follow a different procedure. I will add that nowhere is it described what steps to start with): The first thing I did was to start creating the front-end (HTML, CSS and JS) because it was quite simple for me. Then I created a database and worked on the Backend (PHP). In between these steps I created on an embedded device using C++, because of the Arduino. Once I had the software and hardware ready, I went to the Makers Lab where I created my physical product design in the Laser cutting machine.

Embedded Device

I was working with hardware for the very first time so I spent a lot of time on various tutorials. This is what my embedded device looked like in the beginning:

Alternative text

Alternative text

I’m using a Wemos D1 mini connected to an Arduino Uno because I didn’t have enough pinmodes on the Wemos D1 mini and used a large breadboard. I had to use the Wemos D1 mini because I had to adhere to certain requirements, such as the product must have WiFI. I’ve got two input buttons. One button on the right generates numbers from 1 to 6. The second button on the left generates numbers from 0 to 9. And as an additional input, I also have an IR remote with an IR receiver. The requirement was also to have 2 outputs. As one I have a 7segment display showing a random number. And as a second output I use a buzzer. The embedded device sends the actual sensor data to the application backend via https. And this is what my finished embedded device looks like:

Alternative text

When the button is pressed, a random number is displayed in the image. In order for the Geacube to work, you need to connect two USB C cables to the Wemos D1 mini and Arduino uno. Since I didn’t have long enough cables and also for better cable management I will use a USB hub.

Alternative text

Program Code

Below you can see my commented code for Wemos D1 mini and Arduino Uno. ⬇️

Wemos D1 mini code

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#define BAUD 115200
#define DELAY 1000
#define CONTENT_TYPE "Content-Type"
#define APPLICATION_JSON "application/json"
#define DICE_TYPE_6 "D06"
#define DICE_TYPE_9 "D09"
#define RESPONSE "response"
#define JSON_NUMBER "1024"
#define CONNECTED "connected"
#define ZERO 0
#define NUMBER 6

/**
 * This C++ script builts the DigitalDice.
 * @author Lucie Banszelova
 * @license MIT License
 *
 */


int currentNumber = 0;
String URL = "http://banszel.loca.lt/dice.php";  // API endpoint URL


void setup() {
  const char* ssid = "Your_SSID";  // Change to your Wi-Fi network SSID
  const char* password = "Your_Password";        // Change to your Wi-Fi network password

  WiFi.begin(ssid, password);
  Serial.begin(BAUD);

  // Wait until the board is connected to the Wi-Fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(DELAY);
    Serial.println("Connecting to Wi-Fi...");
  }
  Serial.println("Connected to Wi-Fi.");
}

void loop() {

  currentNumber = Serial.parseInt();  // reads number from arduino
  if (currentNumber > ZERO)              //when the number is more than zero
  {
    addRoll(currentNumber);
  }
}

void addRoll(int currentNumber) {
  WiFiClient client;                               // Get current wifi connection
  HTTPClient httpClient;                           // Client HTTP request
  DynamicJsonDocument jsonBuffer(JSON_NUMBER);
  jsonBuffer[JSON_NUMBER] = currentNumber;

    if (currentNumber > NUMBER ) {
      jsonBuffer["dice_type"] = "DICE_TYPE_6";
    } else {
      jsonBuffer["dice_type"] = "DICE_TYPE_9";
    }

  String jsonString;
  serializeJson(jsonBuffer, jsonString);
  Serial.println(jsonString);

  httpClient.begin(client, URL);
  httpClient.addHeader(CONTENT_TYPE, APPLICATION_JSON);


  int httpResponseCode = httpClient.POST(jsonString);  // Send post request
  Serial.println(RESPONSE);
  Serial.println(httpResponseCode);
  if (httpResponseCode == HTTP_CODE_OK) {
    String response = httpClient.getString();
    Serial.println(RESPONSE);

    // Parse the JSON response and retrieve the "message" field
    DynamicJsonDocument jsonResult(JSON_NUMBER);
    deserializeJson(jsonResult, response);
    String message = jsonResult["message"];
    Serial.println("Response message: " + message);
  } else {
    Serial.println("Failed to retrieve message from API.");
  }
  httpClient.end();
}


void setup() {
   WiFiManager wm;
   bool res;
   res = wm.autoConnect("GeacubeAP", "password"); //password protected ap
   Serial.begin(BAUD);

   if (!res) {
  Serial.println("Failed to connect");
   //ESP.restart();
   }
   else {
      //if you get here you have a connected to the WiFi
  Serial.println(CONNECTED)
}
}

Arduino Uno code

#include <IRremote.h>
#define SERIAL 115200
#define RIGHTBUTTONONE 1
#define RIGHTBUTTONTWO 7
#define LEFTTBUTTONONE 1
#define LEFTTBUTTONTWO 10
#define BUTTONDELAY 200
#define TONEBUZER 980
#define BUZERDELAY 1000
#define APPLICATIONJS "application/json"
#define DICETYPE6 "D06"
#define DICETYPE9 "D09"
#define RESPONSE "response"
#define SERIAL_RECEIVER 9600
#define DELAY 100
#define NUMBER_ONE 1
#define NUMBER_SEVEN 7
#define NUMBER_TEN 10

/**
 * This C++ script builts the DigitalDice.
 * @author Lucie Banszelova
 * @license MIT License
 *
 */


const int A = 2;
const int B = 3;
const int C = 4;
const int D = 7;
const int E = 8;
const int F = 12;
const int G = 13;

const int lowButton = 6;
const int highButton = 9;

const int buzzer = 11; //buzzer to arduino pin 15
const int irPin = 10;
int random_int = 0;
IRrecv receiver(irPin);

decode_results results;


void setup() {
  Serial.begin(SERIAL);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // Turn off built-in LED
  pinMode(lowButton, INPUT_PULLUP);
  pinMode(highButton, INPUT_PULLUP);
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);

  pinMode(buzzer, OUTPUT); // Set buzzer as an output
  receiver.enableIRIn();
  // Wait until the board is connected to the Wi-Fi network
}

void loop() {
  int push_button_1 = digitalRead(lowButton);
  int push_button_2 = digitalRead(highButton);
  // If either push button is pressed, generate a new random number and display the corresponding LED pattern
  if (push_button_1 == LOW) {
    random_int = random(NUMBER_ONE, NUMBER_SEVEN); // Generate a random number between 1 and 6
// Wait for 2 seconds before allowing another roll
    sendNumb(random_int);
    displayLED(random_int);
  }

  if (push_button_2 == LOW)
  {
    random_int = random(NUMBER_ONE, NUMBER_TEN); // Generate a random number between 1 and 9
    sendNumb(random_int);
    displayLED(random_int);
  }

  // If neither push button is pressed, display the last generated random number
  else {
    Serial.write(random_int);
  }
  delay(BUTTONDELAY);
}
void buzzerSound(){
  tone(buzzer, TONEBUZER); // Send 1KHz sound signal...
  delay(BUZERDELAY);        // ...for 1 sec
  noTone(buzzer);     // Stop sound...
}

void sendNumb(int random)
{
    Serial.write(random); //send numbers to Wemos
    Serial.println();
    buzzerSound(); // make sound to wemos
}

void setup()
  Serial.begin(SERIAL_RECEIVER);
  irrecv.enableIRIn(); // Start the receiver

  void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  delay(DELAY);
}


void displayLED(int num) {
  // Turn off all LEDs
    digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  // Display the corresponding LED pattern for the given number
  switch (num) {
    case 0:
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(E, HIGH);
      digitalWrite(F, HIGH);
      break;
    case 1:
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      break;
    case 2:
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(E, HIGH);
      digitalWrite(G, HIGH);
      break;
    case 3:
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(G, HIGH);
      break;
    case 4:
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(F, HIGH);
      digitalWrite(G, HIGH);
      break;
    case 5:
      digitalWrite(A, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(F, HIGH);
      digitalWrite(G, HIGH);
      break;
    case 6:
      digitalWrite(A, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(E, HIGH);
      digitalWrite(F, HIGH);
      digitalWrite(G, HIGH);
      break;
      case 7:
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      break;
    case 8:
      digitalWrite(A, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(D, HIGH);
      digitalWrite(E, HIGH);
      digitalWrite(F, HIGH);
      digitalWrite(G, HIGH);
      break;
      case 9:
      digitalWrite(A, HIGH);
      digitalWrite(C, HIGH);
      digitalWrite(B, HIGH);
      digitalWrite(F, HIGH);
      digitalWrite(G, HIGH);
      break;
  }
}

Database MySql

The database is used to store all the necessary data about my digital dice. I have created a database in which I can see all the data such as the results of the dice and the date they were used. My database system is able to provide services such as: efficient database manipulation, database structure definition, concurrent data access and data protection. If a number is generated, it is automatically written to my front-end page and stored in the database.🔍

I wrote this code SQLcode.

Backend

Here you can see my commented code. PHP programming language was required.

<?php

// @author Lucie Banszelova
// @information Backend PHP
// @license MIT License
// @goal Create Rest API. And to store and display dice rolls in the database.

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");

// set up database connection
$servername = "Your_Server_Name";
$username = "Your_User_Name";
$password = "Your_Password";
$dbname = "Your_DB_Name";

// connect to database
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// set headers
header("Content-Type: application/json");

// check request method
$method = $_SERVER["REQUEST_METHOD"];

// get data from request body
$data = json_decode(file_get_contents("php://input"), true);
// handle GET request
if ($method === "GET") {
    // get all data from table
    $sql = "SELECT RollID, result, date, dice_type FROM DigitalDiceRoll";
    $result = $conn->query($sql);

    // check if any data is returned
    if ($result->num_rows > 0) {
        // create an array to store data
        $data = array();
        while ($row = mysqli_fetch_assoc($result)) {
            $data[] = $row;
        }

        // return data as JSON
        echo json_encode($data);
    } else {
        // return error message
        // echo json_encode(array("message" => "No data found."));
    }
}
// handle POST request
if ($method === "POST") {

    // set date to current datetime
    $data["date"] = date("Y-m-d H:i:s");

    // prepare and execute SQL statement
    $sql = "INSERT INTO DigitalDiceRoll (result, date, dice_type) VALUES (?, ?, ?)";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("iss", $data["result"], $data["date"], $data["dice_type"]);
    if ($stmt->execute()) {
        // return success message
        echo json_encode(array("message" => "Data inserted successfully."));
    } else {
        // return error message
        echo json_encode(array("message" => "Failed to insert data."));
    }
}

// close database connection
$conn->close();
?>

Frontend

Here you can see my commented code. HTML and CSS programming languages were required. This is what my Front-end page looked like. ⬇️

Alternative text

Code HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      href="data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAqGMUAE2vuAAVll4AvXgqADWPDgA2jpYAJIyeAEansAAnipwANbBJAIxLAAAnlagARrCCAAAAAAAAAAAAAAALu6rQAAAAC7u9o90wAAC7uxzaOqoAC7sREczaG7ALsREauxERsLsREcG7FBG7uxHay7sRQRu7FisbuxERG7sYKxu7EUEbu8yaGrsRQRu7wsLcqxERuwvIhyyqFBGwC6Xc3VVRG7AAul3boRG9AAAF1bu7G9AAAAANXbuwAAD4HwAA4AcAAMADAACAAQAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAQAAwAMAAOAHAAD4HwAA"
      rel="icon"
      type="image/x-icon"
    />
    <link rel="stylesheet" href="static/css/app.css" />
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="static/js/tunnel-script.js"></script>
    <script src="static/js/api.js"></script>
    <title>My 7 segment digital dice</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Tomorrow:wght@700;800&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
  </head>

  <body class="m-auto">
    <h1 class="h1">Dice roll results</h1>
    <div id="roll-container" class="flex flex-col space-y-4"></div>

    <footer class="flex flex-row-reverse p-5">
      <ul
        id="footer-nav"
        class="flex flex-wrap items-center mt-3 text-sm text-gray-500"
      >
        <li>
          <a href="/phpmyadmin" class="mr-4 hover:underline md:mr-6"
            >PhpMyAdmin</a
          >
        </li>
      </ul>
    </footer>
  </body>
</html>

Code CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background: linear-gradient( #19335A,#8FC8EB) 0 100% no-repeat;
  max-width: 600px;
  margin: 0px auto;
}



.Result {
  font-size: 24px;
  font-weight: bold;
}

.rollBox {
  border-bottom: 10px solid green;
}

h1 {
  font-size: 64px !important;
  color: white;
  padding-top: 100px;
  padding-bottom: 50px;
}

Physical Design

For the physical design, I could choose whether my product would be made from a laser cutting machine or a 3D printer. I chose the laser cutting machine because it’s much faster and I honestly think it’s easier. For my next project, if I have more time, I will definitely choose the 3D printer, because then the PLA product looks much better.

The selected machine is a PRO 1600 laser cutting machine from BRM Lasers. The cutting area of the PRO 1600 is 1600mm x 1000mm, providing ample space for cutting large sheets of materials.

The dimensions of my cube are 19 x 19 x 19 cm. The dimensions of the buttons are 1,3 cm x 1,3 cm. The dimensions for my display are 13.40 mm x 20.04 mm. The kerf is -0,050 mm. My Geacube still contains one cut-out with the same dimensions as the 7-segment display, which is used for cables and receiver. I use MDF 4 mm. This material refers to a type of engineered wood product made from wood fibers and resin, with a thickness of 4 millimeters. MDF stands for Medium Density Fiberboard, which is a popular building material used in a variety of applications, such as furniture, cabinetry, and decorative molding.

This is what the PRO 1600 laser cutting machine looks like:

Alternative text

This is what my visualization looks like:

Alternative text

I created a model of the cube in https://www.makercase.com/. It’s a simple six-sided cube. And then I imported my file of the model of my six-sided cube into the program https://lightburnsoftware.com/. I used LightBurn because of the teacher’s recommendation. Here I attach my file: DesignFileImportedIntoTheLaserCutter DesignFile

Here you can see my sketches.⬇️

Alternative text

This is what I wanted my cube to look like:

Alternative text

In creating. Firstly, I measured my embedded device and then used the dimensions to design the models in the software. Then I picked up the material and started getting familiar with the laser cutting machine. I imported my file of the model of my six-sided cube into the program https://lightburnsoftware.com/. Then, I pointed the laser “pencil” at the edge of the material to save as much space as possible during production. And lastly, I pressed the button to turn on the laser cutting. I waited less than 15 minutes and then assembled my dice. I waited less than 15 minutes for the machine to complete its task. If, as I mention below, I had tested my file, I might have been able to put the cube together on the first try. All the sides fit together perfectly.

Alternative text

Alternative text

Alternative text

Alternative text

Of course, there was a failure during my project. For example, this is what a material looks like that wasn’t measured correctly so I couldn’t use it.

Alternative text

And this is what it looks like in real life:

Alternative text

This is what the Geacube display looks like when the button is displayed.

Alternative text

And what it currently looks like as a finished product.⬇️

Alternative text

Profile phase

In my profile section I chose to do research on the question: “How can my “Geacube” make the viewer experience in public gaming competitions more enjoyable?”. I suggested 3 other ways that would improve my Geacube, especially for the audience at public competitions. I developed a survey and summarized the results in a chart. Most respondents were interested in the addition of Bluetooth technology, which allows them to see the results displayed visibly on a screen during the public competition.

Conclusion

In the end, I’m happy with my project and I’m proud of myself for actually getting to the finished product. Of course, my product is not the most beautiful, but I think I got a nice result for this project being my first. I really enjoyed this project, even though it was very stressful for me. I would definitely size down my product next time. I would use an Inter-Integrated Circuit that would communicate with Wemos D1 mini and then I wouldn’t have to use an Arduino Uno, which would then not have to have such a large breadboard that made the Geacube this huge.


Last update: April 23, 2023