Maker Pro
Maker Pro

PIC Assembly Code Not Working, PICKit2, Ultrasonic Sensor

Hello all!
I am trying to mess around with some electronics, and like it so far! Got a PICKit 2 with a PIC16f1824 to code on. And i got myself a breadboard, with some leds, wires and a ultrasonic sensor. The sensor has 2 pins, 1 for trigger, and 1 for echo. This is my assembly code, but it does not work. The red led does not light up, at all.
I can't see what i have done wrong.

The breadboard is working and all is connected correctly, as far as i can tell. I have tested with simply turning on and off leds.

The code i have so far:

Code:
#include <p16f1824.inc>

CBLOCK 0x70 ; DEFINE VARIABLES USED
d1
d2
d3
d4
Count
ENDC

ORG 0x00 ;RESET VECTOR

BANKSEL TRISA
movlw b'00000010' ;Setting all but RA1 to output, RA1 is input
movwf TRISA

MAINLOOP
CALL TRIG ;short burst to trigger pin
GOTO COUNT ;cout untill a signal is received
MLOOP
GOTO COUNTCHECK ;RA1, or echo, receives a signal, check how far
GOTO MAINLOOP

TRIG
CLRF Count
BANKSEL LATA
BSF LATA,0 ;trigger signal on
CALL Delay
BCF LATA,0 ;trigger signal off
RETURN

COUNT
INCF Count,1 ;increase by 1
CALL Delay ;delay 0.001 seconds
BANKSEL PORTA
BTFSS PORTA,1 ;checking if RA1 has recevied anything
GOTO COUNT ;loops
GOTO MLOOP ;RA1 received, go to main loop middle

COUNTCHECK
movlw d'6' ;gives w a value of 6
;movf Count,w ;
subwf Count,w ;count - w
BTFSC STATUS,C ;cheking c, is anything borrowed from w(nagative result) C is 0, nothing borrowed C is 1
;if result is 0, Z is 1(set), negative or positive is 0(clear)
GOTO REDLED ;turn on red led, Count is less than w(6) which means the obstacle is 1 meter away
GOTO GREENLED ;Count is larger than w(6), took more than 0.6 seconds before echo return, which means more than 1 meter away

REDLED
BANKSEL LATA
BCF LATA,3 ;turn off red led
BSF LATA,2 ;turn on green led
GOTO MAINLOOP ;go back to main loop, new trigger

GREENLED
BANKSEL LATA
BCF LATA,2 ;turn off green led
BSF LATA,3 ;turn on red led
GOTO MAINLOOP ;go back to main loop, new trigger

Delay ;1 millisecond, 0.001 seconds
;993 cycles
movlw    0xC6
movwf    d1
movlw    0x01
movwf    d2
Delay_0
decfsz    d1, f
goto    $+2
decfsz    d2, f
goto    Delay_0

;3 cycles
goto    $+1
nop

;4 cycles (including call)
return

END
 
Hi, and welcome to the forum.

Your code looks reasonably good, but I have a few suggestions and questions.

1. Learn how to use relocatable code. Absolute code will just get you in trouble.

2. You have not set any configuration bits. This should always be done in the code, so it is obvious to someone reading the code.

3. Your delay routine seems to assume 1uSec per instruction, or 4MHz clock. Are you using a 4 MHz crystal? If you are using the internal oscillator, the default is 500kHz, and you must set bits in the OSCCON register to change it.

4. Change your comment about comparing to 0.6 seconds to be 0.006 seconds, or 6 milliseconds.

But here is the likely solution to your problem. You cannot use a pin as a digital input unless you turn off the analog function for that pin. Add the following code during initialization

banksel ANSELA
clrf ANSELA

Look at section 12.2.2 in the datasheet to learn about this.

Bob
 
Thanks for the reply! Really appreciate some pointer!
I'm quite new as you probably understand :p

What do you mean by relocatable code?

I'll look into the other stuff. For some reason i thought the internal oscillator was sat to 4mhz as default :/
 
Thanks for the reply! Really appreciate some pointer!
I'm quite new as you probably understand :p

What do you mean by relocatable code?

I'll look into the other stuff. For some reason i thought the internal oscillator was sat to 4mhz as default :/
Relocatable code does not use absolute (numeric) addresses like you use in your code. You simply declare the data and the linker decides on the actual addresses. Read about it in the MPLAB ASM help. Once you get to more complex projects that have more than 1 file, it is the only way to go, so you might as well start out that way in the first place.

Bob
 
RA3 is input only and is normally used for reset line(MCLR). If not it can only be used for an input and you have to set this in CONFIG 1 to disable the reset function.
Adam
 
Thanks! Didn't even think about that. Changed to RC0 and RC1.
Made these additions, am i doing it right?

