Usb host shield cinese e continui reboot di arduino alla lettura di un file di testo da chiavetta

Salve. Ho un programmino che sto facendo per un amico, per alcune partite di soft air, che mi sta facendo impazzire.
La stessa versione che lavora con gli rfid va alla grande, ma la lettura da una chiavetta usb dei codici, spesso fa resettare la board.

Non riesco a capire se e' un problema di pin in conflitto, una cavolata nel codice o di alimentazione (via usb su porta usb2 od usb3).

Idee? Illuminazioni? Cose da controllare o metodi per isolare la problematica?

Codice in allegato:
usbread_check20250312.ino (6.5 KB)

se volete lo riporto qui, ma e' corposo :wink:

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>

//non disponibili nel simulatore, da aggiungere a partecon zip librerie diponibli in email
#include <SPI.h>
#include <UsbFat.h>
#include <masstorage.h>

// USB host objects.
USB usb;
BulkOnly bulk(&usb);

// File system.
UsbFat key(&bulk);

// Test file.

File file;

//valore del codice letto da usb
String codiceLetto;

//controlla con uno scanner i2c se il tuo display ha l'indirizzo corretto
//LiquidCrystal_I2C lcd(0x27,16,2);
LiquidCrystal_I2C lcd(0x3f,16,2);

// Keypad setup
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

char keys[ROWS][COLS] ={
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//byte rowPins[ROWS] = {8, 7, 6, 5}; //connect to the row pinouts of the keypad
byte rowPins[ROWS] = {10, 6, 5,4}; //connect to the row pinouts of the keypad
byte colPins[COLS] =  {A0, A1, A2, A3}; //connect to the column pinouts of the keypad

//Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

// per arduino uno e arduino nano a4=SDA e a5=SCL
//const int SDA = A4;
//const int SCL = A5;

//usb host shield uses pins 13, 12, 11, 10, 9 and ICSP
// ICSP e' il pettine 2X3 che sta nel lato corto di arduino

// LED setup
const int ledPin = 4;

// Codes
const char codeA[] = "12345678"; // Countdown
const char codeB[] = "87654321"; // Lock
const char codeC[] = "11223344"; // Unlock

// Variables
char enteredCode[9];
int codeIndex = 0;

enum States { ATTESA, COUNTDOWN, LOCKED, BOOM };
States currentState = ATTESA;

long countdownStartTime;

// 30 minutes in milliseconds
//unsigned long countdownDuration = 30UL * 60UL * 1000UL;
unsigned long countdownDuration = 30UL * 60UL * 1000UL;

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  displayState();
  Serial.println("board resettata");
  Serial.println(countdownDuration);
  keypad.setDebounceTime(10);
}

void loop() {
  char tasto = keypad.getKey();
  if (tasto) {
    if (tasto == '#') {
      checkCode();
    } else if (tasto == '*') {
        clearCode();
        displayState();
    } else if (tasto == 'A') {
        readUsb();
        checkCode();
    } else {
      enteredCode[codeIndex++] = tasto;
      displayEnteredCode();
    }
  }

  if (currentState == COUNTDOWN) {
    updateCountdown();
  }
}

void readUsb() {
  Serial.println(F("leggo da usb"));
  /* provo a leggere la chiavetta usb
  se non riesco a inizializzare, scrivo errore di lettura
  se inizializzo ma non c'e' chiavetta, scrivi collegare chiavetta
  se la chiavetta c'e' ma il file non c'e', da errore file codice non presente
  se codice c'e' mettilo nella variabile enteredCode ed esci
  */

  // Initialize the USB bus.
  if (!initUSB(&usb)) {
    Serial.println(F("initUSB failed"));
    displayMessage("Cannot Init USB!");
    delay(1000);
    clearCode();
    displayState();
    return;    
  }

  // se sono qui significa che l'init dell'usb e' andata a buon fine e provo ad inizializzare la chiavetta
  if (!key.begin()) {
    Serial.println(F("USB key begin failed"));
    displayMessage("USBKey not Found");
    delay(1000);
    clearCode();
    displayState();
    return;
  }

  // se sono qui significa che posso leggere dalla chiavetta
  file.open("code.txt");
  if (file) {
    Serial.println("leggo il contenuto di code.txt:");
    int indice=0;
    while (file.available()) {
      //strncpy(enteredCode, file.read(), 8);
      //Serial.write(file.read());
      char c = file.read();
      if (isPrintable(c)){
        codiceLetto.concat(c);
        enteredCode[indice++] = c;
      } else if (c == '\n') {
          //Serial.println(codiceLetto);
          Serial.println(enteredCode);
          //strncpy(enteredCode, codiceLetto, 8); 
      }
    }
    file.close();
  } else {
    Serial.println("error opening code.txt");
    displayMessage("code not found !");
    delay(1000);
    clearCode();
    displayState();
    return;
  }

  //tanto per testare
  //strncpy(enteredCode, "12345678", 8);
}

