projects:dice

You are not allowed to perform this action

Dobbelsteen op basis van Arduino

We kennen allemaal de reguliere dobbelsteen met 1 tot 6 ogen. We zouden deze natuurlijk ook elektronisch uit kunnen voeren, in dit project doen we dat met 7 LEDs, aangestuurd door een Arduino.

Zie ook het project Stamtafel Klup77 waarin een twee elektronische dobbelstenen zijn verwerkt:

  • Arduino Uno of Nano
  • 7 LEDs (per dobbelsteen)
  • 7 weerstanden (pakweg 300 tot 800 ohm) (per dobbelsteen)
  • Drukknop of andere inputsensor

Arduino pin 3 t/m 8 verbinden met serieschakeling van weerstand en LED, vanuit elke LED terug naar ground van de Arduino.

https://www.youtube.com/watch?v=RlgmNdrkF0Y

Eerste versie, volledig gebaseerd op het voorbeeld van Uri Shaked: https://wokwi.com/playground/dice-roller . In plaats van de drukknop uitgevoerd met een random input op een seriële terminal om de dobbelsteen te “rollen”.

// Arduino Dice Roller
// Copyright (C) 2020, Uri Shaked

#define BUTTON_PIN A0

const byte die1Pins[] = { 2, 3, 4, 5, 6, 7, 8};
//const byte die2Pins[] = { 9, 10, 11, 12, A3, A4, A5};  //uncomment entire line to enable second die

void setup() {
  pinMode(A0, INPUT_PULLUP);
  for (byte i = 0; i < 7; i++) {
    pinMode(die1Pins[i], OUTPUT);
    //pinMode(die2Pins[i], OUTPUT);  //uncomment entire line to enable second die
  }
  Serial.begin(9600);
}

void displayNumber(const byte pins[], byte number) {
  byte states = pins[0];
  for (byte i = 0; i < 7; i++) {
    digitalWrite(pins[i], LOW);
    delay(25);
  }
  switch (number) {
    case 1:
      digitalWrite(pins[3], HIGH);
      break;
    case 2:
      digitalWrite(pins[0], HIGH);
      digitalWrite(pins[6], HIGH);
      break;
    case 3:
      digitalWrite(pins[0], HIGH);
      digitalWrite(pins[3], HIGH);
      digitalWrite(pins[6], HIGH);
      break;
    case 4:
      digitalWrite(pins[0], HIGH);
      digitalWrite(pins[1], HIGH);
      digitalWrite(pins[5], HIGH);
      digitalWrite(pins[6], HIGH);
      break;
    case 5:
      digitalWrite(pins[0], HIGH);
      digitalWrite(pins[1], HIGH);
      digitalWrite(pins[3], HIGH);
      digitalWrite(pins[5], HIGH);
      digitalWrite(pins[6], HIGH);
      break;
    case 6:
      digitalWrite(pins[0], HIGH);
      digitalWrite(pins[1], HIGH);
      digitalWrite(pins[2], HIGH);
      digitalWrite(pins[4], HIGH);
      digitalWrite(pins[5], HIGH);
      digitalWrite(pins[6], HIGH);
      break;
  }
}

bool randomReady = false;

void loop() {
  bool buttonPressed = 0;
  Serial.println("Hit the button?");   //ask for input on serial terminal
  while(Serial.available() == 0) {}    //wait for input
  String answer = Serial.readString(); //read from serial terminal
  buttonPressed = 1;                   //as soon as any input is given, continue program
  
  
  if (!randomReady && buttonPressed) {
    // Use the time until the first button press
    // to initialize the random number generator
    randomSeed(micros());
    randomReady = true;
  }

  if (buttonPressed) {
    for (byte i = 0; i < 15; i++) {
      int num1 = random(1, 7);
      int num2 = random(1, 7);
      displayNumber(die1Pins, num1);
      //displayNumber(die2Pins, num2);  //uncomment entire line to enable second die
      delay(50 + i * 10);
      
    }
  }
}

In de eerste versie is het rollen gesimuleerd door een random input te lezen vanaf de seriële terminal. Elke willekeurige input volstaat om het programma door te laten gaan met een worp. Deze code handelt dat af:

  Serial.println("Hit the button?");
  while(Serial.available() == 0) {} //wait for input
  String answer = Serial.readString();
  buttonPressed = 1;
  

