STEAM BOX Stargate

Mi è stato chiesto negli scorsi giorni se le STEAM BOX sono oggetti sperimentati con le mie classi, certamente sì non tutte quelle che propongo ma le ho utilizzate durante i corsi di formazione per docenti e con gli studenti, ma non solo per le mie classi, colleghi della secondaria di primo grado, prendendo spunto dai miei suggerimenti ne hanno realizzato altre molto interessanti.

Per un futuro progetto che coinvolgerà le classi prime del mio istituto ne sto realizzando altre che mostro in anteprima nel corso STEAM BOX.

La scorsa settimana ho avuto occasione di rivedere, credo per la quinta volta, STARGATE, film di fantascienza del 1994 e dal film ne ho tratto un semplice gioco didattico che coinvolge diverse discipline del biennio dell’ITIS, di seguito condivido la trama della storia e dettagli fotografici del gioco. Per chi è iscritto al corso condividerò procedura di costruzione, file grafici, template per la creazione di attività simili e molto altro.

La storia introduttiva

Dovete riuscire ad attivare il portale! Potrebbe aprire un varco e riportarvi sulla Terra… o almeno lontano da questo pianeta. Ma il sistema è danneggiato: gli Anelli di Attivazione sono stati rimossi e chiusi in cinque contenitori di sicurezza, ognuno protetto da un codice a 4 cifre.
Sul pannello del manufatto si vedono anche 10 punti di connessione numerati. Dagli antichi schemi che siete riusciti a ricostruire emerge che il portale non è automatico: va ricablato manualmente. Solo collegando con precisione i 5 cavi di energia alle coppie di punti corrette e riposizionando i cinque anelli l’intero circuito si chiuderà. In quel momento, una luce si accenderà attraversando gli anelli e segnando l’attivazione del Gate.

Ora tocca a voi:

  • 5 squadre,
  • 5 anelli da recuperare,
  • 5 codici da decifrare,
  • 5 connessioni da completare.

Avete 60 minuti per risolvere i quesiti, aprire i contenitori, collegare i cavi e tentare l’attivazione del portale. Se ci riuscirete, forse rivedrete la Terra. Se fallirete, resterete bloccati su questo pianeta alieno…

Buon Making a tutti 🙂

Dirimere i conflitti con il pensiero computazionale – educazione civica – sketch Arduino – lezione 03

Ora traduciamo lo pseudocodice in uno sketch Arduino. Usiamo input da Serial Monitor per simulare le scelte e il LED integrato (e un buzzer opzionale) per avere feedback fisico. L’obiettivo non è “automatizzare i conflitti”, ma allenare il pensiero procedurale e la gestione consapevole dei passi. Si faccia riferimento alla lezione precedente (seguire il link) in cui è stato mostrato il diagramma di flusso nella modalità Mermaid e classica.

Nella dimostrazione viene usato un Arduino UNO R4 WiFi.

Di seguito una possibile soluzione, il funzionamento lo trovate nei commenti.

/* Prof. Maffucci Michele
  data: 18.11.25
  Risoluzione di un conflitto
  Input da Serial Monitor

  - LED integrato (pin 13) usato come feedback visivo
  - Buzzer opzionale su pin 5 (beep brevi)
  Istruzioni:
  1) Aprire la Serial Monitor (115200 baud).
  2) Rispondere alle domande con i tasti indicati (y/n, a/f) o premi invio quando richiesto.
*/

const int pinLed = LED_BUILTIN;  // pin 13
const int pinBuzzer = 5;         // pin a cui è connesso il Buzzer
int numeroBeep = 0;

bool chiaveMsg = 0;  // per controllo stampa msg

// emissione della nota
void beep(int durataMs) {
  tone(pinBuzzer, 880);  // nota La4
  delay(durataMs);
  noTone(pinBuzzer);
}

// sequenza di beep ripetuta all'avvio del programma
void sequenzaAvvio() {
  for (int i = 0; i < 10; i++) {
    beep(100);
    delay(100);
  }
}

// Attende che ci sia almeno un carattere sulla seriale e lo legge (minuscolo)
char leggiChar() {
  while (!Serial.available()) {
    // lampeggio lento del LED per indicare "in attesa"
    digitalWrite(pinLed, HIGH);
    delay(200);
    digitalWrite(pinLed, LOW);
    delay(200);
  }

  // Legge un solo byte dalla seriale e lo mette in c (di tipo char).
  // Questo è il primo carattere che l’utente ha inviato.
  char c = Serial.read();

  // Svuota il buffer rimanente leggendo tutto quello che è ancora arrivato
  // (ad esempio il \n dell’invio, o più caratteri se l’utente ha incollato del testo).
  while (Serial.available())
    Serial.read();
  if (c >= 'A' && c <= 'Z')  // Conversione in minuscolo se il carattere è una lettera maiuscola.
    c = c - 'A' + 'a';
  return c;
}

