You are on page 1of 15

Linbot advanced line following robot

by : activerobot

Linbot is an advanced line tracer robot. It has one pair of infrared emitters and sensors directed forward, as well as
three pairs of infrared emitters and sensors directed downward. Linbot can follow a black line placed on a white floor
as well as a white line on a black floor.

When it meets with an obstacle while following the line, it makes a U-turn and continues on. It comes in kit form,
allowing the user to acquire hands on experience in robotic principles.

Features

PIC16F876(Microchip).
Two modes: Simple line-tracer mode.
Line-tracer with obstacle avoidance.
Four speed settings.
Trace a black line or a white line.(Selectable)
Pulse Width Modulation(PWM) motor control.
Intelligent line tracing.
-Continual Adjustment.
-If goes off the line, can find way back.
-Can handle intersecting lines.
-In-System Programming(ISP) port.
-Source program is available on the web.
-Downloadable free development tools(MPLAB : Assembler, Linker, Debugger).

Specifications

Item Description
SIZE 125.5 x 87 x 41(H) mm
CPU PIC16C876
SENSOR Bottom: Infrared emitter x 3, Infrared sensor x 3
Front: Infrared emitter x 1, Infrared sensor x 1
MOTOR MRM-GM03 Gearbox(DC Motor x 2)
SPEED 4 speed modes : 20 - 60 cm/s
BUZZER Piezo Buzzer(ALP1205S)
LED Sensor data indicator LED x 4
KEY Jumper switch x1, Push switch x 1
PORT ISP port for MPLAB-ICD
BATTERY AA x 4(not included)

;==================================================
;
; This file is a basic code for Linbot.
; Linbot is a intelegent line tracer.
; Linbot's CPU is a PIC16F876.
;
;==================================================
;
; Filename: LINBOT.ASM
; Date: Sept,2001
; File Version: 1.0
;
; Author: James Jeong
; Company: Microrobot(www.microrobot.com)
;
;===============================================

LIST P=16F876
#INCLUDE <P16F876.INC>

;; Macros.
BANK0 MACRO
BCF STATUS,RP1
BCF STATUS,RP0
ENDM

BANK1 MACRO
BCF STATUS,RP1
BSF STATUS,RP0
ENDM

BANK2 MACRO
BSF STATUS,RP1
BCF STATUS,RP0
ENDM

BANK3 MACRO
BSF STATUS,RP1
BSF STATUS,RP0
ENDM

TURN_ON MACRO ARG1,ARG2


BCF ARG1,ARG2 ; Bit Clear.
ENDM

TURN_OFF MACRO ARG1,ARG2


BSF ARG1,ARG2 ; Bit Set.
ENDM

;;; Tempolary register defination.

START_GPR EQU 0x20 ; Start of the General Purpose Register.


DELAY_CNT1 EQU START_GPR+0
DELAY_CNT2 EQU START_GPR+1
DELAY_STACK1 EQU START_GPR+2
DELAY_STACK2 EQU START_GPR+3

TEMP_STACK1 EQU START_GPR+4


TEMP_STACK2 EQU START_GPR+5
TEMP_STACK3 EQU START_GPR+6

;;; Register defination.

L_AD_REG EQU START_GPR+8


C_AD_REG EQU START_GPR+9
R_AD_REG EQU START_GPR+10
F_AD_REG EQU START_GPR+11
VR_AD_REG EQU START_GPR+12
FRONT_REF_REG EQU START_GPR+13
SENSOR_REG EQU START_GPR+14
HISTORY_REG EQU START_GPR+15

;;; Each bit defination of the register.

#DEFINE PRE_OP_FLAG HISTORY_REG,0 ; Previous Operation.

#DEFINE LEFT_FLAG SENSOR_REG,0 ; AD


#DEFINE CENTER_FLAG SENSOR_REG,1 ; AD
#DEFINE RIGHT_FLAG SENSOR_REG,2 ; AD
#DEFINE FRONT_FLAG SENSOR_REG,3 ; AD
;;; Port pin defination.

#DEFINE LEFT_AD_IN PORTA,0 ; AN0


#DEFINE CENTER_AD_IN PORTA,1 ; AN1
#DEFINE RIGHT_AD_IN PORTA,2 ; AN2
#DEFINE FRONT_AD_IN PORTA,3 ; AN3
#DEFINE BUZZER_OUT PORTA,4 ; BUZZER
#DEFINE REF_AD_IN PORTA,5 ; REFRENCE VOLTAGE AN4

#DEFINE PUSH_SW_IN PORTB,0 ; PUSH SWITCH


