Arduino Forum

International => Italiano => Software => Topic started by: barlettaag on Mar 16, 2013, 02:50 pm

Title: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 02:50 pm
Utilizzando la porta seriale con il c# e arduino mi è sorto un dubbio,se volessi indirizzare due valori a due variabili diverse.... tipo
"A123" per a = 123
"B235" per b = 235
... come faccio ? ... ho provato in questo modo...
Quote
if (Serial.available()>0 )
 {
   if (Serial.read() == 'b')
   {
    x = Serial.parseInt();
    Serial.flush();
    Serial.println("b");
   }
   else if (Serial.read() == 'c')
   {
     delayTime = Serial.parseInt();
     Serial.flush();
     Serial.println("c");
   }

Ho cercato di farlo in questo modo, con la b funziona tutto, quando metto un valore tipo c125 non succede niente (non mi stampa nemmeno la c sul seriale)... come mai ?
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 03:27 pm
Ciao, io non sono un'esperto anzi sono alle prime armi con arduino e la sua programmazione, ma credo di avere un suggerimento al riguardo perchè l'ho sperimentato qualche settimana fa e funziona bene:

Code: [Select]


void loop(){
 
if (Serial.available()) {

   ser = Serial.read();   //ser è la variabile che raccoglie il contenuto del buffer seriale in ingresso dell'arduino.

  if(ser == 'a'){
     Trasmissione_Dati_a_PC();     //<----trasmette un dato al pc... o qualsiasi valore letto sulle porte ADC/digitali per esempio...
  }
 
  else if(ser == 'c'){
          Rx_New_Data_da_PC();        //<----riceve i dati trasmessi dal pc da memorizzare nellèarray...
  }
 
  }


poi, in una function chiamata Rx_New_Data_da_PC() inserisco il seguente codice:

Code: [Select]


void Rx_New_Data_da_PC){   //questa function riceve dei dati ... poi modifica l'array con i nuovi valori...  

Azzera_Valori();   //function dove vengono azzerati i vari contatori e/o variabili global usate.
Rx_Data();          //function che receve i dati...
    Value1 = Value;
Rx_Data();
   Value2 = Value;
Rx_Data();
   Value3 = Value;
Rx_Data();
   Value4 = Value;
 
//Errore_RX è un contatore di errore, se i dati ricevuti non sono compresi da byte da 0 a 9 ovvero riceve "m" invece di "1" viene
//incrementato il contatore da 0 (nessun errore) a 1 e il seguente if provvede a inmettere dei valori di default, ma l'uso che se
//ne può fare dipende dalla singola applicazione...
 
 if (Errore_Rx==1) {(Value1 = Linearizzazione_Sensore[0]); (Value2=Linearizzazione_Sensore[1]);    
                    (Value3= Linearizzazione_Sensore[2]); (Value4=Linearizzazione_Sensore[3]);}
 
 
Linearizzazione_Sensore[0] = Value1 ;  //modifica l'array con il nuovo dato...
Linearizzazione_Sensore[1] = Value2;
Linearizzazione_Sensore[2] = Value3;
Linearizzazione_Sensore[3] = Value4;
}



e questa la function che ci consente di prendere ogni valore arrivato nel buffer:

Code: [Select]


void Rx_Data(){
 
 delay(50);   ////<------------------questo delay è indispensabile!!
if (Serial.available()) {

   Ser2 = Serial.read();                                           //legge il primo byte arrivato dopo in byte "comando"
   if (Ser2<48 || Ser2>57) (Errore_Ricezione() );        //una sorta di check, se non incluso nei caratteri 0@9 da errore.
     
   Ser3 = Serial.read();                                           //secondo byte ricevuto,
   if (Ser3<48 || Ser3>57) ( Errore_Ricezione() );
     
   Ser4 = Serial.read();                                           //terzo byte ricevuto
   if (Ser4<48 || Ser4>57)  (Errore_Ricezione() );
   
   Ser5 = Serial.read();                                            //quinto byte ricevuto (una virgola ma per uso separatore)
   if (Ser5!=',') (Errore_Ricezione() );
   
   Ser2 = Ser2 - 48;
   Ser3 = Ser3 - 48;
   Ser4 = Ser4 - 48;
   
   Value = ((Ser2 * 100) + (Ser3 * 10) + (Ser4 * 1) );   //questa semplice formuletta trasformerà i singoli caratteri
                                                                        //numerici in una cifra int che poi potrà essere trattata nei
                                                                         //calcoli dell'arduino se necessari...
}
}




ovviamente, le variabili sono global, se sai come passarle tra funzioni potresti fare di meglio, a me va bene così per ora.  Spero di essere stato d'aiuto.

Ciao,
Antonio
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 03:57 pm
haha... non ci ho capito un *******..
1) Trasmissione_Dati_a_PC(); non mi serve a niente visto che non devo trasmettere niente...devo solo ricevere...
2)Errore_Ricezione() altrettanto visto che sono io (da un programma in c#) ad inviare dati [ad esempio Serialport1.write("A1234")]
3)Azzera_Valori(); che è ?
4) if (Errore_Rx==1) idem
5)se i caratteri sono piu di 3 ???
6)alla fine Rx_New_Data_da_PC(); non serve a niente visto che quello che fa tutto è Rx_Data(); ....
7) che cacchio è la ","
scusa ... ma secondo me per quello che devo fare non serve tutto questo "casino"...

