Memory error + query error rfid sql

Salve, mi ritrovo ancora qui a urtarvi :frowning:

Non riesco a capire come mai dal monitor seriale legge valori diversi delle stesse carte e arrivano alcuni errori dopo varie letture per poi finire con un “memory error” finale…

Probabilmente la memoria credo sia piena dopo le letture, conoscete qualche comando per azzerarla?
se si dove lo inserireste?

In caso estremo collego un pin al reset di arduino per resettarlo ogni lettura, ma questo implica una connessione al database per ogni lettura e quindi una perdita di tempo rilevante…

Grazie mille per la disponibilità di tutta la community e scusate il disturbo…

CODICE ARDUINO:

/*
Questo programma permette di collegarsi ad un DB MySQL per verificare se il codice della tessera magnetica è corretto
PINOUT:
  
RC522 MODULE    Uno/Nano    
SDA             D10
SCK             D13
MOSI            D11
MISO            D12
IRQ             N/A
GND             GND
RST             D9
3.3V            3.3V
Autore Giacomo Bellazzi
Versione 1.0
*/
#include "SPI.h"
#include "Ethernet.h"
#include "sha1.h"
#include "mysql.h"
#include "RFID.h"
/* Vengono definiti PIN del RFID reader*/
#define SDA_DIO 8  // 53 per Mega
#define RESET_DIO 9
#define delayRead 2000 // Time of delay 
//#define LEDGREEN 13
//#define LEDRED 12
  
/* Viene creata una istanza della RFID libreria */
RFID RC522(SDA_DIO, RESET_DIO); 
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server_addr(192, 168, 0, 120);
Connector my_conn;
char user[] = "arduser";
char password[] = "arduser";
char QUERY_POP[70] = "Select * From school.alunno as AK Where AK.Codice='%s'";
char query[65];
int buzzer = 3;
  
void setup() {
 Ethernet.begin(mac_addr);
 Serial.begin(9600);
 pinMode(buzzer, OUTPUT);
 /* Abilita SPI*/
 SPI.begin(); 
 /* Viene inizilizzato RFID reader */
 RC522.init();
 pinMode(13,OUTPUT);
 while (!Serial);
 delay(500);
 Serial.println("Connecting...");
 if (my_conn.mysql_connect(server_addr, 3306, user, password)){
Serial.println("Connected!");
 } else {
 Serial.println("Connection failed.");
 }
}
void loop() {
   /* Temporary loop counter */
  byte i;
  // Se viene letta una tessera
  if (RC522.isCard())
  {
    // Viene letto il suo codice 
    RC522.readCardSerial();
    String codiceLetto ="";
    Serial.println("Codice delle tessera letto:");
  
    // Viene caricato il codice della tessera, all'interno di una Stringa
    for(i = 0; i <= 4; i++)
    {
      codiceLetto+= String (RC522.serNum[i],HEX);
      codiceLetto.toUpperCase();
   // Serial.println("yesfor");
    }
    char charBuf[12];
    codiceLetto.toCharArray(charBuf, 12); 
    Serial.println(codiceLetto);
    Serial.println(charBuf);

    
    if(isAuthorized(charBuf)){
      Serial.println("Tessera autorizzata");
      
 char QUERY_POP1[] = "insert into school.presenza  values (ID,now(),'%s')";
 sprintf(query,QUERY_POP1,charBuf);
 tone(buzzer,1000,200);
 /*
my_conn.cmd_query("select max(id) from school.presenza");
      
my_conn.get_columns();
row_values *row = NULL;
 row = my_conn.get_next_row();

int id = (int) row->values[0];
  Serial.println(id);

 */
 
 //     query_insert=QUERY_POP1+charBuf;
      Serial.println(query);
     if( my_conn.cmd_query(query))
     Serial.println("inserito");
      //accendiLed(LEDGREEN);
    }else{
      Serial.println("Tessera non autorizzata");
      //accendiLed(LEDRED);
      tone(buzzer,1250,500);
    }
  delay(delayRead);  
  }
 }

  
// Controlla se un codice è autorizzato
boolean isAuthorized(char Codice[]){
  // Serial.println("sprint");
   
  sprintf(query, QUERY_POP,Codice);
  //Serial.println(QUERY_POP);
  Serial.println(query);
my_conn.cmd_query(query);
my_conn.get_columns();
row_values *row = NULL;

 int number = 0;
 row = my_conn.get_next_row();
  Serial.println(row->values[0]);
  Serial.println(Codice);
  if(row->values[0]!=NULL) 
number++;
 my_conn.free_columns_buffer();
 my_conn.free_row_buffer();
 Serial.println(number);
// break;
// }

//my_conn.cmd_query("");
if(number>0){
   return true;
 }else{
  return false; 
 }
}
 
/*// Questa funzione permette di accendere un LED per un determinato periodo
void accendiLed(int ledPin){
  digitalWrite(ledPin,HIGH);
  delay(delayRead);
  digitalWrite(ledPin,LOW);
}*/

Monitor seriale arduino

