Eliminazione offset

Buondì a tutti.
Ho un segnale analogico proveniente da un sensore prototipo che può variare tra 3.6680V a 3.6650V circa.
Volendo leggerlo con un ingresso analogico di arduino, avrei una pessima risoluzione per via del fatto che ho fondamentalmente 3.66V sempre presenti.

Esiste un modo hardware per eliminare l'offset di 3.66V prima di entrare nell'ingresso analogico?
In questo modo potrei usare l'AREF ad 1,1V ed aumentarne la risoluzione.

Con un operazionale puoi risolvere il problema applicando sull'ingresso invertente la tensione di "zero" (3.66V) e sull'ingresso non invertente il segnale dal sensore.

Poiché il segnale utile oscilla di soli 3mV, ti conviene anche amplificare il segnale di almeno 1000 volte usando due operazionali, il primo con guadagno 10 ed il secondo con guadagno 100.

Ottimo!
Appena riesco mi metto subito sotto per il "trattamento" del segnale.

Grazie mille dell'aiuto!

Edit: Errore mio... il segnale varia di 10mV ma la sostanza non cambia. Prima devo eliminare l'offset e poi amplificarlo in maniera compatibile con l'ingresso di arduino.

Chiedo conferma per il dimensionamento del circuito.
Io avrei pensato ad un amplificatore differenziale con amplificazione 50, così in un solo circuito ho l'eliminazione dell'offset e l'amplificazione.

Le R di ingresso sia sull'invertente che sul non invertente le ho ipotizzate da 1,1k mentre le due di feedback da 56k.
Se non ho sbagliato le formule dovrei avere una amplificazione di 50,9 circa.

Il mio segnale sarebbe di 3.69V (max) sull'ingresso non invertente e di 3.6V sull'invertente, in uscita dovrebbe essere al massimo di 4.58V. Come amplificatore devo cercare nel mio magazzino qualcosa funzionante a 5V non duale.

Può andare?

Come tipologia di operazionale è meglio un Rail-To- Rail o un tradizionale?

se vuoi usare un'alimentazione singola, decisamente rail-to-rail ...

Con una amplificazione di 50, otterrai solo 50x3mV = 150mV: non sono pochi visto che vuoi misurare con un Aref di 3.3V?

cyberhs:
Con una amplificazione di 50, otterrai solo 50x3mV = 150mV: non sono pochi visto che vuoi misurare con un Aref di 3.3V?

Errore mio, i mV in uscita sono 10.
Comunque hai ragione, 500mV sono comunque pochi… Rifaccio i calcoli.

Io uso la formula classica (Rf/R)*(V2-V1)… è giusta?

Edit: scusa Cyberhs, ma secondo i miei calcoli…
Se uso cone riferimento per l’offset uno zener da 3,6V, ottengo una uscita dal differenziale che è di 0,08V (assumendo una risposta massima del mio sensore pari a 3,68V).
Quindi 50x80mV fa 4V in uscita all’amplificatore…
Il mio sensore passa da 80mV a 65mV circa quindi per aumentare ancora la risoluzione dovrei togliere tipo altri 50mV magari con un diodo in serie. Giusto?

I calcoli sono esatti, ma non mi è chiaro il circuito che intendi usare.

Il circuito differenziale richiede 4 resistori (almeno 1%) a due a due uguali ed il rapporto tra i due valori determina l'amplificazione, come giustamente hai detto.

In uscita vuoi 3.3V, quindi il rapporto tra i due valori di resistenza deve essere:

R2 / R1 = 3.3V / 0.08V = 41.25 (meglio scegliere 40 per evitare di amplificare troppo e superare i 3.3V).

R1 = 1k e R2 = 40k (che approssimerai al valore commerciale 40.2k)

Ho fatto un pò di casino mi sa 8) ... riassumo per chiarire.

Ho un sensore che ha una risposta in frequenza che varia tra 6kHz e 7kHz (grossomodo), al quale ho collegato un LM331 in configurazione standard con alimentazione 5V; esso in uscita da 10mV/kHz ed in effetti io in uscita ho una variazione di tensione approssimativamente di 10mV (da 3,675V a 3,685V).

Ho impiegato un LM331 perchè mi sembrava la strada più semplice da percorrere.

Una variazione così lieve di tensione, tuttavia, non viene praticamente letta da arduino con la Aref standard e, a meno di Aref particolari, è troppo alta la tensione per la Aref interna (1,1V).

A questo punto, sotto tuo suggerimento, ho simulato con Multisim un Amplificatore differenziale con diversi guadagni sino a raggiungere un compromesso dato da un guadagno di circa 110, ottenuto con resistori da 1,1k sugli ingressi e 120k sui feedback (tra invertente ed uscita e tra non invertente e massa).
In questo modo ottengo una tensione in uscita che, ipotizzando una variazione di ingresso più ampia e compresa tra 3,66V e 3,69V (mi tengo del margine) è compresa tra 1,18V e 4,45V ma solamente se all'ingresso invertente applico una tensione di 3,65V.