niente parolacce, grazie
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 04:20 pm
Scusa, ma quello che ti ho postato è un esempio di quello che ho fatto io, ovviamente, tu devi adattarti il programma alle tue necessità!  quelle che non ti serve lo togli, quello che ti manca ce lo metti, e così via!  

tutte quelle cose a me mi servono per creare una comunicazione bidirezionale con il pc, il pc manda delle richieste, arduino esegue. se a te serve solo che riceva, semplicemente usa la parte ricezione.  i controlli di errore mi servono per essere sicuro di non ricevere GARBAGES dalla seriale, se ricevesse un b1w0 invece di un b130 e con il primo l'arduino non eseguirebbe nulla, perchè non lo riconosce, se invece non vi è un minimo di controllo errori, quella "w" potrebbe incasinare (dicasi bloccare) l'esecuzione o no?  AH, giusto per chiarezza, i dati ricevuti dalla seriale sono byte, quindi ricevere lettere significa avere dei valori della tabella ASCII, dove a = "65" per esempio...  Ma se a te non serve, non lo usare!
idem per la function che azzera i contatori, a me, particolarmente, serve.

il codice da me postato fa parte di uno che è almeno 50 volte più grande e che funziona benissimo, riconosce gli errori, esegue solo i comandi riconosciuti e posso inviare dal pc anche una sequenza di comandi del tipo:

b100,100,130,150,c140,150,160,170, ....   nel mio caso, ogni trasmissione comando implica che il pc invia 4 blocchi di 4 numeri di tre cifre in formato ASCII separati da virgola(ma se ne può fare a meno), la lettera all'inizio di ogni blocco è il comando.

mi dispiace di averti fatto perdere del tempo a leggere il mio codice, forse avevi ragione, di sicuro non c'e bisogno di tutto sto casino di programma, magari il tuo fa solo un paio di cose semplici, il mio magari è molto più complicato ed io l'ho complicato ulteriormente...

Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 04:30 pm
Ovviamente se sai programmare bene (io no, sto imparando) magari trovi altre 100 forme migliori di fare la ricezione dei comandi, nel mio caso, al ricevere un comando da seriale, il ciclo if..else if mi seleziona il primo carattere arrivato (il comando), poi lo indirizza alla function corrispondente (per facilitare il mio compito) ma per evitare di ripetere le stesse istruzioni della function ->RX_Data() per quanti comandi ne ho, quindi allungare il programma di molto sia di lunghezza in linee scritte che in bytes occupati in compilazione, ho "meccanizzato" una parte delle operazioni ripetitive, il mio programma ha comandi dalla "a" alla "o" (15 comandi) per ora e quasi tutti in ricezione, e non sono nemmeno ad 1/4 del totale, capirai che ci vuole un certo ordine.  Come detto, magari un esperto lo farebbe in 4 righe, io non sono all' altezza per il momento.

