Schud-geactiveerde Arduino Dobbelsteen met LED Matrix
Onderdelen en Benodigdheden
| Onderdeel | Aantal |
|---|---|
| Arduino Nano R3 | 1 |
| 3mm 8x8 Dot Matrix MAX7219 | 1 |
| Kantschakelaar module met digitale interface | 1 |
| Schuifschakelaar | 1 |
| MT3608 DC 2A Step Up Power Module (2V-24V naar 5V/9V/12V/28V) | 1 |
Benodigde Tools en Machines
- Solderbout (algemeen)
- Lijmpistool (algemeen)
Apps en Online Services
- Arduino IDE
- Autodesk Fusion 360
Over dit Project
Ongeveer een jaar geleden bouwden mijn zoon en ik een elektronische dobbelsteen met een Arduino en enkele LEDs. Dat was nog steeds een ideaal project voor beginners. We hebben dit jaar veel geleerd, dus het is hoog tijd voor een update.
De dobbelsteen blijft een perfect startproject. De functie is voor iedereen duidelijk en het is makkelijk om de verschillende gebieden te begrijpen: microcontroller, eenvoudige elektronica en programmeren.
Versie 2.0
De dobbelsteen is ook fantastisch om een stap verder te gaan: het koppelen van andere domeinen. Tegenwoordig is er voor bijna alles een kant-en-klaar component. Dit zie je goed in starterskits voor Arduino of Raspberry Pi. Componenten zoals LEDs, drukknoppen en sensoren zitten al op een printplaat en kunnen met enkele draden aan GPIO's worden aangesloten.
Eenvoudige 3D-printers zijn voor minder dan €140 te koop. Bijna alle beugels, montages of behuizingen kun je ermee maken. Onze nieuwe dobbelsteen 2.0 is een voorbeeld van deze mogelijkheden.
Kantsensoren
We realiseren de dobbelsteen op een totaal andere manier. Binnenin werkt een Arduino Nano (om ruimteredenen). Er zit nog een aan/uit-schakelaar, maar geen knop. Het dobbelen gebeurt door de hele kubus te schudden.
Hiervoor gebruiken we kantsensoren of trillingssensoren. Ze werken net als een knop. In een glazen buis beweegt een balletje. Als het de contacten raakt, sluit het de stroomkring. Dit contact, soms heel kort, wordt als signaal gebruikt. De beweging van het metalen balletje is goed te horen als je de sensor schudt.
Normaal is de montagepositie beslissend voor een kantsensor. Het moet een signaal triggeren bij een bepaalde hoek. In ons geval gebeurt dit door de behuizing te schudden. De richting is niet zo belangrijk, want in elke richting ontstaat een signaal. Voor zekerheid gebruiken we twee sensoren, 90° verspringend gerangschikt, zodat we altijd een betrouwbaar schudsignaal krijgen.
Interrupts
Om te herkennen wanneer er geschud wordt, zouden de ingangspinnen van de kantsensoren in de sketch moeten worden uitgelezen. Afhankelijk van het moment en wat de sketch anders doet, kunnen gebeurtenissen gemist worden.
Een betere oplossing is het gebruik van hardware-interrupts. Dit wordt gedefinieerd met de functie attachInterrupt. Als parameter geef je een subprogramma op dat bij het signaal wordt aangeroepen. De Arduino biedt twee hardware-interrupts: pinnen D2 en D3.
Display
Het dobbelbeeld kan weer met 7 losse LEDs worden getoond, maar het is interessanter om een kant-en-klaar component te gebruiken. Onze keuze valt op een 8x8 LED-matrix met MAX7219 driver IC. Het neemt weinig ruimte in, kost weinig en is eenvoudig te programmeren.
Afhankelijk van waar je het koopt, moet je de losse onderdelen zelf solderen en monteren. Dat is normaal geen probleem. De enige fout die je kunt maken is de LED-matrix verdraaid in de sokken plaatsen. Dit herken je aan de afbeelding hierboven. Het is voldoende om de matrix voorzichtig uit de sokken te halen en 180° te draaien.
Wat Natuurkunde
De LED-matrix moet niet alleen het dobbelresultaat tonen. Het moet ook show-effecten bieden. De zes dobbelogen bewegen over de matrix: ze botsen tegen de randen en verlopen langzaam aan snelheid.
Via de twee kantsensoren meten we hoeveel er geschud wordt. Deze informatie geven we aan de dobbelogen als "snelheid" voor hun beweging. We gebruiken een vergelijkbaar effect bij het tonen van het resultaat: de ogen rollen van hun willekeurige positie naar de correcte positie in het dobbelbeeld.
Voeding
Eerst hebben we twee 3V CR2032 knoopcellen geïnstalleerd om ruimtebesparende redenen. In het begin werkte het goed. De Arduino en LED-matrix speelden mee. Maar na enkele minuten zakte de spanning van de knoopcellen in. Als je de Arduino na elke worp uitschakelt, zou het kunnen werken, maar dat is niet ideaal. Daarom gebruiken we twee AAA-batterijen. Deze leveren samen 3V, dus we hebben nog een step-up converter nodig die de spanning naar 5V optrekt. De aansluiting gebeurt nog steeds op de VIN-pin van de Arduino.
Behuizingontwerp
De beste optie voor een passende behuizing is een eigen ontwerp en productie via 3D-printen. Er zijn veel ontwerpprogramma's. We hebben Autodesk Fusion 360 gebruikt. Het heeft geweldige functies en 3D-printen is goed geïntegreerd met de Print Studio software.
Onze behuizing bestaat uit 3 delen:
- Bovenkant
- Onderkant met batterijhouder voor AAA-cellen
- Plexiglas deksel (niet verplicht)
De LED-matrix ziet er nog beter uit met een melkig plexiglasdeksel ervoor. Hierdoor zijn de uitgebrande LEDs niet zichtbaar en is het beeld helderder.
Sketch
Om de LED-matrix aan te sturen is de LedControl bibliotheek vereist. Als deze nog niet geïnstalleerd is, kan deze worden gedownload van arduino.cc.
Vervolgens definiëren we de overige variabelen. Eerst bepalen we hoe de dobbelogen op de matrix worden weergegeven. Een dobbeloog bestaat uit 4 LED-punten. In de array wordt de linkerbovenhoek opgegeven als X/Y-coördinaat (-1 betekent buiten het display).
De overige uitleg vind je direct in de code.
Montage
We plaatsen onze Arduino op een socketstrip, als een soort shield. De vijf contacten van de LED-matrix worden op dezelfde manier aangesloten. Als de Arduino gecentreerd zit, wordt de ruimte optimaal benut. Daarom is het best om pinnen 5, 6, 7 te gebruiken voor CS, CLK en DIN van de matrix. Daarna hoeven alleen de soldeerpuntsverbindingen gemaakt te worden. De verbinding met 5V en GND loopt via een kleine jumper.
We sluiten ook de twee kantsensoren met korte draden aan. Deze zitten op pin 2 en 3 en 5V en GND.
Nu kan alles gemonteerd worden. Het plexiglas wordt eerst met lijm vastgemaakt. Hetzelfde doen we met de LED-matrix. Een klein puntje lijm is voldoende. Vervolgens wordt de aan/uit-schakelaar gemonteerd, bevestigd met lijm en aangesloten op de juiste draden.
Voeding Montage
De voeding is een beetje knutselwerk. Afhankelijk van welke opties en componenten je hebt, kunnen de contacten voor plus en min dienovereenkomstig worden aangepast. We gebruiken de veertjes en pennen van een gebruikt batterijvak. Voor de bevestiging aan de onderkant van de behuizing gebruiken we weer draden en een beetje lijm.
De step-up boost converter wordt het beste van tevoren ingesteld op ongeveer 5V. Hiervoor moet de weerstand iets worden gedraaid. Dan worden boven- en onderkant samengevoegd. Door de pas van 0,1 mm is samendrukken zonder verdere bevestiging voldoende. En ze kunnen nog steeds geopend worden voor batterijwissel.
En dan is hij klaar! De dobbelpret 2.0 kan beginnen!
Wat Je Nodig Hebt
- Arduino Nano (of ESP8266)
- 2 x kantsensoren (met geïntegreerde weerstanden)
- 8x8 LED Matrix met MAX7219 IC, SPC
- Socketstrip
- Aan/uit-schakelaar
- Printplaat
- 2 x AAA batterijen
Meer Informatie
Wil je meer lezen? Bekijk onze website techpluscode.de/arduino-wuerfel-2-0. Let op: deze uitgebreide blog is alleen in het Duits beschikbaar ;-)
Code
wuerfel8x8.ino (Arduino)
/* Blog-Artikel: Schüttel-Würfel mit LED Matrix und Bewegungssimulation
https://techpluscode.de/schuettel-wuerfel-mit-led-matrix-und-bewegungssimulation/
techpluscode.de Copyright 2019 von Thomas Angielsky */
#include "LedControl.h"
int PinTiltX = 2;
int PinTiltY = 3;
int PinCLK = 7;
int PinCS = 6;
int PinDIN = 5;
LedControl lc = LedControl(PinDIN, PinCLK, PinCS, 1);
int DicePic[8][6][2] = {
{ // Lege matrix en startpositie
{9,9}, {9,8}, {9,7}, {9,6}, {9,5}, {9,4}
},
{ // 1
{4,4}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}
},
{ // 2
{2,2}, {6,6}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}
},
{ // 3
{2,6}, {6,2}, {4,4}, {-1,-1}, {-1,-1}, {-1,-1}
},
{ // 4
{2,2}, {2,6}, {6,2}, {6,6}, {-1,-1}, {-1,-1}
},
{ // 5
{2,2}, {2,6}, {6,2}, {6,6}, {4,4}, {-1,-1}
},
{ // 6
{2,1}, {2,4}, {2,7}, {6,1}, {6,4}, {6,7}
},
{ // Start
{-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1}
}
};
float DiceXpos[6];
float DiceXdir[6];
volatile byte DiceXspeed[6];
float DiceYpos[6];
float DiceYdir[6];
volatile byte DiceYspeed[6];
int DiceValue;
unsigned long timestamp;
byte Mode;
int volatile shakes;
int ShakesPerSecond;
int step;
void InterruptChecks() {
shakes = shakes + 1;
timestamp = millis();
}
void SetSpeedX() {
if (Mode == 0) {
for (int i = 0; i < 6; i++) {
if (DiceXspeed[i] < 255) DiceXspeed[i] = DiceXspeed[i] + 5;
}
}
InterruptChecks();
}
void SetSpeedY() {
if (Mode == 0) {
for (int i = 0; i < 6; i++) {
if (DiceYspeed[i] < 255) DiceYspeed[i] = DiceYspeed[i] + 5;
}
}
InterruptChecks();
}
void ShowLed(int x, int y, bool onoff) {
if ((x < 8) && (y < 8) && (x >= 0) && (y >= 0)) {
lc.setLed(0, x, y, onoff);
}
}
void ShowDot(int x, int y, bool onoff) {
ShowLed(x-1, y-1, onoff);
ShowLed(x, y-1, onoff);
ShowLed(x-1, y, onoff);
ShowLed(x, y, onoff);
}
void ShowDicePic(int value) {
boolean done;
for (int i = 0; i < 6; i++) {
DiceXspeed[i] = 100;
DiceYspeed[i] = 100;
DiceXdir[i] = 0;
if (int(DiceXpos[i]) > DicePic[value][i][0]) DiceXdir[i] = -1;
else if (int(DiceXpos[i]) < DicePic[value][i][0]) DiceXdir[i] = 1;
DiceYdir[i] = 0;
if (int(DiceYpos[i]) > DicePic[value][i][1]) DiceYdir[i] = -1;
else if (int(DiceYpos[i]) < DicePic[value][i][1]) DiceYdir[i] = 1;
}
do {
for (int i = 0; i < 6; i++) {
if (int(DiceXpos[i]) != DicePic[value][i][0]) DoStep(DiceXpos[i], DiceXdir[i], DiceXspeed[i], false);
if (int(DiceYpos[i]) != DicePic[value][i][1]) DoStep(DiceYpos[i], DiceYdir[i], DiceYspeed[i], false);
}
lc.clearDisplay(0);
for (int i = 0; i < 6; i++) ShowDot(int(DiceXpos[i]), int(DiceYpos[i]), true);
delay(50);
done = true;
for (int i = 0; i < 6; i++) {
if (int(DiceXpos[i]) != DicePic[value][i][0]) done = false;
if (int(DiceYpos[i]) != DicePic[value][i][1]) done = false;
}
} while (done == false);
lc.clearDisplay(0);
for (int i = 0; i < 6; i++) ShowDot(DicePic[value][i][0], DicePic[value][i][1], true);
}
void DoStep(float &pos, float &dir, volatile byte &sp, bool check) {
pos = pos + float(sp)/255 * dir;
if (check == true) {
if (pos > 7) { pos = 7; dir = dir * (-1); }
if (pos < 1) { pos = 1; dir = dir * (-1); }
}
if (sp > 0) sp = sp - 1;
}
void MoveDots() {
for (int i = 0; i < 6; i++) {
DoStep(DiceXpos[i], DiceXdir[i], DiceXspeed[i], true);
DoStep(DiceYpos[i], DiceYdir[i], DiceYspeed[i], true);
}
lc.clearDisplay(0);
for (int i = 0; i < 6; i++) ShowDot(int(DiceXpos[i]), int(DiceYpos[i]), true);
}
void setup() {
lc.shutdown(0, false);
lc.setIntensity(0, 8);
lc.clearDisplay(0);
randomSeed(analogRead(0));
DiceValue = 0;
for (int i = 0; i < 6; i++) {
DiceXpos[i] = DicePic[7][i][0];
DiceYpos[i] = DicePic[7][i][1];
DiceXdir[i] = random(3) - 1;
DiceYdir[i] = random(3) - 1;
DiceXspeed[i] = random(126) + 120;
DiceYspeed[i] = random(126) + 120;
}
pinMode(PinTiltX, INPUT_PULLUP);
pinMode(PinTiltY, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PinTiltX), SetSpeedX, CHANGE);
attachInterrupt(digitalPinToInterrupt(PinTiltY), SetSpeedY, CHANGE);
lc.clearDisplay(0);
timestamp = millis();
Mode = 1;
ShowDicePic(6);
delay(1000);
lc.clearDisplay(0);
Mode = 0;
Serial.begin(9600);
step = 0;
shakes = 0;
}
void loop() {
delay(50);
step = step + 1;
if (step > 20) {
step = 0;
ShakesPerSecond = shakes;
shakes = 0;
}
if (Mode == 0) {
MoveDots();
if (millis() - timestamp > 2000) {
Mode = 1;
DiceValue = random(6) + 1;
ShowDicePic(DiceValue);
}
}
if (ShakesPerSecond > 5) {
Mode = 0;
}
}
Schema
Dit is mijn schets voor de schakeling.
Productieproces
- De Geschiedenis, Ontwerp en Productie van Dobbelstenen: Van Oude Hulpmiddelen tot Modern Gaming
- Arduino-gebaseerd schakelaar- & LED-paneel voor Microsoft Flight Simulator 2020
- Arduino Digitale Dobbelsteen: Bouw Je Eigen LCD-willekeurige Getalgenerator
- Bluetooth-gecontroleerde Arduino Spybot bouwen
- FlickMote: Gebarengecontroleerde IR-afstandsbediening voor Slimme Huizen
- DIY Arduino TV-B-Gone: Universele TV-uit-schakelaar
- Bouw een Aangepaste LED Hoofdklok met Alarm – Zichtbaar vanaf 12 Meter
- Bouw een Tetris-spel met Arduino Nano op een Zelfgemaakte 16×8 LED-matrix
- Find Me: Slimme Item Locator met Arduino en Bluetooth
- Geoptimaliseerde Voedingsoplossingen voor Arduino Projecten
- Slimme Draadloze Lichtschakelaar Controller: Arduino-gebaseerde Remote Switch Manipulator