Chiarito questo, ho i seguenti quesiti:

  • la strada dell'LM331 è giusta o ci sono soluzioni più furbe?
  • per ottenere 3,65V come riferimento posso impiegare un regolatore di tensione variabile e configurarlo per tale tensione o è una "porcata"?

Chiedo scusa per la confusione iniziale e per avervi fatto perdere tempo... resettiamo tutto e partiamo da quì.

Ma, giusto per la cronaca, se ci dessi il part number del sensore per poter vedere il suo datasheet, o magari ancora meglio un link al datasheet, non potremmo aiutarti meglio ? … ad esempio ora ci dici che ha un’uscita in frequenza, perche’ non leggere direttamente la frequenza, anziche’ convertirla in tensione, amplificarla, condizionarla e leggere la tensione risultante … oppure dimensionare il primo stadio in modo cheti dia gia qualcosa di piu leggibile … :wink:

gualandd:
Ho fatto un pò di casino mi sa 8) ... riassumo per chiarire.

Mi pare tanto casino, ma che senso ha convertire una frequenza in tensione, per giunta con un delta di solo 10 mV, quando è molto più semplice leggere direttamente la frequenza ?

Etemenanki:
Ma, giusto per la cronaca, se ci dessi il part number del sensore per poter vedere il suo datasheet, o magari ancora meglio un link al datasheet, non potremmo aiutarti meglio ? ... ad esempio ora ci dici che ha un'uscita in frequenza, perche' non leggere direttamente la frequenza, anziche' convertirla in tensione, amplificarla, condizionarla e leggere la tensione risultante ... oppure dimensionare il primo stadio in modo cheti dia gia qualcosa di piu leggibile ... :wink:

Il sensore purtroppo non è commerciale ed al momento non ha documentazione (è in fase di sviluppo).
L'uscita è una quadra 0÷5V con variazione in frequenza secondo quanto ho già scritto.

Con PulseIn ho già tentato la lettura ma le variazioni (lette su Monitor seriale) sono comunque di qualche decina e non mi fornisce molta risoluzione di lettura.
Secondo il mio punto di vista il suggerimento dell'amplificazione di un segnale analogico mi permetterebbe una miglior discretizzazione, a patto di convertire la frequenza in tensione e per questo ho a disposizione solamente gli LM331.

Se avete suggerimenti per avere una tensione trattata partendo da una frequenza in ingresso ben venga, mi faciliterebbe notevolmente le cose anche a livello realizzativo (considerate che devo saldare a mano i componenti, per lo più SMD per contenere gli ingombri e per il momento, essendo un prototipo, su millefori).

astrobeed:
Mi pare tanto casino, ma che senso ha convertire una frequenza in tensione, per giunta con un delta di solo 10 mV, quando è molto più semplice leggere direttamente la frequenza ?

A sto punto, dato che siete in due a suggerirlo, riprovo anche a leggere direttamente la frequenza, tuttavia ho tassativamente bisogno di un sistema non bloccante e quindi Pulsein è da scartare.

Mi sta poco simpatica la lettura diretta della frequenza :smiling_imp: ma ci provo comunque...

gualandd:
A sto punto, dato che siete in due a suggerirlo, riprovo anche a leggere direttamente la frequenza, tuttavia ho tassativamente bisogno di un sistema non bloccante e quindi Pulsein è da scartare.

Con pulsein non ci fai nulla nel tuo caso, prima cosa ti basta una lettura al secondo senza bloccare nulla, ovvero mentre viene misurata la frequenza Arduino può fare altre cose ?
Ovviamente leggendo la frequenza la risoluzione è 1Hz e ottieni 1000 step, praticamente i 10 bit del ADC, tra 6 e 7 kHz, ovviamente tocca vedere il reale range di frequenza.
In alternativa è possibile leggere il periodo del segnale, un pochino più complesso da fare, che ti permette di ottenere oltre 1000 letture al secondo, devo fare due conti sulla risoluzione possibile con questo metodo ma dovremmo essere sempre attorno ai 1000 step, probabilmente anche 2000.

gualandd:
Se avete suggerimenti per avere una tensione trattata partendo da una frequenza in ingresso ben venga, mi faciliterebbe notevolmente le cose anche a livello realizzativo (considerate che devo saldare a mano i componenti, per lo più SMD per contenere gli ingombri e per il momento, essendo un prototipo, su millefori).

Se leggi direttamente la frequenza, visto che parliamo di un'onda quadra 0-5V, non ti serve nessun componente aggiuntivo, colleghi direttamente il sensore al micro, se le alimentazioni sono diverse, ovvero il sensore non è alimentato da Arduino, meglio mettere in mezzo una resistenza da 220-300 ohm per disaccoppiare.