ciao.
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 04:55 pm
ok, ho provato a fare qualche modifica....
Quote
if (Serial.available()>0 )
  {
    if(Serial.read() =='a')
    {
      delay(50);
      a = Serial.read()-48;
      b = Serial.read()-48;
      c = Serial.read()-48;
      d = Serial.read()-48;
      delayTime = (a*1000)+(b*100)+(c*10)+(d*1);
      Serial.println(a);
      Serial.println(b);
      Serial.println(c);
      Serial.println(d);
      Serial.println(delayTime);
     
    }
    else if (Serial.read() == 'b')
    {
      x = 1;
      Serial.println(x);
    }

in effetti la variabile delayTime viene cambiata ...ad esempio se scrivo a0030 allora delayTime = 30, il problema arriva con il comando b... x non diventa 1 e non stampa nemmeno il suo valore...(questo accade anche togliendo l'esle)...
Giusto per informazione sto facendo un progetto in cui cambio orientamento e velocità di un motore passo passo, il delayTime è la velocità del motore ( tempo tra un passo[scatto] e l'altro) e la x mi decide la rotazione [x =0 fermo, x =1 orario, x = 2 antior]...come posso risolvere ?
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 05:01 pm
ho di menticato di mettere il delay(50); nell'istruzione Serial.read == 'b'...ma il problema persiste..
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 05:37 pm
ok, ho giocato un po con il tuo codice (bravo per la compattazione!) ed ho trovato il problema:

Code: [Select]

if (Serial.available() )
 { ser=Serial.read();
   if(ser=='a')
   {
     delay(50);
     a = Serial.read()-48;
     b = Serial.read()-48;
     c = Serial.read()-48;
     d = Serial.read()-48;
     delayTime = (a*1000)+(b*100)+(c*10)+(d*1);
     Serial.println(a);
     Serial.println(b);
     Serial.println(c);
     Serial.println(d);
     Serial.println(delayTime);
     delay(50);
   }
 
   else if (ser== 'b')
   {
     x = 1;
     Serial.println(x);
   }
   
 }


semplicemente, ho inserito una variabile "var" la quale viene assegnato il valore in entrata su Serial.read(), semplicemente, dovevi eliminare la seconda chiamata a Serial.read perché già all'interno del ciclo if Serial.available() l'ho collaudata e funziona. spero che ti sia d'aiuto.
ciao.
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 05:56 pm
il delay(50), l'ho aggiunto alla fine del blocco, infatti, se riceviamo una stringa molto lunga dal pc, si rischia di perdere bytes, adesso, puoi inviare ad arduino anche un serie di comandi del tipo:

a1200ba1250ba1400b.... ovvero, puoi concatenare una serie di comandi, ma per quello che devi fare, con b, se fatto così come da esempio, dovrai usare un contatore per poter mettere arduino in uno dei 3 stati previsti, giusto? o invierai il comando: b0, b1, b2? forse la soluzione migliore o a tutt' al  più, potresti fare 3 comandi, s=stop, f=forward, r=reverse.  non sarebbe anch'esso utilizzabile? da una parte complica ma dall'altra rende il protocollo più immune ad eventuali errori di ricezione perchè dovrebbe passare attraverso il filtro del comandi singoli.  E per questo che nel mio shetch ho previsto il controllo degli errori, per ora è del tutto grossolano, se non sono numeri non fa nulla, ma nella versione definitiva dovrà contenere un sistema di checksum, le operazioni da eseguire sono alquanto critiche e devo essere sicuro che i dati ricevuti o trasmessi siano integri, altrimenti, succedono casini, anche gravi.  Nel tuo caso, se devi fargli fare solo questo senza che il motore faccia muovere nulla che possa fare danni se sbaglia comando, allora procedi come pianificato, perchè come dicono spesso gli americani ed gli informatici, K.I.S.S. (Keep It Simple, Stupid)http://it.wikipedia.org/wiki/KISS_(informatica) (http://it.wikipedia.org/wiki/KISS_(informatica))
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 05:57 pm
Ok, grazie, funziona benissimo :-)
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 06:52 pm
si, in effetti usero b0 = stop b1= orario e b2 = antior. .... in pratica devo creare una specie di "stampante 2d" con 2 motori passo passo che muovono una penna sul foglio (tipo questa http://www.youtube.com/watch?v=sHrL4k2hAnE).... nelle linee rette il problema del delay(50) non si pone ... visto che dall'inizio alla fine della linea le velocità rimarranno fisse, ma quando inizierò a creare funzioni per fare circonferenze ... allora avrò qualche problema perchè la velocità dei motori cambierà molto frequente mente ( quasi 0.001 s)... secondo te in quella situazione come potrei fare ?
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 09:42 pm
ok, adesso mi è più chiaro.  darti una risposta univoca non posso, non ho mai "giocato" abbastanza con i passo-passo, ma se richiedi un'aggiornamento ogni 1 ms, credo che farlo in real time da seriale sarà un problema secondo me, magari qualcuno esperto ti potrà essere più d'aiuto, tieni presente la velocità di trasmissione della seriale, per esempio, la più veloce che potresti usare è 115200 bit per secondo ovvero 115.2 bit per ms.  il delay(50) potresti provare a ridurlo o eliminarlo e vedere come va, a me, andava bene fin quando non mandavo catene di comandi e dati lunghe, per quelle da singolo comando anche senza ricordo che mi funzionava (da premettere che ho fatto prove solo a 9600 bps quindi molto al di sotto del massimo possibile).  Quindi prova a vedere se non ti perde comandi/passi togliendo del tutto i delay(50), se invece succede, prova ad aumentare gradualmente, del tipo delay(5)...10, 15, 20...

ho testato un po il tuo codice a 115200 bps inviando una catena casuale di almeno 40 numeri e sembra ok ma senza un sistema di controllo errori non so se davvero è ok.

ho testato il mio codice a 115200, senza delay o con delay fino a 5ms, se provavo a trasmettere molti dati, ottenevo errore, solo se inviavo un singolo carattere "a" anche in una catena di 60 contemporaneamente, ottengo 60 risposte positive da arduino. quindi come vedi, qui dovrai lavorarci un po su e provare diverse soluzioni.

Dovresti studiare qualche sketch di quelli che si sono creati una CNC con arduino e capire come hanno fatto.
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 09:55 pm
ok, cmq la soluzione migliore sarebbe gestire le linee dal programma c# e le circonferenze direttamente dall'arduino ricevendo da serial solo il centro ed il raggio....di spiare da altri programmi simili non ne ho molta voglia, visto che mi piace sperimentare ( e sbagliare) per apprendere meglio :-)
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 16, 2013, 10:12 pm
stavo per consigliarti propio quella strada, o inviare i dati e poi arduino li esegue in autonomo o gli invii solo i dati base, poi, con dei calcoli interni si incaricherebbe del pilotaggio dei motori.  intuisco come potrei fare ma non so ancora come lo farei se fossi al tuo posto. 
Beh, non credo che andare a vedere il codice di uno sketch sia una cosa grave, dopotutto lo spirito dell'open source è proprio questo, condividere le proprie conoscenze e/o lavori per puro divertimento o spirito di partecipazione o aiuto al prossimo.  Ovviamente se ti senti meglio facendo tutto da te, sei libero di fare come credi meglio, avvolte anche io preferisco la strada più lunga e laboriosa, perche alla fine, qualsiasi risultato ottengo, buono o meno che sia, sarà stato frutto del mio impegno ed ingegno.  Questo però non toglie che vedere come qualcun'altro ha affrontato una cosa simile, sia sbagliato, ovviamente a me non piace copiarlo con taglia ed incolla e via, voglio metterci del mio, adattarlo alle mie necessità o meglio, alle mie capacità.  Per esempio, esistono un sacco di librerie, farebbero la felicità di chiunque, ma essendo che ancora non domino bene la programmazione e preferisco andare per gradi, mi sembra più complicato tentare di far funzionare una libreria fatta da un professionista e che per tanto, difficilmente io comprenderò a fondo in ogni sfumatura e quindi preferisco di creare una mia versione, a modo mio, magari poi, dopo un po, la rivedo e la miglioro.
Comunque buona fortuna, fai tante prove pratiche.

Ciao ;)
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 16, 2013, 10:42 pm
cmq visto che hai detto che stai ancora imparando ... ti puo essere utile questi video.. in pratica ti spiega come fare videogiochi in 2d partendo da 0... è in inglese ma tutto sommato si capisce, io per creare le funzioni di linee e circonferenze mi sono ispirato a questo, magari può esserti utile anche a te.
http://www.youtube.com/watch?v=cIv5FhTQsn0&feature=share&list=PLF9B0522C7BC3C1C2
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 17, 2013, 11:50 am
cmq.... a chi interessa , ho modificato il codice per avere lapossibilità di mettere più comandi in una sola linea di codice utilizzando il metodo che credo si chiama "ricorsivo"[chiamare la funzione nel codice della stessa funzione (in pratica chiamare se stessi)]
Quote

void leggi()
{
  if (Serial.available() )
  {
    ser=Serial.read();
    if(ser=='a')
    {
      delay(50);
      a = Serial.read()-48;
      b = Serial.read()-48;
      c = Serial.read()-48;
      d = Serial.read();
     
     
      delayTime = (a*100)+(b*10)+(c*1);
      Serial.println(a);
      Serial.println(b);
      Serial.println(c);
     
     
      Serial.println(delayTime);
      delay(50);
      if (d == ' ')
      {
        leggi(); // ricorsione
      }
    }
    else if (ser == 'b')
    {
      delay(50);
      f = Serial.read()-48;
      d = Serial.read();
      x = f;
      Serial.println(x);
      Serial.flush();
      if (d == ' ')
      {
        leggi(); // ricorsione
      }
     
    }
   
   
   
 
 
  }

in questo modo possiamo scrivere piu comandi nella stessa riga separandoli con uno " "(spazio) ... chiaramente chiameremo la funzione leggi(); nel void loop.
Title: Re: Comunicazione seriale
Post by: PaoloP on Mar 17, 2013, 12:04 pm
Occhio che la ricorsione brucia risorse in fretta.
Rischi di bloccare il micro se gli arriva una serie molto lunga di comandi.
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 17, 2013, 04:16 pm
molto lungha quanto ? (a me servono 20 caratteri....)
Title: Re: Comunicazione seriale
Post by: leo72 on Mar 17, 2013, 04:24 pm

molto lungha quanto ? (a me servono 20 caratteri....)

Dipende da quante risorse occupa il tuo sketch nel globale. Lo stack che serve a gestire i salti ricorsivi vive nella memoria RAM, gli stessi 2048 byte che contengono tutte le variabili del tuo programma ed i buffer seriali.
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 17, 2013, 04:55 pm
Interessante, ma effettivamente, chiamare se stesso troppe volte potrebbe riempire la RAM disponobile se il numero di chiamate è elevato o se si sta già a corto di RAM, nei picaxe vi era un limite al numero di gosub utilizzabili altrimenti si bloccavano, immagino sia quasi la stessa cosa.

io invece lo avevo risolto creando una function ->Rx_Data() che ha una struttura pensata in base alla ricezione di di 3 cifre (char numerico ASCII) ogn' una, questa function assegna alla variabile ->Value il valore ricevuto, il programma da cui ti ho mandato degli spezzoni,  consta (per ora) di 15 comandi diversi, alcuni ricevono solo 1 numero compreso tra 000 e 999, altri ne hanno 4 numeri da 000 a 999, altri ne hanno 8 numeri da 000 a 999 ed altri ne avranno fino a 256 (una matrice di 16x16) sempre da 000 a 999 (quest'ultima parte no l'ho ancora realizzata).   E per questo che ho quel grado di complessità, come detto nei post precedenti, magari un programmatore esperto lo farebbe molto meglio di me (io sto imparando!), per me sta bene così (per ora), magari non è perfetto, ma funziona e ci capisco tutto, così in caso di ampliamenti o modifiche future, ci capirò.  

ciao.

PS. attualmente questo mio programma (non completo) occupa 700 linee di codice, compilato occupa 9700 bytes (tanti, devo "tagliare" o rischio che il resto non mi entra) e mi tiene liberi 900 bytes di RAM (troppi pochi considerando tutto quello che ci manca!) ma tieni presente che uso solo variabili global e qualche local, e un totale di 400 bytes in arrays varie, tra cui, una da 16x16.  Man mano imparerò di più, il prodotto finito sarà più efficiente e compatto.
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 17, 2013, 06:31 pm
ho apportato qualche modifica al codice e tentato di fare come sul mio programma, attualmente ha due chiamate a function, leggi() e leggi2(), la prima riceve 4 numeri ASCII e li converte in un numero (senza il controllo errore, non è garantito il range 0000 a 9999 se si ricevesse dei "garbages" ), la seconda function, leggi2() invece è pensata per il comando b che da come so, usa un'unico numero e quindi aspetta solo questo.  Basterà prevedere a priori la struttura di comandi in RX e creare le function necessarie, poi si aggiunge nel ciclo if...else if (o in un switch case) cosa fare al ricevere tale carattere comando.

Code: [Select]

void loop(){
 
if (Serial.available() )
  { ser=Serial.read();
    if(ser=='a')
    {
      leggi();
    }
 
    else if (ser== 'b')
    {
      leggi_b();
     
    }
    else if (ser== 'c')            //aggiungere qui altri comandi e chiamare le function corrispondenti, in questo caso, ho aggiunto un'utile chiamata a freeRam()
    {
      Serial.println(freeRam());
    }
  }
 
}

//*****************************************************
  void leggi(){  //legge 3 caratteri numerici ASCII sulla seriale, li converte a integer
   
    //Serial.println("OK, a premuto");
     
     delay(50);   ////<------------------questo delay è indispensabile!!
     if (Serial.available()) {
     
      a = Serial.read()-48;                       //viene sottratto 48 per rientrare nel range dei caratteri numerici ASCII (0=49,1=50....9=58)
      b = Serial.read()-48;                       //senza un sistema di check errore, se il sistema ricevesse una "a" per esempio, 
      c = Serial.read()-48;                       //verrebbe calcolato come "65"... x1000 o x100 o x10 o x1, quindi errato.
      d = Serial.read()-48;
      delayTime = (a*1000)+(b*100)+(c*10)+(d*1);  //se si deve ricevere 1, dalla seriale dovrà arrivare 0 0 0 1
      Serial.println(a);                          //debug
      Serial.println(b);                          //debug
      Serial.println(c);                          //debug
      Serial.println(d);                          //debug
      Serial.println(delayTime);                  //debug
    }

}
  //******************************************************
  void leggi_b(){  //questa function riceve un singolo carattere numerico, per esempio: 0=stop, 1=Forrard, 2=Reverse...
   
    //Serial.println("OK, b premuto");
    delay(5);
    if (Serial.available()) {
      x = Serial.read()-48;
     
      Serial.println(x);}
 
  }
 
  //*******************************************************
  int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);

}



Ho aggiunto il comando "c" per un'utile chiamata a freeRam(), ovviamente è solo un'esempio. in questo caso, vi sono liberi 1823 bytes su 2048 bytes.  Se si ottimizza occupa sicuramente meno (nel mio sketch le variabili sono tutte global).

Spero sia di aiuto a qualcuno.
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 17, 2013, 07:56 pm
scusa ... ma non ho capito la funzione freeRam().. che cosa fa ? come funziona ?
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 17, 2013, 08:10 pm
ok, la funzione freeRam() l'ho trovata in giro, serve per conoscere grossolanamente, la quantità di RAM libera, ma va invocata in diverse parti dello sketch, tipo alla fine di un loop() o magari dentro delle functions che gestiscono molti dati locali per esempio, così ti possono dare un'idea della RAM libera durante tutta l'esecuzione dello sketch, così se in qualche parte si blocca, e sospetti sia la RAM esaurita, potresti verificare se e così o no.  Mi e stata molto utile per capire che devo ottimizzare un pò, riducendo l'uso di variabili globali in favore di quelle locali (ed imparare a passarle per valore o riferimento, ma ancora non so farlo bene) o usando variabili byte invece di int se i valori da memorizzare non superano il range 0-255, infatti, spesso, mi capita di lavorare con valori che non superano 255 e non sono negativi, quindi in quel caso, le dichiaro byte, occupano meno RAM anche se global.  Quelle che occupano in assoluto più bytes di RAM e FLASH sono le variabili string!.
Title: Re: Comunicazione seriale
Post by: PaoloP on Mar 17, 2013, 08:12 pm
Schema della memoria in un chip AVR.

(http://jeelabs.org/wp-content/uploads/2011/05/malloc-std.png)
--> http://en.wikipedia.org/wiki/Data_segment (http://en.wikipedia.org/wiki/Data_segment)

La RAM esterna nel Atmega328 non c'è.
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 17, 2013, 09:30 pm
PaoloP, grazie dello schema, molto interessante, sapevo che le MCU non hanno la RAM esterna (forse solo le CPU dei computer?) ma capisco poco, o almeno, non mi è chiaro del tutto, potresti spiegare per favore?  a quanto ho visto, la prima zona è per le variabili static e global, la seconda per quelle local ecc e poi non ci ho capito quasi nulla! :smiley-red:   la function freeRam() l'ho trovata se non ricordo male, sul Reference/Playground ufficiale, e spiegava che serve ad avere un'idea della RAM libera, ma vedendo questo schema ed analizzando la function (per quel poco che ci capisco), la zona "misurata" non è sul totale della RAM, ma su una porzione di essa, ho capito bene o sto solo farneticando?

grazie
Title: Re: Comunicazione seriale
Post by: leo72 on Mar 17, 2013, 10:55 pm
Ti riposto questo mio intervento passato:
Quote

La memoria SRAM viene suddivisa in 5 pezzi:
1) all'inizio della SRAM viene messa l'area .data, che contiene le variabili dichiarate nel programma
2) dopo c'è l'area .bss/.init: essa contiene le variabili non inizializzate
3) a seguire c'è l'HEAP, che contiene i dati per l'allocazione dinamica della memoria. L'HEAP cresce verso l'alto.
4) dopo l'HEAP c'è un'area vuota che funge da "materasso"
5) infine c'è lo STACK, collocato a partire dall'ultima locazione di memoria a crescere verso il basso, verso l'HEAP. Nello STACK ci vanno a finire non solo i punti di ritorno per i salti alle subroutine ma anche i registri di sistema durante le ISR nonché le variabili create localmente.

