PDA

View Full Version : PIC16F877A for application in mobile robot...



mcbeasleyjr
- 30th January 2009, 07:24
A friend and I have been working on a robot for a while now. It started as a senior design project in college. As our knowledge of the PIC grew, we made certain improvements to the project such as changing from the PIC16F628A to the PIC16F877A. Currently, my partners robot is fully functional. I am providing my entire code for you to look over and maybe use yourself at some point. The only problem that I am currently faced with is the fact that my ADC doesn't seem to be functioning. I'm going to be purchasing another 877a to be certain of this. Enjoy!



'************************************************* ********
'Identify all defines for crystal, LCD display, and ADC
'************************************************* ********
DEFINE OSC 20 ' Define 20MHz Oscillator
DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 3 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 2 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 2 ' Set number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Set command delay time in us
DEFINE LCD_DATAUS 50 ' Set data delay time in us
'DEFINE ADC_BITS 10 ' Defines number of adc bits (o - 255 output)
'DEFINE ADC_CLOCK 3 ' ADC clock speed
'DEFINE ADC_SAMPLEUS 1 ' How often the adc samples inputs

'************************************************* ********
'Declaring all variables and alias's
'************************************************* ********
OBJECTSTATUS VAR BYTE ' Variable for object detection
'BATVOLTAGE VAR WORD ' Variable for battery voltage
'BAT_DIGIT VAR BYTE ' Variable for voltage digits before decimal
'BAT_DEC VAR BYTE ' Variable for voltage digits after decimal
A VAR BYTE ' Loop variable for right object detection
B VAR BYTE ' Loop variable for left object detection
'FPC VAR WORD ' Variable for Front Photocell on ADCIN 1
'RPC VAR WORD ' Variable for Rear Photocell on ADCIN 2
'LPC VAR WORD ' Variable for Left Photocell on ADCIN 3
'RIPC VAR WORD ' Variable for Right Photocell on ADCIN 4
RIGHT_IRLED VAR PORTD.0 ' Alias Right_Irled to PortD.0
LEFT_IRLED VAR PORTD.1 ' Alias Left_Irled to PortD.1
IR_RECEIVER VAR PORTD.2 ' Alias Ir_Receiver to PortD.2
PAUSE 1000 ' Pause 1 second to allow power to stabilize

'************************************************* ********
'Configurations for all ports on PIC16F877A.
'************************************************* ********
ADCON1 = %10000010 ' ADC configuration
TRISA = %11111111 ' Configure PortA
TRISB = %00000000 ' Configure PortB
TRISC = %10000000 ' Configure PortC
TRISD = %00000100 ' Configure PortD
TRISE = %00000000 ' Configure PortE

'************************************************* ********
'This is the main loop of the program. It calls all the subroutines for
'their operations and then continues from where it called them. It uses
'variables determined by the subroutines to search for objects, find
'distance to objects, and eventually, check for light sources and charge
'the batteries.
'************************************************* ********

MAIN:

'Read the battery voltage (NO LONGER WORKING)
' GOSUB CHECK_BATTERIES ' Check the battery voltage
' PAUSE 100 ' Allow time for samples

'Check light sources (IS NOT WORKING PROPERLY)
' GOSUB CHECK_LIGHT
' PAUSE 100

'Look for objects and move the robot accordingly
GOSUB CHECK_RIGHT ' Check for object on right
PAUSE 100 ' Allow time for signal
GOSUB CHECK_LEFT ' Check for object on left
PAUSE 100 ' Allow time for signal
IF (OBJECTSTATUS.0 = 0 && OBJECTSTATUS.1 = 0) THEN GOSUB FORWARD
IF (OBJECTSTATUS.0 = 1 && OBJECTSTATUS.1 = 0) THEN GOSUB LEFT
IF (OBJECTSTATUS.0 = 0 && OBJECTSTATUS.1 = 1) THEN GOSUB RIGHT
IF (OBJECTSTATUS.0 = 1 && OBJECTSTATUS.1 = 1) THEN GOSUB BACK
GOTO MAIN

'************************************************* ********
'This subroutine is used to measure the voltage remaining on the batteries.
'If this voltage reaches a certain point, it will tell the robot to find
'the brightest light and charge itself. This is still experimental as I
'have not determined how to implement solar technology. However, I can
'use this subroutine to just calculate the voltage and display it on LCD.
'Also, at this point in time, this has stopped working due to problems with
'the ADC on my PIC.
'************************************************* ********
'CHECK_BATTERIES: ' Check for the current battery voltage
' ADCIN 0, BATVOLTAGE ' Store the 10-bit conversion in variable
' BATVOLTAGE = BATVOLTAGE * 3
' BAT_DIGIT = (BATVOLTAGE * 5) / 1000
' BAT_DEC = (BATVOLTAGE * 5) - (BAT_DIGIT * 1000)
' LCDOUT $FE, 1 ' Clear display
' LCDOUT $FE, 2 ' Return home (beginning of first line)
' LCDOUT $FE, $0C ' Cursor Off
' LCDOUT "VOLTS: ", DEC BAT_DIGIT, ".", DEC BAT_DEC, "V"
' PAUSE 500
' IF (BAT_DIGIT <= 6) THEN GOSUB CHECK_LIGHT
'RETURN

