settare una costante char con un valore da eeprom

ciao a tutti, sto sviluppando un progetto che in pratica è un contatore di punti per un gioco da tavolo.

il risultato che vorrei ottenere è: entrambi i 2 giocatori scrivono il proprio nome tramite 4 pulsanti, accettano la selezione della sequenza di lettere, poi inizia il contatore su display lcd 16x2, in ogni riga è presente il nome del giocatore e i suoi punti.
quando i punti arrivano a 0 arduino si resetta, e dovrebbe ricominciare con i nomi inseriti la volta precedente a meno che non si voglia cambiarli con apposito tasto.

Il programma funziona alla perfezione, scrivo le lettere di ogni nome su eeprom tramite pulsantiera, le riesco a leggere e a procedere avanti. essenzialmente il mio programma è un unione di 3 programmi diversi che ho scritto mentre imparavo a usare la piattaforma:
il primo che fa il contatore di per se, con nomi preimpostati nello sketch.
il secondo che permette di scrivere un nome su display con 3 pulsanti e uno di “accetta nome”.
il terzo che salva il nome su memoria eeprom e lo legge.

Il problema insormontabile che ho trovato è che lo sketch non può essere compilato e caricato a meno che le due righe che definiscono il nome dei giocatori non si trovino fuori dalle funzioni void()…
ovvero le due righe che definivano i nomi sul primo script usato (il contatore) sono fondamentali:

char giocatoreuno[] = "MARCO";
char giocatoredue[] = "GIOVANNI";

però il risultato che voglio ottenere è scrivere su queste due costanti, due diverse variabili!
la costante è: char giocatoreuno= , la variabile è il nome.

la parte di programma dove leggo e ricavo il nome è la seguente:

 //CICLO PER LA LETTURA DEL NOME GIOCATORE UNO
  for (int memoryuno=0; memoryuno<=EEPROM.read(10)-1; memoryuno++){     
    nomeuno= EEPROM.read(memoryuno);
    char giocatoreuno = char(nomeuno);}

 //CICLO PER LA LETTURA DEL NOME GIOCATORE DUE
  for (int memorydue=0; memorydue<=EEPROM.read(22)-1; memorydue++){
    nomedue= EEPROM.read(memorydue);
    char giocatoredue = char(nomedue);}

non credo abbia senso che posto tutto lo sketch perchè molto lungo e il problema è più che altro concettuale: con quale riga di codice posso definire la costante char in modo che riporti il nome scritto su eeprom? le lettere sono salvate in numeri ascii…

Da qualche parte devi definire la lunghezza massima dei nomi, tipo:

#define MAX_NOME 16

E quindi cambiare la definizione delle variabili includendola:

char giocatoreuno[MAX_NOME] = {0};
char giocatoredue[MAX_NOME] = {0};

Per semplificare un po’ le cose, assumiamo che in EEPROM ci sia abbastanza spazio per salvare i nomi interi con la lunghezza massima, per cui la lettura diventa:

for (int i = 0; i < MAX_NOME; i++) {
  giocatoreuno[i] = EEPROM.read(i);  // Il nome del G1 inizia all'indirizzo EEPROM 0
  giocatoredue[i] = EEPROM.read(16 + i);    // Il nome del G2 inizia all'indirizzo EEPROM 16
}

Ricorda che in C le stringhe devono sempre essere terminate da ‘\0’, per cui la lunghezza massima che devi fare impostare è di 15 caratteri.

fantastico, grazie mille provo subito la tua soluzione. dovrei avere spazio, a quanto ho capito la memoria EEPROM salva 1 carattere a byte e io ne ho massimo 10 a nome, quindi 20 totali +2 che indicano la lunghezza di lettere del nome.

grazie ancora per la velocissima risposta è troppo utile avere il vostro supporto, sarei ancora a far lampeggiare i led a quest'ora senza di voi :)

Non serve salvare la lunghezza, leggi sempre 11 (10 + 1) caratteri e sei a posto, quelli "vuoti" saranno riempiti da '\0'.

zartas90: sarei ancora a far lampeggiare i led a quest'ora senza di voi

La cara, vecchia nobile arte di fare lampeggiare i LED... sempre sottovalutata :)

P.S. fra le "funzioni occulte delle EEPROM che ci sono ma pochi conoscono" forse c'è qualcosa che fa al caso tuo...

ho fatto come hai consigliato, mi sembrava un ottima soluzione dato che usi una variabile i per fare meglio quello che io ho fatto con 6 variabili diverse :slight_smile:
solo che ora mi va in crash, ogni volta che premo un bottone… reset immediato, non parte più nessuna parte di programma eccetto void setup()