Sia lo STACK che l'HEAP si espandono nell'area materasso. Se queste 2 aree vengono a collidere sovrapponendosi, il micro crasha.
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 18, 2013, 09:25 am
Grazie Leo72!  la risposta più chiara e concisa che ho visto in giro per spiegare il concetto!

Quindi la function freeRam() non mi da la RAM libera di tutta quella disponibile ma solo quella compresa tra il Heap e lo STACK giusto? mi sai dire quanto è grande lo spazio .data e .bss per favore sull'arduino? dal datasheet Atmel, non mi è chiaro:

Figure 8-3. Data Memory Map
32 Registers                      0x0000 - 0x001F
64 I/O Registers                 0x0020 - 0x005F
160 Ext I/O Reg.                0x0060 - 0x00FF
Internal SRAM                    0x0100(inizio)
(512/1024/1024/2048 x 8)  0x02FF/0x04FF/0x4FF/0x08FF (fine in base alla capacità della SRAM, l'ultimo è il 328P dell'arduino uno)

non mi è chiaro chi sia chi,  ma da come vedo, i 2048 bytes sono separati dagli altri registri, vero?  o sto mi sto confondendo, forse le aree .data, .bss heap e stack sono all'interno di quei 2048 bytes ed i registri sono un'altra cosa?  a me sembra più logico così.  Con i picaxe sapevo solo che avevo a disposizione un determinato numero di byte per dichiarare variabili e le dovevo amministrare sapientemente per far funzionare il tutto, spesso creavo forme di riciclarle (copiandole in una zona di RAM libera apposita e leggendola quando mi servivano) ma qui è più complicato.  Scusate la mia ignoranza e/o confusione!! :~