// -- Utility: attende qualsiasi tasto (usata come "invio per continuare")
// “un puntatore a char costante”, cioè una stringa in stile C non modificabile
// (tipicamente una stringa letterale come "Ciao").

void attendiConferma() {
  const char* messaggio = "Premi invio per continuare";
  Serial.println(messaggio);
  while (!Serial.available()) {
    digitalWrite(pinLed, HIGH);
    delay(150);
    digitalWrite(pinLed, LOW);
    delay(150);
  }
  // svuota
  while (Serial.available())
    Serial.read();
  beep(100);
}

// -- Utility: domanda sì/no
bool domandaSiNo(const char* domanda) {
  Serial.println(domanda);
  Serial.println("Digita 'y' per SI, 'n' per NO");

  //ripetiamo finché l’utente non inserisce una risposta valida.
  // Il ciclo si interrompe con un return (es. quando l’utente digita ‘y’ o ‘n’).
  for (;;) {
    char c = leggiChar();
    if (c == 'y') {
      Serial.println("Hai risposto: SI");
      beep(100);
      return true;
    }
    if (c == 'n') {
      Serial.println("Hai risposto: NO");
      beep(100);
      return false;
    }
    Serial.println("Risposta non valida. Usa 'y' o 'n'.");
  }
}

// Pausa "simulata breve" al posto di 2 minuti reali
void pausaBreve(const char* motivo, int secondi = 5) {
  Serial.print("Pausa: ");
  Serial.print(motivo);
  Serial.print(" (");
  Serial.print(secondi);
  Serial.println("s)");
  for (int i = 0; i < secondi; i++) {
    digitalWrite(pinLed, HIGH);
    delay(300);
    digitalWrite(pinLed, LOW);
    delay(700);
    Serial.print(".");
  }
  Serial.println();
  beep(100);
}

void setup() {
  pinMode(pinLed, OUTPUT);
  Serial.begin(115200);
  delay(1000);
  Serial.println("=== Risoluzione Conflitto - VERSIONE BASE ===");
  Serial.println("Benvenuto! Segui le istruzioni sul Serial Monitor.");
  pinMode(pinBuzzer, OUTPUT);
  sequenzaAvvio();
}

void loop() {
  // 1) Sicurezza del confronto
  bool sicuro = false;
  do {
    sicuro = domandaSiNo("E' sicuro parlare adesso?");
    if (!sicuro) {
      Serial.println("OK, facciamo un time-out breve al posto di 2 minuti.");
      pausaBreve("time-out", 5);
    }
  } while (!sicuro);

  // 2) Definizione del problema
  Serial.println("Definisci il problema in UNA frase (in classe va bene scriverla su carta).");
  attendiConferma();

  // 3) Turni + Parafrasi
  bool parafrasiOk = false;
  do {
    Serial.println("Turno A (60s simulati).");
    attendiConferma();
    Serial.println("Turno B (60s simulati).");
    attendiConferma();
    parafrasiOk = domandaSiNo("Parafrasi reciproca corretta?");
  } while (!parafrasiOk);

  // 4) Opzioni di soluzione (almeno 2)
  int numeroOpzioni = 0;
  Serial.println("Genera almeno 2 opzioni di soluzione.");
  for (;;) {
    Serial.println("a = aggiungi opzione, f = fine (consentita solo se >= 2 opzioni)");
    char c = leggiChar();
    if (c == 'a') {
      numeroOpzioni++;
      Serial.print("Opzione aggiunta. Totale: ");
      Serial.println(numeroOpzioni);
      beep(100);
    } else if (c == 'f') {
      if (numeroOpzioni >= 2) {
        Serial.println("OK, passiamo alla decisione.");
        beep(100);
        break;
      } else {
        Serial.println("Servono almeno 2 opzioni prima di terminare.");
      }
    } else {
      Serial.println("Scelta non valida. Usa 'a' o 'f'.");
    }
  }

  // 5) Decisione finale
  bool accordo = domandaSiNo("C'e' accordo su una opzione?");
  if (accordo) {
    Serial.println("Piano d'azione: definire chi/fa/cosa/entro quando (scrivere su carta).");
    Serial.println("Promemoria: verifica dopo 24 ore.");
    Serial.println("FINE. Riavvio tra 5 secondi...");
    pausaBreve("chiusura", 5);
  } else {
    Serial.println("Coinvolgi un mediatore o rinvia il confronto.");
    Serial.println("Ritorno al controllo 'E' sicuro parlare?'.");
    pausaBreve("ritorno", 3);
  }
}

