Trying to add a sleep function or pretend to sleep


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    May 2009
    Location
    Montreal, QC, Canada
    Posts
    118

    Default Trying to add a sleep function or pretend to sleep

    Hi,

    I have built a simple Ultrasonic distance measurement with a user defined zero setting
    and user interface is like a traffic light so Red = Red, Green = Green and Yellow = Green+Red.

    I am however scratching my head as I am trying to add a functionality.
    As it is presently, I always have One or two LEDs ON but I would like to have all OFF if after 1 minute I detect no change or a change of less than 2 or 3 units.
    Note: I calculate the distance by units as I don't really care if a unit is 1 inch, 1 foot or 1 cm but my testing shows that one unit is approx half an inch.

    This is my complete code so if anyone can guide me that would be great.
    Code:
    @ __config _XT_OSC & _WDT_OFF & _MCLRE_ON & _LVP_OFF & _CP_OFF
    
    Clear
    DEFINE OSC 4
    
    TRISA       = $07               
    TRISB       = $05  
    CMCON       = $06
    INTCON      = $10
    OPTION_REG  = $C0
    
    UserSetting    VAR WORD		
    Counter        VAR BYTE
    SampleValue    VAR WORD
    DataA          VAR WORD
    RawData        VAR WORD [16]
    Upd            VAR BIT
    
               
    READ 0,WORD UserSetting 	; get user setting
    IF UserSetting = 65535 then UserSetting = 0
    
    Counter = 0
    SampleValue = 0
    Upd = 0
    TMR1H = $B1:TMR1L = $E7		; adjust timer1 to 50Hz @ 4MHz Prescale = 1
    
    ; -----------------Power on self test sound ---------------------
    sound PORTB.1,[90,5,100,5,105,5,90,5,100,5,105,5,90,5,100,5,105,5,90,5,100,5,105,5]
    PORTB.5 = 1 : PAUSE 1000           ; Red ON
    PORTB.4 = 1 : PAUSE 1000           ; Red and Green ON
    PORTB.5 = 0 : PAUSE 1000           ; Green ON 
    PORTB.4 = 0                        ; all OFF
    ; ===============================================================
    
    ;---------By Darrel Taylor---------------------------------------
    INCLUDE "DT_INTS-14.bas"    ; Base Interrupt System
    INCLUDE "ReEnterPBP.bas"    ; Include if using PBP interrupts
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   INT_INT,  _SignalFound,   PBP,  yes
            INT_Handler   TMR1_INT,  _SignalTimeOut,   PBP,  yes
            endm
        INT_CREATE              ; Creates the interrupt processor
    ENDASM
    @   INT_ENABLE  TMR1_INT	; Enable Timer1 Interrupts 
    @   INT_ENABLE  INT_INT    	; Enable RB0 Interrupts 
    ;=================================================================
    T1CON.0 = 1                 ; Start timer1
    GOTO Main 
        
    Main:
    	IF Upd = 1 THEN GOSUB UpdReading   
    	IF PORTB.2 = 1 then GOSUB UpdUserSetting
    GOTO Main
    
    UpdUserSetting:
    @   INT_DISABLE  TMR1_INT	    ; Enable Timer1 Interrupts 
    @   INT_DISABLE  INT_INT    	; Enable RB0 Interrupts 
        pause 10
    	WRITE 0,WORD SampleValue    ; Set this distance as Zero distance
        sound PORTB.1,[123,10]      ; Beep
        UserSetting = SampleValue
    @   INT_ENABLE  TMR1_INT	    ; Enable Timer1 Interrupts 
    @   INT_ENABLE  INT_INT    	    ; Enable RB0 Interrupts
    Debounce:   if PORTB.2 = 1 then  debounce
    RETURN
    
    UpdReading:
    	T1CON.0 = 0			     	; Stop timer1
        ; Not in sight so keep the green light on 
        IF SampleValue-UserSetting < 50000 AND SampleValue-UserSetting >= 15 then
            PORTB.5 = 1
            PORTB.4 = 0
        ; Getting close so kep green + red light on
        ELSEIF SampleValue-UserSetting < 15 AND SampleValue-UserSetting > 1 then
            PORTB.5 = 1
            PORTB.4 = 1
        ; got there so make the light red
        ELSEIF SampleValue-UserSetting = 1 then
            PORTB.5 = 0
            PORTB.4 = 1
        ; too far, make the red light blink        
        ELSEIF SampleValue-UserSetting > 50000 THEN
            PORTB.5 = 0
            toggle PORTB.4
        ENDIF
        
    	Upd = 0
    	T1CON.0 = 1					; Start timer1
    
    RETURN
    
    '---[INT - interrupt handler]------Signal found at RB0, take a reading
    SignalFound:
        T1CON.0 = 0 	                  	 	; Stop timer, Don't send burst during calculations
    	RawData(Counter) = TMR1H * 256 + TMR1L	; Add 15 readings to RaData()
    	Counter = Counter + 1    
    	if Counter => 14 then
    
    ;------[Sort a list of 15 readings]---By Melanie-----------------------
    SortArray:
    		Counter = 0
    SortLoop:
    		If RawData(Counter + 1) < RawData(Counter) then
    			DataA = RawData(Counter)
    			RawData(Counter) = RawData(Counter + 1)
    			RawData(Counter + 1) = DataA
    			If Counter > 0 then Counter = Counter - 2
    		ENDIF
    		Counter = Counter + 1
    		If Counter < 15 then goto SortLoop
    		;===============================================================
    
    		Upd = 1							; Set flag to read sample
    		SampleValue = RawData(7)/100	; Select the middle guy
    		
    		For Counter = 0 to 14			; -------------------------------
    			RawData(Counter) = 0		; I probably don't need this part
    		Next							; -------------------------------
    		Counter = 0                    	; Reset counter
    	ELSE                            
    		T1CON.0 = 1						; Start timer1
        ENDIF
    @   INT_DISABLE  INT_INT    			; Do not take another reading on RB0 untill
    										;    the next burst is sent
    @ INT_RETURN
    
    '---[TMR1 - interrupt handler]------TMR1 Overflow, send burst
    SignalTimeOut:
    	HPWM 1,127,40000			; Send burst DC 50%, 40KHz
        PAUSEUS 200             	; length of burst.
        CCP1CON = 0             	; Stop sending HPWM
        PAUSEUS 500            		; Wait until Tx vibrations stops 
    	T1CON.0 = 0					; Stop timer1
    	TMR1H = $B1:TMR1L = $E7	 	; adjust timer1 to 50Hz @ 4MHz Prescale = 1
    @   INT_ENABLE  INT_INT    		; enable RB0 interrupt 
    	T1CON.0 = 1					; Start timer1
    @ INT_RETURN
    
    end

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Which PIC are you using?
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    Join Date
    May 2009
    Location
    Montreal, QC, Canada
    Posts
    118


    Did you find this post helpful? Yes | No

    Default

    Sorry about that,

    Using 16F628A

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    One easy way would be to increment a counter variable in your Timer1 int handler, and turn off all LEDs & enter sleep mode once it reaches a certain value.

    During normal operation, reset the counter var in the INT_INT handler.

    Timer1 increments counter on each interrupt, external interrupt clears it. Just monitor the count value in your main loop.

    Just remember that if you enter sleep mode, Timer1 stops unless you have an external crystal for your Timer1 clock source.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    May 2009
    Location
    Montreal, QC, Canada
    Posts
    118


    Did you find this post helpful? Yes | No

    Default

    The problem I have is I can not stop Timer1 because that is where the PWM burst happens.

    If I stop this timer I have no way to wake it up so I can not go in sleep mode.

    I can only get the LEDs off based on a counter and I guess compare it with its own value from the previous loop.

    What I can't figure out is, how many loops I get in one minute? and how much can I count with a word variable?

    Perhaps I need to use nested counters? or is there a better way?

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    A word var can count up to 65,535. If your Timer1 interrupts happen every 20mS, then count up to 3000.

    It won't be right on the money for 1 second with your delays, HPWM, etc, in your Timer1 interrupt handler, but you can adjust for overhead if you need it closer to 1 second exactly.

    You could also use a Timer0 interrupt to increment your counter.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts