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

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)