 Entire Forum This board This topic Members Entire Site Pages: Author Topic: Decimal point in 8-bit Uc.  (Read 5449 times) 0 Members and 1 Guest are viewing this topic.
naseerak
Inactive Muted Offline

Posts: 3

Thank You
-Given: 4 « on: January 23, 2014, 01:56:51 13:56 »

Hi!
I am trying to build an  voltmeter using PIC16f72 and 3-digit 7-segment display, but don,t know how to implement the decimal point my code snippets are:

VIN = VIN/4
VIN = VIN*511

VIN = VIN/10

'sort a/d value in 100, 10, 1 's
adrd: ONE = Dig VIN , 0
TEN = Dig VIN , 1
HUN = Dig VIN , 2
Return

My highest voltage is 50V and voltage divider consists of 10k in the upper arm and 1k in the lower arm. Logged
TucoRamirez
Senior Member     Offline

Posts: 305

Thank You
-Given: 255  « Reply #1 on: January 23, 2014, 02:54:30 14:54 »

no idea, where do you want to display or use the point in? Logged

Whoever double crosses me and leaves me alive... he understands nothing about Tuco.
pablo2048
Active Member    Offline

Posts: 113

Thank You
-Given: 129 « Reply #2 on: January 23, 2014, 03:24:40 15:24 »

Ok, according to datasheet this type of MCU has 8 bit A/D converter. In line VIN = VIN/4 You loose 2 bits of resolution. Better is 1. multiply and then divide... What is Your reference voltage? If 5V, then maximum voltage on the A/D input is approximately [email protected] input. Logged
sam_des
Active Member    Offline

Posts: 236

Thank You
-Given: 108 « Reply #3 on: January 23, 2014, 06:16:11 18:16 »

@naseerak,

• pablo2048 is right, you should multiply first then divide. Although sequence of operation for mul/div is not important in our math, but with integers it is always multiply first.
e.g. Consider this, (2/5)*50 = 20, but with integer math, result is 0 So you should do it as (2*50)/5.
• When you multiply/divide by power of 2, use shift operation instead of math mul/div. It will be faster and code efficient.
• Watch out when multiply two nos., result may require additional byte. 8-BIT x 8-BIT may result in 16-BIT no.
• Your Resistor divider causes ADC input to vary from 0V(0V) to 4.5454V(50V). For simplicity, can you modify your upper arm to be (18k||18k) or Even better if you can use a variable res . This will give you exact 1/10th value. Even better if you can use a var-res to get correct ratio.  Also check power dissipation in resistors. At 50V, upper arm nearly dissipates 225mW. I think 5mA is too much current for sensing. 1mA is enough. Modify resistors accordingly, keeping ratio same.  Note this gives no head room for over-voltage.
• Watch out for temp cos of resistors in divider, if you need long term stability. MFRs (metal film resistors) may be a good choice.

Now with precise 1/10th value at adc input, it is very easy to get 1 digit beyond decimal point, with only integer math. Simply scale the calculations by 10.
For 50V -> ADC INPUT = 5V -> ADC Conversion = 1023,  Now if 1023 represents 500, any adc result "x" will represent, (x*500)>>10.
e.g. For ADC result = 150, V = (150*500)>>10 = 73.24 precise or 73 for integer math giving 07.3 as 3 digit display.
Note that you will require 16-BIT x 16-BIT=>32-BIT math multiply.

You can work on it further to optimize in terms of code as well as hardware.

Hope this helps,
sam_des
 « Last Edit: January 23, 2014, 06:18:23 18:18 by sam_des » Logged

Never be afraid to do something new. Remember Amateurs built the Ark, Professionals built the Titanic !
naseerak
Inactive Muted Offline

Posts: 3

Thank You
-Given: 4 « Reply #4 on: January 25, 2014, 08:27:24 20:27 »

@Sam_des
You are right but my problem is 8-bit of ADC i 16f72. I have done my display code but stuck ni the calculation and display of decimal point, the 50v limit may increased in the upward direction as I am measuring two PVs in series, The Variable VIN has a word size thats why I have implied divided by 4. Logged
gan_canny
Junior Member   Offline

Posts: 88

