Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC ADC only measuring from 2.5V to 5V. Why?

Status
Not open for further replies.

riccardo

Member
Hi,

I'm trying to use the 8-bit result from an ADC to make a time delay. It is working except that time delay is only increasing after the input goes above 2.5V. The input is 0V to 5V from a 1k POT.

Any ideas why it would not start working until half way?

It is a 12F675, Main code below...

Code:
; ADC CONFIGURATION
	BCF STATUS,RP0 				; BANK 0
	BCF ADCON0, ADFM			; Left justified (clear and use just ADRESH for an 8bit result)
	BCF ADCON0, VCFG			; Vdd reference
	BCF ADCON0, CHS1			; Set AN0 as analogue input
	BCF ADCON0, CHS0			; Set AN0 as analogue input
	BSF STATUS,RP0 				; BANK 1
	MOVLW b'00010001'			; Fosc/8 (2us), AN0 is selected for reading
	MOVWF ANSEL

; The output pulse with delay
DISCHARGE
	BSF DISCHARG				; DISCHARGE
	CALL READPOT
	CALL WAITPOT
	BCF DISCHARG				; END DISCHARGE
	RETURN

; Get analogue input
READPOT
	BSF ADCON0, ADON			; Enable AD
	BSF ADCON0, GO				; Start AD conversion
AD	BTFSC ADCON0, GO			; TEST if conversion is finished
		GOTO AD					; Loop until conversion is done
	MOVF ADRESH, W				; High side byte from AD (8-bit)
	MOVWF POT					; Stores ns delay value in POT
	BCF ADCON0, ADON			; Disable AD
	RETURN

; Time dealy
WAITPOT
	INCF POT	; make sure not zero
WAITPOTL
	DECFSZ  POT,F		; Decrement POT
        GOTO WAITPOTL	; Loop until 0
	RETURN
 
deleted, error
 
Last edited:
Well one obvious thing is you're incrementing a variable (Pot) to make sure it's not zero, but if it was already 255, then you're making it zero.

I would suggest hanging a row of LED's on a spare port, and writing the value to it, to confirm the value is as expected.
 
Hi,

One thing disappoints me ...

Code:
; ADC CONFIGURATION
	BCF STATUS,RP0 				; BANK 0
	BCF ADCON0, ADFM			; Left justified (clear and use just ADRESH for an 8bit result)
	BCF ADCON0, VCFG			; Vdd reference
	BCF ADCON0, CHS1			; Set AN0 as analogue input
	BCF ADCON0, CHS0			; Set AN0 as analogue input
	BSF STATUS,RP0 				; BANK 1
	MOVLW b'00010001'			; Fosc/8 (2us), AN0 is selected for reading
	MOVWF ANSEL

you never go back to BANK 0 ... anywhere in your program ...

Alain
 
Last edited:
Nigel,
This does not cause a problem for me as the voltage input never quite gets to 5V and therefore wont get to 255.

Alain,
Yeah, I do. I had not shown the whole code here. Here's the whole thing...
Code:
		Processor       12F675
		Radix   DEC
		EXPAND
		include         "p12F675.inc"

; -- CONFIGURATION --

	__CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_OFF & _BODEN_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT 


; -- VARIABLES --
	CBLOCK 0x20
	L1
	L2
	L3
	POT
	TIME
	TEMP
	ENDC

	; INPUTS
	#define DUTYVOLT GPIO, AN0 ; (GP0)	#define CHARGEEN GPIO, GP1
	#define READYSIG GPIO, GP3
	#define POWERSWI GPIO, GP4
	#define HIGHTEMP GPIO, GP5
	; OUTPUTS
	#define CHARGEEN GPIO, GP1
	#define DISCHARG GPIO, GP2

; -- CONSTANTS --
	
relayTime EQU 255 ; Time in ms for relay to move

