codice, eeprom e 2 sketch distinti al reset, vs consigli

la settimana scorsa chiedevo come far eseguire uno sketch ed al reset eseguirne un altro, ho ripreso per mano il codice di prova ma come l'ho scritto sembra contorto pure a me che ne capisco poco, potete dagli un occhiata?

per funzionare funziona ma che altri modi ci sono per chiudere un ciclo su se' stesso, io li uso goto...

#include <EEPROM.h>

int val;

void setup(){
  
  pinMode(13, OUTPUT);
  
  val=EEPROM.read(0);   //leggo la eeprom in posizione 0
 
}

void loop(){
  if(val==1){
   {EEPROM.write(0,0);  //scrivo la eeprom in posizione 0 val=0
   goto sketch1;}       //salto a sketch1
  }
  if(val==0){
   {EEPROM.write(0,1);  //scrivo la eeprom in posizione 0 val=1
   goto sketch2;}       //salto a sketch2
  }  
 
  sketch1:
  {
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // set the LED off
  delay(1000);              // wait for a second
  goto sketch1;             // richiudo il ciclo sketch1
  }
  sketch2: 
  {
  digitalWrite(13, HIGH);   // set the LED on
  delay(100);               // wait for a 1/10 second
  digitalWrite(13, LOW);    // set the LED off
  delay(100);               // wait for a 1/10 second
  goto sketch2;             // richiudo il ciclo sketch2
  }
}

Ciao,
personalmente aborro i goto.... dovresti usare delle funzioni

void loop(){
	if(val){
		EEPROM.write(0,0);  //scrivo la eeprom in posizione 0 val=0
		sketch1();
	}
	else
		EEPROM.write(0,1);  //scrivo la eeprom in posizione 0 val=1
		sketch2();
	}

void sketch1(){
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // set the LED off
  delay(1000);              // wait for a second
  sketch2();
}

void sketch2(){
  digitalWrite(13, HIGH);   // set the LED on
  delay(100);               // wait for a 1/10 second
  digitalWrite(13, LOW);    // set the LED off
  delay(100);               // wait for a 1/10 second
  sketch2();
}

il codice è comunque da ottimizzare ulteriormente...sketch1() e sketch2() fanno la stessa cosa a meno del tempo di delay. Puoi lavorarci ancora su.
N

Ecco come la vedo io:

byte sketch;

void setup() {
  sketch=leggiEEPROM(); //leggi
  .... //qui farai quel che devi fare
}

void loop() {
..... //tuo programma
}

byte leggiEEPROM() {
  byte tempByte=EEPROM.read(0);
  if ((tempByte != 0) && (tempByte != 1)) { //valore non conforme
    EEPROM.write(0, 0); //parto con "0"
    tempByte = 0;
  } else { //valore corretto (o 0 o 1)
    EEPROM.write(0, tempByte^1); //inverto per la prox volta 
  }
  return tempByte
}

leo72:
Ecco come la vedo io:

byte sketch;

void setup() {
  sketch=leggiEEPROM(); //leggi
  .... //qui farai quel che devi fare
}

void loop() {
..... //tuo programma
}

byte leggiEEPROM() {
  byte tempByte=EEPROM.read(0);
  if ((tempByte != 0) && (tempByte != 1)) { //valore non conforme
    EEPROM.write(0, 0); //parto con "0"
    tempByte = 0;
  } else { //valore corretto (o 0 o 1)
    EEPROM.write(0, tempByte^1); //inverto per la prox volta
  }
  return tempByte
}

L'approccio di Leo è il più sicuro. Leggere e scrivere dalla/sulla EEPROM nel loop non è mai consigliato (correggetemi se sbaglio). Una volta che ti tiri fuori il valore che hai memorizzato in EEPROM usalo per gestire il tempo di delay che vuoi implementare. del genere:

long time_delay;
void setup() {
  sketch=leggiEEPROM(); //leggi
  if (sketch){
       time_delay = 1000;
  }
  else{
       time delay = 100;
  }
}

void loop(){
        digitalWrite(13, HIGH);   // set the LED on
	delay(time_delay);              // wait for a second
	digitalWrite(13, LOW);    // set the LED off
	delay(time_delay);              // wait for a second
	time_delay = 100;
}

così dovrebbe fare quello che chiedi con poco codice.
N

grazie dei vostri esempi, e' quello che cercavo, io riesco a farlo ma avete visto come, tipo a martellate :stuck_out_tongue_closed_eyes: volevo qualche altro esempio piu' raffinato che ora mi studio :wink:

scusate 2 domande OT sulla eeprom dell'atmeg328

gli spazi son 512bytes ma come li indirizzo?
e' giusto scrivere cosi? EEPROM.write(150,12)?
indirizzo 150 dato 12 ?
(e l'ultimo indirizzo possibile e' 511?)

finora ho solo messo sull'indirizzo 0 zero o uno

e domanda tecnica, se io scrivo sull'indirizzo 0 fino a renderlo inutilizzabile, gli indirizzamenti successivi continuano a funzionare?