#DEFINE JUMPER_SW_IN PORTB,1 ; JUMPER SWITCH
#DEFINE FRONT_IR_OUT PORTB,2 ; INFRARED LED
#DEFINE RIGHT_IR_OUT PORTB,3 ; INFRARED LED
#DEFINE CENTER_IR_OUT PORTB,4 ; INFRARED LED
#DEFINE LEFT_IR_OUT PORTB,5 ; INFRARED LED

#DEFINE RM_IN2_OUT PORTC,0 ; RIGHT MOTOR IN2 (RIGHT MOTOR CONTROLS LEFT WHEEL.)
#DEFINE RM_IN1_OUT PORTC,1 ; RIGHT MOTOR IN1
#DEFINE LM_IN1_OUT PORTC,2 ; LEFT MOTOR IN1 (LEFT MOTOR CONTROLS RIGHT WHEEL.)
#DEFINE LM_IN2_OUT PORTC,3 ; LEFT MOTOR IN2
#DEFINE FRONT_LED_OUT PORTC,4 ; LED
#DEFINE RIGHT_LED_OUT PORTC,5 ; LED
#DEFINE CENTER_LED_OUT PORTC,6 ; LED
#DEFINE LEFT_LED_OUT PORTC,7 ; LED

;;; Constant defination.

#DEFINE PWM_HIGH .115


#DEFINE PWM_LOW .20
#DEFINE PWM_VLOW .5

;=============================================

ORG 0X000 ; PROCESSOR RESET VECTOR


NOP ; FOR ICE
GOTO START ; GO TO BEGINNING OF PROGRAM

ORG 0X004 ; INTERRUPT VECTOR


GOTO ISR

;=============================================

ISR
RETFIE
;=============================================

START
CALL INIT_PORT
CALL INIT_ADC
CALL INIT_PWM

CALL START_SIGN

MOVLW .50
MOVWF FRONT_REF_REG

;;

MAIN
CALL READ_LEFT
CALL DELAY_1MS
CALL READ_CENTER
CALL DELAY_1MS
CALL READ_RIGHT
CALL DELAY_1MS
CALL READ_VR
CALL READ_FRONT

CLRF SENSOR_REG ; CLEAR SENSOR_REG

MOVF L_AD_REG,W
SUBWF VR_AD_REG,W ; VR - L_AD_REG
BTFSC STATUS,C
BSF LEFT_FLAG ; IF L_AD_REG > VR_AD_REG THEN SET FLAG.

MOVF C_AD_REG,W
SUBWF VR_AD_REG,W
BTFSC STATUS,C
BSF CENTER_FLAG ; IF C_AD_REG > VR_AD_REG THEN SET FLAG.

MOVF R_AD_REG,W
SUBWF VR_AD_REG,W
BTFSC STATUS,C
BSF RIGHT_FLAG ; IF R_AD_REG > VR_AD_REG THEN SET FLAG.

MOVF F_AD_REG,W
SUBWF FRONT_REF_REG,W
BTFSS STATUS,C
BSF FRONT_FLAG ; IF F_AD_REG > VR_AD_REG THEN SET FLAG.

TURN_OFF LEFT_LED_OUT
TURN_OFF CENTER_LED_OUT
TURN_OFF RIGHT_LED_OUT
TURN_OFF FRONT_LED_OUT

BTFSC LEFT_FLAG
TURN_ON LEFT_LED_OUT

BTFSC CENTER_FLAG
TURN_ON CENTER_LED_OUT

BTFSC RIGHT_FLAG
TURN_ON RIGHT_LED_OUT

BTFSC FRONT_FLAG
TURN_ON FRONT_LED_OUT
CALL DELAY_1MS

MOVLW B'00000111' ;
ANDWF SENSOR_REG,W ;
ADDWF PCL ; JUMP WITH TABLE.
GOTO NO_LINE ;0
GOTO LEFT_LINE ;1
GOTO CENTER_LINE ;2
GOTO LEFT_CENTER_LINE ;3
GOTO RIGHT_LINE ;4
GOTO NUL_LINE ;5
GOTO RIGHT_CENTER_LINE ;6
GOTO CENTER_LINE ;7

NO_LINE BTFSC PRE_OP_FLAG


GOTO LEFT_LINE
GOTO RIGHT_LINE

GOTO MAIN
LEFT_LINE CALL LEFT_SMALL
BSF PRE_OP_FLAG ; PRE_OP_FLAG=1
GOTO MAIN
CENTER_LINE CALL GO1
GOTO MAIN
LEFT_CENTER_LINE CALL LEFT_VSMALL
GOTO MAIN
RIGHT_LINE CALL RIGHT_SMALL
BCF PRE_OP_FLAG ; PRE_OP_FLAG=0
GOTO MAIN
NUL_LINE CALL GO1
GOTO MAIN
RIGHT_CENTER_LINE CALL RIGHT_VSMALL
GOTO MAIN

