Mini progetto “dado elettronico” – due soluzioni

Ricordate la lezione: “randomSeed() su Arduino come usarla“. Vi avevo proposto un semplice esercizio sulla realizzazione di un dado digitale che genera un numero casuale da 1 a 6.

Vi propongo le due soluzioni:

  1. Con pulsante su pin digitale (lancio “fisico”)
  2. Con input da Serial Monitor (lancio “software”, immediato)

Entrambe sono adatte sia a Arduino UNO R3 sia a Arduino UNO R4.

Riprendiamo i concetti chiave visti nella lezione su randomSeed():

random(1,7) genera un numero pseudo-casuale tra 1 e 6.
Per evitare che la sequenza sia sempre uguale dopo un reset, conviene inizializzare il generatore con randomSeed(…). Nel dado, la cosa migliore è legare il seed a qualcosa di “imprevedibile”, ad esempio il momento in cui premete un pulsante (tempo umano) oppure un input seriale.

Versione A: dado con pulsante (pin digitale)

Materiale

  • 1 × Arduino UNO R3 o UNO R4
  • 1 × pulsante
  • cavetti e breadboard

Collegamenti

Usiamo la resistenza di pull-up interna, quindi niente resistenze esterne.

  • un piedino del pulsante -> GND
  • l’altro piedino del pulsante -> D2

Nel codice imposteremo pinMode(2, INPUT_PULLUP): a riposo il pin legge HIGH, quando premete legge LOW, ciò permette un cablaggio più semplice e rapido.

Nello sketch che segue imposteremo

  • debounce software (anti-rimbalzo)
  • seed inizializzato alla prima pressione usando micros() (molto efficace perché dipende dal tempo umano)
/*
  Prof. Maffucci Michele
  15.02.26
  Dado elettronico 1..6 con pulsante su D2 (INPUT_PULLUP).
  Include debounce e inizializzazione randomSeed al primo lancio.
*/

const byte PIN_PULSANTE = 2;

const unsigned long DEBOUNCE_MS = 30;

bool seedInizializzato = false;

int ultimoStatoLetto = HIGH; // con pull-up: HIGH a riposo
int statoStabile = HIGH;
unsigned long ultimoCambio = 0;

void setup() {
  Serial.begin(9600);
  delay(1000);
  pinMode(PIN_PULSANTE, INPUT_PULLUP);

  Serial.println("Dado elettronico (pulsante su D2).");
  Serial.println("Premi il pulsante per lanciare.\n");
}

void loop() {
  int lettura = digitalRead(PIN_PULSANTE);

  // Rilevo cambiamenti (possibili rimbalzi)
  if (lettura != ultimoStatoLetto) {
    ultimoCambio = millis();
    ultimoStatoLetto = lettura;
  }

  // Se è passato il tempo di debounce, considero stabile
  if (millis() - ultimoCambio > DEBOUNCE_MS) {
    if (lettura != statoStabile) {
      statoStabile = lettura;

      // Evento: pressione (con pull-up la pressione è LOW)
      if (statoStabile == LOW) {
        lanciaDado();
      }
    }
  }
}

void lanciaDado() {
  // Seed al primo lancio: il tempo umano rende la sequenza non ripetibile
  if (!seedInizializzato) {
    unsigned long seme = micros() ^ (unsigned long)analogRead(A0); // A0 può anche essere scollegato
    randomSeed(seme);
    seedInizializzato = true;
  }

  int risultato = random(1, 7); // 1..6

  Serial.print("Lancio! Risultato: ");
  Serial.println(risultato);
}

Versione B: dado con Serial Monitor (input testuale)

Una volta caricato lo sketch procedete in questo modo:

  • aprite il Serial Monitor a 9600 baud
  • impostate “Invio” (newline) o “CR+LF”
  • digitate un qualsiasi tasto e premete invio -> il dado lancia
/*
  Prof. Maffucci Michele
  15.02.26
  Dado elettronico 1..6 con input da Serial Monitor.
  Scrivete un carattere e premete invio per lanciare.
*/

bool seedInizializzato = false;

void setup() {
  Serial.begin(9600);
  delay(1000);
  Serial.println("Dado elettronico (Serial Monitor).");
  Serial.println("Scrivi un carattere e premi INVIO per lanciare.");
  Serial.println("Esempio: scrivi 'l' e invia.\n");
}

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();

    // (Opzionale) scarto newline e carriage return
    if (c == '\n' || c == '\r') return;

    if (!seedInizializzato) {
      // Seed legato al momento in cui arriva il comando (tempo umano)
      unsigned long seme = micros() ^ (unsigned long)analogRead(A0);
      randomSeed(seme);
      seedInizializzato = true;
    }

    int risultato = random(1, 7);

    Serial.print("Comando ricevuto: '");
    Serial.print(c);
    Serial.print("' -> Risultato dado: ");
    Serial.println(risultato);

    Serial.println();
  }
}

In questo sketch l’istante in cui l’utente invia un carattere non è prevedibile: questo rende il seed variabile e quindi la sequenza di random() non riparte “uguale” ad ogni reset.

Esercizi per gli studenti

Attività 01: verifica del seed

  • lanciate 10 volte, annota i risultati;
  • premete reset e riprovate:
    • con seed legato alla pressione/comando dovreste vedere sequenze diverse.

Attività 02: statistica veloce

  • lanciate 60 volte;
  • contate quante volte esce ogni faccia (1..6);
  • discussione: la distribuzione è “circa uniforme?” Perché non è perfetta su pochi lanci?

Attività 03: debug consapevole

modificate il codice per usare un seed fisso, ad esempio randomSeed(1234) e confrontate:

  • questo è utile nei test perché rende i risultati ripetibili.

Buon Coding a tutti 🙂

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.