posto una porzione di codice per completezza cosi potete magari capire meglio di che parlo
(scusate i virtuosismi che faccio per passare fra gli if e i while ma sono ancora agli inizi e aggiungo variabili a casaccio per far più o meno girare il tutto…

la parte di inizio e di definizione

#include <EEPROM.h>

#define MAXNOME 9
char giocatoreuno[MAXNOME]={0};
char giocatoredue[MAXNOME]={0};
//blocco costanti per salvataggio del nome su memoria EEPROM
int i=0;

//blocco costanti del ciclo while
const int duegiu = 9; //accetta selezione
unsigned long TEMPO;
bool premuto;
bool finegioc1;
bool finegioc2;


//CICLO SETUP
void setup() { 
  pinMode(unosu, INPUT);
  pinMode(unogiu,INPUT);
  pinMode(duesu, INPUT);
  pinMode(duegiu, INPUT);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("scrivere nome");
  lcd.setCursor(0,1);
  lcd.print("premendo + o -");
  premuto = false;
  TEMPO = millis(); 
}

e la parte di loop più importante che crasha:

//CICLO LOOP
void loop(){
    for (int i=0; i<=MAXNOME; i++){     
    giocatoreuno[i] = EEPROM.read(i);//CICLO PER LA LETTURA DEL NOME GIOCATORE UNO
    giocatoredue[i]= EEPROM.read(11+i);}//CICLO PER LA LETTURA DEL NOME GIOCATORE DUE

  if(millis()< 3000){ //3 secondi per premere il pulsante che apre la scrittura dei nomi
  if (digitalRead(duegiu) == HIGH) {     
     premuto = true;
     delay(100);
     lcd.clear();}} 
  if(premuto) {   //inizio scrittura nome giocatore 1
  lcd.print("GIOCATORE 1:");
    while (finegioc1==false){//fino a che il bottone non è premuto, rimane in ciclo
      delay(100);
     lcd.setCursor(0,1);//sposta cursore sulla 2 riga
    SCRITTURANOMEUNO(); //SCRITTURA NOME 1
    
     if (digitalRead(duegiu) == HIGH){//bottone premuto, si passa al nome del giocatore 1

      finegioc1 = true; //inizio scrittura nome giocatore 2   
      lcd.clear();
      lcd.print("GIOCATORE 2:");
     while(finegioc2==false){//fino a che il bottone non è premuto, rimane in ciclo
      lcd.setCursor(0,1);//sposta cursore sulla 2 riga  
     SCRITTURANOMEDUE(); //SCRITTURA NOME 2

     if (digitalRead(duegiu) == HIGH) {//esce dal ciclo iniziando il programma dei punti
    
     finegioc2 = true;
     premuto=false;
     delay(200);
     lcd.clear();
     }      
      }
     delay(100);    
    }}}

  if(premuto==false)           //inizio del magic counter
    if(millis() > 3000) {   //se passano 3 secondi senza premere, inizia il programma con
                            // i nomi della partita precedente

      MAGIC(); //richiama lo script del programma per i punti
      }

}

Io ho scritto:

for (int i = 0; i < MAX_NOME; i++) {

Tu invece:

for (int i=0; i<=MAXNOME; i++){

Riesci a notare la piccola, ma importante differenza? :wink:

Ti consiglio comunque di usare la Formattazione Automatica dell’IDE, almeno mette un po’ posto l’indentazione. Ci sarebbero poi moooolti altri commenti da fare, ma per ora fermiamici qua :).

caspita, quando l'uguale... fa la differenza :)

beh se hai commenti da fare su come scrivere che possano aiutarmi, spara pure che meglio saperli prima che dopo!

SukkoPera: Non serve salvare la lunghezza, leggi sempre 11 (10 + 1) caratteri e sei a posto, quelli "vuoti" saranno riempiti da '\0'.

un dubbio: qua dici che i caratteri vuoti saranno riempiti da \0, ma alla fine nel codice non l'ho mai scritto, lo dovrei aggiungere? se si dove? lcd legge male gli spazi vuoti, segnando caratteri strampalati come righe orizzontali o rettangoli completamente pieni

mamma, mi sento ad un passo dalla fine grazzzzie

In teoria è scritto qua.

char giocatoreuno[MAXNOME]={0};
char giocatoredue[MAXNOME]={0};

Però, però, però... Ci sono un sacco di però. Dipende essenzialmente tutto da come li salvi su EEPROM e da come li visualizzi a display, per cui ti suggerirei di postare lo sketch completo, così vediamo.

Uno spunto di riflessione: sei proprio sicuro che alla fine del "giro" Arduino si debba resettare? Non c'è nessun bisogno che avvenga questo, se organizzi meglio il programma puoi farlo facilmente ripartire dall'inizio senza un reset. Questo eliminerebbe la necessità di scrivere i nomi su EEPROM, basta tenerli in memoria. Ricorda che la EEPROM ha una vita limitata. Certo, ti serviranno almeno 100000 partite per raggiungere il limite, però se si può evitare a priori...

molte meno dato che scrivo 20 caratteri ogni volta che cambio i nomi :)

in realtà non ho valutato altre soluzioni perchè sono davvero a digiuno di programmazione e non ho trovato una guida affidabile da cui prendere spunto. Ho iniziato con qualche guida online che mi ha davvero aiutato nei primi passi con esempi, sketch e elettronica, ma ora sento il bisogno di imparare anche la parte "teorica" di programmazione, data la mia ignoranza.

per farti un esempio, solo ieri ho capito che non esistono solo le funzioni void setup() e void loop(), ma che posso fare un void a mio piacimento e poi richiamarlo in più punti... utilissimo, mi ha permesso di andare avanti con questo progetto.

in pratica la funzione reset completo di arduino è stata la prima cosa a cui son venuto incontro cercando su internet, e dato che sono ancora agli inizi, poco male se fra qualche mese dovrò cambiare scheda e usare questa per un progettino fisso di poco conto

Ho visto un bellissimo libro: Arduino, progetti e soluzioni di Morgolis ma ahimè, 60 euro sono un po troppi per ora...

Se hai da consigliare qualcosa, leggo ben volentieri anche in inglese ;) (cmq ho risolto aggiungendo di nuovo la lunghezza in lettere dei nomi e scrivendo spazi ovunque fossero rimasti vuoti :P )