;==========================================

DELAY_10US
GOTO $+1
GOTO $+1
RETURN

;===========================================

DELAY_50US
MOVWF DELAY_STACK1
MOVLW .15
MOVWF DELAY_CNT1
D_50US_1
DECFSZ DELAY_CNT1
GOTO D_50US_1
MOVF DELAY_STACK1,W
RETURN

;===========================================

DELAY_100US
MOVWF DELAY_STACK1
MOVLW .30
MOVWF DELAY_CNT1
D_100US_1
DECFSZ DELAY_CNT1
GOTO D_100US_1
MOVF DELAY_STACK1,W
RETURN

;===========================================

DELAY_500US
MOVWF DELAY_STACK1
MOVLW .164
MOVWF DELAY_CNT1
D_500US_1
DECFSZ DELAY_CNT1
GOTO D_500US_1
MOVF DELAY_STACK1,W
RETURN

;===========================================

DELAY_1MS
MOVWF DELAY_STACK1
MOVLW .198
MOVWF DELAY_CNT1
D_1MS_1
GOTO $+1
DECFSZ DELAY_CNT1
GOTO D_1MS_1
MOVF DELAY_STACK1,W
RETURN

;===========================================

DELAY_5MS
CALL DELAY_1MS
CALL DELAY_1MS
CALL DELAY_1MS
CALL DELAY_1MS
CALL DELAY_1MS
RETURN

;===========================================

DELAY_50MS
MOVWF DELAY_STACK2
MOVLW .50
MOVWF DELAY_CNT2
D_50MS_1
CALL DELAY_1MS
DECFSZ DELAY_CNT2
GOTO D_50MS_1
MOVF DELAY_STACK2,W
RETURN

;===========================================

DELAY_100MS
MOVWF DELAY_STACK2
MOVLW .100
MOVWF DELAY_CNT2
D_100MS_1
CALL DELAY_1MS
DECFSZ DELAY_CNT2
GOTO D_100MS_1
MOVF DELAY_STACK2,W
RETURN

;===========================================

DELAY_500MS
CALL DELAY_100MS
CALL DELAY_100MS
CALL DELAY_100MS
CALL DELAY_100MS
CALL DELAY_100MS
RETURN

;===========================================

DELAY
MOVWF DELAY_CNT2
DELAY_LOOP1
CALL DELAY_1MS
DECFSZ DELAY_CNT2
GOTO DELAY_LOOP1
RETURN

;=======================================

INIT_PORT
BANKSEL PORTA

MOVLW B'11111111' ; BUZZER OFF


MOVWF PORTA

MOVLW B'11111111' ; IRLEDs OFF


MOVWF PORTB

MOVLW B'11110000' ; LEDs(1111) & MOTORs(0000) OFF


MOVWF PORTC

BANKSEL TRISC
MOVLW B'00000000'
MOVWF TRISC
MOVLW B'11000011'
MOVWF TRISB
BCF OPTION_REG,NOT_RBPU ; PULL UP PORTB
; FOR PUSH AND JUMPER SWs INPUT.

MOVLW B'00101111'
MOVWF TRISA

BANK0
RETURN

;===========================
;===========================

INIT_ADC
BANKSEL ADCON0
MOVLW B'01000001' ; FOSC/8, AN0, A/D IS TURNED ON.
MOVWF ADCON0

BANKSEL ADCON1
MOVLW B'00000010' ; LEFT JUSTIFIED. AD=AN0~AN5. REF=VDD,VSS.
MOVWF ADCON1

BANK0
RETURN

;=============================================

INIT_PWM
BANKSEL T2CON
MOVLW B'00000101'
MOVWF T2CON ; PRESCALER =4, POSTSCALER =1:1
; TIMER2 ON
; TIMER2 CLOCK = 0.25MHz

MOVLW B'00001111'
MOVWF CCP1CON ; 2 LSBS=0, PWM MODE
MOVWF CCP2CON ; 2 LSBS=0, PWM MODE

BANKSEL PR2
MOVLW 0XFF
MOVWF PR2 ; PERIOD = 980HZ = 250000/255

BANKSEL CCPR1L
MOVLW 0X00 ; STOP RIGHT WHEEL(LEFT MOTOR)
MOVWF CCPR1L ; PWM DUTY CYCLE REGISTER
MOVLW 0X00 ; STOP LEFT WHEEL(RIGHT MOTOR)
MOVWF CCPR2L ; PWM DUTY CYCLE REGISTER

RETURN

;========================================
;========================================