void checkCode() {
  if (currentState == LOCKED) {
    if (strcmp(enteredCode, codeC) == 0) {
      currentState = ATTESA;
      displayMessage("Unlocked");
      delay(1000);
      clearCode();
      displayState();
    } else {
        displayMessage("Locked");
        delay(1000);
        clearCode();
        displayState();
    }
    return;
  }

  if (strcmp(enteredCode, codeA) == 0 && currentState == ATTESA) {
    startCountdown();
  } else if (strcmp(enteredCode, codeB) == 0) {
      currentState = LOCKED;
      countdownStartTime = 0; //reset countdown
      displayMessage("Locked");
      delay(1000);
      clearCode();
      displayState();
  } else if (currentState == COUNTDOWN && strcmp(enteredCode, codeB) == 0) {
      currentState = LOCKED;
      displayMessage("Locked");
      delay(1000);
      clearCode();
      displayState();
  } else {
      displayMessage("Invalid Code");
      delay(1000);
      clearCode();
      displayState();
  }
}

void startCountdown() {
  // metto in countdownStartTime il momento in millisecondi in cui e' stato avviato il timer
  countdownStartTime = millis();
  currentState = COUNTDOWN;
  displayState();
  clearCode();
}

void updateCountdown() {
  //long remainingMillis = countdownDuration - (millis() - countdownStartTime);
  if ((millis() - countdownStartTime) >= countdownDuration) {
    digitalWrite(ledPin, HIGH);
    displayMessage(">> IGNITION <<");
    currentState = BOOM;
    delay(5000);
    digitalWrite(ledPin, LOW);
    displayState();
  } else {
      long remainingMillis = countdownDuration - (millis() - countdownStartTime);
      long remainingSeconds = remainingMillis / 1000;
      long minutes = remainingSeconds / 60;
      long seconds = remainingSeconds % 60;

      lcd.setCursor(16 - 5, 0); // Right-aligned
      if (minutes < 10) lcd.print("0");
      lcd.print(minutes);
      lcd.print(":");
      if (seconds < 10) lcd.print("0");
      lcd.print(seconds);
      lcd.print(" ");
  }
}

void clearCode() {
  codeIndex = 0;
  memset(enteredCode, 0, sizeof(enteredCode));
}

void displayEnteredCode() {
  //lcd.clear();
  lcd.setCursor(0,1);
  for (int i = 0; i < 15; i++) {
        lcd.print("");
  }
  lcd.setCursor(0,1);
  lcd.print("Code: ");
  for (int i = 0; i < codeIndex; i++) {
    lcd.print(enteredCode[i]);
  }
}

void displayMessage(const char* message) {
  lcd.clear();
  lcd.print(message);
}

void displayState() {
  lcd.clear();
  switch (currentState) {
    case ATTESA:
      lcd.print("ENTER CODE:");
      break;
    case COUNTDOWN:
      lcd.print("COUNTDOWN:");
      break;
    case LOCKED:
      lcd.print("SYSTEM LOCKED");
      break;
    case BOOM:
      lcd.print("LANCIO ESEGUITO");
      break;
  }
}

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

fatta presentazione sorry :wink:

Che board? Con collegato cosa?

Ciao, Ale.

hai ragione.
la board e' una di queste che si trovano a poco su aliexpress e similari:
usb host shield
Non ho trovato riferimenti ai pin da riservargli ed il "tutorial", con la sola board e lettura e scrittura su seriale, funziona bene.
Solo che quando connetto schermo lcd via i2c e tastierino numerico, impazzisce tutto.
Alle volte (spesso) il display si accende ma non disegna.
Alle volte fa caratteri strani.
Alcune volte, si resetta proprio arduino.

Vabbè, abbiamo capito che hai uno shield USB, non hai ancora detto montato su cosa (arduino UNO?), e nemmeno cosa siano di preciso lo schermo LCD ed il tastierino numerico, nè come siano collegati. Senza uno schema e possibilmente una foto del setup non è possibile aiutarti.
Ah, e il codice allegalo al messaggio, usando i tag < CODE> che vedi in alto.

Ciao, Ale.

Mah, che ti dico. E' tutto nel codice allegato al primo messaggio :wink:
Io commento tutto, anche perche' di solito devo analizzare il codice di 10 applicazioni differenti, al giorno. Spesso non scritte da me :smiley:
Do sempre per scontato che si sappia "leggere il codice" ....
La board e' un arduino uno. Il display lcd 16x2 e' connesso con interfaccia i2c, il tastierino numerico a matrice righe/colonne, onnipresente nei progetti arduino.
Boh ... grazie del cortese supporto.

Ok, a posto.

Ciao, Ale.

Per cortesia, non allegare il programma, ma inseriscilo nel messaggio usando il pulsante <CODE/> che trovi in alto mentre modifichi il messaggio.

Grazie
Gianluca

Ok. Messo nel corpo del messaggio (con qualche piccola variazione alla versione in allegato).
Ho notato che le lib che uso sono un po' vecchiotte e che esiste una nuova versione ...

vi dicessi pero' che ho capito come utilizzarla ....

per la cronaca ... vedendo questo tutorial su youtube (https://www.youtube.com/watch?v=a24kk8yusSE)
sembrerebbe che lo shield usa:

arduino pins					shield pins
ic-sp connector					ic-sp onnector
gpio pin 10 					pin 10 (slide select line)
gpio pin 8						pin 8 (interrupt line)
gpio pin 7						pin 7 (general pourpose pin)

ic-sp connector:
  [miso   vcc ]
  [sck    mosi]
  [rst    gnd ]

modifico il codice e vediamo che viene fuori