Code:
;----- CONFIG1 Options --------------------------------------------------
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_ON

;----- CONFIG2 Options --------------------------------------------------
__config _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_HI & _LVP_OFF

.....

BANKSEL OSCCON
movlw   B'01101000'
movwf   OSCCON
banksel ANSELA
clrf ANSELA

from what i can find, bit 6-3 should be 1101 for a 4mhz internal oscillator

progress! It appears to be working somewhat, the signal is sent and received. The red led turns on, even if there isn't any objects nearby. Also when it turns on, it never triggers again. I have a yellow led that blinks when it triggers
 
Last edited:
The changes look good. You might want to try blinking the yellow LED the number of times that you counted before seeing the return signal. This might tell you something.

Bob
 
Starting to look good, it now turns red when too close and green when far enough away. But my problem now is that it won't start a new trigger, so the led goes on, and nothing more. ideas?

Also, tried as you said bob and make a led do a blink job so i can see what the Count is.
But it doesnt blink
Does this look correct?:
Code:
Check2
banksel LATC
bsf LATC,2
call Delay
bcf LATC,2
decfsz Count
goto Check2
goto Ch2return

Ch2return goes back to the COUNTCHECK to check the STATUS,C
 
You need a call to Delay after the bcf in the code above. Otherwise it is off for only a few microseconds, which you would not see.

Post your whole program again and maybe I can help.

Bob
 
Ofcourse -.- because i loop back and clear it.
Here is entire now:

Code:
#include <p16f1824.inc>

;----- CONFIG1 Options --------------------------------------------------
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_ON

;----- CONFIG2 Options --------------------------------------------------
__config _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_HI & _LVP_OFF

CBLOCK 0x70 ; DEFINE VARIABLES USED
d1
d2
Count
Test
ENDC

ORG 0x00     ;RESET VECTOR

BANKSEL OSCCON
movlw   B'01101000'
movwf   OSCCON
;banksel ANSELA
;clrf ANSELA
BANKSEL TRISA
BCF TRISA,0
BSF TRISA,1
;movlw b'00000010' ;Setting all but RA1 to output, RA1 is input
;movwf TRISA
BANKSEL TRISC
BCF TRISC,0
BCF TRISC,1

MAINLOOP
banksel ANSELA
clrf ANSELA
CALL TRIG ;short burst to trigger pin
GOTO COUNT ;cout untill a signal is received
MLOOP
GOTO COUNTCHECK ;RA1, or echo, receives a signal, check how far
GOTO MAINLOOP

TRIG
CLRF Count
BANKSEL LATA
BSF LATA,0 ;trigger signal on
CALL Delay
BCF LATA,0 ;trigger signal off
RETURN

COUNT
INCF Count,1 ;increase by 1
CALL Delay ;delay 0.001 seconds
BANKSEL PORTA
BTFSS PORTA,1 ;checking if RA1 has recevied anything
GOTO COUNT ;loops
GOTO MLOOP ;RA1 received, go to main loop middle

COUNTCHECK
movlw d'6' ;gives w a value of 6
;movf Count,w ;
subwf Count,w ;count - w
goto Check2
Ch2return
BTFSS STATUS,C ;cheking c, is anything borrowed from w(nagative result) C is 0, nothing borrowed C is 1
;if result is 0, Z is 1(set), negative or positive is 0(clear)
GOTO REDLED ;turn on red led, Count is less than w(6) which means the obstacle is 1 meter away
GOTO GREENLED ;Count is larger than w(6), took more than 0.006 seconds before echo return, which means more than 1 meter away

Check2
banksel LATC
bsf LATC,2
call Delay
bcf LATC,2
call Delay
decfsz Count
goto Check2
goto Ch2return

GREENLED
BANKSEL LATC
BCF LATC,0 ;turn off red led
BSF LATC,1 ;turn on green led
GOTO MAINLOOP ;go back to main loop, new trigger

REDLED
BANKSEL LATC
BCF LATC,1 ;turn off green led
BSF LATC,0 ;turn on red led
GOTO MAINLOOP ;go back to main loop, new trigger

Delay       ;1 millisecond, 0.001 seconds
            ;993 cycles
    movlw    0xC6
    movwf    d1
    movlw    0x01
    movwf    d2
Delay_0
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    Delay_0

            ;3 cycles
    goto    $+1
    nop

            ;4 cycles (including call)
    return

END

See i forgot to set the TRISC for RA2, changed that, it only blinks once at Check2
 
Last edited:
Update:
It works! :D it actually works. But not nearly perfected. If the distance is too short or too long it stops working and get stuck. Any tips on how to develop this further? I want it to trigger a different pin on different lengths
 
Top