STEAM BOX della Creatività

Tra le varie STEAM BOX che sto progettando, ce ne sono alcune pensate proprio per lavorare su questi aspetti: aiutano a capire che cosa intendiamo per creatività, come ci si può allenare ad esserlo e in che modo si può sviluppare il pensiero divergente in modo strutturato ma giocoso.

Appena apri la STEAM BOX della Creatività trovi una serie di piccole bustine: in ognuna, solo 6 mattoncini LEGO. Da lì parte un viaggio alla scoperta di cosa vuol dire davvero essere creativi, grazie alla Lego Duck Challenge. Con una serie di esercizi semplici e accessibili, realizzati in autonomia ed in gruppo, potrete sperimentare in prima persona come, a partire dagli stessi pezzi, nascano anatre completamente diverse: un modo concreto per parlare di innovazione, gestione del cambiamento, punti di vista e unicità.

Ho parlato della Lego Duck Challenge in modo più approfonditamente in questo articolo:
LEGO e creatività didattica: dalla Duck Challenge al Coding collaborativo

Perché è così potente in ambito educativo

Rispetto a una semplice “attività con i LEGO”, questa proposta lavora su diversi piani:

Creatività sotto vincolo
Pochi pezzi e tempo limitato costringono ad abbandonare l’idea di “progetto perfetto” e ad accettare l’esplorazione rapida, l’errore, il tentativo.

Divergenza e unicità
Il confronto tra le anatre diventa un’occasione per visualizzare la diversità di approccio: ognuno interpreta il compito in modo personale. Questo è un punto di partenza straordinario per parlare di creatività, ma anche di valutazione e aspettative.

Collaborazione e dialogo
Dopo la fase individuale, è possibile passare a una fase di gruppo: costruire un’anatra “di squadra” con gli stessi 6 pezzi obbliga a discutere, argomentare, cedere, mediare. È un piccolo laboratorio di team working in miniatura.

Metacognizione
Le domande finali del debriefing (“Cosa hai pensato quando…?”, “Cosa cambieresti la prossima volta?”, “In che cosa la tua anatra ti rappresenta?”) aiutano i partecipanti a osservare come hanno ragionato, non solo cosa hanno costruito.

Dalla Duck Challenge al Coding collaborativo
Nell’articolo che ho citato sopra, propongo un’estensione naturale dell’attività: collegare la Duck Challenge al Coding, ad esempio con una scheda BBC micro:bit che funge da cronometro per i 60 secondi di costruzione.

Tutto ciò permette di mostrare in modo molto concreto come:

  • una semplice attività con i mattoncini possa trasformarsi in percorso STEAM completo;
  • sia possibile passare dalla creatività “manuale” alla progettazione algoritmica;
  • il Coding possa avere una funzione sociale e cooperativa, non solo tecnica.

Se volete partecipare al corso: “STEAM-BOX: Il laboratorio STEAM in valigetta” seguite il LINK.

Buona creatività a tutti 🙂

STEAM-BOX: Il laboratorio STEAM in valigetta

Quattro valigette componibili, basate su making, gamification, sensori e AI, per realizzare attività personalizzabili per ogni classe e disciplina.

STEAM-BOX è un corso online dedicato ai docenti della secondaria di I e II grado che trasforma una semplice valigetta di cartone in un vero laboratorio STEAM portatile. Partendo dal making e arrivando a sensori, robotica, piccole applicazioni di intelligenza artificiale “leggera” e dinamiche di gioco/escape, il percorso mostra come progettare attività coinvolgenti e personalizzabili per qualsiasi disciplina, anche senza competenze tecniche avanzate. Sono previsti 4 incontri in webinar (per un totale di 8 ore), con materiali operativi, template e schede riutilizzabili direttamente in classe.

Durante il corso i partecipanti impareranno a progettare e costruire la propria valigetta: struttura in cartone rinforzata, pannello frontale modulare con LED, pulsanti e jack per sensori, coperchio “attivo” per puzzle e meccanismi di gioco. Da lì si passerà a esempi concreti di attività: micro-indagini con sensori e data logging, piccole sfide di robotica “dal coperchio”, escape room analogico-digitali e utilizzo consapevole dell’IA in classe, con particolare attenzione all’inclusione, alla valutazione formativa e alla documentazione del lavoro degli studenti.

