Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to use PIC10F220 ADC to set the length of a delay?

Status
Not open for further replies.

max0412

Full Member level 5
Full Member level 5
Joined
Oct 26, 2003
Messages
251
Helped
34
Reputation
66
Reaction score
5
Trophy points
1,298
Activity points
1,999
I want to use the ADC of the 10F220 to set the length of a delay. Could I use equate to define specific ranges of the ADC input to a number that would be inserted into the delay subroutine. Or should I use constant or is this all wrong and should I do it some other way.

Pseudo code
Code:
Sense ADC
IF ADC <=1       THEN K =10
IF ADC >1 <=2  THEN K=20
Where K is the variable I want passed to my delay loop counter.

Thanks
 

pic10f220 example

I would not use the ADC to create delays. Delays can easily be created in SW, without the need for and external timing network and ADC.

You can use TMR0 or simply software loops to create any delay you want.
 
  • Like
Reactions: g.smita

    max0412

    Points: 2
    Helpful Answer Positive Rating

    g.smita

    Points: 2
    Helpful Answer Positive Rating
tmr0 pic10f220

VVV said:
Delays can easily be created in SW, without the need for and external timing network and ADC.

Yes I realize that but I want the delay to be user selectable. The only way I can think of doing this is to use a POT with markers that the user could see off the ADC that a user can adjust for say 5ms to 20ms in 5ms increments. It doesn’t have to be precise.

I know I could use a more expensive PIC with keypad LCD screen but this is too expensive and to complicated for me right now.
 

pic 10f220 code

If you need to use a pot to set timing then ADC is a good way to. You can use a simplified form, such as a cap charged by a variable resistance, so when cap charges enough, it triggers the input port. If you have a few spare input ports, you could use a dil switch, a 4 way one could give you from 1-15 seconds etc for instance.
 

    max0412

    Points: 2
    Helpful Answer Positive Rating
p10f220.inc

What I had in mind is (see snippet below) is use the user selected value of the ADC, convert this to number and insert it in the delay routine below. The user can adjust the POT from the outside of the enclosure the POT will be marked at interval’s corresponding to delay lengths, printed on the enclosure. The value should be passed to “Number of times through delay2” currently it’s set at 4.

snippet

Code:
delay
      movlw   .4      ;Number of times through delay2 (Loop Counter)
      movwf   dc4

delay2
      movlw   .180    ;Offtime
      movwf   dc3
dly3
      decfsz  dc3,f
      goto    dly3

dly4
      decfsz  dc4,f
      goto    delay2
      goto    con


I thought when you used code tags formatting is supposed to be retained . Sorry it's a bit messy. Corrected thanks btbass.

If a user finds the delay to long or short they can adjust it by adjusting the POT on the adc.

Is there a way I can assign a number for an ADC range then have this number inserted in” Number of times through delay2”.

For example if the ADC voltage level is 0.5V to 1V insert 6 in the loop counter. If the ADC is greater then 1 and less then or equal to 1.5V insert 7 into the loop counter.

I’ve considered using cap’s but I figured this would offer better consistency.
 

pic10f220 source

OK, now I understand what you need to do.
I think the easiest way is this: your ADC will provide a number from 0 to 255, depending on the position of the pot. That is 256 steps.
You require a certain number of steps, say 8 or 16. It's nice to keep them powers of two. Let's assume you need 16 steps.
So you create a delay routine that gives you the step delay, say 5ms. Call it Dly_5ms. All you need now is a counter that counts how many 5ms delays to insert and you load that counter with a number based on the pot position.

So take the ADC reading, divide it by 16 and you get a number from 0 to 15. in other words, if the ADC reading is between 0 and 15 the result is 0, if it's between 16 and 31 the result is 1, and so on.

Add to that number a constant, depending on wha the minimum delay should be. For instance, if you need a min delay of 5ms, add 1, if the minimum delays has to be 25ms, then add 5. Check the result of the addition to make sure the maximum is not exceeded. For example, if the maximum delay is supposed to be 50ms, then make sure the number is not greater than 10.

