Problem programming a third ADC input on an PIC:16F88

Status
Not open for further replies.

Kai-Itza

New Member
After solving a previous problem with my fledging project of which can be seen in the link below, I've got on with the task of duplicating that solved code which is an ADC input featuring a 10kΩ LDR as a way of controlling the input depending on the level of light with an output being that of a simple LED.
I wanted to have more sensors on this so I duplicated areas of code and assigned more register locations for the data that would be processed later; as a way to create multiple ADC inputs, the second ADC input process went 'easy-as-pie' but when it came to the third and final ADC input, it acted all... weird.

Linky

The output that I got appeared at the wrong LED (pin RB0 instead of pin RB7) and even when at this location, the LED won't continue to stay on even after the 'threshold voltage'

It's obvious that I missed something here, something that I didn't pick up during my 'studying' of the 16F88's datasheet, or is it a perk of the 16F88 that I'm totally unaware of?

Can someone help me on this, please?

Thanks

Code:
; TUTAADC.INC 23MAR04
; illustrating use of ADC
;
;	Create  list file and select processor :
	list p = 16f88
;
#DEFINE BANK0 BCF STATUS,5
#DEFINE BANK1 BSF STATUS,5
#DEFINE BLOCK0 BCF STATUS,7             ; clear STATUS bit 7 (IRP)
#DEFINE BLOCK1 BSF STATUS,7             ; set   STATUS bit 7 (IRP)
;
#DEFINE CHAN0 iorlw B'00000000'
#DEFINE CHAN1 iorlw B'00001000'
#DEFINE CHAN2 iorlw B'00010000'
#DEFINE CHAN3 iorlw B'00011000'
#DEFINE CHAN4 iorlw B'00100000'
#DEFINE CHAN5 iorlw B'00101000'
#DEFINE CHAN6 iorlw B'00110000'
#DEFINE CHAN7 iorlw B'00111000'
;
;	Include file containing register labels:
	Include "p16f88.inc"
;
	CBLOCK
ADCLDR
ADCTH
ADCSMS
	ENDC
;
;
PORTA	EQU	H'05'
PORTB	EQU	H'06'
TRISB	EQU 	H'86'	; Port B direction register
TRISA	EQU 	H'85'	; Port A direction register
STATUS	EQU	H'03'	; STATUS register
z	EQU	2	;Zero flag
c	EQU	0
count 	EQU	H'20'	; assign General Purpose Register, Bank 0 for counter
valtes	EQU	H'35'	;testing value
totldr	EQU	h'36'
totth	EQU	h'2A'
totsm	EQU	h'2B'
half	EQU	h'2C'
hlvadc	EQU	h'2D'
;
	; set up code for 16F88 ports
	BSF	3,5		;switch to page 1
	CLRF	H'9b'		;clear ansel file - set ports to digital io
	BCF 	3,5		;switch to page 0
;
; *********** SETTING PORTA FOR ANALOGUE ***********
;
point                BLOCK0
                BANK1
                clrf	TRISB             ; PORTB as output
                movlw	B'00000000'       ; set Left justify, RA0, RA1, RA3 as analog inputs
                movwf	ADCON1            ; with RA, RE digital, ref to +VE and 0V
                movlw	B'11011011'       ; RA0, RA1, RA3, RA4 as input, RA2, RA5 as output
                movwf	TRISA
                BANK0
;
; *********** SETTING ADC CHANNEL AND READING ITS VALUE *****
;
part1         movlw	B'01000101'	; set AD on, Fosc/8
          CHAN0			; set for CHAN0 - RA0
          movwf	ADCON0
          call	DELAY          	; short delay following channel change
start1     bsf	ADCON0,GO       	; start data conversion
	call	DELAY
          call	GETADC          	; get ADC value
          goto	part2
;
; ******** GET ADC VALUE FROM SELECTED PORT PIN *****
;
GETADC          btfsc	ADCON0,GO
                goto	GETADC
                movf	ADRESH,W          ; get ADC MSB val
                movwf	ADCLDR            ; store it into ADCMSB
;
;
;******* TEST ADC VALUE AGAINST "DARK TIME" VALUE 
;
		movlw	d'102'
		movwf	valtes
;
		movf	ADCLDR, w
		subwf	valtes, totldr
		btfss	STATUS, c
		goto	ledon
		goto	ledoff
		return
