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.
'************************************************* ********
'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.