Ciao a tutti. Premetto di essere molto ignorante in tema di arduino ma spero di non fare una domanda del tutto idiota.
Sto cercando di creare un piccolo logger e ho dei problemi con la frequenza di campionamento.
Il logger dovrà acquisire un 2 canali analogici a 50 o 100 Hz (meglio) e calcolare gli rpm di un motore a combustione interna, partendo da sensore amperometrico collegato a una bobina. Quindi, considerando un regime massimo di 20'000rpm (x stare sul sicuro) che corrispondono a 330rps, e supponendo che mi bastino 3 letture analogiche per ogni giro motore, avrei bisogno di 1000Hz.
Per l'output, sia utilizzando la seriale, sia scrivendo su una SD, mi trovo che la frequenza di campionamento è piuttosto bassa. O meglio, la frequenza arriva fino a 100Hz (che comunque non mi bastano per calcolare gli rpm), ma per alcuni campioni scende fino a meno di 10Hz.
E' possibile utilizzare qualcosa come un buffer? Penso che se memorizzassi i valori in memoria (cosa che dovrebbe essere più rapida), potrei aumentare le prestazioni. Ho provato utilizzando un array, ma ovviamente quando lo riverso sulla sd, tutto si ferma per tempi impraticabili...
per mia esperienza memorizzando su sd il tempo di scrittura minimo è circa un decimo e mezzo se ti puoi permettere pause di quel tempo si può fare sennò...
per la seriale aumenta il baud rate vedi fino a quanto si spinge.
quanto spazio hai bisogno? un'eprom?
il tuo discorso dei giri non lo capisco...
ti servono 100 campionamenti al secondo dei giri motore? o devi beccare ogni impulso per fare tipo una centralina?
se ti servono i giri da tenere in memoria tipo per fare analisi dati non mi spingerei oltre i 20 hz oltre cosa te ne fai di tutti sti dati?
Ciao, grazie per l'interesse.
Per quanto riguarda il campionamento, ho bisogno di salvare i dati a 100 Hz, o almeno a 50. Per tarare una centralina, è il minimo...
Invece per quanto riguarda i giri motore, la frequenza alta mi serve per poterli calcolare. La mia idea era quella di utilizzare il segnale inviato a una bobina e di calcolare il tempo intercorso tra 2 impulsi. Non credo vi siano altri sistemi, a parte un'improponibile dialogo con la centralina...
cerca sul reference il comando: pulsein
ci metti un ampli in ingresso che pulisce il segnale e lo squadra quindi leggi il tempo che sta alto (o basso) e di conseguenza becchi la frequenza.
I consigli harware sono molto più che graditi, ma sono un bel po' avanti rispetto al punto a cui sono. Anche perchè credo ci siano 2 soluzioni: la prima è quella di prendere proprio i 12V che vanno alla bobina e tagliarli (non credo Arduino accetti 12V su pin digitali). La seconda è quella di leggere la corrente alla bobina con un sensore amperometrico. In entrambi i casi, mi serve leggere l'ingresso con frequenze altissime anche perchè se penso alle centraline semifasate, che mandano il segnale alle bobine tutti i giri (e non solo a ogni scoppio), mi viene male...
Invece i dati sulla SD (rpm calcolati e 2 canali analogici) mi basta salvarli a 100Hz (posso scendere fino a 50 se necessario).
Non è possibile continuare a calcolare ed acquisire, mentre si salvano i dati su SD?
Non capisco. Non mi pare che l'invio via seriale sia più veloce che la scrittura su SD, almeno a giudicare dalle prove che ho fatto col PC. Inoltre, se il secondo Atmega riempie un buffer e lo spedisce a SD, non potrei far riempire il buffer direttamente dalle letture, invece che dalla seriale?
il baud rate massimo e di 115200 quindi ipotizzando anche un invio di 10 byte hai una frequenza di 11520Hz di trasmissione credo che la seriale sia decisamente veloce ..
ciao dave70
Ci sono alcune cose che non capisco:
Perché vuoi usare una bobbina per rivelare i giri del motore. e perché vuoi avere 3 impulsi per rotazione. Hai indicato la velocitá massima ma non la velocitá minima che devi rilevare.
Per rilevare la velocitá di rotazioni ci sono 2 possibilitá: misurare quanti impulsi hai per un tempo determianto oppure il tempo tra 2 impulsi. Se hai una velocitá di rotazione minima di ca 700rpm (tipico di un motore quando non dai gas) con un impulso per giro il tempo tra un impulso e l' altro sono di 86 msec. Percui se vuoi avere una misura attendibile devi misurare almeno qualche multiplo di questo tempo. non potai avere mai un campionamento di 100Hz (che sono 10 mSec).
Per secondo se il tuo programma che hai scritto é troppo lento per rivelare perché non lo pubblichi in modo che possiamo vedere di poterti suggeriere come fare a farlo piú veloce.
Facendo delle prove con un EEprom seriale ho constatato che un ciclo di scrittura necesstia di 6msec. Non so quanto ti serve per scrivere un dato sulla SD. È una cosa da verificare!
Ciao Uwe
da prove effettuate un array di circa 20 byte con la libreria fat16 impiega tempo quasi nullo finchè non si richiama il sinc dei dati
il chè implica 150ms con un kingston classe 6
nel mio programma ovvio a questo facendo il sinc ogni tre scritture immaginarie e il sinc dura pressochè lo stesso tempo sempre meno di 200 ms
sotto questo tempo non sono riuscito a scendere mi servirebbe ma non posso
in un primo momento usavo due arduini uno solo sd e l'altro cicleva continuamente
i dubbi su come memorizzi i giri li avevo già esposti in quanto secondo me c'è ci sono modi migliori (più veloci)...
Io pensavo di calcolare il tempo tra 2 impulsi e non quanti impulsi ho in un certo tempo. I giri minimi, potrebbero essere intorno ai 2000 (nelle moto il minimo è più alto).
Ora farò un po' di calcoli più precisi sul tempo necessario alla scrittura di dati sulla SD, ma a un primo esame, posso dirti che il mio programma semplicissimo che per il momento acquisisce soltanto 3 canali analogici e li scrive sulla SD necessita di 9ms (alcuni però 10, 11, 17ms) tra una lettura e l'altra. Il problema è che per un campione ogni tanto prende 133-142ms.
I 3 impulsi per rotazione di cui parlavo sono dovuti al modo in cui pensavo di calcolare gli rpm, cioè leggendo un segnale analogico e individuando il passaggio per un threshold di circa 6V. Questo comunque è un discorso che non ho ancora affrontato approfonditamente perchè devo prima capire se c'è la fattibilità del progetto, in dipendenza dalle frequenze acquisibili.
Ora forse capisco il perchè ogni tanto io abbia tempi tra un campione e l'altro così elevati (come scritto nella risposta a Uwe). Il tempo quasi nullo di cui parli, a me risulta essere compreso tra 9 e 17ms. Ti torna?
Cosa serve il sinc? E' possibile rimandarlo alla fine di tutta l'acquisizione?
ciao dave70
Perché vuoi calcolare i giri ? e non memorizzi direttamente il tempo tra 2 impulsi? Il calcolo dei giri puoi farlo quando leggi i dati dalla memoria.
Ciao Uwe
Anche questa è un'ipotesi, anche se preferirei scrivere gli rpm e non il tempo intercorso tra 2 impulsi. Comunque, come dicevo, è un problema che affronterò più avanti perchè se non trovo il modo di velocizzare il sistema, dovrò rinunciare o cambiare hardware.
Però, supponendo che decida di salvare il tempo e non gli rpm, non mi pare che la questione si sposti molto. Se ho 20'000 impulsi al minuto (330 al secondo) dovrò controllare l'ingresso ad almeno 660Hz, giusto?
acquisisce soltanto 3 canali analogici e li scrive sulla SD necessita di 9ms (alcuni però 10, 11, 17ms) tra una lettura e l'altra. Il problema è che per un campione ogni tanto prende 133-142ms
Concordando con Uwefed sul fatto che sarebbe utile vedere il codice sotto esame, dall'affermazione sopra quotata è possibile desumere che l'imprevedibilità dei tempi è dovuta al fatto che sul microprocessore sono attivi degli interrupt e sotto questi ci possono essere delle condizioni dipendenti da eventi esterni, come ad esempio la seriale che per cause esterne (come il rumore generato dalla scintilla di un motore a scoppio) non riuscendo a comunicare in modo "cristallino" si ritrova ad impegnare il processore più del dovuto generando così un ritardo inatteso.
E questa potrebbe essere la vera e unica causa della variazione che viene rilevata nella velocità di campionamento.
Per risolvere un problema a questo livello occorrono interventi sia hardware che software:
Nell'hardware servirà individuare le sorgenti di disturbo per limitarne l'intensità, e sopratutto impiegare connessioni schermate tra i dispositivi che comunicano via seriale (ricordando che la calza deve essere connessa solo da un lato!).
Nel software sarebbe corretto mettere la procedura di acquisizione sotto interrupt modificando la gestione degli altri interrupt in modo che la seriale abbia un livello di priorità inferiore a quello necessario all'acquisizione. Acquisizione che però dovrà anche avere un buffer nella ram interna per compensare eventuali ritardi nella scrittura dei dati in seriale verso il dispositivo esterno (PC o memoria SD che sia)
Innanzitutto, ci tengo a precisare che il progetto non si è ancora mai avvicinato a un motore a combustione interna, quindi ancora non possiamo parlare di disturbi.
Il codice che ho usato è uno degli esempi che si possono scaricare qui: Google Code Archive - Long-term storage for Google Code Project Hosting.
Nello specifico ho usato l'esempio fat16analoglogger, in cui ho portato a 1ms il tempo tra le letture (velocità ovviamente non raggiungibile). Come diceva qualcuno nei messaggi sopra, il tempo aggiuntivo si ottiene a causa del sinc (non ho idea di cosa sia e ho già chiesto qualche spiegazione sopra).
il sinc lo fai quando svuoti il buffer sul quale vengono memorizzati i dati in attesa di essere scritti sulla sd
a meno che tu non possieda una ram enorme(non il caso di arduino) devi limitare l'uso del buffer e fare il sync ogni volta che è pieno
il tempo lungo penso derivi dal fatto che debba cercare il file aprirlo e poi finalizzarlo menter chiude sennò il file non funziona( esempio per capirci prova a toglie la corrente mentre fa il sync e vedrai che il file risulta di 0 byte e illeggibile
il tempo aumenta con l'aumentare della dimensione del file perchè penso( ma non mi sono addentrato nella lib perchè sono riuscito a ridurre i tempi in altre parti del circuito) che derivi dal fatto che debba contare fisicamente la memoria occupata e per scrivere deve cercare posti nuovi liberi , sempre se sbaglio correggetemi , ma non è capae a scrivere in modo sequenziale e quindi trovare spazio libero man mano che la memoria è occupata diventa sempre più lungo come processo. occorrerebbe scrivere i file in modo sequenziale (come fa il defrag)( ps stesso problema me lo fa il nokia mentre registra a massima qualità un video ma questo è OT cmq si risolve con un defrag ogni tanto)
se mi ascolti o fai una scheda come datalogger con processore per conto suo e una che si occupa del resto e fa il lavoro in modo continuo... oppure bo..
il pulsein no ti dà problemi sul tempo in quanto è veloce quanto l'impulso però mi sa che dovrai usare due captatori sennò rischi che il secondo lo salti perchè cicla il programma
il tempo che impiega arduino per fare un calcolo è irrisorio... puoi calcolare i giri direttamente
cmq non capisco il fatto di dover calcolare tutti i giri del motore...
è come voler calcolare la velocità istantanea non sarà mai istantanea ma solo una media...
@garinus: credo tu stia sopravvalutando Arduino in maniera enorme...
il sistema è talmente limitato che non può prevedere una gestione intelligente della memoria (e di fatto non lo fa). A mia conoscenza non esiste neppure una libreria in grado di capire quanta memoria sia occupata, quanta sia quella disponibile e dove e come sia organizzata.
Tutti questi aspetti appartengono al mondo dei sistemi mooooooooolto superiori ad Arduino.
Con Arduino la memoria la deve gestire il programmatore contanto i singoli byte utilizzati (se non i singoli bit... : )
@dave70: ok per la possibile assenza di disturbi (anche se mi sto chiedendo come tu faccia a verificare il tuo codice senza degli ingressi realistici, visto che la stessa conversione A/D prevede tempi di conversione che vanno dai 13[ch956]S ai 260 [ch956]s e quindi implicando tempi diversi che possono andarsi a sommare a tempi esistenti), ma il fatto che tu ti accorga di differenze di tempi nel normale flusso del programma deve pur avere una spiegazione, o no?
E l'unica che io conosca (e mi risulta sia possibile) è quella di uno o più interrupt che intervengono nel normale loop del programma... e qui ritorna il mio ragionamento fatto sopra!
Dimenticavo: sul discorso del "sinc" (o "sync" che dir si voglia) credo tu debba rifarti a quanto ho scritto a garinus, perchè comunque non stiamo lavorando con un vero sistema multitasking ma con un processo sostanzialmente lineare interrotto solo dagli interrupt che tu stesso puoi controllare e programmare.