reizel:
scusate 2 domande OT sulla eeprom dell'atmeg328

gli spazi son 512bytes ma come li indirizzo?

Il 328 ha 1024 byte di memoria EEPROM. Se hai preso il dato dall'esempio allegato all'Arduino, è sbagliato ed è relativo all'168, che ha metà memoria.

e' giusto scrivere cosi? EEPROM.write(150,12)?
indirizzo 150 dato 12 ?
(e l'ultimo indirizzo possibile e' 511?)

Il modo è giusto, l'ultimo indirizzo è 1023.

finora ho solo messo sull'indirizzo 0 zero o uno

e domanda tecnica, se io scrivo sull'indirizzo 0 fino a renderlo inutilizzabile, gli indirizzamenti successivi continuano a funzionare?

In teoria sì, ma non so esattamente a livello elettrico cosa può succedere quando parte la circuiteria relativa ad una cella, se cioè poi si danneggiano anche i contatti adiacenti .

grazie leo, e si' i 512 li avevo letti dall'esempio di arduino.cc :*

per la domanda tecnica credo che solo utenti uwe compatibili potrebbero darci una risposta certa ]:smiley:

altrimenti per noi mortali non resta che scriverci uno sketch che faccia piantare la eeprom e contare le scritture :roll_eyes:

Ci vorrebbe astrobeed, ma è un po' latitante ultimamente. Mi pareva che se ne fosse già parlato in passato ma non mi ricordo cos'ho fatto stamattina, figurati se mi ricordo cose lette 6 mesi fa :astonished:

io ricordo che avevo chiesto cosa succedeva quando superavi le massime scritture di codice sull'atmega, dissero che semplicemente non lasciava piu' scrivere nulla, per questo mi chiedevo se usando la eeprom ad indirizzi questa rimaneva utilizzabile nei bytes "ancora buoni"

Ma sicuramente perdi la cella (byte) e basta.

Se scrivi troppe volte sulla stessa cella e quella si "rompe" le cose sono le seguenti.

Una cella eeprom é un MOSFET con un gate isolato nel silico. Programmandolo inietti per effetto tunnel delle cariche sul gate isolato. Cancellando li togli. A causa di materiali non perfetti restano nel tempo sempre cariche nel silicio (isolatore) che disturbano la programmazione e fanno che il gate non é piú isolato perfettamente. La cella si scarica e cambia dopo un po di tempo stato.
Tutti dei effetti poco da tenere sotto controllo.

Ciao Uwe

superp:
Ciao,
personalmente aborro i goto.... dovresti usare delle funzioni

void loop(){
if(val){
	EEPROM.write(0,0);  //scrivo la eeprom in posizione 0 val=0
	sketch1();
}
else
	EEPROM.write(0,1);  //scrivo la eeprom in posizione 0 val=1
	sketch2();
}

void sketch1(){
 digitalWrite(13, HIGH);   // set the LED on
 delay(1000);              // wait for a second
 digitalWrite(13, LOW);    // set the LED off
 delay(1000);              // wait for a second
 sketch1();
}

void sketch2(){
 digitalWrite(13, HIGH);   // set the LED on
 delay(100);               // wait for a 1/10 second
 digitalWrite(13, LOW);    // set the LED off
 delay(100);               // wait for a 1/10 second
 sketch2();
}



il codice è comunque da ottimizzare ulteriormente...sketch1() e sketch2() fanno la stessa cosa a meno del tempo di delay. Puoi lavorarci ancora su. 
N

una ciamata recursiva della funzione nella stessa funzione riempe in pochissimo lo Stack e blocca o fa fare cose inaspettate al programma.

neanche l' uso del goto mi piace. io consiglio un loop con for o con while:

void sketch1(){
for( ;; )
{
codice del sketch 1
}}

oppure

void sketch1(){
while(1)
{
codice del sketch 1
}}

Ciao Uwe

grazie uwe, anche per la spiegazione della eeprom, ora io e leo ce ne ricorderemo :wink:

superp: non ti ho risposto prima, il blink con 2 tempi diversi era solo per testare il codice senza rompimenti, lo sketch ovviamente e' tutt'altra cosa

Ora non voglio confondere le idee dicendo che il goto non deve essere odiato come la peste a prescindere.

Il problema del goto è legato alle etichette a cui si fa il salto, se per rapidità di esecuzione voglio usare un salto incondizionato dovrei farlo in codice non visibile al programmatore, tipo una funzione di libreria.

Devo anche fare attenzione alla leggibilità, il goto etichetta è un problema quando la fuzione contiene molto codice e l'eticchetta si trova distante dalla chiamata goto. La leggibilità peggiora quando nel codice ci sono più goto e più etichette, a questo punto è meglio passare ad asm inline.

if ((tempByte != 0) && (tempByte != 1)) { //valore non conforme

// così è più logico
byte n_max_sketch = 2;
if (tempByte > n_max_sketch - 1) { //valore non conforme

Ciao.