; BANK0 = TMR0, PCL, STATUS, FSR, GPIO, PCLATH, INTCON, PIR1, TMR1L, TMR1H, T1CON, CMCON, ADRESH, ADCON0
; BANK1 =  OPTION_REG, PCL, STATUS, FSR, TRISIO, PCLATH, INTCON, PIE1, PCON, OSCCAL, WPU, IOC, VRCON, EEDATA, EEADR, EECON1*, EECONT2, ADRESL, ANSEL
;*nOT PHYSICAL REGISTER


; -- MAIN PROGRAM INITILIZATION --
        ORG     0x000			; coding begins here

	; ANALOGUE CONFIG
	BCF STATUS,RP0 				; BANK 0
	BCF ADCON0, ADFM			; Left justified (clear and use just ADRESH for an 8bit result)
	BCF ADCON0, VCFG			; Vdd reference
	BCF ADCON0, CHS1			; Set AN0 as analogue input
	BCF ADCON0, CHS0			; Set AN0 as analogue input

	BSF STATUS,RP0 				; BANK 1
	MOVLW b'01010001'			; Fosc/16 (4us), AN0 is selected for reading
	MOVWF ANSEL

	; DIGITAL IO CONFIG	
	BCF STATUS,RP0 				; BANK 0
	CLRF GPIO					; Clear IO Data
	MOVLW b'00000111' 			; Set GPIO to (disables comparators)
	MOVWF CMCON 				; digital IO
	BSF STATUS,RP0 				; BANK 1
	MOVLW b'00111001'			; GP0, GP3:GP5 Inputs - GP1:GP2 Outputs
	MOVWF TRISIO				; Set IO's as Output

	BCF STATUS,RP0 				; BANK 0

; <-V INITILIZE V->
POWERON
	BCF CHARGEEN				; DISABLE Charging
	BCF DISCHARG				; DISABLE Discharge
	BTFSS POWERSWI				; IF power switch is ON THEN contiunue
		GOTO POWERON			; ELSE Loop until power on
PON	BTFSC POWERSWI				; IF power switch is OFF THEN contiunue
		GOTO PON				; ELSE Loop until switch is released

;  <-V Pulse output to indicate ready to go V->
	CALL FLASHLED3
	MOVLW 200					; Set delay in 100's mS
	MOVWF TIME
	CALL WAIT100MS
	CALL FLASHLED2
	MOVLW 200					; Set delay in 100's mS
	MOVWF TIME
	CALL WAIT100MS
	CALL FLASHLED
	MOVLW 250					; Set delay in 100's mS
	MOVWF TIME
	CALL WAIT100MS
	CALL WAIT100MS
	CALL WAIT100MS
	CALL WAIT100MS

; <-V MAIN LOOP V->
START
	BTFSC HIGHTEMP				; TEST for high temperature
		GOTO POWERON			; If too hot goto POWERON (Disables OUTPUTS)
	BSF CHARGEEN				; BEGIN CHARGING CAPACITOR
	BTFSC READYSIG				; TEST if capactor is charged
		CALL DISCHARGE			; If charged, disccharge it
	BTFSS POWERSWI				; TEST if power switch is ON
		GOTO START				; Loop if not pressed
POF	BTFSC POWERSWI				; TEST if power switch is OFF
		GOTO POF				; Loops until button is released
	GOTO POWEROFF				; Shut down

; <-V DISCHARGE PULSE V->
DISCHARGE
;	BCF CHARGEEN				; DISABLE Charging
	MOVLW relayTime				; Set delay in mS
	MOVWF TIME
	CALL WAIT100MS				; Small delay for relay to move
	CALL READPOT
	MOVF POT, W
	MOVWF TEMP					;Make temp copy of POT
	BSF DISCHARG				; DISCHARGE
	CALL WAITPOT
	MOVF TEMP, W
	MOVWF POT					;Restore temp copy of POT
	CALL WAITPOT
	BCF DISCHARG				; END DISCHARGE
	CALL WAIT100MS				; Small delay for relay to move
	CALL WAIT100MS				; Small delay for relay to move
	RETURN

READPOT
	CLRF ADCON0				; Reset A/D
	BSF ADCON0, ADON			; Enable AD
	BSF ADCON0, GO				; Start AD conversion
	MOVLW 1					; Set delay in mS
	MOVWF TIME
	CALL WAITMS
