1 di 8 Voltmetro/Amperometro con Pic16F785 Ciao a tutti, molto spesso su grix vedo molti progetti con pic 16F84 che ormai e' un pic costoso e con poche periferiche rispetto all' ultima generazioni di pic16F come il mitico 16F690 (20 pin), o come quello che vi propongo oggi il pic16F785(20 pin). Il costo dei nuovi pic e' molto contenuto e in hardware hanno gia' molte periferiche. Descrizione Qualche settimana fa in un momento di relax , ho deciso di aggiungere ad un alimentatore autocostruito ( con lm317 limitazione in corrente e transistor di potenza per elevare la corrente massima disponibile a 2A e tensioni da 1,5Volt a 30volt) , un bel voltmetro e amperometro su display LCD Alfanumerico ,utilizzando cio' che avevo in casa e con il numero minore di componenti. Rovistando nella mia cassettina dei sample , ho trovato questo bel pic16HV785, che rispetto a tutti i suoi fratelli della serie 16F , ha un bel regolatore interno ( una specie di Zener di precisione ) che grazie a una resistenza esterna, permette di alimentare questo pic in modo semplice e senza regolatori esterni ( non serve un 7805) . Un'altra peculiarita' di questo pic e' di avere al suo interno 2 Amplificatori Operazionali con buone caratteristiche che per l'uso che ne volevo fare si sono dimostrati ottimi. Per chi e' andato a scuola qualche anno fa come il sottoscritto ricordo brevemente le poche equazioni che descrivono il funzionamento di un amplificatore operazionale in modalita' amplificatore di differenze ( nel mio caso devo misurare una tensione quindi una differenza di potenziale) Queste equazioni si ricavano facilmente con il teorema della sovrapposizione degli effetti essendo tutti i componenti del circuito lineari. Se impongo l'uguaglianza dei rapporti R2/R1=R4/R3 Si ottiene che Vout = (R2/R1) ( Vi+ - Vi-) Per realizzare un Amperometro , si misura la tensione ai capi di una resistenza di piccole dimensioni in serie al carico.Si vuole che il resistore per tale misura sia il piu' piccolo possibile (0,1 ohm o meno),quindi la tensione ai suoi capi e' di basso valore e quindi non leggibile con un ADC del pic. Per utilizzare tutta la precisione degli ADC del Pic che ricordo che per questo modello e' di 10bit (quindi di 1024 livelli di quantizzazione) la tensione ai capi della resistenza viene amplificata con un operazionale ( in questo caso interno al pic ) in configurazione di amplificatore di differenze , in quanto la massa del pic e il riferimento a tensione piu' bassa dell' amperometro non sono la stessa cosa.L'amplificatore Operazionale interno al Pic16HV785 funziona tranquillamente con tensione non duale, (come lm358) ma la sua uscita non puo' arrivare alla tensione Vcc di alimentazione , ma si ferma a Vcc-0,1 Volt ( come accade spesso ad operazionali rail-to-rail non speciali). Cio' significa che se utilizzo VCC anche come riferimento per il convertitore analogico digitale ADC del pic , non riesco ad utilizzare tutti i 10 21/11/2009 7.00 2 di 8 bit dell ADC. Per ovviare a questo , ho utilizzato un lm385 che e' uno zener di precisione a 2,5 volt , che viene utilizzato come riferimento per l'ADC , mentre tutto il resto del circuito e' alimentato a 5 volt prevenienti dal regolatore interno del pic 16HV785. Con l'accorgimento del lm385 , riesco ad utilizzare gli ADC con la massima precisione possibile. Le equazioni che regolano l'amperometro sono: Resistenza di shunt 0,11 ohm ( il convento passava 2 resistenze da 0,22 ohm collegate in parallelo) L'amplificatore di differenze è costituito da R4 R6 R9 R10 e dall' operazionale OP2 del pic16HV785, il rapporto di amplificazione e' R10/R6=R9/R4 = 10. L'ADC ha come tensione di riferimento 2,5 V forniti dal riferimento di tensione LM385 Tensione massima di ingresso (I+ I-) per il fondoscala e' di 2,5V/10 = 250 mV La corrente massima misurata e' quindi I=V/R che risulta I=0,25/0,11= 2,27 Ampere La minima corrente misurabile e' semplicemente Imax/(numero passi quantizzazione dell' ADC) Imin=2,27/1024 = 0,00221946 A che corrispondono a 2,21 mA , da qui la risoluzione dell' amperometro e' di 2,21 mA Per quanto riguarda il voltmetro si utilizza l'altro operazionale OP1 all' interno del pic ,sempre in configurazione amplificatore differenziale , ( posso misurare la tensione senza avere lo stesso riferimento di massa ) , ma in questo caso invece di amplificare ho un partitore di tensione 1/12 in modo da poter misurare 2,5x12 e cioe' con 30 fondo scala. Le equazioni che regolano il voltmetro con Fondo Scala 30 volt: Amplificatore differenze formato da OP1 interno al pic e R3 R5 R7 R8 il rapporto di amplificazione e' R3/R8=R5/R7 = 1/12. L'ADC ha come tensione di riferimento 2,5 V forniti dal riferimento di tensione LM385 21/11/2009 7.00 3 di 8 Tensione massima di ingresso (V+ V-) per il fondoscala e' di 2,5V/(1/12) = 30 V La minima corrente misurabile e' semplicemente Vmax/(numero passi quantizzazione dell' ADC) Vmin=30/1024 = 0,002929 V che corrispondono a 29,29 mV che corrisponde alla minima risoluzione del voltmetro. Circuito dell' Alimentatore Questo e' il circuito dell' alimentarore stabilizzato regolabile in tensione con 5 livelli limitazione di corrente, costruito attorno all famoso lm317 ( non raccontero' questo circuito , visto piu' volte anche su grix e descritto egregiamente da i2viu il Sig. Crepella, noto frequentatore di questo sito) che ho costruito tempo addietro e ho aggiornato con il voltmetro/amperometro , aggiungendo il Transistor PNP darlington TIP 145 ( correttamente alettato) che amplifica in corrente LM317 consentendo al circuito di raggiungere comodamente i 2 Ampere di uscita. Il convento forniva il TIP 145 , ma si puo' utilizzare qualsiasi PNP o PNP darlington che supporti una corrente maggiore di 5 Ampere ( per garantire i 2 Ampere di uscita massimi). Se si utilizza un PNP non darlington R1 va abbassata di valore a valori intorno ai 2 - 4 ohm a seconda del beta del transistror in questione. Nota: per calcolare i valori di resistenza R5-R9 secondo le proprie esigenze , basta utilizzare questa semplice equazione: Rx=0,7Volt/(Corrente limite) dove , 0,7 corrisponde alla tensione di accensione del tranistor NPN Q2 BC237 ( va bene qualsiasi NPN per piccoli segnali ) e la corrente Limite esperessa in Ampere. Es Voglio limitare la corrente a 100mA Rx=0,7/0,1=70 Ohm che e' approssimata al valore 68Ohm della serie standard dei resistori. Realizzazione Per i puristi , nel progetto allegato c'e' anche il file DRB ( formato Eagle) per costruirsi un circuito 21/11/2009 7.00 4 di 8 stampato ( Il disegno dello stampato l'ho fatto di corsa e solo come aiuto per realizzarne uno su millefori). Per comodita' e velocita' ho realizzato il circuito ( che e' veramente semplice e con pochissimi componeti con una piccola basetta millefori . Il convento mi ha passato dei resistori da 150Kohm e non da 120Kohm quindi nel software le formule per il voltmetro hanno un rapporto di guadagno di 1/15 e non 1/12. Per i primi esperimenti con il pic16F785 ho utilizzato una scheda di prototipazione della microchip che e' in kit con il programmatore pickit2 . Questa board monta a bordo di solito un 16F690 ( che non ha gli amplificatori operazionali a bordo), che ha le stesse pedinature del 16F785 ( per alimentazione e programmazione ). Il display LCD utilizzato (reciclato da una vecchia console di allarme) e' a una sola riga 16 Caratteri, compatibile con hd4480 . Per puro caso il display e' mappato su due righe di 8 caratteri allineate ( non chiedetemi il perche' non ho il datasheet del display) quindi nei sorgenti mi sposto sia sulla prima riga che sulla seconda. Il TIP 145 e sotto alla basetta millefori con il LM317 , l'aletta di raffreddamento e' recuperata da una vecchia CPU da PC . Tra aletta e TIP145 c'e' come di consueto un isolante in mica e la vite di fissaggio e' isolata dal corpo del TP145. Tra l'aletta di Raffreddamento e la lastra di alluminio su cui e' fissato il circuito e TIP145 c'e' un bel velo di pasta termoconduttiva al silicone per abbassare la resistenza termica al valore piu' basso possibile. 21/11/2009 7.00 5 di 8 Firmware Passiamo ora alla descrizione del software. Vedo spesso firmware in assembler , complicati e criptici per i non addetti ai lavori, quindi ho deciso per chiarezza e velocita' di scrivere il programma in linguaggio C , utilizzando il complicatore Hitech C che e' free nella versione lite( scaricabile gratuitamente e integrata nell' MPLAB della microchip ). Il Pic16HV785 ha solo 2Kbyte di flash , quindi non ho potuto utilizzare la funzione printf per scrivere a display la tensione come numero a virgola mobile in quanto la libreria printf per i float occupa troppo spazio per essere contenuta nei 2 kbyte di flash. Ho fatto una veloce ricerca nelle mie librerie per Pic18F (dove la printf non ha i float ) e ho trovato una bella funzione che stampa i float e non occupa tanta flash.Ho allegato anche una funzione per stampare un valore intero a 16 bit ( unsigned int ) che rappresenta la corrente. Il programma inizializza i vari registri , setta la velocita' di clock del pic , inizializza il display , abilita 21/11/2009 7.00 6 di 8 gli amplificatori operazionali interni , poi si entra in un loop infinito che legge tensione e corrente tramite l'AN2 e AN0 , converte il valore letto tramite le formule di conversione e le strampa sull' LCD alfanumerico 16x2 ( compatibile HD4480) Mettero' per semplicita' la funzione Main e per i piu' curiosi c'e' in allegato tutto i sorgenti software. #include <pic.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include "delay.h" #include "xlcd.h" #include "adc.h" __CONFIG (INTIO FCMEN ) ; & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT & DUNPROTECT & BOREN & #define SetClock() { OSCCON = OSCCON | 0b01100000 ; } void putch(unsigned char byte) { WriteDataXLCD(byte); } char * mset(char * str,char ch,char len) { while (len--){ str[len]=ch; } return str; } void reverse(char s[]) { unsigned char i, j; char c; for (i = 0, j = strlen(s)-1; i<j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } } void _itoa(unsigned n, char s[]) { char i; i = 0; do { /* generate digits in reverse order */ s[i++] = n % 10 + '0'; /* get next digit */ } while ((n /= 10) > 0); /* delete it */ s[i] = ''; reverse(s); } unsigned char *ftoa (float x, unsigned char *str,char prec,char format); char buffer[9]; int main(void) { unsigned int v,i,vref; 21/11/2009 7.00 7 di 8 double vout,iout; SetClock(); //785 ANSEL0 = ANSEL0 & 0x00; ANSEL1 = ANSEL1 & 0x00; CM1CON0 = 0 ; CM2CON0 = 0 ; TRISA=0xFF; TRISB=0xFF; TRISC=0xFF; DelayMs(100); OpenXLCD(0); ClrXLCD(); ADIF=0; ADIE=0; GIE=0; OPA1ON=1; OPA2ON=1; // Abilito Amplificatori Operazionali interni while (1){ DelayMs(250); i=a0(); v=a2(); vout= v * 0.036621093; // // // // // Leggo ADC0 Leggo ADC2 Vref 2.5 Volt in volt (2,5Volt/1024)*15 dove 15 e' il rapporto di attenuazione iout= i * 2.21946; 2.21 mA // in mA con 0.11 ohm di Shunt ogni bit corrisponde a // (((2.,5Volt/1024)/10)/0.11)*1000 // con 10 rapporto di amplificazione e // 0.11 Resistenza di shunt per la misura della corrente mset(buffer,' ',8); i=(unsigned)iout; i = ( (i>6) ? i-6 : 0); // Pulisco il Buffer // Azzero L'offset del OP interno _itoa(i,buffer); buffer[strlen(buffer)]=' '; buffer[5]='m';buffer[6]='A'; ClrXLCD(); gotoxyXLCD(0,DIPLAY_LINE_2); // Scrivo mA putsXLCDHex(buffer,8); mset(buffer,' ',8); ftoa(vout,buffer,2,'f'); // Scrivo il valore a virgola mobile sul buffer 2 cifre dopo la virgola buffer[5]=' ';buffer[6]='V'; // gotoxyXLCD(0,DIPLAY_LINE_1); putsXLCDHex(buffer,8); } } 21/11/2009 7.00 8 di 8 Conclusioni Sorgenti del Software e Schemi elettrici (eagle) e pcb 21/11/2009 7.00