Usare il convertitore A/D MCP3202 con un PIC18

MCP3202 è un convertitore A/D a 12 bit con circuito di sample & hold incorporato prodotto da Microchip. È provvisto di due canali d’ingresso che possono essere usati come due ingressi single-ended separati o come un solo ingresso (pseudo) differenziale. Quest’ultimo tipo di collegamento è utile per eliminare piccoli disturbi di modo comune, dell’ordine di 100 mV, possibili in ambienti rumorosi. La non linearità differenziale è minore di ±1 LSB, mentre la non linearità integrale è minore di ±1 LSB per la versione MCP3202B. Il convertitore utilizza il metodo SAR (Successive Approximation Register) che permette di ottenere la risoluzione di 12 bit con una velocità di campionamento relativamente elevata. In particolare, se alimentato a 5 V, il tasso di conversione massimo è pari a 100 Ksps, mentre scende a 50 Ksps alla tensione d’alimentazione minima di 2.7 V. La tensione d’alimentazione funge anche da tensione di riferimento per il convertitore, Vref. Così, la corrispondenza tra il codice in uscita ed il valore della tensione in ingresso Vin, è data dalla formula seguente:

Figura 1: comunicazione SPI di MCP3202 con un PIC (mode 1,1)

 

Figura 2: uso di MCP3202 per tensioni di ingresso positive

Interfacciamento SPI

MCP3202 è utilizzato congiuntamente ad un microcontrollore con cui si collega tramite un’interfaccia SPI. Com’è noto, questa è un’interfaccia seriale sincrona particolarmente semplice da utilizzare e veloce: MCP3202 supporta una velocità di clock massima di 1.8 MHz, se alimentato a 5V. Nel grafico in figura 1 possiamo vedere un esempio di comunicazione tra il convertitore  ed un microcontrollore PIC. L’interfaccia SPI del micro è configurata nel cosiddetto Mode 1,1: il segnale di clock è idle a livello alto e la trasmissione di un bit avviene sul fronte di discesa del clock. La comunicazione è iniziata dal micro che emette un primo byte costituito da 7 bit bassi e da un bit di Start: i 7 bit iniziali sono necessari per mantenere l’allineamento su 8 bit (infatti il modulo SPI dei PIC trasmette gruppi di 8 bit alla volta). Segue un byte contenente i bit seguenti

  • SGL/DIFF : 1 se gli ingressi del MCP3202 sono single ended, 0 se differenziali.
  • ODD/SIGN: nel caso d’ingressi single-ended lo 0 seleziona l’ingresso CH0, l’1 l’ingresso CH1. Per ingressi differenziali, 0 indica che CH0 è l’ingresso + e CH1 l’ingresso -, l’inverso se il bit è posto ad 1.
  • MSBF: se posto ad 1, MCP3202 emetterà il risultato della conversione a partire dal MSB, se a 0 lo emetterà una prima volta a partire dal MSB e successivamente anche a partire dal LSB.

L’esempio in figura 1 è relativo al caso di MSBF=1. Dopo aver ricevuto  il bit MSBF, MCP3202 emetterà un bit a zero, quindi inizierà ad emettere il risultato della conversione, MSB first. Alla fine del secondo byte, quindi, il modulo di ricezione del micro avrà ricevuto i primi 4 bit del risultato. I successivi 8 impulsi di clock del micro servono per ricevere  il terzo byte che conterrà gli 8 bit restanti della conversione.

Misurare tensioni positive con MCP3202

Nel caso più semplice, il convertitore  è utilizzato come raffigurato nello schema elettrico di figura 2. MCP3202 è alimentato con la stessa tensione stabilizzata a 5V che alimenta il microcontrollore PIC18F2550. Poiché lo stadio d’ingresso utilizza una tensione di alimentazione singola (single supply), sarà possibile misurare tensioni Vin tra 0 e 5 V, cui corrisponderanno dei codici di uscita compresi tra 0 e 4095. Un circuito del genere presenta però due svantaggi: non è possibile misurare tensioni d’ingresso negative e non c’è una corrispondenza 1:1 tra il codice in uscita e la tensione Vin. Quest’ultimo problema in particolare comporta una leggera complicazione del firmware, come vedremo nel programma d’esempio. Chiaramente, inoltre, la precisione della misura dipende anche dalla precisione della tensione d’alimentazione.

Misura di tensioni  bipolari

Nel caso in cui fosse necessario misurare tensioni sia positive che negative, come ad esempio quelle prodotte da un generatore audio, si può ricorrere al circuito raffigurato in figura 3. In questo caso, è utilizzato l’integrato LM4040-4.1 per generare una tensione di riferimento di 4.096V. Questo integrato è disponibile con una precisione fino allo 0.1%: con questo valore di tensione inoltre il convertitore A/D fornirà un codice d’uscita pari ad 1 LSB per 1 mV di ingresso. Ciò semplifica  i calcoli del firmware e ci permette di ottenere la precisione massima di conversione. Per poter misurare sia tensioni positive che negative, si utilizza l’amplificatore operazionale IC4, un TL081 o equivalente. L’operazionale è alimentato tramite una tensione duale di ±5 V: la tensione di riferimento viene divisa per 4 dal partitore costituito dalle due resistenze di precisione R5 ed  R6, in modo da fornire all’ingresso non invertente un offset di tensione che verrà sommato alla tensione da misurare. In particolare, la tensione d’uscita dell’operazionale sarà data da:

In pratica, nel procedimento di taratura, una volta cortocircuitato l’ingresso Vin del canale, dovremo ruotare il trimmer R3 per ottenere in uscita dall’operazionale una tensione pari a Vref/2 = 2.048 V. Così una tensione d’ingresso compresa tra ±2.048 V sarà convertita tra 0 e 4.096 V.

