728x90

728x90

Saturday, May 30, 2020

Designing a positive and negative DC voltage meter using the 10-bit ADC module

The ADC module's resolution is up to 10-bit, yield an acceptable measuring accuracy with the voltage within 50 V DC.

In this example, I use this ADC module to measure a DC voltage within -25 V to +25 V. So the total voltage magnitude is 50 V.

Since the maximum reference voltage is 5 V in magnitude. I use a voltage divider circuit to scale the input voltage to the lower 5 V.


Designing a positive negative voltage meter using the 10-bit ADC module

From the voltage divider:

Designing a positive negative voltage meter using the 10-bit ADC module

The V(ADC) is at 5 V maximum. V(MEASURE) could be 50 V in magnitude. So we divide the V(MEASURE) by 11.
But in the program simulation I don't use 11. I use 9 because it cause a lot of error. 
In the real hardware test, you can try 11.

The voltmeter display the measuring voltage on a five-digit multiplexed SSD. The ADC reading is scheduled every one second due the timer 0 scheduling. The analog DC input voltage is fed from a -25 V and +25 V voltage terminals, giving a 50 V DC magnitude. 

Designing a positive and negative DC voltage meter using the 10-bit ADC module
Schematic diagram a digital two poles voltmeter. A POT used for adjusting the analog input
voltage, varies from -25 V to +25 V.

Source code:

#include<xc.h>
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = ON
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
/*_XTAL_FREQ use for __delay*/
#define _XTAL_FREQ 4000000

void driveDisplays(  int analogRead){
 unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
 float voltage;
 int _voltage;
 /*Voltage Calculation total reference is
  +5V with centered ground*/
 voltage=((5.0*((float)(analogRead)/1024))-2.5)/9.1;
 //voltage/=11;
 _voltage=(int)(voltage*10000);
 /*Check negative voltage*/
 if(_voltage&0x8000){
     _voltage=-_voltage;
     PORTD=0x00;
 PORTC=0x40;
 PORTD=0x01;
 __delay_ms(10);
 }
 /*Decimal Place*/
 PORTD=0x00;
 PORTC=ssd[_voltage/1000];
 if(_voltage>=1000)
     PORTD=0x02;
 __delay_ms(10);
 /*Floating point*/
 PORTD=0x00;
 PORTC=ssd[(_voltage%1000)/100]|0x80;
 PORTD=0x04;
 __delay_ms(10);
 PORTD=0x00;
 PORTC=ssd[(_voltage%100)/10];
 PORTD=0x08;
 __delay_ms(10);
 PORTD=0x00;
 PORTC=ssd[_voltage%10];
 PORTD=0x10;
 __delay_ms(10);
}
int readADC(void){
    GO=1;
    while(GO);
    return (ADRESH<<8)+ADRESL;
}
void portInit(void){
    /*Analog and digital Port
     Configuration*/
    PORTB=0x00;
    PORTC=0x00;
    PORTD=0x00;
    /*RB4 for analog input*/
    TRISB4=1;
    TRISC=0x00;
    TRISD=0x00;
}
void adcInit(void){
    /*Select external Voltage reference
     +2.5V to -2.5V*/
    VCFG1=1;
    VCFG0=1;
    /*Result is right justify*/
    ADFM=1;
    /*By default is analog,
     but again set it to analog*/
    ANS11=1;
    /*Select FRC Clock of ADC module*/
    ADCON0bits.ADCS=0x03;
    /*Turn on ADC Module*/
    ADON=1;
    /*Select AN11 RB4*/
    ADCON0bits.CHS=0x0B;
    /*initiate a conversion*/
    GO=1;
    /*Wait until GO=0 "done"*/
    while(GO);
}
void timerInit(void){
     /*Select FOSC*/
    T0CS=0;
    /*Select timer 0 Prescaler*/
    PSA=0;
    /*Enable Timer 0 Overflow
     interrupt*/
    T0IE=1;
    /*Turn on Global interrupt
     Control*/
    GIE=1;
    /*Clear interrupt flage*/
    T0IF=0;
    /*Clear timer 0 register*/
    TMR0=0;
}
int adcResult;
int counter=0;
void main(void){
    portInit();
    adcInit();
    timerInit();
    
    while(1){
        driveDisplays(adcResult);
    }
}
void interrupt _ISR(void){
    if(T0IF){
        counter++;
        T0IF=0;
    }
    /* If it's one second*/
    if(counter>=15){
        adcResult=readADC();
        counter=0;
    }
}

Designing a positive and negative DC voltage meter using the 10-bit ADC module
A screen shot shows a positive voltage reading 24.84 V nearest to the positive terminal.

Designing a positive and negative DC voltage meter using the 10-bit ADC module
A screen shot shows a negative voltage reading -24.89 V nearest to the negative terminal.








No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90