Dit is echter verre van praktisch, omdat er altijd een pc met seriële terminal nodig is om de dobbelsteen te laten werken. Daarom kan beter een van de volgende opties worden gekozen, al naar gelang de gewenste manier van 'gooien'.

De eerste praktischere mogelijkheid is het gebruiken van een drukknop. Een 'worp' gebeurt dan door kort op de drukknop te drukken. Prototype twee gebruikt een drukknop van het type APEM TP32. Deze schakelt tussen pin 2 en 3 de ground van de Arduino aan de input pin, die gedefinieerd is als “INPUT_PULLUP”. Bovenstaande code kan dan vervangen worden door de volgende regel:

  buttonPressed  = !digitalRead(BUTTON_PIN);

Een tweede optie is schakelen met een LDR. Door de LDR te verlichten of te verduisteren zou een worp gesimuleerd kunnen worden.

Ook een reedcontact is mogelijk, het 'gooien' gebeurt door een magneet langs de sensor te bewegen. Deze optie lijkt weinig haalbaar (sterkte magneet vs dikte tafelblad (afstand tot sensor), losse magneet nodig (kan kwijtraken). Derhalve bij voorkeur NIET toepassen.

Voorlopig laatste idee om een 'worp' te doen, is met een piëzo-sensor. Door deze in trilling te brengen (klap op tafel?) wordt de 'worp' geïnitieerd. Piezo element wordt aangesloten tussen analoge inputpin en ground, parallel aan het element een hoge weerstand (1MOhm). Uitlezen met een AnalogRead functie, schakelen bij overschrijding drempelwaarde (eerste experiment: ca. 50, voor hardere klap drempel verhogen, bijv. 250).

sensorValue = analogRead(BUTTON_PIN);   //lees analoge sensorwaarde (integer van 0 t/m 1023)
Serial.println(sensorValue);  //geef waarde weer op seriële terminal
if(sensorValue > 50){         //geef aan dat er gerold is als de waarde groter is dan de drempel  
  diceRolled = 1;
  }
  

https://www.arduino.cc/en/tutorial/knock

Bij gebruik van reguliere 5mm LEDs kunnen deze als volgt gepositioneerd worden binnen een vierkant van 40×40 mm:

  • Eén LED in het midden van het vlak.
  • Eén LED links en één LED rechts van deze LED, beide op 12 mm afstand
  • Eén LED boven en één LED onder elk van de in de tweede stap gepositioneerde LEDS, op een verticale afstand van 13 mm.

In geval van gaatjesprint: 15×16 gaatjes per dobbelsteen, middelste LED exact in het midden, links en rechts 4 kolommen vrijlaten, boven en onder 4 rijen vrijlaten. Positie weerstanden nader te bepalen.

Twee dobbelstenen tegelijk? Ja, ook dat kan. De code van versie 1 is er al op voorbereid ;) … Gebruik daarvoor de volgende pinnen (of definieer je eigen selectie): { 9, 10, 11, 12, A3, A4, A5}.

In plaats van elke LED aan een pin van de Arduino te linken, kan er op pinnen/poorten bespaard worden door LEDs die altijd in dezelfde combinatie voorkomen aan 1 output te linken. Van de 7 outputs per dobbelsteen, zouden er dan nog 4 nodig zijn, immers de paren (0,6), (1,5) en (2,4) zijn altijd per paar aan- of uitgeschakeld.

D.w.z. Dat de pinnen 6,5 en 4 kunnen vervallen, als de respectievelijke LEDs aan de pinnen 0, 1 en 2 worden aangesloten, parallel aan de reeds aangesloten LEDs. (check stroom met max. output Arduino ~40mA, evt R verhogen)

Energie besparen: door na een periode van inactiviteit de LEDS uit te schakelen kan energie bespaard worden.

  if (millis() >= time_now + period) {
    //after certain time of inactivity (period) LEDs should go off. (actual timestamp greater or equal to last roll + period)
    fadeOut(die1Pins);
    fadeOut(die2Pins);
  }
  





  • projects/dice.txt
  • Last modified: 22/09/2023 12:41
  • by ron