# Voltage Measurement with PIC16F883

Discussion in 'Embedded Systems and Microcontrollers' started by Nomel, May 5, 2010.

1. ### Nomel Thread Starter New Member

May 5, 2010
2
0
Hello everyone,

I am currently working on a little project here, and it's becoming rather frustrating at the moment. The project is an adjustable power supply with an LCD showing the Voltage.
After preparing the parts for the power supply and the supply for the PIC+Display, i started to work on the measurements. I'm using a PIC16F883 together with a 10 Character LC-Display. I worked my way through the datasheet and started to experiment with the PIC's ADC. I started out small - measuring 0..5 V and displaying it with 10 LED's - and worked my way up from there. I got it to function with the LCD after that.
Currently I set up a Voltage divider, so that I can measure up to 40 V.
This is where it get's problematic. The LCD shows everything just fine, except the ten's digit. I'm measuring 15 Volts from a Laptop power supply and the reading is 05,xxx. I also measured a lead-acid Battery with 11.1xx V and the display is showing 01,1. Same thing with 24 V: 04,xxx. When i hook up a little rechargeable battery with 1.29 V, it reads 01,250 V. (With another ac-adapter (3.3V) I'm getting 03,2xx).

A short review about my code-logic:
First the ADC result is multiplied with 40 (*5*8, because of the scaling)
then the binary number in mV is converted to BCD-code by
-first subtracting 10000 from the result as often as possible (then I count the subtractions and that's my first digit)
-same thing with 1000 for the rest..
-ame thing with 100 for the rest..
-same thing with 10 for the rest..
-and the rest is the last digit
-afterwards, the value 30h is added to each digit and then sent to the LCD

Here's my code: (I'm using MPLAB btw)

Code ( (Unknown Language)):
1.
2. ; Display for Voltage Measurements
3.
4. ;-------------------------------------------
5. ;   PORTC:  0----E
6. ;           1----R/W
7. ;           2----R/S
8. ;   PORTB:  RB0-RB7 ---- D0-D7
10. ;--------------------------------------------
11.
12. list        p=16f883
13.             #include    <P16F883.INC>
14.
15.             __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO
16.             __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
17.
18.             org     0x00
19.
20.             loops   equ 0x2C
21.             loops2  equ 0x2D
22.             loops3  equ 0x2E
23.
24.             xw0     equ 0x22    ;
25.             xw1     equ 0x23    ;
26.             f0      equ 0x24    ;
27.             f1      equ 0x25    ;
28.             counter equ 0x26    ;
29.             Fehler  equ 0x27    ;
30.             SZT     equ 0x2C    ;
31.             ST      equ 0x28    ;
32.             SZ      equ 0x29    ;
33.             SH      equ 0x2A    ;
34.             SE      equ 0x2B    ;
35. [...]
36.
37.
38. ; right justify
43.             bcf     STATUS, 5
44.
45.             BANKSEL ANSEL
46.             BSF     ANSEL, 1        ;Set RA0 to analog
47. ; Select Channel AN1
57.
58. ; start a conversion
59. Main
60.             clrf    f0
61.             clrf    f1
62.             clrf    xw0
63.             clrf    xw1
64.
66.             bsf     ADCON0, 1   ; start
67.
68.             movlw   D'10'       ; wait a bit
69.             movwf   loops
70.             call    WAIT
71. cl
72.             btfsc   ADCON0, 1   ; done?
73.             goto    cl          ; no, go back
74.
77.             bcf     STATUS, 5
78.             movwf   f1
79.
82.             bcf     STATUS, 5
83.             movwf   f0
84.
85.             ;call   x8          ; result x 8
86.             call    mV          ;
87.             call    B2D         ;
88.             call    output
89.
90.             goto    Main
91. [...]
92.
93. ;*********************************************************************
96.          movf    xw0,W           ; xw0 nach W
97.          addwf   f0,F            ; f0 := f0 + xw0
98.
99.          movf    xw1,W           ; xw1 nach W
100.          btfsc   STATUS,C        ; fall ein Überlauf auftrat:
101.          incfsz  xw1,W           ;   xw1+1 nach W
102.          addwf   f1,F            ; f1 := f1 + xw1
103.
104.          return                  ; fertig
105.
106.
107. ;*****************************************************
108. ; 16 Bit Subtraction,
109. Sub16                           ; 16 bit f:=f-xw
110.          clrf    Fehler          ; extraflags löschen
111.
112.          movf    xw0, w          ; f0:=f0-xw0
113.          subwf   f0, f
114.
115.          btfsc   STATUS,C
116.          goto    Sub16a
117.          movlw   0x01            ; borgen von f1
118.          subwf   f1, f
119.
120.          btfss   STATUS,C
121.          bsf     Fehler, C       ; Unterlauf
122.
123. Sub16a
124.          movf    xw1,w           ; f1:=f1-xw1
125.          subwf   f1    ,f
126.
127.          btfss   STATUS,C
128.          bsf     Fehler, C       ; Unterlauf
129.
130.          bcf     STATUS, C       ; C-Flag invertieren
131.          btfsc   Fehler, C
132.          bsf     STATUS, C
133.          return
134.
135.
136. ;*****************************************************
137. ; Division durch 2 wird w-mal ausgeführt
138. ; die zu dividierende Zahl steht in xw
139. Div2
140.          movwf   counter         ; Anzahl der Divisionen speichern
141. Div2a                           ; 16 bit xw:=xw/2
142.          bcf     STATUS, C       ; carry löschen
143.          rrf     xw1, f
144.          rrf     xw0, f
145.
146.          decfsz  counter, f         ; fertig?
147.          goto    Div2a           ; nein: noch mal
148.  return
149. ;*****************************************************
150. ; Wandlung des ADC-Wert in Millivolt (binär)
151. ; Der ADC-Wert steht in f1,f0
152. ; Ergebnis steht in f1,f0
153. mV
154.     ;Multiply the result with 8 (Voltage Divider)
155.     movfw   f0
156.     movwf   xw0
157.     movfw   f1
158.     movwf   xw1
166.
167.     ; multiplication with 5
168.     movfw   f0
169.     movwf   xw0
170.     movfw   f1
171.     movwf   xw1
176.
177.     ; ADC * 5 to xw
178.     movfw   f0
179.     movwf   xw0
180.     movfw   f1
181.     movwf   xw1     ; xw := 5xADC
182.
183.     ; xw durch 64 dividieren (6 mal durch 2)
184.     ; dann ist xw = 5xADC/64
185.     movlw   6
186.     call    Div2
188.
189.     ; xw auf 5xADC/128 verringern
190.     movlw   1
191.     call    Div2
193.     return          ; fertig
194.
195.
196. ;*****************************************************
197. ;Converting the Binary to BCD: STZ, St, SH, ST, SZ, SE
198. B2D
199.     ; Test auf Zehntausender 10000d = 0x2710
200.     movlw   27h
201.     movwf   xw1
202.     movlw   10h
203.     movwf   xw0
204.     call    B2Da
205.     movwf   SZT
206.     ; Test auf tausender 1000d = 0x03E8
207.     movlw   0x03
208.     movwf   xw1
209.     movlw   0xE8
210.     movwf   xw0
211.     call    B2Da
212.     movwf   ST
213.     ; Test auf hunderter 100d = 0x0064
214.     clrf    xw1
215.     movlw   0x64
216.     movwf   xw0
217.     call    B2Da
218.     movwf   SH
219.     ; Test auf zehner 10d = 0x000A
220.     clrf    xw1
221.     movlw   0x0A
222.     movwf   xw0
223.     call    B2Da
224.     movwf   SZ
225.     movfw   f0
226.     movwf   SE
227.     return
228.
229. B2Da
230.     clrf    counter
231. B2Sb
232.     incf    counter, f  ; wie oft abgezogen?
233.     call    Sub16       ; f:=f-xw
234.     btfss   STATUS, C   ; zu oft abgezogen?
235.     goto    B2Sb        ; nein: noch einmal
237.     decf    counter, w  ; weil immer 1 zuviel gezählt wird
238. return
239.
240. [...]
241.
242.
Obviously I didn't include all of the code, I tried to narrow it down to the important parts (sorry if some comments are in German)