Title: Re: Comunicazione seriale
Post by: astrobeed on Mar 18, 2013, 09:28 am

Schema della memoria in un chip AVR.


Attenzione a non confondere la memoria fisica degli AVR con l'utilizzo che ne viene fatto da uno specifico compilatore, ovvero quello schema è valido esclusivamente per avr gcc, altri compilatori C e/o linguaggi usano schemi diversi.
Title: Re: Comunicazione seriale
Post by: leo72 on Mar 18, 2013, 10:20 am
La SRAM dedicata all'utente è al "netto" della memoria utilizzata dal micro, difatti se vedi l'indirizzo di partenza è $100, non è $00.
.data e .bss puoi saperle usando il tool avr-size. Nel link che ho messo ad un mio articolo sull'analisi dell'occupazione della memoria, spiego anche come usarlo.
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 19, 2013, 04:31 pm
Scusate ma ... male che vada ... c'è il rischio di bruciare l'arduino , o semplicemente crasha e quindi basta riavviare e cambiare il codice ?
Title: Re: Comunicazione seriale
Post by: leo72 on Mar 19, 2013, 05:14 pm

Scusate ma ... male che vada ... c'è il rischio di bruciare l'arduino , o semplicemente crasha e quindi basta riavviare e cambiare il codice ?

