Risolto

Si ma non è che magari è l'abbondante uso di "String" che ha quel programma a bloccare Arduino?

Olam0436: Oggi ho posizionato i due zener ma non è cambiata molto la situazione

Ok, meglio lasciarli comunque perché proteggono i contatti del relé evitando extratensioni e scintillii.

Quindi il problema si sposta sull'alimentazione (avremmo la conferma di questo scollegando la serratura dal relé per vedere se il problema persiste).

Inoltre sarebbe utile vedere quale modulo relé è stato usato.

docdoc: Si ma non è che magari è l'abbondante uso di "String" che ha quel programma a bloccare Arduino?

:D

Allora faccio il punto della situazione:
Il relè che uso è un normalissimo relè a due canali per arduino e raspberry con DC 5V. Ho provato ad alimentarlo separatamente, escludendo il GND proveniente da arduino, oppure alimentandolo direttamente da arduino, ma non è cambiato molto.
Se il sistema lo “sposto” sul banco e magari ci metto anche la serratura, ma alimento arduino tramite USB del PC, lo sketch non si blocca mai.
Ho inserito i due zener come mi avete proposto ma il problema non è stato risolto.
L’unica cosa che mi fa pensare e di cui mi sono accorto proprio stamattina, è che (errore dovuto sicuramente alla mia ignoranza, facendo dei copia incolla) per gestire l’rfid lo sketch utilizzava due diverse librerie: MFRC522 ed RFID. Ora ho apportato la modifica allo sketch utilizzando solo la libreria MFRC522, ed apparentemente il sistema non si blocca, almeno fino ad ora (ho fatto la modifica poche ore fa). Secondo voi il blocco può essere dipeso da questo problema?

Grazie mille per l’aiuto che cercate di darmi

Questo è il relè che ho acquistato

Inoltre ho provato a inserire il watchdog come da codice seguente ma riavvia in continuazione la scheda e ad ogni riavvio dà un impulso al relè eccitandolo e facendo aprire il cancello. E’ normale questo comportamento o anche qui sbaglio qualcosa nell’impostare il watchdog?

#include <avr/wdt.h>

…….