;
;***************SETTING ADC CHANNEL AND READIN ITS VALUE (Thermistor)***************************************
;
part2         movlw	B'01000101'	; set AD on, Fosc/8
          	CHAN1			; set for CHAN1 - RA1
          	movwf	ADCON0
          	call	DELAY          	; short delay following channel change
start2     	bsf	ADCON0,GO       	; start data conversion
		call	DELAY
          	call	GETAC2          	; get ADC value
          	goto	part3
;
;**************GET ADC VALUE FROM SELECTED PORT PIN ANS1 (THERMISTOR)*********************************
;
GETAC2          btfsc	ADCON0,GO
                goto	GETAC2
                movf	ADRESH,w          ; get ADC MSB val
                movwf	ADCTH            ; store it into ADCTH
;
;***************TEST ADC VALUE AGAINST "HIGH TEMPERATURE" VALUE*************************************
;	
		movf	ADCTH, w
		subwf	valtes, totth
		btfss	STATUS, c
		goto	led12
		goto	led02		
		return
;
[COLOR="red"];****************SETTING ADC CHANNEL TO READ ITS VALUE (SOIL MOISTURE SENSOR)
;
part3        	movlw	B'01000101'	; set AD on, Fosc/8
	        	CHAN2			; set for CHAN3 - RA3
          	movwf	ADCON0
          	call	DELAY          	; short delay following channel change
start3     	bsf	ADCON0,GO       	; start data conversion
		call	DELAY
          	call	GETAC3          	; get ADC value
          	goto	part1
;
;**************GET ADC VALUE FROM SELECTED PORT PIN ANS1 (SOIL MOISTURE SENSOR)*********************************
;
GETAC3          btfsc	ADCON0,GO
                goto	GETAC3
                movf	ADRESH,w          ; get ADC MSB val
                movwf	ADCSMS            ; store it into ADCSMS
;
;***************TEST ADC VALUE AGAINST "HIGH TEMPERATURE" VALUE*************************************
;
		movf	ADCSMS, w
		subwf	valtes, totsm
		btfsc	STATUS, c
		goto	led13
		goto	led03		
		return[/COLOR]
;
;SUBROUTINE TO GET ANALOGUE INPUT - 20US SETTLING TIME.............
;
DELAY	movlw	d'007'		;time delay of 7x3=21us
	movwf	count		;load counter
again	decfsz	count		;decrement until zero
	goto 	again		;decrement until zero
	return
;
;******** If ZERO BIT IS ON, LED GOES ON ********
;
ledon	clrf	PORTB
	bsf	PORTB,0		; set Port B pin 0 to logic 
	goto	part2
;
ledoff	bcf	PORTB,0		; clear Port B pin 0 
	return
;
led12	clrf	PORTB
	bsf	PORTB,6		; set Port B pin 9 to logic 
	goto	part3
;
led02	bcf	PORTB,6		; clear Port B pin 9 
	return
;
led13	clrf	PORTB
	bsf	PORTB,7		; set Port B pin 8 to logic 
	goto	part1
;
led03	bcf	PORTB,7		; clear Port B pin 8 
	return
;
	END


The code of the third ADC can be seen on red

-Kai-Itza-
 
hi Kai,
The Oshonsoft simulator when running the program, stops at the third LED with a STACK over flow message, check the calls and returns....
 
hi Kai,
The Oshonsoft simulator when running the program, stops at the third LED with a STACK over flow message, check the calls and returns....

Thanks, Eric

I've checked the call and return instructions and, although there isn't many problems with the code there, I wasn't going to take any chances so I 'swapped' the call and return instructions with goto instructions instead, so far it seems to have done the trick.
I've ran through the program again and I've got absolutly no response from the third LED output and the other two worked OK, I've checked this line-for-line and still nothing from the third output, I know I'm missing something vital, but what exactly? I'm sorry if I'm being a nuisance but I'm literally clueless over this .

Thanks for your help so far!

Code:
; TUTAADC.INC 23MAR04
; illustrating use of ADC
;
;	Create  list file and select processor :
	list p = 16f88
;
#DEFINE BANK0 BCF STATUS,5
#DEFINE BANK1 BSF STATUS,5
#DEFINE BLOCK0 BCF STATUS,7             ; clear STATUS bit 7 (IRP)
#DEFINE BLOCK1 BSF STATUS,7             ; set   STATUS bit 7 (IRP)
;
#DEFINE CHAN0 iorlw B'00000000'
#DEFINE CHAN1 iorlw B'00001000'
#DEFINE CHAN2 iorlw B'00010000'
#DEFINE CHAN3 iorlw B'00011000'
#DEFINE CHAN4 iorlw B'00100000'
#DEFINE CHAN5 iorlw B'00101000'
#DEFINE CHAN6 iorlw B'00110000'
#DEFINE CHAN7 iorlw B'00111000'
;
;	Include file containing register labels:
	Include "p16f88.inc"