START_SIGN
BANK0
TURN_ON BUZZER_OUT
TURN_ON LEFT_LED_OUT
CALL DELAY_100MS
TURN_OFF BUZZER_OUT
CALL DELAY_100MS
TURN_OFF LEFT_LED_OUT
TURN_ON CENTER_LED_OUT
CALL DELAY_100MS
CALL DELAY_100MS
TURN_OFF CENTER_LED_OUT
TURN_ON RIGHT_LED_OUT
CALL DELAY_100MS
CALL DELAY_100MS
TURN_OFF RIGHT_LED_OUT

RETURN

;=====================================

READ_FRONT
BANKSEL ADCON0
MOVLW B'01011001' ; FOSC/8, AN3, A/D IS TURNED ON.
MOVWF ADCON0
TURN_ON FRONT_IR_OUT
CALL DELAY_50US
TURN_OFF FRONT_IR_OUT
BSF ADCON0,GO_DONE
R_F_1
BTFSC ADCON0,GO_DONE
GOTO R_F_1
MOVF ADRESH,W
MOVWF F_AD_REG

BANK0
RETURN
;=====================================

READ_LEFT
BANKSEL ADCON0
MOVLW B'01000001' ; FOSC/8, AN0, A/D IS TURNED ON.
MOVWF ADCON0
TURN_ON LEFT_IR_OUT
CALL DELAY_10US
CALL DELAY_10US
TURN_OFF LEFT_IR_OUT
BSF ADCON0,GO_DONE
R_L_1
BTFSC ADCON0,GO_DONE
GOTO R_L_1
MOVF ADRESH,W
MOVWF L_AD_REG

BANK0
RETURN

;======================================

READ_CENTER
BANKSEL ADCON0
MOVLW B'01001001' ; FOSC/8, AN1, A/D IS TURNED ON
MOVWF ADCON0
TURN_ON CENTER_IR_OUT
CALL DELAY_10US
CALL DELAY_10US
TURN_OFF CENTER_IR_OUT
BSF ADCON0,GO_DONE
R_C_1
BTFSC ADCON0,GO_DONE
GOTO R_C_1
MOVF ADRESH,W
MOVWF C_AD_REG

BANK0
RETURN

;====================================

READ_RIGHT
BANKSEL ADCON0
MOVLW B'01010001' ; FOSC/8, AN2, A/D IS TURNED ON
MOVWF ADCON0
TURN_ON RIGHT_IR_OUT
CALL DELAY_10US
CALL DELAY_10US
TURN_OFF RIGHT_IR_OUT
BSF ADCON0,GO_DONE
R_R_1
BTFSC ADCON0,GO_DONE
GOTO R_R_1
MOVF ADRESH,W
MOVWF R_AD_REG

BANK0
RETURN

;======================================

READ_VR
BANKSEL ADCON0
MOVLW B'01100001' ; FOSC/8, AN0, A/D IS TURNED ON
MOVWF ADCON0
CALL DELAY_10US
CALL DELAY_10US
BSF ADCON0,GO_DONE
R_V_1
BTFSC ADCON0,GO_DONE
GOTO R_V_1
MOVF ADRESH,W
MOVWF VR_AD_REG

BANK0
RETURN

;=======================================

SET_STOP
BANKSEL CCPR1L
MOVLW 0X00 ; PWM = 0
MOVWF CCPR1L ;

MOVLW 0X00 ; PWM = 0


MOVWF CCPR2L ;

RETURN

;=======================================
GO1

BANKSEL CCPR1L
MOVLW PWM_HIGH ;
MOVWF CCPR1L ;

MOVLW PWM_HIGH ;
MOVWF CCPR2L ;
BANK0

RETURN

;====================================

LEFT_SMALL

BANKSEL CCPR1L
MOVLW PWM_HIGH ;
MOVWF CCPR1L ;

MOVLW PWM_LOW ;
MOVWF CCPR2L ;
BANK0

RETURN

;====================================

LEFT_VSMALL

BANKSEL CCPR1L
MOVLW PWM_HIGH ;
MOVWF CCPR1L ;

MOVLW PWM_VLOW ;
MOVWF CCPR2L ;
BANK0

RETURN

;===================================

RIGHT_SMALL
BANKSEL CCPR1L
MOVLW PWM_LOW
MOVWF CCPR1L ;

MOVLW PWM_HIGH ;
MOVWF CCPR2L ;
BANK0

RETURN

;======================================

RIGHT_VSMALL

BANKSEL CCPR1L
MOVLW PWM_VLOW
MOVWF CCPR1L ;

MOVLW PWM_HIGH ;
MOVWF CCPR2L ;
BANK0

RETURN

;=====================================

END ; End of Program

;=====================================

You might also like