void setup() {
……..

wdt_enable(WDTO_2S);


…….


void loop() {

………

delay(3000);   

wdt_reset();
    
    }

E ci credo che la riavvia di continuo imposti il watchdog a due secondi poi metti un ritardo di tre secondi...

Il modo corretto di collegare quella scheda relé è il segunete (© Brunello) ...

|449x500

... l'hai collegata in questo modo? ("Alimentatore esterno" è un alimentatore completamente separato da quello di Arduino - Il GND lato Arduino NON va connesso)

Guglielmo

P.S.: Attenzione, impilca "logica inversa" ... pin HIGH -> relé diseccitato, pin LOW -> relé eccitato.

Si ho seguito questo schema che avevo trovato in una vecchia discussione. Ma allora come devo impostare il watchdog?

Guarda questo che spiega come usarlo, ovviamente il tempo minimo del watchdog dovrà essere superiore a delay+tempo di esecuzione del codice che intercorre tra un reset del watchdog e l'altro

Buongiorno a tutti.
Oggi dopo un giorno intero che non si bloccava, arduino si è ribloccato. Ho inserito nello sketch, che vi allego nuovamente, il watchdog, ma non l’ho ancora installato sulla scheda; mi potreste dire se secondo voi l’ho impostato bene?

Vi ricordo cosa deve fare lo sketch:

al passaggio della tessera fa il confronto con le tessere memorizzate; se la tessera non è presente nell’elenco accende il led rosso (delay 2000); se la tessera è presente accende il led verde (delay 2000), dopo che si è spento il led verde si attiva il relè (delay 2000)

Grazie

#include <SPI.h>
#include <MFRC522.h>
#include <avr/wdt.h>

#define SDA_DIO1 10
#define RESET_DIO1 9
#define SDA_DIO2 5
#define RESET_DIO2 8
#define delayRead 1000 
#define delayLed 2000 
#define ledVerde 2
#define ledRosso 3

MFRC522 mfrc522(SDA_DIO1, RESET_DIO1);

 
long previousMillis = 0;
long interval = 10;
 
int rele = 4;                            //pin relè
 
String uidmfrc522[] = {"cdff1b9f",  
                       "bdb15c9f",  
                       "f0397889",  
                       "cd618071", 
                       "cc6785b9",
                       "133eb773",
                       "92d91ed9", 
                       "db6a9179", 
                       "eb8b68d9", 
                       "4d1a54e9",
                       "625566d9", 
                       "fdd3a671", 
                       "656165d9", 
                       "545e24d9", 
                       "b94623d9", 
                       "dd635a9f",
                       "c7ac65d9", 
                       "9d51f99e", 
                       "636524d9", 
                       "bdd74b9f", 
                       "2d90459f",
                       "4d941b9f",
                       "fdc4f19e", 
                       "8d37e79e",
                       "8d6dd39f", 
                       "3d851d9f", 
                       "6d47a871", 
                       "1d8efe9e",
                       "f7b17b3b", 
                       "0700353b", 
                       "3728b53c", 
                       "47f9c03b", 
                       "07a1b53c", 
                       "2771a43b", 
                       "576d613b", 
                       "67d1af3b", 
                       "5497724d", 
                       "9780b53b", 
                       "27ec823b", };
 
void setup() {
   Serial.begin(115200);                       // Inizializza la comunicazione con il PC
   SPI.begin();                                     // Inizializzo il bus SPI
   mfrc522.PCD_Init();                         // Inizializzo il lettore MFRC522 
   pinMode(rele, OUTPUT);
   Serial.println("Ingresso Cancello");
   Serial.println("mfrc522 registrati n° --> "+String(sizeof(uidmfrc522)/sizeof(String)));
   Serial.println("In attesa di lettura...");
   pinMode(ledVerde,OUTPUT);
   pinMode(ledRosso,OUTPUT);
   pinMode(rele,OUTPUT);
}
 
void loop() {
   unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > interval) {
   previousMillis = currentMillis; 
wdt_disable();
   if ( ! mfrc522.PICC_IsNewCardPresent()) {
   return;
    }
   if ( ! mfrc522.PICC_ReadCardSerial()) {
   return;
}
String uid_s = "";
 
if (!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
         
        String uid_a = String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
        String uid_b = String(mfrc522.uid.uidByte[i], HEX);
        uid_s = uid_s+uid_a+uid_b;
      }
  }

  Serial.print("RFID UID rivelato --> ");
  Serial.println(uid_s);
  Serial.println("");
  boolean controllo = false;

  for (int i = 0; i < sizeof(uidmfrc522)/sizeof(String); i++){   

  if(uidmfrc522[i] == uid_s){      
  Serial.println("Accesso consentito");
  openDoor();
  controllo = true;
  break;
       }
    }
  if(!controllo){
  Serial.println("Accesso vietato");      //accendiLed(ledRosso);
  digitalWrite(ledRosso, HIGH);
  delay(delayLed);
  digitalWrite(ledRosso, LOW);
     }
  Serial.println();
  Serial.println("In attesa di lettura...");
  wdt_enable(WDTO_2S); 
  }
}
void openDoor(){
  digitalWrite(ledVerde, HIGH);
  delay(delayLed);
  digitalWrite(ledVerde, LOW);
  digitalWrite(rele, HIGH);
  Serial.println("Relè ON");
  delay(2000);
  digitalWrite(rele, LOW);
  Serial.println("Relè OFF");
 wdt_reset();                         //resetto il watchdog  
}

Altra cosa, c’è differenza nell’usare:

#define relè 4

e usare:

int rele = 4;

Grazie per la pazienza!!!

la define definisce un etichetta che il compilatore userà per posizionare il suo valore (4 nel tuo caso) ovunque tu abbia inserito il noem della define (relé nel tuo caso), la seconda definisci una variabile di tipo int a cui assegni il valore 4, la prima non ha peso in memoria mentre la seconda si (in realtà se non la riassegnai mai il compilatore furbo agirà di conseguenza ma si scende troppo nel tecnico). Se non ti piace usare la define puoi usare anche la definizione della variabile avendo cura percò di farla precedere da const