AD	BTFSC ADCON0, GO			; TEST if conversion is finished
		GOTO AD					; Loop until conversion is done
	MOVF ADRESH, W				; High side byte from AD (8-bit)
	MOVWF POT					; Stores ns delay value in POT
	BCF ADCON0, ADON			; Disable AD
	RETURN

; <-V POWER OFF / SHUTDOWN V->
POWEROFF
	BCF CHARGEEN				; DISABLE Charging
	MOVLW relayTime				; Set delay in mS
	MOVWF TIME
	CALL WAIT100MS				; Small delay for relay to move
	BSF DISCHARG				; DISCHARGE
	MOVLW 200					; Set delay in mS
	MOVWF TIME
	CALL WAITMS					; Small delay allowing capacitor to fully discharge
	CALL WAITMS					; Small delay allowing capacitor to fully discharge
	BCF DISCHARG				; STOP DISCHARGE
	CALL WAITMS					; Small delay allowing capacitor to fully discharge
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS					; Small delay allowing capacitor to fully discharge
	CALL WAITMS					; Small delay allowing capacitor to fully discharge
	GOTO POWERON				; Go back to start

FLASHLED
	BCF CHARGEEN				; DISABLE Charging
	MOVLW 100
	MOVWF TIME					; 10ms delay for WAITMS
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	RETURN

FLASHLED2
	BCF CHARGEEN				; DISABLE Charging
	MOVLW 100
	MOVWF TIME					; 10ms delay for WAITMS
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	RETURN

FLASHLED3
	BCF CHARGEEN				; DISABLE Charging
	MOVLW 100
	MOVWF TIME					; 10ms delay for WAITMS
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	CALL WAITMS
	BSF DISCHARG				; DISCHARGE
	CALL WAITMS
	BCF DISCHARG				; OFF
	RETURN

; <-V TIME DELAY ROUTINES V->
; Put number of msec delay needed into L1
WAITMS   						;MOVLW   10 				; 10 mS Delay (50Hz)
        MOVF TIME, W
		MOVWF   L1
Outer   MOVLW   200
        MOVWF   L2
Inner   NOP
        NOP
        DECFSZ  L2,F
        	GOTO    Inner		; Inner loop = 5 usec.
        DECFSZ  L1,F
        	GOTO    Outer
        RETURN

; Put number of 100 msec delay needed into L1
WAIT100MS
		MOVLW 10			; Loop 10 times
		MOVWF L3			
Loop1	MOVLW 10
		MOVWF TIME			; 10ms delay for WAITMS
		CALL WAITMS
		DECFSZ  L3,F		; Decrement L3
        	GOTO Loop1		; Loop until 0
		RETURN

; Shortest possile loop, loops numper of times from AD (1 to 255)
WAITPOT
	INCF POT, F
;	BTFSC STATUS,Z
;	DECF POT
WAITPOTL
	NOP
	NOP
	NOP
	NOP
	NOP
	DECFSZ  POT,F		; Decrement POT
        GOTO WAITPOTL	; Loop until 0
	RETURN

	END							; directive 'end of program'
 
Hi,

One thing disappoints me ...

you never go back to BANK 0 ... anywher in your program ...

That looks like it may be his problem, he's reading from ADRESL and not ADRESH because he's in the wrong bank. Because he's also in the wrong bank he's never checking ADCON0 for completion of the conversion, or indeed initiating the conversion.
 
Hi, Riccardo

I think you should let some µs ( 50 ? ) between resetting and validating the ADC ( both are not compulsory ! ) and start the conversion ...

simply try memoving the ADC reset + AD on commands and it should work as-is ...

Alain

PS: looks this Homework subject is in the air ... ROFL
 
Last edited:
simply try memoving the ADC reset + AD on commands and it should work as-is ...

Thanks! That did the trick.

I enabled the AD module in the startup code (instead of repeatedly just before using it), and removed the command that disables it. Now it works a treat!

Thanks for your help, that was really frustrating me!
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top