If you need another number of steps, just divide the ADC reading by something else. If you keep the number of steps powers of two then you can divide by rrf instructions (Don't forget to clear the C flag before each rrf). In this code I used a trick to divide by 16 faster, but that is another story.

If you set the MAX to be smaller than the max # of steps will allow, then you reduce the number of steps, but the last portion of the pot will not be usable. See in the code below that MAX is set to 10. That gives you only 10 steps, but they will still be squeezed in the lower portion of the pot, not spread out evenly.
Increasing MIN will also reduce the # of steps, leaving more of the upper portion of the pot unusable.

From my experience with the 10F220 I can say you can safely have 64 steps with this approach. Anything more will be prone to errors due to ADC noise.
I recommend you use a 10K pot connected directly from Vdd to GND and a 0.1uF cap right on the ADC input.
Code:
MIN  EQU 1
MAX EQU 10

     swapf ADRES,W   ;get ADC reading, with nibbles swapped;
     andlw 0x0F      ;clear the upper 4 bits; these 2 instructions effectively divide by 16
     movwf Counter   ;save value in the delay counter
     movlw MIN       ;     
     addwf Counter,F ;ensure Counter has a minimum value greater than 0
     movlw MAX       ;now the checking
     subwf Counter,W ;check if Counter is greater than MAX
     btfsc STATUS,C  ;if not, we are OK
     goto Del        ;and go do the delay

     movlw MAX       ;else force Counter to MAX
     movwf Counter

Del: call Dly_5ms    ;delay 5ms
     decfsz Counter,F  ;done?
     goto Del        ;if not, keep going

Done: .........       ;here do what you need after the programmable delay
 

    max0412

    Points: 2
    Helpful Answer Positive Rating
Re: Using PIC10F220 ADC

Thanks for the detailed instruction. That is exactly what I was looking for.

I finally found some examples (Google) similar to what I wanted to do using look up tables,but I think the way you've shown is much more efficient.

These little PIC's are great! One little 6-SOT-23 PIC eliminates a lot of extra components.
 

Re: Using PIC10F220 ADC

I thought when you used code tags formatting is supposed to be retained . Sorry it's a bit messy

A little off topic but if you want to keep your formatting when using the code tags, dont use tabs in the source code file, convert the tabs to spaces.
 

    max0412

    Points: 2
    Helpful Answer Positive Rating
Re: Using PIC10F220 ADC

I'm having trouble trying to retrieve the value stored in "Counter" to use in my delay routine. I ran some simulations in PIC10F sim and it retrieves the address not the value stored at the address? It puts the address into the W register not the value stored there. See "HERE!!!!!! Below.

What am I doing wrong.

Edit - Nevermind I figured it out. I used the movfw comand. VVV the code you gave me for the ADC part works perfectly .Thank You


Code:
	list      p=10F220            ; list directive to define processor
	#include <p10F220.inc>        ; processor specific variable definitions

	__CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_OFF & _MCPU_OFF & _IOFSCS_4MHZ

;***** VARIABLE DEFINITIONS
TEMP_VAR    UDATA
count1   	res	1
count2   	res	1
count3  	res	1
count4  	res	1
count5  	res	1
count6  	res	1
count7  	res	1
count8  	res	1
count9  	res	1
Counter    res	1
cont1        res	1
cont2   	res	1
MIN          EQU 01h
MAX         EQU 0Ah  
   	   
;**********************************************************************
RESET_VECTOR	CODE   0xFF       ; processor reset vector

; Internal RC calibration value is placed at location 0xFF by Microchip
; as a movlw k, where the k is a literal value.

MAIN	CODE    0x000
	    movwf   OSCCAL            ; update register with factory cal value

;*******JUMP

   goto      MAIN
;*********Delay 20ms

delay20
     movwf         cont1              ;value stored at counter passed here
    movlw         .65
	movwf 	      count5
	movlw	      .237
	movwf	      count6

dloop1
    btfss         GPIO,0               ;Test for high GP0?
    goto          SENSE                ; No keep testing
    btfss         GPIO,3               ;Test for high on GP3?
    goto          SENSE                ; No keep testing
	decfsz    	  count6,f             ;still high continue with delay
	goto	      dloop1
	decfsz	      count5,f
	goto	      dloop1
    decfsz  	  cont1,f                  ;number of times through 20ms delay
    goto	      dloop1
	retlw	      0x00

;------ 500 mS delay at 4 MHz

"
'
'
;******************Delay 10us
'
'
;*****Start here
; This part configures  AN1 for analog. Extracts a value based on anolog reading and inserts this value in "Counter" . The value that is stored in "Counter is to be used in the 20mS delay later.
 
MAIN 
        
        movlw       b'10000101'         ;CONFIG adc: AN1 Analog input
        movwf       ADCON0  
        movlw       .20
        call        Delay10uS
        BSF         ADCON0, 1           ;start conversion
  
loop0 
        NOP
        BTFSC       ADCON0, 1            ;wait for ‘DONE’
        GOTO        loop0

        swapf       ADRES,W             ;get ADC reading, with nibbles swapped;
        andlw       0x0F                ;clear the upper 4 bits; effectively divide by 16
        movwf       Counter             ;save value in the delay counter
        movlw       MIN                 ;     
        addwf       Counter,F           ;ensure Counter has a minimum value greater than 0
        movlw       Counter                 ;now the checking
        subwf       MAX,W               ;check if Counter is greater than MAX
        btfss       STATUS,C            ;if not, we are OK
        goto        start               ;and go do the delay

        movlw       MAX                 ;else force Counter to MAX
        movwf       Counter 
	 
;****Turn off ADC Config GP2 for I/0 output
start 
        CLRF        ADCON0               ;ADC OFF      
        movlw       b'11011111'          ;clear tocs
        OPTION
        BCF         OSCCAL,FOSC4         ;GP2 as I/O !


        movlw       b'1011'              ;gp2 as output
        tris        GPIO
        CLRF        GPIO                 ;start GP2 LOW
        movlw       b'0000' 

;***********This part senses GP0 and GP3 for high if they are both high it passes the value stored at "Counter" to 20mS delay.The value stored at "Counter is supposed to set the amount of times the 20ms delay is done.

SENSE
        btfss       GPIO,0               ;Test for high GP0?
        goto        SENSE                ;No keep testing
        goto        $+1
        goto        $+1
        btfss       GPIO,3               ;Test for high on GP3?
        goto        SENSE                ;No keep testing
        movlw	    Counter              ;HERE !!!!!!!!!!! 
        call        delay20              ;Signal high on both inputs goto delay
        movlw	    .10                  ;Number of pulses counter                 
        movwf	    count8

;*****GP0 and GP3 Both high for dealy time start outputing 10 pulses at 1Hz.

ON
        bsf         GPIO,2               ;GP2 HIGH start outputing pulses 1Hz 10
        movlw       .1                   ;W x 500ms delay
        call        Delay500mS

;**********Off pulse time
Off
        bcf         GPIO,2               ;Gp2 low
        movlw       .1
        call        Delay500mS

        decfsz	    count8,f             ;Pulses counter
        goto        ON                   ;not done keep pulsing
        movlw       .1
        call        Delay500mS           ;provide delay for stabilization.
        goto        SENSE                ;done go back and start over

	    END                              ;directive 'end of program'

Heres the sim output window showing the w register getting the address of counter not the value 4 in this case, circled in red.

2aetldv.png
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top