Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Need help to convert code to show voltage as X,XX and not as XX,X

Status
Not open for further replies.

ggmssr

Member level 2
Joined
Oct 25, 2011
Messages
48
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,586
This is LED voltmeter with 3 digit and all works fine in format xx,xV. Today I need to measure up to 9,99V and how I can change source code to make this? Resolution its nice to sense 10mV. PIC is 16f676.

Code is here

Code:
#include <htc.h>
__CONFIG (FOSC_INTRCIO & MCLRE_OFF & BOREN_ON & CP_OFF & CPD_OFF & WDTE_OFF & PWRTE_ON ); 



#define SPORT PORTA
#define DPORT PORTC
const char SegCode[11] = {0x40,0x57,0x22,0x06,0x15,0x0C,0x08,0x56,0x00,0x04,0xFF};
	//                       0    1    2    3    4    5    6    7    8    9
const char Column[3]   = {0x02,0x01,0x04};
static char Segment[3] = {0x7f,0x7f,0x7f};	
static unsigned char ColCount=0x00;
void CPU_SETUP(void);
void Display(void);
void HTO7S(unsigned int Num);
void delayMs(int x);

unsigned int result;
unsigned int readAdc(void);
void interrupt  timer1_isr(void)
{
if(PIR1bits.TMR1IF==1)
{
PIR1bits.TMR1IF = 0;
	TMR1H=0xDF;
Display();
}
}
void main()
{		
	unsigned char i;
	
	CPU_SETUP();
	while(1)
	{			
		result=0;
		for (i=0;i<3;i++)
		{
			
			delayMs(1); 
			result=result+readAdc();
		}
				HTO7S(result/3);								
		
		delayMs(200);		    
	}
	
}

void CPU_SETUP()
{
	CMCON =0x07;		//Turn off comparator module
	ANSEL =0x8;			//AN3 as analog input
	ADCON1 =0x60; 		//clock/64
	ADCON0 = 0x8D;
   	TRISA=0b00011000;
   	PORTA=0x27;
   	TRISC=0b00000000;
   	PORTC=0x37;
   
   T1CON= 0x00;
  	TMR1H=0xDF;
   	INTCONbits.GIE =1;
	INTCONbits.PEIE=1;
	PIE1bits.TMR1IE =1;
 	T1CONbits.TMR1ON=1;
}
unsigned int readAdc()
{
unsigned int res;
ADCON0bits.GO_DONE =1;
while(ADCON0bits.GO_DONE ==1);
res=ADRESL+(ADRESH*0x100);
return(res);
}
//-------------------------------------
// Display routine
//-------------------------------------
void Display()
{
	PORTA = 0b00100111;	  // off all digits column and Segment G
	PORTC = 0b00111111;   // off segment a-f	

	

	if (ColCount>=3) 
	ColCount=0;
    	
	DPORT = Segment[ColCount];
	SPORT = ((Segment[ColCount] & 0b01000000)>>1) | (Column[ColCount]^0x07);
	ColCount++;				
}	

//--------------------------------------
// Convet HEX 2 byte to 7-Segment code
//--------------------------------------
void HTO7S(unsigned int Num)
{
	
	unsigned int res;

	res = ((30*Num)%1023)/100;
	if(res==10)
	{
	Num=Num+1;
	res=0;
	}
	Segment[2]=SegCode[res];

	res = (30*Num)/1023;
	Segment[1]=SegCode[res%10];

	Segment[0]=SegCode[res/10];
	if (Segment[0]==0x40) 
	Segment[0]=0xFF;	
	
}	

void delayMs(int x)
{
int i;
for (x ;x>0;x--)
{
for (i=0;i<=110;i++);
}
}
 

I hope that is ok if I post this short post, and that will pass without warnings.

I make first two digits, first number and first decimal, but for 2 decimal I cannot find solution.

Code:
//--------------------------------------
// Convet HEX 2 byte to 7-Segment code
//--------------------------------------
void HTO7S(unsigned int Num)
{
	
	unsigned int res;
	
	res = ((9*Num)%1023)/100;		
	 if(res==10)
	 {
	 Num=Num+1;
	 res=0;
	 }
	
	
	Segment[2]=SegCode[res];	  
	
	res = ((9*Num)%1023)/100;
	Segment[1]=SegCode[res];	

	res = (9*Num)/1023;	
	Segment[0]=SegCode[res];
	// if (Segment[0]==0x40) 
	// Segment[0]=0xFF;	
	
}
 