;
	CBLOCK
ADCLDR
ADCTH
ADCSMS
	ENDC
;
;
PORTA	EQU	H'05'
PORTB	EQU	H'06'
TRISB	EQU 	H'86'	; Port B direction register
TRISA	EQU 	H'85'	; Port A direction register
STATUS	EQU	H'03'	; STATUS register
z	EQU	2	;Zero flag
c	EQU	0
count 	EQU	H'20'	; assign General Purpose Register, Bank 0 for counter
valtes	EQU	H'35'	;testing value
totldr	EQU	h'36'
totth	EQU	h'2A'
totsm	EQU	h'2B'
half	EQU	h'2C'
hlvadc	EQU	h'2D'
;
	; set up code for 16F88 ports
	BSF	3,5		;switch to page 1
	CLRF	H'9b'		;clear ansel file - set ports to digital io
	BCF 	3,5		;switch to page 0
;
; *********** SETTING PORTA FOR ANALOGUE ***********
;
point                BLOCK0
                BANK1
                clrf	TRISB             ; PORTB as output
                movlw	B'00000000'       ; set Left justify, RA0, RA1, RA3 as analog inputs
                movwf	ADCON1            ; with RA, RE digital, ref to +VE and 0V
                movlw	B'11011011'       ; RA0, RA1, RA3, RA4 as input, RA2, RA5 as output
                movwf	TRISA
                BANK0
;
; *********** SETTING ADC CHANNEL AND READING ITS VALUE *****
;
part1         movlw	B'01000101'	; set AD on, Fosc/8
          CHAN0			; set for CHAN0 - RA0
          movwf	ADCON0
          call	DELAY          	; short delay following channel change
start1     bsf	ADCON0,GO       	; start data conversion
	call	DELAY
          goto	GETADC          	; get ADC value
;
; ******** GET ADC VALUE FROM SELECTED PORT PIN *****
;
GETADC          btfsc	ADCON0,GO
                goto	GETADC
                movf	ADRESH,W          ; get ADC MSB val
                movwf	ADCLDR            ; store it into ADCMSB
;
;
;******* TEST ADC VALUE AGAINST "DARK TIME" VALUE 
;
		movlw	d'102'
		movwf	valtes
;
		movf	ADCLDR, w
		subwf	valtes, totldr
		btfss	STATUS, c
		goto	ledon
		goto	ledoff
;
;***************SETTING ADC CHANNEL AND READIN ITS VALUE (Thermistor)***************************************
;
part2         movlw	B'01000101'	; set AD on, Fosc/8
          	CHAN1			; set for CHAN1 - RA1
          	movwf	ADCON0
          	call	DELAY          	; short delay following channel change
start2     	bsf	ADCON0,GO       	; start data conversion
		call	DELAY
          	goto	GETAC2          	; get ADC value
;
;**************GET ADC VALUE FROM SELECTED PORT PIN ANS1 (THERMISTOR)*********************************
;
GETAC2          btfsc	ADCON0,GO
                goto	GETAC2
                movf	ADRESH,w          ; get ADC MSB val
                movwf	ADCTH            ; store it into ADCTH
;
;***************TEST ADC VALUE AGAINST "HIGH TEMPERATURE" VALUE*************************************
;	
		movf	ADCTH, w
		subwf	valtes, totth
		btfss	STATUS, c
		goto	led12
		goto	led02		
;

;***************SETTING ADC CHANNEL AND READIN ITS VALUE (Thermistor)***************************************
;
part3         movlw	B'01000101'	; set AD on, Fosc/8
          	CHAN3			; set for CHAN1 - RA1
          	movwf	ADCON0
          	call	DELAY          	; short delay following channel change
start3     	bsf	ADCON0,GO       	; start data conversion
		call	DELAY
          	goto	GETAC3          	; get ADC value
;
;**************GET ADC VALUE FROM SELECTED PORT PIN ANS1 (THERMISTOR)*********************************
;
GETAC3          btfsc	ADCON0,GO
                goto	GETAC3
                movf	ADRESH,w          ; get ADC MSB val
                movwf	ADCSMS            ; store it into ADCTH