const int rele = 4;

Allora il watchdog è usato diciamo non bene, innanzitutto solitamente si attiva nel setup e poi con wdt_reset lo si azzera nel loop, seconda cosa che salta all'occhio è che non ti sei preso la briga di leggerti il tutorial che ti avevo linkato pochi post fa del buon leo che spiega esattamente tutto, continui a impostarlo a due secondi quando hai un ritardo di 2 secondi + tempi di eseguire altre istruzioni e sfori sicuro e arduino si resetterà. Altra cosa che viene detta e ridetta è che il watchdog serve a riavviare in casi imprevisti e non a sanare problemi del programma (Es. una scarica elettrostatica crea un problema di esecuzione non previsto) nel tuo caso (come ti è già stato evidenziato) il blocco lo hai perché usi la classe String invece delle stringhe classiche del C, se non togli l'uso della classe String Arduino è destinato a bloccari a casaccio all'infinito, sana queste cose e vedrai che il watchdog non scatterà mai più. Se poi tu usassi millis() al posto del delay potresti accendere il led e farlo restare acceso per i due secondi e nel contenmpo aprire la serratura senza obbligare l'utente ad attendere i due secondi che il led si spenga

Altra cosa, c'è differenza nell'usare:

Code: [Select]

define relè 4

e usare: Code: [Select]

int rele = 4;

Grazie per la pazienza!!!!

si!, l'accento ... :D

a parte gli scherzi con la define indichi al compilatore di sostituire la parola con il numero prima della compilazione, l'int in questo caso si mangia 2 bytes di memoria ed essendo un pin sarebbe meglio definirlo come costante:

const byte RELE = 4;

(non usare comunque le lettere accentate, è facile sbagliarsi)

EDIT: in contemporanea con fabpolli :)

Olam0436: Oggi dopo un giorno intero che non si bloccava, arduino si è ribloccato

Lo dico per la terza (ed ultima) volta quello che farei io al posto tuo come PRIMA cosa: leva 'ste ca%%o di "String" e sostituiscile con char* (ovviamente adattando poi il modo con cui si manipolano)!!!

Non è tanto la tabella degli ID che non viene toccata ma solo letta, ma il problema GROSSO è che tu hai delle variabili String dentro al loop(), e persino all'interno di questo, in una for(), per cui la memoria si frammenta mooolto rapidamente arrivando a comportamenti imprevisti o al blocco!!!

Lascia perdere per ora i watchdog, zener, collegamenti, o altre cose del genere: PRIMA sistema decentemente quel listato togliendo di mezzo qualsiasi String, e POI vedi se funziona o se si blocca.

Ma da qualche parte c'è un esempio perché non saprei proprio da dove iniziare!!!!

E comunque non mi spiego come mai sul banco il sistema funziona e non si blocca, mentre montato si blocca

Quello può succedere per il problema di come hai collegato la scheda relé, se la colleghi come ti ha detto gpb01 qualche post fa usando due alimentatori allora vedrai che qualcosa migliorerà (sul banco non hai le interferenze della prova reale) e comunque il 98% del problema è l'uso della classe String. Non so se qualcuno ha da indicarti qualcosa di preciso ma per imparare ad usarle cerca "C array di char " "Arduino array di char" e le varie funzioni di manipolazione strncmp, strncpy, ecc. e sicuramente ti serviranno molte ore di studio e prove per capire l'uso delle stringhe ma come sempre con il copia e incolla si va poco lontanto, imparando e capendo cosa si ha davanti allora si riesce ad otttenere risultati.

fabpolli: Quello può succedere per il problema di come hai collegato la scheda relé, se la colleghi come ti ha detto gpb01 qualche post fa usando due alimentatori allora vedrai che qualcosa migliorerà ...

... aggiungerei un quale cosa per eliminare gli scintillii sui contatti del relé ... ad esempio uno "snubber" ... ::)

Guglielmo

Olam0436:
Ma da qualche parte c’è un esempio perché non saprei proprio da dove iniziare!!!

