PDA

View Full Version : Trying to add a sleep function or pretend to sleep



lilimike
- 9th May 2010, 16:18
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.

@ __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

Bruce
- 9th May 2010, 18:10
Which PIC are you using?

lilimike
- 9th May 2010, 18:32
Sorry about that,

Using 16F628A

Bruce
- 9th May 2010, 18:46
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.

lilimike
- 9th May 2010, 18:58
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?

Bruce
- 9th May 2010, 19:10
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.