;
;***************TEST ADC VALUE AGAINST "HIGH TEMPERATURE" VALUE*************************************
;	
		movf	ADCSMS, w
		subwf	valtes, totsm
		btfss	STATUS, c
		goto	led12
		goto	led02
;
;SUBROUTINE TO GET ANALOGUE INPUT - 20US SETTLING TIME.............
;
DELAY	movlw	d'007'		;time delay of 7x3=21us
	movwf	count		;load counter
again	decfsz	count		;decrement until zero
	goto 	again		;decrement until zero
	return
;
;******** If ZERO BIT IS ON, LED GOES ON ********
;
ledon	clrf	PORTB
	bsf	PORTB,0		; set Port B pin 0 to logic 
	goto	part2
;
ledoff	bcf	PORTB,0		; clear Port B pin 0 
	goto	part2
;
led12	clrf	PORTB
	bsf	PORTB,5		; set Port B pin 9 to logic 
	goto	part3
;
led02	bcf	PORTB,5		; clear Port B pin 9 
	goto	part3
;
led13	clrf	PORTB
	bsf	PORTB,6		; set Port B pin 8 to logic 
	goto	part1
;
led03	bcf	PORTB,6		; clear Port B pin 8 
	goto	part1
;
	END


-Kai-Itza-
 
Last edited:
hi Kai,
I have copied your posted program, I will try again, let you know how it goes.
Code:
    movf    ADCLDR, w
   [B] subwf    valtes, totldr[/B] ; reg(35) - reg(36); You cannot subwf from reg(35) and store the result back into a different register(36).
The result must go back into (35) or W.
    btfss    STATUS, c
    goto    ledon
    goto    ledoff
 
Last edited:

I've made the changes and it looks like the outputs remain unchanged; the third LED is still not turning on as I turn the pot through its entire range, output 1 and 2 work perfectly fine. I've added "clear Carry flag" instructions as I've noticed that the Carry flag is still active as the program runs and still nothing, annoyingly enough. I've searched the internet for answers/examples; to see if there's something that I may have missed and (surprisingly) there's nothing to be found that could be of help.
I think it's the program itself that is missing something, although I am keeping an open mind here as there could be another handful of errors that my debugging software has continously failed to notice.

Eric, what do you see that's wrong in this program that my "newbie" eyes can't see? As it is truly intriuging and annoying in equal measure as I'm learning very little from this experience. The answer's out there and I can't seem to find/see it :lol:


-Kai-Itza-
 

hi Kai,
It seems that our assemblers are not fully compatible.
I will look in more detail at your program.

I would suggest that you are making the program over complicated.
Have you considered reading the 3 adc inputs in succession, saving each result and then comparing the fixed SET points with the actual adc values, setting the LED PORT bits high/low as you compare.

If you need a delay, place it at the end of these compares.

EDIT:
Look at this version of the 3 LDR/LED's, it works OK.
 

Attachments

  • ADC_lite_darkV2.asm
    3.1 KB · Views: 187
Last edited:
I've tested out the example program that you've shown me, Eric, and it works pretty well although with a few bugs.

I've tested this with three 10K potentiometers at each of the outputs (RA0, RA1, RA2), turning them up one-by-one until the led's are all on at outputs RB0, RB1 and RB2, it is only until I turn them down again thats when the bug shows, let's say the pot at RA0 which outputs at RB0; when this goes below the threshold voltage (90 decimal) the LED at RB0 turns off normally, but when turned all the way down so that the resistance is =0 ohms that the LED output RB1 also does off - even though its adjoining pot at RA1 is at it's maximum resistance of 10k!
The same goes for RA1, when the resistance of the pot is =0, LED RB2 goes out as well regardless of RA2's pots resistance.
RA2, when the resistance of the pot is =0, it turns back on again.

I've taken out the Configuration codes just to make this work, is this why I'm getting this behaviour from your program? Or have I wired it wrong?


-Kai-Itza-
 
Last edited:

hi Kai,
It could be your wiring or the pots.
Have you measured the actual voltage with a meter at the pins as you adjust the pots.??

Post a sketch.


EDIT:
If you are inputting zero volts on an adc pin, thats never going to happen in the actual LDR circuit .???

EDIT2:
I have just tried the program in the Sim, it works OK, down to 0V, no interaction on the LED's.???
 
Last edited:
It's OK now, after playing around with the circuit I managed to make it work. Turns out I wired it wrong.

Thanks,


-Kai-Itza-
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…