Allora, le String sono una classe di variabili usate su sistemi più potenti di una piccola board come Arduino con pochissima RAM, molto comode per chi programma, ma se continuamente crei e modifichi variabili String, non essendoci su Arduino un “garbage collector”, si rischia seriamente la saturazione di memoria perché i blocchi non più usati dalle String rilasciate non vengono riutilizzati. Quindi bisogna usare le cosiddette “stringhe C” ossia array di char, per cui tutte le variabili String le devi convertire in “char nomevariabile” o “char* nomevariabile” (rappresentazioni analoghe).
Per dettagli su come funzionino le “stringhe C” ti rimando a Google, ci sono milioni di siti che lo spiegano, ad esempio QUI.

Nel tuo caso in particolare, devi fare delle modifiche di questo tipo:

... 
// Conversione da Stringa a char
const char* uidmfrc522[] = {"cdff1b9f",  
                       "bdb15c9f",  
   ...
                       "9780b53b", 
                       "27ec823b", };
int numCod;  // Memorizzo quanti codici ho (per evitare ogni volta di fare sizeof)

void setup() {
...   
   numCod = sizeof(uidmfrc522)/sizeof(uidmfrc522[0]);
   Serial.print("mfrc522 registrati n° --> ");
   Serial.println(numCod);
...
 
char uid_s[16]; // Dimensione sufficiente per il max numero di caratteri+1
char uid_b[4];  // Buffer per la creazione della singola stringa byte hex
byte b;  // Valore da leggere (per evitare tante chiamate a mfrc522.uid.uidByte[i])

  if (!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()) {
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    //String uid_a = String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
    //String uid_b = String(mfrc522.uid.uidByte[i], HEX);
    b = mfrc522.uid.uidByte[i];
    sprintf(uid_b, "%02X", b);  // converte il byte in 2 caratteri hex
    //uid_s = uid_s+uid_a+uid_b;
    strcat(uid_s, uid_b);
  }
...
  for (int i = 0; i < numCod; i++){   
    // Qui devo usare strcmp()
    if( strcmp(uidmfrc522[i],uid_s) == 0 ){      
      Serial.println("Accesso consentito");
      openDoor();
      controllo = true;
      break;
    }
  }
  if(!controllo){
    Serial.println("Accesso vietato");      //accendiLed(ledRosso);
...
}

(è evidente che chi ha scritto quel programma non avesse alcuna idea di cosa fossero le “stringhe C”).

Ovviamente ci sono sempre vari modi per fare la stessa cosa, ma chiedi se hai dubbi sul perché di certe istruzioni (ma DOPO che avrai letto almeno quella pagina che spiega le stringhe C…).

Olam0436:
E comunque non mi spiego come mai sul banco il sistema funziona e non si blocca, mentre montato si blocca

Come ho già detto, non è sicuro che questa modifica possa risolvere il tuo problema, ma dato che è sicuro che un codice che fa uso di String possa dare prima o poi problemi gravi su Arduino, è una cosa che va fatta comunque se vuoi un codice “decente”.

E, sempre come ho detto, una volta che hai tolto le String ed il programma funziona come previsto, vedi se si blocca o meno. Se si blocca ancora c’è sicuramente altro (ed in questo caso tutti i discorsi di watchdog, diodi, GND, eccetera sono sacrosanti) ma hai escluso che il problema sia l’uso scriteriato della memoria di Arduino con le malefiche String.

Ti ringrazio infinitamente dell'aiuto che stai cercando di darmi. Mi sono incaponito su questa cosa e finora ho anche speso un sacco di soldi per realizzare questo impianto e vedere il progetto svanire non mi piacerebbe affatto (serratura elettrica, quadro elettrico nuovo, trasformatori e diciamo che arduino, rfid e schede sono la spesa minore). Grazie Stasera provo a sistemare lo sketch e poi ti faccio sapere

Ringrazio ancora docdoc per i suggerimenti. Ho modificato lo sketch ma c’è qualcosa che non va in quanto rimane sempre acceso il led rosso. Questo è il codice modificato.

#include <SPI.h>
#include <MFRC522.h>

#define SDA_DIO1 10
#define RESET_DIO1 9
#define SDA_DIO2 5
#define RESET_DIO2 8
#define delayRead 1000 
#define delayLed 2000 
#define ledVerde 2
#define ledRosso 3
#define rele 4

MFRC522 mfrc522(SDA_DIO1, RESET_DIO1);
 
//long previousMillis = 0;
//long interval = 10;

// Conversione da Stringa a char
const char* uidmfrc522[] = {"cdff1b9f",  
                       "bdb15c9f",  
                       "f0397889",  
                       "cd618071", 
                       "cc6785b9",
                       "133eb773",
                       "92d91ed9", 
                       "db6a9179", 
                       "eb8b68d9", 
                       "4d1a54e9",
                       "625566d9", 
                       "fdd3a671", 
                       "656165d9", 
                       "545e24d9", 
                       "b94623d9", 
                       "dd635a9f",
                       "c7ac65d9", 
                       "9d51f99e", 
                       "636524d9", 
                       "bdd74b9f", 
                       "2d90459f",
                       "4d941b9f",
                       "fdc4f19e", 
                       "8d37e79e",
                       "8d6dd39f", 
                       "3d851d9f", 
                       "6d47a871", 
                       "1d8efe9e",
                       "f7b17b3b", 
                       "0700353b", 
                       "3728b53c", 
                       "47f9c03b", 
                       "07a1b53c", 
                       "2771a43b", 
                       "576d613b", 
                       "67d1af3b", 
                       "5497724d",    
                       "9780b53b", 
                       "27ec823b", };
int numCod;  // Memorizzo quanti codici ho (per evitare ogni volta di fare sizeof)

void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
SPI.begin();        // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(rele, OUTPUT);
Serial.println("Ingresso Aziendale");
   numCod = sizeof(uidmfrc522)/sizeof(uidmfrc522[0]);
   Serial.print("mfrc522 registrati n° --> ");
   Serial.println(numCod);
Serial.println("In attesa di lettura...");
pinMode(ledVerde,OUTPUT);
pinMode(ledRosso,OUTPUT);
pinMode(rele,OUTPUT);
}
void loop() {
{  
//unsigned long currentMillis = millis();
//if(currentMillis - previousMillis > interval) {
//previousMillis = currentMillis;  
char uid_s[16]; // Dimensione sufficiente per il max numero di caratteri+1
char uid_b[4];  // Buffer per la creazione della singola stringa byte hex
byte b;  // Valore da leggere (per evitare tante chiamate a mfrc522.uid.uidByte[i])

  if (!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()) {
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    //String uid_a = String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
    //String uid_b = String(mfrc522.uid.uidByte[i], HEX);
    b = mfrc522.uid.uidByte[i];
    sprintf(uid_b, "%02X", b);  // converte il byte in 2 caratteri hex
    //uid_s = uid_s+uid_a+uid_b;
    strcat(uid_s, uid_b);
  }
  }
Serial.print("RFID UID rivelato --> ");
Serial.println(uid_s);
Serial.println("");
boolean controllo = false;
  for (int i = 0; i < numCod; i++){   
    // Qui devo usare strcmp()
    if( strcmp(uidmfrc522[i],uid_s) == 0 ){      
      Serial.println("Accesso consentito");
      openDoor();
      controllo = true;
      break;
    }
  }
  if(!controllo){
    Serial.println("Accesso vietato");      //accendiLed(ledRosso);
digitalWrite(ledRosso, HIGH);
  delay(delayLed);
  digitalWrite(ledRosso, LOW);
     }
  Serial.println();
  Serial.println("In attesa di lettura...");
    }
}
void openDoor(){
  digitalWrite(ledVerde, HIGH);
  delay(delayLed);
  digitalWrite(ledVerde, LOW);
  digitalWrite(rele, HIGH);
  Serial.println("Relè ON");
  delay(2000);
  digitalWrite(rele, LOW);
  Serial.println("Relè OFF");
}

Per Guglielmo che come al solito anche lui molto paziente e gentile, ieri ho comprato un nuovo trasformatore per provare nuovamente a separare le due alimentazioni.