Go Down

Topic: Arduino ogni tanto si blocca (Read 1 time) previous topic - next topic

fabpolli

#30
Dec 06, 2018, 09:44 am Last Edit: Dec 06, 2018, 09:44 am by fabpolli
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
Code: [Select]

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



Patrick_M

#31
Dec 06, 2018, 09:50 am Last Edit: Dec 06, 2018, 09:51 am by Patrick_M
Quote
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:
Code: [Select]
const byte RELE = 4;
(non usare comunque le lettere accentate, è facile sbagliarsi)

EDIT: in contemporanea con fabpolli :)
per inserire (lo sketch) il programma, dall'IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

docdoc

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.

Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

Olam0436

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

Olam0436

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

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à (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.

gpb01

#36
Dec 06, 2018, 01:52 pm Last Edit: Dec 06, 2018, 01:52 pm by gpb01
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
Search is Your friend ... or I am Your enemy !

docdoc

#37
Dec 06, 2018, 01:57 pm Last Edit: Dec 06, 2018, 02:00 pm by docdoc
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:

Code: [Select]
...
// 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..).

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.
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

Olam0436

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

Olam0436

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.
Code: [Select]
#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.

gpb01

#40
Dec 07, 2018, 10:19 am Last Edit: Dec 07, 2018, 10:20 am by gpb01
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.
... oltre a separare, metti, come ti dicevo, uno "snubber" sui contatti del relé così da smorsare scintillii ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

fabpolli

Hai un problema con le parentesi graffe, ti resta sempre acceso il led rosso perché la parte di controllo avviene sempre ad ogni ciclo di loop e non solo quando una nuova carta viene rilevata quindi controllo è sempe false e ti accende il led rosso, lo spegne dopo il delay ma è così rapido il loop che lo rieccende subito e sembra sempre acceso
Credo che così sia corretto, prova:
Code: [Select]

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...");

}

fabpolli

#42
Dec 07, 2018, 10:50 am Last Edit: Dec 07, 2018, 10:56 am by fabpolli
Se posso ti suggerico anche due correzioni che migliorano la robustezza del codice, io questo
Code: [Select]

char uid_s[16]; // Dimensione sufficiente per il max numero di caratteri+1

lo sposterei prima del for e lo definirei così:
Code: [Select]

char uid_s[mfrc522.uid.size]; // Dimensione sufficiente per il max numero di caratteri+1

in questo modo se ti dovesse per caso legere una tessera con più caratteri non rischi di oltrepassare la dimensione dell'array con conseguende errori dovuti a scrittura in area di memoria che non compete all'array.
Inoltre dopo il for aggiungerei il terminatore di riga così stai certo che le successive funzioni (strcmp, ecc.) non incappino in errori dovuti alla sua mancanza:
Code: [Select]

uid_s[mfrc522.uid.size] = '\0';

Olam0436

Grazie fabpolli, ho fatto le modifiche che mi hai suggerito ed il loop è sparito, ma il sistema non legge più le tessere. Mi sono accorto che mancava l'azione fondamentale:
Code: [Select]
if ( ! mfrc522.PICC_IsNewCardPresent()) {
   return;
    }
   if ( ! mfrc522.PICC_ReadCardSerial()) {
   return;

ma nulla è cambiato.
Posto nuovamente lo sketch
Code: [Select]

#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()) {
   return;
    }
   if ( ! mfrc522.PICC_ReadCardSerial()) {
   return;
}
  if (!mfrc522.PICC_IsNewCardPresent() && !mfrc522.PICC_ReadCardSerial()) {
 
 
char uid_s[mfrc522.uid.size]; // Dimensione sufficiente per il max numero di caratteri+1

  for (byte i = 0; i < mfrc522.uid.size; i++) {

uid_s[mfrc522.uid.size] = '\0';     
    //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");
}

Guglielmo hai un sito dove poter comprare lo snubber con le caratteristiche che serve a me?
Grazie

gpb01

#44
Dec 07, 2018, 11:28 am Last Edit: Dec 07, 2018, 11:28 am by gpb01
Guglielmo hai un sito dove poter comprare lo snubber con le caratteristiche che serve a me?
... ma fattelo :) ... comincia con una resistenza da un 47Ω in serie ad un condensatore da 220nF e prova ... poi al limite aumenti un po' la capacità e/o la resistenza ... ::)

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up