I can't seem to find my mistake, I've been at this for quite some time now, and I just don't see where I'm going wrong. So any help would be truly appreciated.

Thank you in advance for taking a look at this.

If more code/schematics/information is needed, I will gladly provide it.

Thomas

2. ### rjenkins AAC Fanatic!

Nov 6, 2005
1,015
69
I'd work through it by substituting fixed values for the ADC output and stepping through the code in MPLab.

You can also set breakponts so you don't have to step through every instruction.

You can check the memory locations and see if the results match what you expect for various input values.

Nomel likes this.
3. ### Markd77 Senior Member

Sep 7, 2009
2,796
595
There is a 16bit to 5 digit BCD converter in AN526 from the microchip site if that helps.

4. ### Nomel Thread Starter New Member

May 5, 2010
2
0
Well, I finally figured out how to use the Simulator in MPLAB ( at least a little) and after stepping through the code for hours I noticed that the first digit is overwritten before it is sent to the display..
So I glanced at my variable declarations.. and voila
there was the problem:

Code ( (Unknown Language)):
1.
2. ; Display for Voltage Measurements
3.
4. ;-------------------------------------------
5. ;   PORTC:  0----E
6. ;           1----R/W
7. ;           2----R/S
8. ;   PORTB:  RB0-RB7 ---- D0-D7
10. ;--------------------------------------------
11.
12. list        p=16f883
13.             #include    <P16F883.INC>
14.
15.             __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO
16.             __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
17.
18.             org     0x00
19.
20.             [COLOR="Red"]loops  equ 0x2C[/COLOR]
21.             loops2  equ 0x2D
22.             loops3  equ 0x2E
23.
24.             xw0     equ 0x22    ;
25.             xw1     equ 0x23    ;
26.             f0      equ 0x24    ;
27.             f1      equ 0x25    ;
28.             counter equ 0x26    ;
29.             Fehler  equ 0x27    ;
30.             [COLOR="red"]SZT        equ 0x2C[/COLOR]    ;
31.             ST      equ 0x28    ;
32.             SZ      equ 0x29    ;
33.             SH      equ 0x2A    ;
34.             SE      equ 0x2B    ;
35. [...]
36.
Soo thanks, worked like a charm.. the Simulator is really powerful. I should've started using it earlier

@Markd77:
I checked out microchip's site and found some things about the AN256. That's pretty neat resource ( but too much for me to go through for today )

5. ### rjenkins AAC Fanatic!

Nov 6, 2005
1,015
69
Hi,

happy to hear you got it going!