If I understand correctly you are trying to convert the ADC result (0-1023) to a voltage representation as ASCII.

You seem to be mixing the conversion steps which messes things up.
First calculate the ADC voltage , use
Code:
voltage = adc_result * Vref / 1023;   // for 10bit ADC

Then convert the voltage to ASCII
Code:
voltage=1234;
char lcd[6];

lcd[0]=voltage/1000;		// first digit
lcd[1]=(voltage/100) % 10;	// second digit
lcd[2]=(voltage/10) % 10;	// third digit
lcd[3]=(voltage) % 10;		// fourth digit

lcd[0] +='0'; convert integer to ASCII;
lcd[1] +='0'; convert integer to ASCII;
lcd[2] +='0'; convert integer to ASCII;
lcd[3] +='0'; convert integer to ASCII;

//the result will be "1234"

or
Code:
voltage=1234;
char lcd[6];

lcd[0]=voltage/1000;		// first digit
lcd[1]=(voltage/100) % 10;	// second digit
lcd[2]='.';					// dot
lcd[3]=(voltage/10) % 10;	// third digit
lcd[4]=(voltage) % 10;		// fourth digit

lcd[0] +='0'; convert integer to ASCII;
lcd[1] +='0'; convert integer to ASCII;
lcd[3] +='0'; convert integer to ASCII;
lcd[4] +='0'; convert integer to ASCII;

//the result will be "12.34"

For different ADC ranges change the code accordingly
 
  • Like
Reactions: ggmssr

    ggmssr

    Points: 2
    Helpful Answer Positive Rating
if you dont mind plz explain the whole code , i am a beginner in embedded field, I am also searching for a code for measuring voltage.
 


This code from first post is for 7-seg LED display, and works with 3 7-seg digit, all works fine for voltage range from 0 to 30V in format 30,0 25,3 13,8 7,3 ... and I want now to modify this code to measure up to 9,99 with two decimals, and if possible to increase resolution, I think now is around 45mV for 3-digit. It will be fine that new code can sense second decimal for Li-Ion battery 4,21 3,95 3,74 ....

dp led on 7-seg is connected always in original circuit on second digit, now will be on first digit.
 

I thought it was for LCD :roll:

still I think you can use the code I have provided and just ignore the last lines that convert the digit to ASCII.

- - - Updated - - -

For example

Code:
voltage=123;

Segment[0]=(voltage/100) % 10;	// first digit
Segment[1]=(voltage/10) % 10;	// second digit
Segment[2]=(voltage) % 10;		// third digit
 
  • Like
Reactions: ggmssr

    ggmssr

    Points: 2
    Helpful Answer Positive Rating
I dont have success.


This code works but only for first two digits, and I cant adjust third.

Code:
	res = (9*Num)/1023;	
	Segment[0]=SegCode[res];
	
	res = ((9*Num)%1023)/100;
	Segment[1]=SegCode[res];	

	res = ((9*Num)/1023);
	Segment[2]=SegCode[res];

For this code I get >

voltage is 7,93 and on display i get 797



For this code >

Code:
	res = (9*Num)/1023;	
	Segment[0]=SegCode[res];
	
	res = ((9*Num)%1023)/100;
	Segment[1]=SegCode[res];	

	res = ((9*Num)%1023)/1000;
	Segment[2]=SegCode[res];

Voltage is 7,93 and on display I get 790



for this code I get 008 on display and voltage is 7,93

Code:
	res = (9*Num)/1023;	
	Segment[0]=SegCode[res];
	
	res = ((9*Num)%1023)/100;
	Segment[1]=SegCode[res];	

	res = ((9*Num)%1023)/10;
	Segment[2]=SegCode[res];
 

I'm not sure what you are doing in your code , what I suggested is

Calculate the voltage from the ADC result using
Code:
voltage = adc_result * Vref / 1023;   // for 10bit ADC

What is your Vref , is it 5v?
What is the resolution of the ADC , is it 10bit (0-1023)?

If so then you can use
Code:
unsigned int voltage=0;

voltage = adc_result * (unsigned long)5000 / 1023;   // for 10bit ADC, using Vref=5000mV, result in mV

Segment[0]=(voltage/1000);	// first digit
Segment[1]=(voltage/100) % 10;	// second digit
Segment[2]=(voltage/10) % 10;		// third digit
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top