PDA

View Full Version : A/d 16f88



Steves
- 30th May 2009, 07:13
Hi, I am very new to all of this, hope someone can set me straight. I started a project with a 16F628 and was goin OK but decided I needed to read a battery voltage and swapped to a 16F88. To test the A/D conversion I used the following code.
I am using PBP V2.45 but have just ordered upgrade.

INCLUDE "modedefs.bas" ' Include serial modes

' port A used for LCD
Define LCD_DREG PORTA ' RA0 to RA3 is data pin for LCD
Define LCD_DBIT 0
Define LCD_RSREG PORTA ' RA6
Define LCD_RSBIT 6
Define LCD_EREG PORTA ' RA4
Define LCD_EBIT 4
Define LCD_BITS 4
DEFINE OSC 4
'define A/D setup
Define ADC_BITS 8
define ADC_SAMPLEUS 100

@ DEVICE pic16F88, INTRC_OSC_NOCLKOUT ' system clock options

Ai var PORTB.6 'input to chanel 6 A/D
bat var word 'battery voltage off load
bat1 var word 'battery voltage on load
led var PORTB.0 'speaker/led output

OSCCON = %01101110 'internal clock, is primary clk @ 4 Mhz
CMCON =7 ' Comparator off
TRISA = 0 ' Port A all outputs
TRISB = %11111110 'Port B all inputs 0
ANSEL = %01100000 'all digital except chanel 5&6 which are inputs (analog)
ADCON0 = %00101001 'Frc internal clock, chanel 5 is A/D (RB6/AN5)
ADCON1 = %01000000 'left justify,divide clk by 2, Vref is VDD and VSS

low led 'turn off led
' Allow time for LCD startup
pause 2000

start:
LCDOut $FE,1 ' Clear LCD screen
LCDOut "Goto Bat_Volts" ' See where we are
pause 1000
'test that we loop
toggle led
pause 250
toggle led
pause 250
'Start program ***************************************8
goto Bat_Volts
'check battery off load
Bat_Volts:
LCDOut $FE,1 ' Clear LCD screen
LCDOut "ADCON0 = "
LCDOut $FE,$C0
lcdout #ADCON0 'Display ADCON0
pause 2000
LCDOut $FE,1 ' Clear LCD screen
LCDOut "Before ADC" 'Check where we are
pause 1000
ADCIN Ai, bat 'read A/D chanel 6 and store value to bat
while ADCON0.1=1:WEND ' Check to make sure ADC conversion finished..
LCDOut $FE,1 ' Clear LCD screen
LCDOut "After ADC" 'Check where we are
pause 1000
LCDOut $FE,1 ' Clear LCD screen
LCDOut "ADCON0 = "
LCDOut $FE,$C0
lcdout #ADCON0 'Display ADCON0
pause 2000
LCDOut $FE,1 ' Clear LCD screen
LCDOut "Battery = ",#bat ' Display Voltage
LCDOut $FE,$C0
lcdout "Volts"
pause 2000
goto start

end 'End of program

When I run it I only read 255 whether inputing VDD or VSS, and ADCON0 is 41 before the ADCIN command and 193 after.
Have been thru the data sheet and thought I had all registers set up correctly but maybe not.
This is a lot of fun but I don't get much sleep these days.Thanks for any help.
Steve

flotulopex
- 30th May 2009, 10:59
Hi Steve,

Don't use a VAR to define the A/D channel. Use the channel's number instead:

ADCIN 5, bat
You can test your project with your code I trimmed to minimum:
INCLUDE "modedefs.bas"

Define LCD_DREG PORTA
Define LCD_DBIT 0
Define LCD_RSREG PORTA
Define LCD_RSBIT 6
Define LCD_EREG PORTA
Define LCD_EBIT 4
Define LCD_BITS 4

bat var byte

OSCCON = %01100000
ANSEL = %00100000

Bat_Volts:
ADCIN 5, bat
LCDOut $FE, 1, "Battery = ",DEC bat, "V"
PAUSE 2000
goto Bat_Volts:
end

BTW, PORTB.6 is ADC Channel 5
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=3431&stc=1&d=1243677507">

tenaja
- 30th May 2009, 14:38
Don't use a VAR to define the A/D channel. Use the channel's number instead:

ADCIN 5, bat

I strongly disagree with this. First, in this particular example, he's using Ai as a constant, not a changing variable. That allows you to change PICs (or PIC pins), and just change the setup constant, without searching for all of the references to the pin.

Second, there is nothing wrong with using a variable variable to read adcin.

What you did do wrong, however, is you referenced the AN# with a PORT#. You don't do that. You should only use the ANx number; in this case, assuming your comments are your target, 6, NOT Portb.7.

Correct:
adcin 6, bat
NOT Correct:
adcin portb.7, bat

Correct:
Ai var 6 'Notice we use "x" of ANx.
adcin Ai, bat

NOT Correct:
Ai var portb.7 'Do NOT use the Port pin the ANx is on.
adcin Ai, bat

flotulopex
- 30th May 2009, 15:29
hum...

Correct:
Ai var 6 'Notice we use "x" of ANx.
adcin Ai, bat
Doesn't work for me.

It will work like this:

Ai CON 6
ADCIN Ai, bat
... or:

Ai VAR BYTE
Ai = 6
ADCIN Ai, bat

Or do I miss something?

NB: addressing PORTs via variable/constant is a best practice not a must.

tenaja
- 30th May 2009, 18:32
Yes, you are right... in my haste I edited it incorrectly.

I believe using a number is the worst way to do it, because it has no description behind it.

A constant is just as tight as far as compiling goes, and a variable is the way to go if you need to change which port you are reading within the loop. Both of these have the advantage that you can change all of your constants up at their definitions on the top, and you can change them easily when you move things around, like to a different PIC or pin. Also, compare these two, which do the exact same thing:

adcin 6
vs.
adcin BatteryVoltagePin

Which is easier to understand? Obviously the second. And if you use three a/d ports, with the constants all defined in a row and then you need to move things, it's one edit at the top for each... no searching and replacing multiple lines.

Steves
- 31st May 2009, 01:19
Thanks to you both. Roger your code works fine. I'll read thru your comments and revisit the data sheet for a better grasp of it all.;)