Connecting...
Connected to server version 5.5.5-10.1.13-MariaDB
Connected!
Codice delle tessera letto:
320404                                    ******In realtà il codice della tessera è "5B50272B7"******
Tessera non autorizzata

Codice delle tessera letto:
5B50272B7                                 ******Codice letto correttamente ed esecuzione della query******
Tessera autorizzata

Codice delle tessera letto:
5B50272B7                               ******Nonostante il codice letto correttamente non riconosce la tessera******
Tessera non autorizzata


Codice delle tessera letto:

32040B5                                      *****il vero codice della tessera è B9802C2B3E*****

Bad mojo. EOF found reading column header.    *****Errore nella query****
ERROR: You must read the columns first!

Tessera non autorizzata

Codice delle tessera letto:
B9802C2B3E                              ****Codice corretto ma non parte la query****

Memory error.                              *****MEMORY ERROR??****

Questo purtroppo accade con l'uso indiscriminato della classe String, che qui noi SEMPRE sconsigliamo ...

NON sei su un PC dove c'è un sistema operativo ed un "garbage collector", sei su una piccola MCU con solo 2KBytes di SRAM, dove devi fare tutto tu e dove usare la classe "String", a causa dell'allocazione e riallocazione dinamica della memoria, porta quasi sempre ... [u]a sicuri problemi[/u] ! :D

Impara ad usare le stringhe classiche del C ... ovvero semplici array di char terminati dal carattere null (0x00) e le funzioni che trovai nella libreria standard (... che, oltretutto, è automaticamente inclusa dal IDE) AVR libc. ;)

Buon lavoro !

Guglielmo

gpb01: Questo purtroppo accade con l'uso indiscriminato della classe String, che qui noi SEMPRE sconsigliamo ...

NON sei su un PC dove c'è un sistema operativo ed un "garbage collector", sei su una piccola MCU con solo 2KBytes di SRAM, dove devi fare tutto tu e dove usare la classe "String", a causa dell'allocazione e riallocazione dinamica della memoria, porta quasi sempre ... [u]a sicuri problemi[/u] ! ]:D

Impara ad usare le stringhe classiche del C ... ovvero semplici array di char terminati dal carattere null (0x00) e le funzioni che trovai nella libreria standard (... che, oltretutto, è automaticamente inclusa dal IDE) AVR libc. ;)

Buon lavoro !

Guglielmo

Grazie per la disponibilità

Potrei avere magari uno "schizzo veloce" su cosa e come sostituire string? ho provato ma non credo di aver fatto correttamente dato l'esito..

Hai letto i link che ti ho dato ? In particolare cosa è una stringa classica del ‘C’ ?

In pratica devi usare, al posto della classe String, dei normali char array dimensionati già staticamente per il massimo numero di caratteri che prevedi.

Poi, tutte le stringhe classiche del ‘C’ devi terminarle con il carattere 0x00 quindi, nella lunghezza, devi sempre considerare un caratteri in più per metterci, appunto, il carattere di fine stringa (0x00).

Infine, tutte le manipolazioni, oltre che con i classici sistemi del ‘C’ (accesso ai singoli elementi di un array tramite indice) le fai con le funzioni che trovi in <string.h> (che devi includere in testa la programma) e che fa parte della detta AVR libc che è sempre disponibile nell’IDE.

Per il resto … beh … è semplicemente ‘C’ :slight_smile:

Guglielmo

ciao

una "pezza" potrebbe essere quella di usare la macro F() nelle serial.print ovvero da così:

Serial.println("Connecting...");

a così:

Serial.println(F("Connecting..."));

Questo ti fa risparmiare un po' di ram. Con questo non voglio contraddire Guglielmo; è l'uso della classe "String" che ti mangia la ram, ti sto solo proponendo un modo per risparmiarne un po'. ;)

ciao pippo72

pippo72:
Questo ti fa risparmiare un po’ di ram.
Con questo non voglio contraddire Guglielmo; è l’uso della classe “String” che ti mangia la ram, ti sto solo proponendo un modo per risparmiarne un po’. :wink:

Vero, ne risparmia un po’, la qual cosa significa che … allunga solo il tempo prima che il problema si presenti :smiling_imp:

Guglielmo

So che è una cosa banale, ma mi sto bloccando e non sto riuscendo a capire come "convertirle"..

GiovaT18:
So che è una cosa banale, ma mi sto bloccando e non sto riuscendo a capire come “convertirle”…

Cosa vuoi convertire ? Non c’è un convertitore, occorre riscrivere il programma pensandolo in tutt’altro modo … eliminando tutte le classi String, implementando al loro post i char array e effettuando tutte le operazioni o usando gli operatori classici del ‘C’ o le funzioni che sono in <string.h>.

Guarda che non è una cosa che fai in mezz’ora …
… devi studiare come funzionano le stringhe classiche, tutte le funzioni di <string.h>, ecc. ecc. dopo di che … riscrivere il tutto in altro modo …

Ti consiglio, nel ricominciare, di fare UNA piccola cosa per volta … e quando una funziona passare alla successiva :slight_smile:

Guglielmo