Si blocca o si resetta. Non può bruciare.  ;)
Se ti riferisci a quei video che si trovano su Youtube sono ovviamente dei montaggi
Title: Re: Comunicazione seriale
Post by: barlettaag on Mar 19, 2013, 08:21 pm
che video ? non l'ho visto ...
Title: Re: Comunicazione seriale
Post by: leo72 on Mar 19, 2013, 11:08 pm

che video ? non l'ho visto ...

Ci sono dei video in cui fanno vedere chip che esplodono perché vanno in overflow o roba simile, pensavo che le tue paure nascessero da quelli  XD
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 19, 2013, 11:30 pm
Fin' ora, l'unica cosa che so per esperienza, è che si bruciano solo se in un pin ADC/digitale (o qualsiasi a sto punto) malauguratamente gli viene alimentato a 12V!!  alcuni anni fa ho avuto una doppia "disgrazia" con dei moduli Basicx BX24, avevo una breadboard alimentata con un trasformatore da parete a 12v, poi un regolatore di tensione a 5v ed i canonici condensatori e quindi avevo da un lato della breadboard la linea 12V - GND e dall'altra 5V - GND, poi dalla breadboard (lato 5V) alla scheda del modulo Bx24 che ha già onboard un regolatore tensione (5V), tutto ok per più di un paio d'anni, poi un giorno, stavo spostando uno dei fili volanti di un channel ADC, malauguratamente mi è caduto... dove? esattamente dentro uno dei pin della 12v sulla breadboard!!  MANNAGGIA !!!  BX24 defunto.  Ne comprai un'altro e questo fece la stessa fine dopo pochi mesi, da lì ho imparato la DURA lezione, adesso ho schermata la zona delle tensioni over 5V, con tanti pin dove poteva entrarci e non fare danni.  Ma proprio nella fila dei 12V doveva capitare? e su due MCU (dal costo complessivo di oltre 120 €!!) ?
Bèh, e per questo che si dice, sbagliando s'impara! e che sbaglio!!  Adesso con Arduino ho fatto un'altro upgrade nella sicurezza, ho un'alimentazione a 5V sulla breadboard, quindi un rischio in meno!
Title: Re: Comunicazione seriale
Post by: Janos on Mar 20, 2013, 03:41 pm
Basta non spostare i fili mentre la scheda è alimentata...  ;) ;) ;)
Title: Re: Comunicazione seriale
Post by: hiperformance71 on Mar 20, 2013, 09:10 pm

Basta non spostare i fili mentre la scheda è alimentata...  ;) ;) ;)



Certamente, ma se tra una selva di fili volanti, capita di far spostare uno dalla sua posizione?  Purtroppo può capitare, togliere l'alimentazione ogni volta che si apporta una modifica non è sempre una scelta pratica, ma effettivamente, riduce i pericoli, per fortuna, ora il pericolo è stato eliminato alla base, le breadboard sono alimentate a 5V quindi nessun pericolo per la UNO, qualche pericolo concreto per la DUE ma per ora non me ne preoccupo molto, no ho ancora una DUE, anzi, per ora l'ho accantonata propio per la sua "diversità" di alimentazione rispetto ai canonici 5V.