Thank You
-Given: 100 « Reply #5 on: January 26, 2014, 01:14:31 13:14 »

In mathematics numbers are notation. You have two types of notation base 10 decimal and yes your PIC is binary and uses base 2 notation. The two notations are compatible across the integers (whole numbers). Now we know the pic will use integers to maintain notational accuracy we need to think about the number of base 10 decimal places we need in our result. Suppose it is two base 10 decimal places. The pic is binary so we are only compatible in our notation if we scale everything up by 100 ( base 10).
An aside
Now binary also has a binary point just as decimal has a decimal point you will encounter the binary point if you were to use float variables with your pic.
Notation is not perfect
..Ex 1/3 can't be expressed fully in the decimal ( base 10) system and 0.1 decimal can't be fully expressed in the binary system. Coders often call this inability to fully express things as rounding errors. It is common usage but not perfectly pure mathematics. There is valid math rounding where the notation of numbers is shortened by looking at the least significant digit and rounding up or down.
Again scale all your calculations up and use integers within the pic code.
On output convert back to the decimal system and place the decimal point taking into account your scaling factor.
Now when things need displaying another notation comes in namely ASCII. Your LCD uses this notation for activating pixels. The character representing '0' ( zero) in this notation is 48 (base10). The conversion from 1 base 2 ( binary) to ASCII character notation would involve adding 110000 ( 48 base 10) to get get the character '1'.

Oh, coders can assume the pic calculates like a handheld calculator. A hand held calculator uses BCD ( binary coded decimal) for its calculations. It is slow and cumbersome but it never leaves the decimal notation system so it is notionally accurate in the decimal system. The hand calculator is fine for humans but too slow for a pic. Coders can think a 64 bit PC avoids the notational issue...it does in a way since it is pushed back to very small quote "coder rounding error" in about the 20th least significant digit place.
 « Last Edit: January 26, 2014, 01:18:22 13:18 by gan_canny » Logged
naseerak
Inactive Muted Offline

Posts: 3

Thank You
-Given: 4 « Reply #6 on: January 27, 2014, 06:53:51 18:53 » Logged
thunderer
Junior Member   Offline

Posts: 61

Thank You
-Given: 19 I try to be patient « Reply #7 on: February 16, 2014, 02:09:47 02:09 »

Code for printing a voltage on a LCD (in a format like 12,345V).

Code:
tlong0 = adc_rd0 * 5000 * 12 (transform 1024 in 60000 - coresponding to 60,000V)
tlong0 = tlong0 >> 10
ch0 = tlong0 div 10000 'Extract the tens of thousands
if ch0 = 0 then            ' If 0, do not print
Lcd_Out(1, 1," ")
else
Lcd_Chr(1, 1, 48+ch0)
end if
ch0 = (tlong0 div 1000) mod 10 'Extract the thousands
Lcd_Chr(1, 2, 48+ch0)
Lcd_Chr(1, 3, ".")
ch0 = (tlong0 div 100) mod 10 'Extract the hundreads
Lcd_Chr(1, 4, 48+ch0)
ch0 = (tlong0 div 10) mod 10 'Extract the tens
Lcd_Chr(1, 5, 48+ch0)
ch0 = (tlong0 div 1) mod 10 'Extract the units
Lcd_Chr(1, 6, 48+ch0)

I know this answer comes late, but better have a working code posted. Logged

Interested and hopefully helpful in: DC brushed motor control (mainly R/C - PPM/PWM), analog audio, PIC (mikrobasic PRO). Feel free to ask, and if I can, I will help. But only on forum topics, any started private conversation will continue in a public topic.
pablo2048
Active Member    Offline

Posts: 113

Thank You
-Given: 129 « Reply #8 on: February 16, 2014, 08:40:56 08:40 »

I think that if you have 10bit A/D convertor, the accuracy is 60/1024 = 0.05859 V/bit. That means the maximum valuable precision is 1 decimal place... Displaying three decimal places is wrong. Logged
krishna.velu
Newbie  Offline

Posts: 13

Thank You
-Given: 10 « Reply #9 on: July 30, 2014, 11:43:50 11:43 »

The ADC you have in PIC16f72 is 8Bit.

2^8 = 256. Logged