astrobeed:
Con pulsein non ci fai nulla nel tuo caso, prima cosa ti basta una lettura al secondo senza bloccare nulla, ovvero mentre viene misurata la frequenza Arduino può fare altre cose ?
Ovviamente leggendo la frequenza la risoluzione è 1Hz e ottieni 1000 step, praticamente i 10 bit del ADC, tra 6 e 7 kHz, ovviamente tocca vedere il reale range di frequenza.
In alternativa è possibile leggere il periodo del segnale, un pochino più complesso da fare, che ti permette di ottenere oltre 1000 letture al secondo, devo fare due conti sulla risoluzione possibile con questo metodo ma dovremmo essere sempre attorno ai 1000 step, probabilmente anche 2000.

Partiamo per gradi.
Come faccio per leggere la frequenza senza il pulsein?
Si, durante la lettura arduino non può, ma deve fare altre cose... ecco perchè mi serve non bloccante!

La risoluzione di 1Hz potrebbe anche bastarmi forse, devo provare col sensore collegato.
Il sensore è alimentato tramite un pin digitale di arduino che abilito nel momento della lettura; il consumo del sensore è di circa 1mA, quindi non ci sono problemi di consumi eccessivi.

gualandd:
Partiamo per gradi.
Come faccio per leggere la frequenza senza il pulsein?

Utilizzando un timer come contatore e gate, il tutto gestito tramite interrupt senza dare fastidio all'esecuzione del programma.

La risoluzione di 1Hz potrebbe anche bastarmi forse, devo provare col sensore collegato.

Usando la conversione frequenza tensione ottieni meno punti utili in quanto l'ADC è d solo 10 bit e difficilmente riesci ad ottimizzare le cose in modo da usare tutta la dinamica da 1024 step.
Per contro leggendo la frequenza con risoluzione 1 Hz hai una dinamica compresa tra la differenza frequenza massima e minima, se sono 7kHz e 6kHz hai 1 kHz di differenza pari a 1000 step di risoluzione, il limite è che in questo modo ottieni solo una lettura ogni secondo, se ti basta questa è la via più semplice ed esiste una libreria pronta all'uso che ti risolve il problema in un attimo.
Lo scotto da pagare nell'uso del frequenzimetro è l'impegno del Timer 1 e il non poter usare la libreria servo e due canali pwm, però non credo che questo ti crea dei problemi.

astrobeed:
Utilizzando un timer come contatore e gate, il tutto gestito tramite interrupt senza dare fastidio all'esecuzione del programma.

Usando la conversione frequenza tensione ottieni meno punti utili in quanto l'ADC è d solo 10 bit e difficilmente riesci ad ottimizzare le cose in modo da usare tutta la dinamica da 1024 step.
Per contro leggendo la frequenza con risoluzione 1 Hz hai una dinamica compresa tra la differenza frequenza massima e minima, se sono 7kHz e 6kHz hai 1 kHz di differenza pari a 1000 step di risoluzione, il limite è che in questo modo ottieni solo una lettura ogni secondo, se ti basta questa è la via più semplice ed esiste una libreria pronta all'uso che ti risolve il problema in un attimo.
Lo scotto da pagare nell'uso del frequenzimetro è l'impegno del Timer 1 e il non poter usare la libreria servo e due canali pwm, però non credo che questo ti crea dei problemi.

No, non mi servono PWM e servo e nemmeno il Timer 1, quindi potrebbe essere ok co una lettura al secondo.
Mi potresti gentilmente indicare la libreria?

gualandd:
Mi potresti gentilmente indicare la libreria?

Ne esistono diverse, quella migliore è questa, il pin ingresso frequenza deve essere l'8 sulla UNO o il 49 sulla Mega.
L'esempio allegato alla libreria è abbastanza esplicativo su come va usata, in linea di massima basta che ad ogni ciclo della loop verifichi se è disponibile una nuova lettura tramite FreqMeasure.available(), nel caso leggi il valore acquisito tramite FreqMeasure.read(), per tutto il resto del tempo, 1 secondo per ogni lettura, puoi fare quello che ti pare.

astrobeed:
Ne esistono diverse, quella migliore è questa, il pin ingresso frequenza deve essere l'8 sulla UNO o il 49 sulla Mega.
L'esempio allegato alla libreria è abbastanza esplicativo su come va usata, in linea di massima basta che ad ogni ciclo della loop verifichi se è disponibile una nuova lettura tramite FreqMeasure.available(), nel caso leggi il valore acquisito tramite FreqMeasure.read(), per tutto il resto del tempo, 1 secondo per ogni lettura, puoi fare quello che ti pare.

Grazie mille, ora la implemento e vedo il risultato se mi soddisfa.