Dietro le quinte 🙂

Progetto HÉLIOS – Faro Stratosferico

Siamo nel 2076, un faro stratosferico (Faro N-7) è fuori uso e solo una console remota può riattivarlo. Ogni gruppo di studenti controlla un modulo diverso della console (Energia, Calibrazione, Stabilità, Segnale, Sicurezza, Sincronismo). A ciascun gruppo viene assegnata una Carta-Quesito collegata a una specifica tematica della disciplina scelta dal docente (es. fisica, storia, lingue, ecc.): se la risposta è corretta, il gruppo imposta il proprio interruttore su ON, altrimenti lo lascia su OFF. Inserita la chiave nel pannello SYSTEM ACTIVATION e premuto START, gli studenti hanno poco tempo per coordinarsi e, alla fine, premere CHECK: se tutti i moduli sono nella configurazione giusta, il sistema HÉLIOS si riavvia; in caso contrario, avranno un secondo e ultimo tentativo prima dell’arresto di sicurezza.
Questa è solo una delle tante attività che verranno presentate: durante il corso vedremo come costruire meccanismi simili anche con materiali poveri (carta, cartone, pulsanti, interruttori, lampadine) e, quando utile, con piccola elettronica low-cost, così che ogni docente possa adattare facilmente le idee alla propria realtà di classe.

Calendario del corso

  • Martedì 25 novembre 2025 – Dalle 17.00 alle 19.00
  • Mercoledì 3 dicembre 2025 – Dalle 17.00 alle 19.00
  • Martedì 9 dicembre 2025 – Dalle 17.00 alle 19.00
  • Mercoledì 17 dicembre 2025 – Dalle 17.00 alle 19.00

Per maggiori informazioni sul programma e l’iscrizione seguite il LINK.

Vi aspetto 🙂

Arduino esercizi – Base marziana ELYSIUM – correzione fase 1 – solo pulsante

In riferimento alla lezione: Arduino esercizi – Base marziana ELYSIUM, riporto di seguito tre possibili soluzioni, nei commenti di ogni sketch la spiegazione sul funzionamento.

Fase 1 – solo pulsante

// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1 - solo pulsante

const int PIN_LED = 9;
const int PIN_PULSANTE = 2;  // pull-down esterno: HIGH quando premuto

void setup() {
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_PULSANTE, INPUT);  // nessun pull-up interno
  digitalWrite(PIN_LED, LOW);
}

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

  if (statoPulsante == HIGH) {    // pulsante premuto
    digitalWrite(PIN_LED, HIGH);  // accendo la luce di cortesia
    delay(1500);                  // 1,5 s
    digitalWrite(PIN_LED, LOW);  // spengo
    delay(50);                   // piccolo anti-rimbalzo
  }
}

Con questa soluzione alla pressione del pulsante il LED si accende e se rilasciate si spegne, però se mantenete premuto il pulsante notare un veloce spegnimento ed una riaccensione del LED ovvero ciò che stiamo facendo e riaccendere immediatamente il LED.

Per evitare ciò bisogna implementare la versione che evita il retrigger.

Evitare il retrigger significa impedire che, tenendo il pulsante premuto, il ciclo riparta subito dopo lo spegnimento del LED e lo riaccenda di nuovo. Per evitarlo, dopo la sequenza (LED acceso per 1,5 s > LED spento) si controlla se il pulsante è ancora premuto: finché lo è, si rimane dentro un ciclo while bloccante che attende il rilascio. Solo quando il pulsante torna allo stato di riposo si esce dal while, si applica un breve anti-rimbalzo (es. 50 ms) e il programma riprende il loop normale.

ATTENZIONE

il while è bloccante ciò vuol dire che blocca l’intera esecuzione del programma. Va benissimo per questo esercizio semplice; in progetti più complessi è preferibile preferisce rilevare il fronte di salita (variabile di stato) o un approccio non bloccante con millis() che ancora non conoscete (mi sto rivolgendo ai ragazzi di 3′) e che vedremo più avanti.

Fase 1 – solo pulsante – evita il retrigger con while bloccante

// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1B - solo pulsante
// evitare il retrigger

const int PIN_LED = 9;
const int PIN_PULSANTE = 2;  // pull-down esterno: HIGH quando premuto

