Spero di non chiedere troppo.
Vorrei campionare 2 o 4 canali analogici (differenziali o single-ended) con il TI ADS1015, o meglio con una delle sue tante breackout board (ad esempio: https://www.adafruit.com/product/1083). Vorrei impostare lo ADS1015 per campionare a frequenza fissa di, diciamo, 1600Sps. Vorrei poi leggere la sua uscita con un uC, ad esempio Arduino, per poi scrivere i 4x1600 valori al secondo su un file di testo (ed avrò quindi anche bisogno di una perfiferica di r/w su microSD card, via SPI o I2C. Ma il mio uC dovrebbe nel frattempo fare anche altre cose e quindi potrà leggere l'uscita del DAS105 solo a tratti, in time-sharing.
Per far questo dovrei bufferizzare i dati in uscita dal ADS1015, in modo da conservarli per un momento, per poi trasferirli in una SD card e svuotare il buffer, che poi si riempirà di nuovo e così via. Ci sono strategie standardizzate per questo problema? Quali componenti HW sarebbe opportuno usare? Immagino che il problema non sia facilissimo, posso chiedere qualche suggerimento per iniziare? Grazie in anticipo.
bufferizzazione ADC
Moderatore:
Paolino
44 messaggi
• Pagina 1 di 5 • 1, 2, 3, 4, 5
0
voti
Che io sappia, in generale ci sono due modi per fare quello che dici.
Uno si adotta solo in casi particolari, quando la frequenza di campionamento è relativamente alta o è necessario campionare dei canali secondo una temporizzazione molto precisa. Questo prevede la presenza di hardware (generalmente periferiche del micro) dedicato, come il Direct Memory Access (DMA) per l'ADC, che quindi può autonomamente scrivere sequenze di campioni in memoria, oppure altri meccanismi che vanno a sequenziare le acquisizioni in base ad eventi di un timer (ad esempio su una periferica PWM) e a scrivere i valori in certi registri (vedi lo "Start-Of-Conversion", SOC, dei C2000 di TI).
Direi che nel tuo caso è da escludere, sia perché Atmega 328 non ha questo hardware, sia perché la frequenza di campionamento di cui parli è tranquillamente gestibile in altro modo.
L'altro modo, molto più comune, è quello di usare un interrupt legato ad un timer, cioè una chiamata automatica ad una funzione (che è chiamata "Interrupt Service Routine", ISR), che viene legata ad un evento (nel tuo caso il raggiungimento del valore di overflow da parte di un timer). Questa chiamata interrompe l'esecuzione del resto del codice, sulla base di un timer hardware (che conta autonomamente rispetto all'esecuzione del codice), perciò hai alcuni importanti vantaggi:
- la temporizzazione è molto precisa, molto più che se si usassero dei delay in un loop;
- non si spreca tempo del processore per aspettare (delay);
- si può suddividere il codice in compiti da eseguire con temporizzazione precisa e possibilmente in poco tempo (meno del periodo di campionamento), cioè "real-time" e compiti da eseguire in modo più "rilassato".
Se si fanno le cose per bene, si può gestire facilmente la coordinazione tra le due parti (nel tuo caso l'ISR ed il loop) per quanto necessario, non preoccupandosi invece del resto (cioè, ad esempio, di quando viene realmente eseguito il codice del loop o di quanto tempo impiega la sua esecuzione).
Uno si adotta solo in casi particolari, quando la frequenza di campionamento è relativamente alta o è necessario campionare dei canali secondo una temporizzazione molto precisa. Questo prevede la presenza di hardware (generalmente periferiche del micro) dedicato, come il Direct Memory Access (DMA) per l'ADC, che quindi può autonomamente scrivere sequenze di campioni in memoria, oppure altri meccanismi che vanno a sequenziare le acquisizioni in base ad eventi di un timer (ad esempio su una periferica PWM) e a scrivere i valori in certi registri (vedi lo "Start-Of-Conversion", SOC, dei C2000 di TI).
Direi che nel tuo caso è da escludere, sia perché Atmega 328 non ha questo hardware, sia perché la frequenza di campionamento di cui parli è tranquillamente gestibile in altro modo.
L'altro modo, molto più comune, è quello di usare un interrupt legato ad un timer, cioè una chiamata automatica ad una funzione (che è chiamata "Interrupt Service Routine", ISR), che viene legata ad un evento (nel tuo caso il raggiungimento del valore di overflow da parte di un timer). Questa chiamata interrompe l'esecuzione del resto del codice, sulla base di un timer hardware (che conta autonomamente rispetto all'esecuzione del codice), perciò hai alcuni importanti vantaggi:
- la temporizzazione è molto precisa, molto più che se si usassero dei delay in un loop;
- non si spreca tempo del processore per aspettare (delay);
- si può suddividere il codice in compiti da eseguire con temporizzazione precisa e possibilmente in poco tempo (meno del periodo di campionamento), cioè "real-time" e compiti da eseguire in modo più "rilassato".
Se si fanno le cose per bene, si può gestire facilmente la coordinazione tra le due parti (nel tuo caso l'ISR ed il loop) per quanto necessario, non preoccupandosi invece del resto (cioè, ad esempio, di quando viene realmente eseguito il codice del loop o di quanto tempo impiega la sua esecuzione).
-

SandroCalligaro
2.970 2 4 5 - G.Master EY

- Messaggi: 1181
- Iscritto il: 6 ago 2015, 19:25
0
voti
Problema interessante.
SandroCalligaro ti ha risposto meglio di quanto non sarei in grado di fare io.
Ho dato una occhiata al data sheet del ADS1015:
12 bit , max sample rate 0,0033 Msps = 3,3 kHz presumo riferito a un canale.
Uscita bus I2C.
Qualche considerazione:
Hai supposto 2 canali quindi vorresti campionare a 1,6 kHz.
Tempo per commutazione e assestamento del multiplexer?
due byte per dato: 4x1600x2 = 12800 byte di RAM tampone. Il uC ha abbastanza ram ?

Ho dato una occhiata al data sheet del ADS1015:
12 bit , max sample rate 0,0033 Msps = 3,3 kHz presumo riferito a un canale.
Uscita bus I2C.
Qualche considerazione:
Hai supposto 2 canali quindi vorresti campionare a 1,6 kHz.
Tempo per commutazione e assestamento del multiplexer?
con 4 canali forse sei limitato a 0,8 kHz.per poi scrivere i 4x1600 valori al secondo s
due byte per dato: 4x1600x2 = 12800 byte di RAM tampone. Il uC ha abbastanza ram ?

0
voti
12bit a 1600Sps = 19200bit/s sei attorno ai 20KHz
Leggendo I2C a 400KHz devi inviare 7bit address + bit rd/wr + 12bit read sample = 20bit
400KHz/20bit = 20KHz. Leggi i campioni a 20KHz
Quindi devi essere in lettura continua sull'I2c per mantenere 1600Sps io direi che non ce la fai
L'ADC può funzionare in high speed mode con clock a 3.4MHz più che abbondante. BIsonga vedere se arudino ti permette di usare I2C a frequenza dopra i 400KHz.
Se la prima valutazione è positiva per la memorizzazione di solito si utilizzando due blocchi di memoria
su uno scrivi i dati che leggi dall'ADC sull altro leggi i dati da inviare alla SD. Dipende dalla RAM disponibile ma se possibile fai i blocchi della dimensione del blocco della SD.
Con SPI su SD puoi essere molto veloce (non so arudino ma alla SD puoi accedere a 4bit quindi quadruplichi facilmente la velocità) quindi dovresti riuscire a leggere tutto il blocco prima che i dati dell'ADC riempiano l'altro blocco. Non serve dirlo che a cose fatte inverti il ruolo dei due blocchi e riparti con le stesse procedure di lettura/scrittura.
Il tutto va sincronizzato perché non puoi permetterti il lusso di scrivere tutto su SD tralasciando la lettura dell'ADC. Probabilmente l'ADC ti informerà muovendo un pin che il nuovo dato è disponibile. Tu devi mollare tutto leggere , memorizzare e riprendere da dove hai lasciato.
Leggendo I2C a 400KHz devi inviare 7bit address + bit rd/wr + 12bit read sample = 20bit
400KHz/20bit = 20KHz. Leggi i campioni a 20KHz
Quindi devi essere in lettura continua sull'I2c per mantenere 1600Sps io direi che non ce la fai
L'ADC può funzionare in high speed mode con clock a 3.4MHz più che abbondante. BIsonga vedere se arudino ti permette di usare I2C a frequenza dopra i 400KHz.
Se la prima valutazione è positiva per la memorizzazione di solito si utilizzando due blocchi di memoria
su uno scrivi i dati che leggi dall'ADC sull altro leggi i dati da inviare alla SD. Dipende dalla RAM disponibile ma se possibile fai i blocchi della dimensione del blocco della SD.
Con SPI su SD puoi essere molto veloce (non so arudino ma alla SD puoi accedere a 4bit quindi quadruplichi facilmente la velocità) quindi dovresti riuscire a leggere tutto il blocco prima che i dati dell'ADC riempiano l'altro blocco. Non serve dirlo che a cose fatte inverti il ruolo dei due blocchi e riparti con le stesse procedure di lettura/scrittura.
Il tutto va sincronizzato perché non puoi permetterti il lusso di scrivere tutto su SD tralasciando la lettura dell'ADC. Probabilmente l'ADC ti informerà muovendo un pin che il nuovo dato è disponibile. Tu devi mollare tutto leggere , memorizzare e riprendere da dove hai lasciato.
-

luxinterior
4.311 3 4 9 - Master EY

- Messaggi: 2690
- Iscritto il: 6 gen 2016, 17:48
0
voti
OMG!! per capire tutto quello che mi avete risposto mi ci vorrà un bel po' di tempo, ho la digestione lenta e non molte conoscenze pregresse
ma vi ringrazio e mi ci metto di buzzo buono.
Per il momento mi bastano due canali ad almeno 1.000 Sps, quindi sì, mi ci vorrà tutta la velocità di 3.3 Sps da dividere per i due canali (quindi 1150 Sps per canale).
Ho anche pensanto ad una RAM esterna e mi sono procurato quattro chip seriali che hanno anche un enable che mette le uscite in three-state:
https://www.microchip.com/wwwproducts/en/23LC1024
Inoltre mi sonoa nche procurato un po' di buffer Three-state per vedere se, con due uC, riesco a giocare con la lettura di un banco di ram da parte del primo, che dopo un segnale di clock (ad esempio di un secondo o di emzzo secondo) passa a riempire un secondo banco di Ram mentre il secondo uC scrive il primo banco su SD e poi si scambiano i ruoli.
Follia??
Per il momento mi bastano due canali ad almeno 1.000 Sps, quindi sì, mi ci vorrà tutta la velocità di 3.3 Sps da dividere per i due canali (quindi 1150 Sps per canale).
Ho anche pensanto ad una RAM esterna e mi sono procurato quattro chip seriali che hanno anche un enable che mette le uscite in three-state:
https://www.microchip.com/wwwproducts/en/23LC1024
Inoltre mi sonoa nche procurato un po' di buffer Three-state per vedere se, con due uC, riesco a giocare con la lettura di un banco di ram da parte del primo, che dopo un segnale di clock (ad esempio di un secondo o di emzzo secondo) passa a riempire un secondo banco di Ram mentre il secondo uC scrive il primo banco su SD e poi si scambiano i ruoli.
Follia??
0
voti
Non so se è sfuggito a me, ma non è chiaro per quanto tempo dovresti acquisire (acquisizione continua per N secondi e poi pausa, oppure continua per 1 h?).
La differenza potrebbe essere importante.
Visto quello che dici, usando un ADC esterno in I2C, una RAM esterna in seriale e l'Arduino secondo me rischi di non uscirne, e tutto per campionare a qualche kS/s!
Mi porrei qualche domanda a monte...
Ti servono davvero 12 bit? Hai mai pensato di sovra-campionare? Un sovra-campionamento di 4x più filtraggio corrisponde, a grandi linee, a 1 bit in più.
Hai considerato l'idea di usare un altro ADC (ad esempio con interfaccia SPI o parallela)?
Oppure, ancora meglio, forse, un micro con ADC a 12 bit interno? Mi pare ci siano schede Arduino con MCU che hanno questa risoluzione, ma ci sono anche le schede con TI MSP430 (anch'esse molto economiche, tanto che alcune erano offerte 4,30 $), che si possono programmare con Energia, in pratica un clone delle librerie Arduino.
La differenza potrebbe essere importante.
Visto quello che dici, usando un ADC esterno in I2C, una RAM esterna in seriale e l'Arduino secondo me rischi di non uscirne, e tutto per campionare a qualche kS/s!
Mi porrei qualche domanda a monte...
Ti servono davvero 12 bit? Hai mai pensato di sovra-campionare? Un sovra-campionamento di 4x più filtraggio corrisponde, a grandi linee, a 1 bit in più.
Hai considerato l'idea di usare un altro ADC (ad esempio con interfaccia SPI o parallela)?
Oppure, ancora meglio, forse, un micro con ADC a 12 bit interno? Mi pare ci siano schede Arduino con MCU che hanno questa risoluzione, ma ci sono anche le schede con TI MSP430 (anch'esse molto economiche, tanto che alcune erano offerte 4,30 $), che si possono programmare con Energia, in pratica un clone delle librerie Arduino.
-

SandroCalligaro
2.970 2 4 5 - G.Master EY

- Messaggi: 1181
- Iscritto il: 6 ago 2015, 19:25
0
voti
Grazie delle vostre risposte, sto leggendole e tentando di capirle bene, nel frattempo mando alcune mie ulteriori considerazioni, ispirate dalle vostre. Scusate per le poche idee, ma ben confuse
Preferirei usare un ADC esterno (non integrato su uC) per molti motivi, innanzitutto modularità, ma anche perché avrei bisogno di un campionamento con temporizzazione accurata e la temporizzazione di un uC dipende totalmente dalla stabilità del risuonatore o quarzo, mentre immagino che la stabilità della frequenza di acquisizione a 3,3Khz del ADS1015 sia maggiore, ma se mi sbaglio correggetemi. Certamente potrei anche immaginare un ADC con interfaccia SPI o parallela, ma per il momento mi piacerebbe capire se c'è una soluzione con quanto ho già in mano.
Devo acquisire per un tempo indefinito, diciamo un'ora o un giorno, e via via mettere i valori su una SDcard. Sarebbe perfetto se la SDcard fosse formattata con un qualche FileSystem come FAT32, il che comporterebbe di dover ogni tanto (diciamo ogni secondo) aprire il file, scriverci dentro i valori accumulati in quel secondo e poi richiudere il file. Inoltre mi andrebbe benissimo usare un secondo uC2 tutto dedicato per questa funzione, di preferenza ancora Arduino, ma ho già in mano anche i Teensy 2.0 e 3.5 (però preferirei sempre Arduino).
La temporizzazione è per me importante. Diciamo che dall'esterno ho già una sorgente affidabile di clock ad un secondo, che potrebbe essere usata come interrupt per scatenare la lettura del buffer ed il suo traferimento sulla SDcard, eventualmente usando due uC, come suggerito da luxinterior.
Siccome non vorrei perdere campionamenti, mi rimane da capire come posso accumulare al meglio quei dati in un qualche buffer mentre il uC1 è occupato a scrivere il file e non può leggere nei registri del ADS1015 e quindi ci dovrebbe forse leggere qualcun altro, diciamo il secondo uC2, che dovrebbe occuparsi di mettere momentaneamente quei valori in un buffer. Quando il uC1 tornerà libero, andrà a leggere in quel buffer e trasferirà in blocco sulla SDcard tutti i dati che troverà nel buffer (e tutto questo potrebbe essere temporizzato dal clock esterno ad un secondo). Come buffer avevo pensato alle serial Ram esterne che avevo messo in link ieri (che ho già disponibili), ma qualunque altra soluzione sarebbe interessante da valutare, è uno degli aspetti che mi incuriosisce di più.
Anzi, mentre scrivo mi viene in mente che in questa architettura avevo immaginato un uC1 master ed un uC2 slave, ma forse i due uC potrebbero essere paritetici e scambiarsi simmetricamente i ruoli ogni secondo nel leggere dall'ADC e scrivere su SDcard. Così potrebbero ognuno dei due usare solo la propria Ram interna come buffer, senza necessità delle Ram esterne. In questa strada però immagino che non sia facile gestire i conflitti fra il primo ed il secondo uC nell'accesso ai registri dell'ADC e della SDcard, ma anche qui qualsiasi vostro parere è prezioso. Grazie a tutti.
Preferirei usare un ADC esterno (non integrato su uC) per molti motivi, innanzitutto modularità, ma anche perché avrei bisogno di un campionamento con temporizzazione accurata e la temporizzazione di un uC dipende totalmente dalla stabilità del risuonatore o quarzo, mentre immagino che la stabilità della frequenza di acquisizione a 3,3Khz del ADS1015 sia maggiore, ma se mi sbaglio correggetemi. Certamente potrei anche immaginare un ADC con interfaccia SPI o parallela, ma per il momento mi piacerebbe capire se c'è una soluzione con quanto ho già in mano.
Devo acquisire per un tempo indefinito, diciamo un'ora o un giorno, e via via mettere i valori su una SDcard. Sarebbe perfetto se la SDcard fosse formattata con un qualche FileSystem come FAT32, il che comporterebbe di dover ogni tanto (diciamo ogni secondo) aprire il file, scriverci dentro i valori accumulati in quel secondo e poi richiudere il file. Inoltre mi andrebbe benissimo usare un secondo uC2 tutto dedicato per questa funzione, di preferenza ancora Arduino, ma ho già in mano anche i Teensy 2.0 e 3.5 (però preferirei sempre Arduino).
La temporizzazione è per me importante. Diciamo che dall'esterno ho già una sorgente affidabile di clock ad un secondo, che potrebbe essere usata come interrupt per scatenare la lettura del buffer ed il suo traferimento sulla SDcard, eventualmente usando due uC, come suggerito da luxinterior.
Siccome non vorrei perdere campionamenti, mi rimane da capire come posso accumulare al meglio quei dati in un qualche buffer mentre il uC1 è occupato a scrivere il file e non può leggere nei registri del ADS1015 e quindi ci dovrebbe forse leggere qualcun altro, diciamo il secondo uC2, che dovrebbe occuparsi di mettere momentaneamente quei valori in un buffer. Quando il uC1 tornerà libero, andrà a leggere in quel buffer e trasferirà in blocco sulla SDcard tutti i dati che troverà nel buffer (e tutto questo potrebbe essere temporizzato dal clock esterno ad un secondo). Come buffer avevo pensato alle serial Ram esterne che avevo messo in link ieri (che ho già disponibili), ma qualunque altra soluzione sarebbe interessante da valutare, è uno degli aspetti che mi incuriosisce di più.
Anzi, mentre scrivo mi viene in mente che in questa architettura avevo immaginato un uC1 master ed un uC2 slave, ma forse i due uC potrebbero essere paritetici e scambiarsi simmetricamente i ruoli ogni secondo nel leggere dall'ADC e scrivere su SDcard. Così potrebbero ognuno dei due usare solo la propria Ram interna come buffer, senza necessità delle Ram esterne. In questa strada però immagino che non sia facile gestire i conflitti fra il primo ed il secondo uC nell'accesso ai registri dell'ADC e della SDcard, ma anche qui qualsiasi vostro parere è prezioso. Grazie a tutti.
0
voti
Se la registrazione non dev'essere di qualità valuta la possibilità di comprimere il segnale audio limitando di molto la quantità di dati da memorizzare. Io affronterei una cosa del genere con un micro dotato di ADC una volta programmato te lo dimentichi. Riusciresti a gestire in automatico l'acquisizione dei canali e il trasferimento dei dati in DMA, come ti hanno già suggerito eliminando il trasferimento ADC micro. Tu dovresti occuparti solo della codifica dei dati ricevuti e del trasferimento su SD. Avresti hw e fw molto molto più semplici e paradossalmente molto più veloci.
Capisco l'idea di usare arduino ma ho paura che risulti il collo di bottiglia di tutto il progetto.
Ci sono altre discussioni nel forum su STM32. Con poche decine di euro avresti un sistema di sviluppo completo.
Partire da zero sarà faticoso ma personalmente credo ne valga la pena.
Capisco l'idea di usare arduino ma ho paura che risulti il collo di bottiglia di tutto il progetto.
Ci sono altre discussioni nel forum su STM32. Con poche decine di euro avresti un sistema di sviluppo completo.
Partire da zero sarà faticoso ma personalmente credo ne valga la pena.
-

luxinterior
4.311 3 4 9 - Master EY

- Messaggi: 2690
- Iscritto il: 6 gen 2016, 17:48
0
voti
Ti suggerisco di provare a rispondere (almeno mentalmente, non mi interessa che tu posti la risposta) alle domande che ti ho fatto nell'ultimo post. Non penso di avere la verità in tasca, ma ho l'impressione che tu ti stia incamminando su un sentiero molto difficile, senza avere chiaro quel che comporta (interfacciare micro, RAM, SD, un secondo micro...).
Meglio pensarci due volte prima, che accorgersi dopo di aver sbagliato strada...
Meglio pensarci due volte prima, che accorgersi dopo di aver sbagliato strada...
-

SandroCalligaro
2.970 2 4 5 - G.Master EY

- Messaggi: 1181
- Iscritto il: 6 ago 2015, 19:25
0
voti
I colleghi ti stanno dando ottimi consigli che ti suggerisco di prendere bene in esame.
Io aggiungo che usare due micro al posto di uno, quasi sempre non risolve i problemi, ma li aumenta. E non è che li raddoppi, li aumenta di 10^2...
Io aggiungo che usare due micro al posto di uno, quasi sempre non risolve i problemi, ma li aumenta. E non è che li raddoppi, li aumenta di 10^2...
44 messaggi
• Pagina 1 di 5 • 1, 2, 3, 4, 5
Torna a Realizzazioni, interfacciamento e nozioni generali.
Chi c’è in linea
Visitano il forum: Nessuno e 3 ospiti

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)


