Buon giorno a tutti, sono nuovo del forum e del mondo Arduino, quindi scusate il livello elementare delle mie domande.
Devo semplicemente leggere dalla porta analogica il segnale da un fotodiodo e il tempo per ogni rilevazione, vorrei creare un array e prendere di questo array soltanto alcuni dati.
Ho scritto questo codice per la creazione dell'array, alla fine mi stampa l'array ma ancora non riesco ad estrapolare solo i dati che voglio.
Incollo il codice cosi da dare l'idea:
int i = 0;
int tot [440];
int tempo [440];
void setup() {
Serial.begin(9600);
}
void loop() {
if(i<440) {
int totale=0;
int sensorValue = analogRead(A0);
totale=totale+sensorValue;
tot*=totale;*
_ tempo*=millis();_
_ i++;_
_ if(i==440) {*_
* Serial.println(i, DEC);*
* for(int i=0; i<440; i++) {* _ Serial.println(tot*, DEC); Serial.println(tempo, DEC); } i++; } } } Ora le mie domande sono, - se creo un array più grande di quello creato, quindi tipo sui 450 dati, non mi stampa nulla perchè credo siano troppi e la memoria non è sufficiente, quindi qual'è la capacità massima di memorizzazione? sono dati che comunque posso riprendere in un secondo tempo per successive valutazioni o li perdo?*_
C'è un'apposito thread per le presentazioni. Il codice mettilo all'interno dei tag CODE (compaiono premendo l'icona "#" sopra all'area dove scrivi il tuo post).
L'Atmega328 ha limitata memoria SRAM, solo 2 kB. All'interno deve starci lo stack della CPU nonché tutte le variabili dichiarate nel programma: è basato sull'architettura Harward, quindi a differenza dei computer a cui sei abituato separa la memoria del programma da quella dei dati.
Un tipo integere occupa 2 byte per valore, quindi un array con 440 byteelementi occupa 880 byte, crearne 2 significa occupare 1760 byte. Se metti i 2 array a 450 vai ad occupare 1800 byte di memoria, probabilmente il resto del codice satura la memoria.
Se concatenassi i valori di stampa all'interno di una variabile stringa in modo da ottenere una cosa simile a questa:
totale = "12,13,45,56,67,....,100";
potrei fare un explode di "totale" e quindi stampare il tutto?
grazie
oh un programmatore di PHP XD
l'explode come funzione in C/C++ non esiste in quanto in realtà non esistono stringhe ma array di caratteri in C
esiste però strtok http://www.cplusplus.com/reference/clibrary/cstring/strtok/ che è molto simile (puoi fare un "explode" su più caratteri)
altrimenti un loop che controlla tutti i caratteri e crea un secondo array con i valori che ti servono (esattamente ciò che fa strtok )
comunque nel tuo codice qualcosa non torna.. soprattutto quell'if(i<440) quando poi fai un for in cui dichiari i come int ma era già dichiarato e lo porti al valore di 440...
superlol:
comunque nel tuo codice qualcosa non torna.. soprattutto quell'if(i<440) quando poi fai un for in cui dichiari i come int ma era già dichiarato e lo porti al valore di 440...
Le due i sono diverse perché è diverso lo scope.
Una è globale, l'altra interna al ciclo for.
Però sarebbe meglio chiamarla in un altro modo.
int i = 0;
int tot [440];
int tempo [440];
void setup() {
delay(2000);
Serial.begin(9600);
}
void loop() {
if(i<440) {
int totale=0;
int sensorValue = analogRead(A0);
totale=totale+sensorValue;
tot[i]=totale;
tempo[i]=millis();
i++;
if(i==440) {
Serial.println(i, DEC);
for(int x=0; x<440; x++) {
Serial.println(tot[x], DEC);
Serial.println(tempo[x], DEC);
}
i++;
}
}
}
Ciao, guarda su Arduino generalmente usare array cosi' grandi non e' una buona idea, se un domani volessi aggiungere una nuova funzionalita' o anche semplicemente rivedere il codice ti potresti trovare costretto a ricominciare tutto da capo.
Se un campionamento piu' lento ti puo' bastare, puoi provare questo:
Il campionamento viene fatto/inviato a intervalli di circa 8-9 millisecondi, quindi molto piu' lentamente del tuo codice "bufferizzato" ma hai il vantaggio di avere un footprint praticamente nullo e di poter campionare a lungo quanto ti pare.
Nell'esempio che ti ho scritto ogni volta che mandi un carattere qualsiasi tramite il serial monitor Arduino ti risponde con "tot" campioni.
Puoi usare l'offset temporale che viene mandato in testa all'output per sincronizzare i rilevamenti.
Spero ti sia utile
Ciao!
[Edit]
Ho provato a 115200 bps e il campionamento arriva a quasi 2 KHz, quindi molto simile al tuo campionamento originale
Mi sono messo ad utilizzare un codice per la lettura dei giri di un'elica, funziona correttamente ma non capisco perchè mi stampa due volte ai 50 millisecondi. Io vorrei una singola lettura ogni 50ms. Vi incollo il codice:
int val;
unsigned long tempo;
int stat=LOW;
int stat2;
int contar=0;
int i = 0;
int sens=65;
void setup()
{
Serial.begin(9600);
}
void loop() {
if (tempo <= 5000)
{
val=analogRead(0);
if(val<sens)
stat=LOW;
else
stat=HIGH;
if(stat2!=stat){
contar++;
stat2=stat;
}
tempo=millis();
if (tempo%50==0) {
Serial.print (i);
Serial.print ("\t");
Serial.print (contar);
Serial.print ("\t");
Serial.println (tempo,DEC);
}
i++;
}
}
Un esempio di quello che mi stampa sulla serial monitor:
Guarda così ad occhio ( non posso testare il codice ora ) direi che semplicemente la tua routine è troppo veloce, quindi tra un ciclo e l'altro passa meno di un millisecondo e il risultato di millis() è lo stesso per 2 volte. Puoi ovviare in 3 modi:
salvandoti il risultato dell'ultima lettura di millis() e fare la lettura solo quando millis() restituisce un risultato maggiore a quel valore, o ancora meglio, uguale a quel valore + 50 ( il modo più semplice )
aggiungendo una delay(1) dopo Serial.println (tempo,DEC); ( il modo ancora più semplice )
agganciandoti alla callback di interrupt di uno dei timer ( possibilmente timer2 ), settato opportunamente a intervalli di 50 millisecondi ed eseguire la routine all'interno di essa ( molto più complessa, può darti un sacco di grane la trasmissione asincrona sulla seriale, ma in linea di massima la soluzione ottimale secondo me ).
cunctator:
Guarda così ad occhio ( non posso testare il codice ora ) direi che semplicemente la tua routine è troppo veloce, quindi tra un ciclo e l'altro passa meno di un millisecondo e il risultato di millis() è lo stesso per 2 volte. Puoi ovviare in 3 modi:
salvandoti il risultato dell'ultima lettura di millis() e fare la lettura solo quando millis() restituisce un risultato maggiore a quel valore, o ancora meglio, uguale a quel valore + 50 ( il modo più semplice )
aggiungendo una delay(1) dopo Serial.println (tempo,DEC); ( il modo ancora più semplice )
agganciandoti alla callback di interrupt di uno dei timer ( possibilmente timer2 ), settato opportunamente a intervalli di 50 millisecondi ed eseguire la routine all'interno di essa ( molto più complessa, può darti un sacco di grane la trasmissione asincrona sulla seriale, ma in linea di massima la soluzione ottimale secondo me ).
int val;
unsigned long tempo;
int stat=LOW;
int stat2;
int contar=0;
unsigned long i = 0;
int sens=65;
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (tempo <= 10000)
{
val=analogRead(0);
if(val<sens)
stat=LOW;
else
stat=HIGH;
if(stat2!=stat)
{
contar++;
stat2=stat;
}
if (tempo!=millis())
{
tempo=millis();
if (tempo%50==0)
{
Serial.print (i);
Serial.print ("\t");
Serial.print (contar);
Serial.print ("\t");
Serial.println (tempo,DEC);
}
}
i++;
}
}
Ciao a tutti, vi chiedo un ulteriore suggerimento...il codice sopra funziona bene, ora però devo creare un array dei print (i, contar, tempo) per poi stamparli.
Di seguito vi incollo il codice con l'array creato per "contar" e funziona, ma non riesco a farlo per le "i" e per il "tempo"...come posso risolvere???
int val;
unsigned long tempo = 0;
int stat=LOW;
int stat2;
int contar=0;
unsigned long i = 0;
int valori[100];
int sens=65;
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (tempo < 10000)
{
val=analogRead(0);
if(val<sens)
stat=LOW;
else
stat=HIGH;
if(stat2!=stat)
{
contar++;
stat2=stat;
}
if (tempo!=millis())
{
tempo=millis();
if (tempo%100==0)
{
valori[i]=contar;
}
}
i++;
}
else if(tempo==10000)
{
for(int j=0;j<100;j++)
{
Serial.println (valori[j], DEC);
}
tempo=tempo + 1;
}
}