void setup() {
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_PULSANTE, INPUT);  // nessun pull-up interno
  digitalWrite(PIN_LED, LOW);
}

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

  if (statoPulsante == HIGH) {    // pulsante premuto
    digitalWrite(PIN_LED, HIGH);  // accendo la luce di cortesia
    delay(1500);                  // 1,5 s
    digitalWrite(PIN_LED, LOW);   // spengo

    // attendo il rilascio per evitare retrigger continui
    while (digitalRead(PIN_PULSANTE) == HIGH) {
      delay(10);
    }
    delay(50);                    // piccolo anti-rimbalzo
  }
}

Attenzione alla parte di codice:

...
while (digitalRead(PIN_PULSANTE) == HIGH) {
      delay(10);
    }
...

potreste essere tentati di scrivere:

...
while (statoPulsante == HIGH) {
      delay(10);
    }
...

se agite in questo modo, dopo la prima accensione e il successivo spegnimento non riuscirete più ad accendere il LED con successive pressioni del pulsante.

Considerate statoPulsante come uno “scatto fotografico” fatto ad inizio loop(), pertanto se scrivete:

while (statoPulsante == HIGH) { ... }

la condizione resta sempre vera (perché non non viene mai aggiornata).
Risultato: si resta bloccati per sempre in quel while dopo la prima attivazione > il LED si accende una volta e poi il programma non torna più al loop().

Fase 1 – solo pulsante – evita il retrigger senza while bloccante

Fornisco un’altra soluzione in cui non si fa uso del while bloccante.

Invece di “restare fermi” dentro un while finché il pulsante non viene rilasciato, leggiamo il pulsante ad ogni giro del loop e facciamo scattare l’azione solo quando cambia da NON premuto a premuto. Questo momento si chiama fronte di salita.

// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1C - solo pulsante
// evitare il retrigger senza while bloccante
// con variabile di stato

const int PIN_LED      = 9;
const int PIN_PULSANTE = 2;   // pull-down esterno: HIGH = premuto

bool premutoPrima = false;

void setup() {
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_PULSANTE, INPUT);   // nessun pull-up interno
}

void loop() {
  // Snapshot della lettura
  int statoPulsante = digitalRead(PIN_PULSANTE);

  // Converto HIGH/LOW in booleano
  bool premuto;
  if (statoPulsante == HIGH) {
    premuto = true;    // pulsante premuto
  } else {
    premuto = false;   // pulsante rilasciato
  }

  // Fronte di salita: ora premuto, prima no
  if (premuto && !premutoPrima) {
    digitalWrite(PIN_LED, HIGH);
    delay(1500);
    digitalWrite(PIN_LED, LOW);
    delay(50); // anti-rimbalzo semplice
  }

  // Aggiorna lo stato per il prossimo giro
  premutoPrima = premuto;
}

Come funziona il programma

  • premuto = stato attuale del pulsante (TRUE se è premuto ora, FALSE altrimenti).
  • premutoPrima = stato del pulsante al giro precedente del loop.
  • Condizione di innesco: premuto == true e premutoPrima == false > significa “hai appena iniziato a premere”.

Quando la condizione è vera:

  1. esegui l’azione (es. LED acceso 1,5 s, poi spento),
  2. non restate bloccato: il loop continua a girare,
  3. finché tenete premuto, la condizione non si ripete (perché ora premutoPrima è anch’esso TRUE),
  4. quando rilasciate, premuto torna FALSE; alla prossima pressione avrete di nuovo il fronte di salita.

Questa soluzione offre i seguenti vantaggi:

  • Niente blocchi: il programma continua a leggere ingressi/aggiornare uscite mentre il LED è stato gestito (utile in progetti più grandi).
  • No retrigger con pressione prolungata: scatta una sola volta all’inizio della pressione.
  • Struttura “a eventi”: reagisce ai cambiamenti, non al livello costante del pulsante.

Di seguito la tabella “fronte di salita” (versione con pull-down: HIGH = premuto)

Fase Descrizione Lettura pin premuto (ora) premutoPrima (prima) Condizione premuto && !premutoPrima Azione
T0 Riposo prima della pressione LOW FALSE FALSE FALSE Nessuna
T1 Inizio pressione (fronte salita) HIGH TRUE FALSE TRUE Esegui sequenza LED
T2 Tenuto premuto HIGH TRUE TRUE FALSE Nessuna
T3 Rilascio LOW FALSE TRUE FALSE Nessuna (solo aggiornamento stato)
T4 Nuova pressione (nuovo fronte) HIGH TRUE FALSE TRUE Esegui sequenza LED

Buon Coding a tutti 🙂