'************************************************* ********
'As my ADC doesn't seem to be working properly, this does not work.
'************************************************* ********
'CHECK_LIGHT: ' Check for brightest light
' ADCIN 1, FPC ' Get input from front photocell
' ADCIN 2, RPC ' Get input from rear photocell
' ADCIN 3, LPC ' Get input from left photocell
' ADCIN 4, RIPC ' Get input from right photocell
' IF (FPC > RPC) && (FPC > LPC) && (FPC > RIPC) THEN GOSUB FORWARD
' IF (RPC > FPC) && (RPC > LPC) && (RPC > RIPC) THEN GOSUB BACK
' IF (LPC > FPC) && (LPC > RPC) && (LPC > RIPC) THEN GOSUB LEFT
' IF (RIPC > LPC) && (RIPC > RPC) && (RIPC > LPC) THEN GOSUB RIGHT
' IF (FPC == RPC == LPC == RIPC) THEN GOSUB CALC
'RETURN

'************************************************* ********
'Object Detection subroutines
'************************************************* ********
CHECK_RIGHT: ' Check for objects on right
FOR A = 1 TO 50 ' Execute for C 50 times
HIGH RIGHT_IRLED ' Sending this high and low for 13us generates
PAUSEUS 13 ' roughly a 38khz signal. Leaves PWM open for
LOW RIGHT_IRLED ' use with another application. This will
PAUSEUS 13 ' generate at roughly 38khz for 50 cycles.
IF (IR_RECEIVER == 0) THEN OBJECTSTATUS.0 = 1
IF (IR_RECEIVER == 1) THEN OBJECTSTATUS.0 = 0
NEXT A '
RETURN

CHECK_LEFT: ' Check for objects on left
FOR B = 1 TO 50 ' Execute for D 50 times
HIGH LEFT_IRLED ' Same operation as with the right irled.
PAUSEUS 13 '
LOW LEFT_IRLED '
PAUSEUS 13 '
IF (IR_RECEIVER == 0) THEN OBJECTSTATUS.1 = 1
IF (IR_RECEIVER == 1) THEN OBJECTSTATUS.1 = 0
NEXT B '
RETURN

'************************************************* ********
'Motor control subroutines. As is, it is configured for 4 wheel drive.
'Two H-Bridges are implemented with two sets of Tamirya Gearbox Motors.
'************************************************* ********
FORWARD: ' Move forward
HIGH PORTD.4
LOW PORTD.5
HIGH PORTD.6
LOW PORTD.7
RETURN

LEFT: ' Turn left
LOW PORTD.4
HIGH PORTD.5
HIGH PORTD.6
LOW PORTD.7
RETURN

RIGHT: ' Turn right
HIGH PORTD.4
LOW PORTD.5
LOW PORTD.6
HIGH PORTD.7
RETURN

BACK: ' Back up
LOW PORTD.4
HIGH PORTD.5
LOW PORTD.6
HIGH PORTD.7
RETURN

'NOGO: ' Stop
' LOW PORTD.4
' LOW PORTD.5
' LOW PORTD.6
' LOW PORTD.7
'RETURN

'************************************************* ********
'This subroutine calculates the percentage of light that the CDS_Photocells
'are receiving in. If it is above 80% it will stop the robot to allow the
'batteries to charge.
'************************************************* ********
'CALC: ' Determine whether to keep searching or stop
'IF (FPC < %11110011) THEN GOSUB FORWARD 'light less than 80%
'IF (FPC >= %11110011) THEN GOSUB NOGO 'light more or equal to 80%
'RETURN
END

If anyone thinks that they may be able to help me with my ADC problem, please let me know. Thanks to all.

mackrackit
- 30th January 2009, 07:57
Take a look at this
http://www.rentron.com/PICX2.htm
I never liked the ADCIN command.

And or you may want to try 8 bit, just to see what happens.

mister_e
- 30th January 2009, 14:15
Problem may at least be in this line

DEFINE ADC_SAMPLEUS 1 ' How often the adc samples inputs

This is WAY too short as a sampling time unless you're using a REALLY small input impedance.

As usual, schematic would help.

mcbeasleyjr
- 30th January 2009, 14:28
I have attached a schematic of what my circuit looks like. However, I have switched the 100 ohm resistors with 10k resistors and swapped the positions of the resistors with the photocells.

Basically,

Vcc---->Photocell---->PIC's ADC<----10K resistor---->Gnd

Please keep in mind that this is already working on my partners robot. For some reason, all of a sudden the other day my ADC variables just stopped storing the correct values. For instance, I was able to use the battery voltage routine in my program to measure the total voltage of my circuit (i.e., up to 15v i believe). Of course that had to go through a voltage divider which i used 3 10k resistors and simply multiplied my variable by 3 and a few other things during calculation to get my result. This was working until a few days ago and now I can't seem to get anything right using my ADC. So far, everything else works fine (i.e., i can blink 8 leds on all 8 bits of PORTB).

mister_e
- 30th January 2009, 14:39
so I would say it's possible that you have burned the ADC section for some odd reasons.

mcbeasleyjr
- 30th January 2009, 14:47
that's what i'm thinking but i'm not entirely certain... i've tried a couple of different things but to no avail so far...