Un esempio  con PIC18

Nel listato 1 è riportato parte del codice del programma d’esempio. Il  programma è stato sviluppato tramite l’IDE MPLAB ed il compilatore C18 di Microchip. Sono state usate anche le funzioni di libreria per la gestione del modulo SPI fornite con il compilatore. Nella procedura main() sono dichiarate le variabili che conterranno i risultati delle conversioni: notiamo che è usata la compilazione condizionale in modo da poter utilizzare  il codice sia con il collegamento a tensione singola che duale. Se la costante MCP_SS è definita, sarà compilata la versione per tensione singola, altrimenti quella a tensione duale. Il codice prosegue con le inizializzazioni delle porte del PIC, viene quindi inizializzato il modulo SPI. Nel loop infinito successivo, si esegue la lettura dei due canali di MCP3202: un ciclo di lettura è iniziato dall’attivazione del pin CS, dopodichè è emesso il  primo byte di controllo (contenente  il bit di start) da parte del PIC. Il secondo byte emesso contiene i  bit di controllo SGL, ODD e MSBF che abbiamo descritto in precedenza. Alla fine dell’emissione di questo byte, il buffer di lettura del PIC conterrà i primi 4 bit risultanti dalla conversione del canale CH0: questi bit (opportunamente mascherati) saranno copiati nella variabile MSB_AD_CH. L’istruzione successiva legge il  terzo byte tramite la funzione ReadByte() copiandolo in LSB_AD_CH: questo conterrà i restanti  8 bit della conversione. Si disattiva CS terminando così la comunicazione. Il risultato a 12 bit è ricavato componendo i due gruppi di bit in AD_CH:

AD_CH = ((unsigned int) MSB_AD_CH << 8) + LSB_AD_CH;

Il codice seguente differisce a seconda che sia stata scelta l’alimentazione singola o duale. Nel primo caso, AD_CH sarà moltiplicato per un valore costante V_CONST pari a Vref/4096, con Vref espressa in mV. Questo è pari al valore dell’LSB. Quindi la tensione misurata del canale sarà:

Vin_CH[i] = AD_CH * V_CONST;

Si noti che in questo caso è necessaria una moltiplicazione per un float, cosa che introduce un ritardo nei calcoli. Nel caso di alimentazione duale, il valore di AD_CH è innanzitutto cambiato di segno (l’operazionale d’ingresso infatti inverte la tensione Vin), quindi è sommato alla costante V_OFFS pari alla tensione di offset di 2048 mV:

Vin_CH[i] = -AD_CH + V_OFFS;

Il ciclo successivo compie le stesse operazioni per il canale CH1 e così via.

Figura 3: uso di MCP3202 per tensioni d’ingresso bipolari

Figura 3: uso di MCP3202 per tensioni d’ingresso bipolari

#include <p18cxxx.h> // definizioni per i
PIC18
#include <spi.h>
#include “MCP3202.h” // Config Bits, defines
// Togliere il commento se SINGLE SUPPLY
//#define MCP_SS
void main(void) {
char i = 0; // contatore
// MSB ed LSB conversione A/D MCP3202
unsigned char MSB_AD_CH, LSB_AD_CH;
// 12 bit conversione A/D MCP3202
unsigned int AD_CH;
#ifdef MCP_SS
float Vin_CH[2]; // Vin CHx
float V_CONST; // LSB = Vref/4096 mV
V_CONST = 1.220703; // 5000/4096
#else
int Vin_CH[2]; // Vin CHx
int V_OFFS=2048; //OFFSET per tensioni
bipolari
#endif
/*** INIZIALIZZAZIONI PIC ***/
PORTA = 0;
PORTB = 0;
PORTC = 0;
TRISA = 0B00000000; // PORTA
TRISB = 0B00000000; // PORTB
TRISC = 0B00000000; // PORTC
/*** inizializza l’SPI ***/
// disattiva CS
CS_MCP3202 = 1;
// SDO Idle
SDO = 0;
//configura SPI per MCP3202 (Mode 1,1)
//CKP=1, CKE=0
//SMP=0
// freq. clock SPI = Fosc/64
OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);
// loop scrittura/lettura verso MCP3202
while (1) {
for (i=0; i<2; i++) {
// attiva CS
CS_MCP3202 = 0;
// emette il primo byte: Start
WriteSPI(0B00000001);
// secondo byte: Single Ended, CH i, MSB First
if (i==0)
WriteSPI(0B10100000); // CH0
else
WriteSPI(0B11100000); // CH1
// legge i 4 MSB del risultato
MSB_AD_CH = (0x0F & SSPBUF);
// legge gli 8 LSB del risultato
LSB_AD_CH = (ReadSPI());
// disattiva CS
CS_MCP3202 = 1;
// compone i 12 bit del risultato..
AD_CH = ((unsigned int) MSB_AD_CH << 8) +
LSB_AD_CH;
// ..e lo elabora
#ifdef MCP_SS
//*** SINGLE SUPPLY
// Vin = AD_CH*Vref/4096
Vin_CH[i] = AD_CH * V_CONST;
#else
//*** DUAL SUPPLY
// Vin = -AD_CH + V_OFFS
Vin_CH[i] = -AD_CH + V_OFFS;
#endif
//*** altre elaborazioni del risultato
//...
} // fine for
} // fine while(1)
} // fine main()
Listato 1

 

 

STAMPA     Tags:, , ,

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio Di Paolo Emilio 15 gennaio 2017

Scrivi un commento