PDA

View Full Version : ULPWU & PLVD on 12F635 & 16F684



dsicon
- 19th August 2007, 22:36
Hi all
anyone one have any experience using the ULPWU (ultra low power wake up) module on the PIC12F635 ?
it seems to have started life in the PIC16F684
looking for any tips or code snips using PBP

i need to also use the PLVD (programmable low voltage detect) module but at 20+ uA i don't have the power budget to leave it on all the time for low battery warning indication

so my thought is to use the ULPWU (if i can figure it out) and wake up once in a while and enable the PLVD to sniff the battery

at first read it looks like the ULPWU will interrupt and wake up the unit roughly every 30ms using a 1000pf cap
this way too often for me, guess i could keep a counter or something

but using PBP it is not clear to me how to proceed
make the pin an output, set HI briefly, turn it back to an input and go to sleep?
something like that ?

TIA
ds

Bruce
- 21st August 2007, 00:16
Well, that was interesting. I've never used ULPWU or PLVD yet, but I have used the 12F635
in a ton of applications.

Out of curiosity, I put this together to tinker with today, and it works just like the book says.

You'll probably want to experiment with the series resistor & cap value. As voltage drops, the
wake up frequency increases, so you'll need to find some happy medium there to work in your
own application. I used a 200ohm series resistor with 1kpF cap.


@ DEVICE PIC12F635,MCLR_OFF,INTRC_OSC_NOCLKOUT,WDT_OFF,BOD_ OFF
@ DEVICE PWRT_ON,FCMEN_OFF,IESO_OFF,WUREN_OFF,PROTECT_OFF

SYMBOL PROBE = GPIO.1 ' scope probe indicates wakeup from sleep
SYMBOL PLVD_LED = GPIO.2

OSCCON = %01100000 ' Internal 4MHz select
OPTION_REG = 128 ' internal pull-ups off
CMCON0 = 7 ' disable comparator
VRCON = 0 ' disable internal Vref

GPIO = %00000000 ' LED off on boot
TRISIO = %00000001 ' GPIO.0 = input, rest outputs
PIR1 = 0 ' clear peripheral int flags
PCON.5 = 1 ' ultra low power wakeup enabled

Main:
GPIO.0 = 1 ' set data latch on GPIO.0
TRISIO.0 = 0 ' GPIO.0 = output (charging cap)
PAUSEUS 24 ' charge cap for 24uS
TRISIO.0 = 1 ' GPIO.0 = input to discharge cap
IOCA.0 = 1 ' int on change enabled for GPIO.0
INTCON = %00001000 ' global ints disabled, int on change enabled
@ SLEEP ' put PIC to sleep
TOGGLE PROBE ' indicate ULPWU wake up from sleep & clear mismatch
INTCON.0 = 0 ' clear wake up on change int flag
GOSUB TestVolts ' go test for under voltage condition
GOTO Main ' not sure what this does...;o}

TestVolts:
INTCON.6 = 1 ' peripheral ints enabled
LVDCON = %00010101 ' enable PLVD. set trip point to 4.0V

' enable PLVD interrupt only when PLVD internal Vref is stable
IF LVDCON.5 = 1 THEN PIE1.6 = 1 ' if stable, enable

IF PIR1.6 = 1 THEN ' voltage <= 4.0V?
HIGH PLVD_LED ' yes. indicate voltage is <= 4.0V
PIR1.6 = 0 ' clear int flag
ELSE
LOW PLVD_LED ' else, indicate voltage is > 4.0V
ENDIF
LVDCON = 0 ' PLVD disabled before returning to sleep
INTCON.6 = 0 ' peripheral ints disabled
PIE1 = %00000000 ' low voltage detect int disabled
RETURN

END
At 5 volts it wakes up around every 30mS, and trips PLVD at <= 4.0 V.

dsicon
- 21st August 2007, 01:21
wow that's great Bruce, thanks a lot
you got farther along than i did, but this was pretty much what i was thinking about
doing

i think i will go to a 0.1mf cap for about 3 seconds

question
do you see a way to distinguish this ULPWU interrupt from some other pin that may have caused wake up from SLEEP ?
i don't

also
in your example code PROBE is for your scope and not directly related to the ULPWU pin, when you
TOGGLE PROBE
your comment says 'clear mismatch register'
does this mean that writing to any pin will clear the mismatch ?
i thought there was a mismatch bit for each pin ?

Bruce
- 21st August 2007, 03:08
question
do you see a way to distinguish this ULPWU interrupt from some other pin that may have
caused wake up from SLEEP ? i don't

If you had int on change enabled for more pins, you would need to read the port & look for
a change immediately on wake up. Other interrupts would set the flag bit associated with
that interrupt. I don't see any specific flag bit for ULPWU alone.


also
in your example code PROBE is for your scope and not directly related to the ULPWU pin, when
you TOGGLE PROBE
Yes. I just used this pin for the scope to see the timing when using different cap and resistor
values.


your comment says 'clear mismatch register' does this mean that writing to any pin will clear
the mismatch ?
A normal wake up on change requires you to read or write to the port to clear the
mismatch condition. Then clear the interrupt flag bit.

i thought there was a mismatch bit for each pin
The only pin that affects wake up on change is the one that has this feature enabled, and
is an input. There aren't any mismatch bits, but there are individual interrupt on change
enable and disable bits in IOCA.

You can remove the TOGGLE PROBE & INTCON.0 = 0 after. This gets taken care of before
the sleep instruction.

dsicon
- 21st August 2007, 17:34
thanks again Bruce,

I have one main input pin which needs to wake up the unit

so what you are saying is that if it is NOT that pin when it comes out of SLEEP then by elimination it must be the ULPWU pin ?

so then i would check the state of that pin, i.e. there is no bit that says which specific pin caused the wake up ? (i know there is not for the ULPWU)

also sorry if i am being dense here but can you explain the mismatch deal some more?
so if i read or write to *any* pin it will clear that mismatch?

Bruce
- 21st August 2007, 18:53
I have one main input pin which needs to wake up the unit

so what you are saying is that if it is NOT that pin when it comes out of SLEEP then by elimination it must be the ULPWU pin?
Yes. Assuming you don't have anything else enabled that could cause the wake up from
sleep.



so then i would check the state of that pin, i.e. there is no bit that says which specific pin caused the wake up ? (i know there is not for the ULPWU)
Yes.



also sorry if i am being dense here but can you explain the mismatch deal some more?Sure. Say you have GPIO.1 configured for wake up. It's normally held high.

When a switch or other external device pulls this pin low, you want the PIC to wake up.
Wait for GPIO.1 to go high (by reading the port pin). Normally it will be held high by an
external or internal pull-up.

Once it's in the high state, enable wake up on change, then put the PIC to sleep.

Once it goes low, there's a mismatch, and it wakes up. Wait for the pin to return high, and
go through the process again. If the PIC enters sleep mode again, before the port pin was
returned high, then it will wake up again once the pin returns high.


so if i read or write to *any* pin it will clear that mismatch?
Yep. As long as it's a pin on that port, but I normally read the whole port into a variable,
then test for the bit in question.

Testing several bits in a row leaves too much time for another one to change.

dsicon
- 21st August 2007, 20:48
ok i think i have it all now
my program isn't working right but i will figure it out now that i understand things a bit better

FromTheCockpit
- 3rd November 2009, 19:41
Hi, I may be too late to ask this as this thread is few years old, but I will take my chances.
I am trying to understand internal pull up on/off along with making sure pins are low before going to sleep.
If I wish the pins to be low when the program starts is it ok to use the statement: OPTION_REG=0 : GPIO=0
Since I am trying to understand internal pull up on/off so I will ask if there is any significance of OPTION_REG=128 over what I wrote above.

Secondly,
In the following code


Main:
GPIO.0 = 1 ' set data latch on GPIO.0
TRISIO.0 = 0 ' GPIO.0 = output (charging cap)
PAUSEUS 24 ' charge cap for 24uS
TRISIO.0 = 1 ' GPIO.0 = input to discharge cap
IOCA.0 = 1 ' int on change enabled for GPIO.0
INTCON = %00001000 ' global ints disabled, int on change enabled
@ SLEEP ' put PIC to sleep
TOGGLE PROBE ' indicate ULPWU wake up from sleep & clear mismatch
INTCON.0 = 0 ' clear wake up on change int flag
GOSUB TestVolts ' go test for under voltage condition
GOTO Main ' not sure what this does...;o}

Suppose my port (Lets say sensor attached to GPIO.1) is held low and I want PIC to wake up once it goes high, does what its suppose to do, and when it again goes low PIC goes to sleep.
At what position in the code should I check to make sure port is LOW before PIC goes to sleep.

As lets say I put "WHILE gpio.1:wend" before capacitor is charged in the main loop, I fear that port could go high again while capacitor is getting charged and pic will go to sleep with the port being high.

If I put it after the capacitor charge statement, I fear the capacitor getting discharged while waiting for the port to go low which may take 1-2 seconds.

Hope I can have some help over the two issues. Thanks a lot

Bruce
- 4th November 2009, 19:52
If I wish the pins to be low when the program starts is it ok to use the statement: OPTION_REG=0 : GPIO=0
Yes, but you might want to clear TRIS registers for any pin you want to be an output, and properly setup the
WDA and WPUDA registers first.


Since I am trying to understand internal pull up on/off so I will ask if there is any significance of
OPTION_REG=128 over what I wrote above.

Yes. Bit 7 in OPTION_REG enables or disables internal pull-ups/pull-downs. 1=disabled 0=enabled.

The 12F635 has pull-ups or pull-downs. You write to WDA to select pull-ups or pull-downs, and WPUDA to
enable or disable each one indidually.

Secondly,
In the following code


Code:
Main:
GPIO.0 = 1 ' set data latch on GPIO.0
TRISIO.0 = 0 ' GPIO.0 = output (charging cap)
PAUSEUS 24 ' charge cap for 24uS
TRISIO.0 = 1 ' GPIO.0 = input to discharge cap
IOCA.0 = 1 ' int on change enabled for GPIO.0
INTCON = %00001000 ' global ints disabled, int on change enabled
@ SLEEP ' put PIC to sleep
TOGGLE PROBE ' indicate ULPWU wake up from sleep & clear mismatch
INTCON.0 = 0 ' clear wake up on change int flag
GOSUB TestVolts ' go test for under voltage condition
GOTO Main ' not sure what this does...;o}



Suppose my port (Lets say sensor attached to GPIO.1) is held low and I want PIC to wake up once it goes high,
does what its suppose to do, and when it again goes low PIC goes to sleep. At what position in the code should
I check to make sure port is LOW before PIC goes to sleep.

Wait for the pin to go low, clear the interrupt flag bit, then SLEEP.



As lets say I put "WHILE gpio.1:wend" before capacitor is charged in the main loop, I fear that port could go
high again while capacitor is getting charged and pic will go to sleep with the port being high.

If I put it after the capacitor charge statement, I fear the capacitor getting discharged while waiting for the
port to go low which may take 1-2 seconds.

If all you need is to wake-up on pin change with low power sleep, I wouldn't use internal pull-ups or pull-downs
or the pin-change timed wake-up with ULPWU. If your sensor holds the pin low during idle periods, I would just
let the sensor hold GPIO.1 low with interrupt-on-change enabled only for GPIO.1.

FromTheCockpit
- 5th November 2009, 00:12
Hi Bruce, thanks for replying. This is how I am doing now:

@ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _BOD_OFF & _CPD_ON & _IESO_OFF & _FCMEN_ON & _WUREN_OFF

OSCCON = %01100000 ' Internal 4MHz select
OPTION_REG = 0 ' internal pull-ups on/off according to value written on port
CMCON0 = 7 ' disable comparator
VRCON = 0 ' disable internal Vref
GPIO = %00000000 ' LED off on boot
TRISIO = %011001 ' GPIO.0 / 3,4= input, rest outputs
PIR1 = 0 ' clear peripheral int flags
PCON.5 = 1 ' ultra low power wakeup enabled
Include "modedefs.bas"

Main:
GPIO.0= 1 ' set data latch on GPIO.0
TRISIO.0= 0 ' GPIO.0 = output (charging cap)
PAUSEUS 100 ' charge cap for 1
TRISIO.0= 1 ' GPIO.0 = input to discharge cap
IOCA.0= 1 ' int on change enabled for GPIO.0
IOCA.4=1 ' int on change enabled for sensor @ GPIO.4
while gpio.4 : wend
INTCON= %00001000 ' global ints disabled, int on change enabled
@ SLEEP ' put PIC to sleep
GOSUB Test ' go test for under voltage condition AND send data if pin is made high by sensor
GOTO Main

Though the code is working fine for now, I would still like an opinion if the above way of doing this is the reliable way in long term.
Thanks again

Bruce
- 5th November 2009, 03:51
What exactly is it you're trying to do?

FromTheCockpit
- 5th November 2009, 03:58
I am trying to build an PIR sensor with PIC attached. My aim is to make PIC sleep and wake up like every few seconds or minutes (Which I know will be based on Res/Cap value on GPIO.0) and check for voltage OR wake up if the sensor makes its pin go high.

Bruce
- 5th November 2009, 04:37
I see. If it's battery powered, then you don't want to waste current with internal pull-ups,
and you don't want one on GPIO.0 connected to the internal ULPWU current sink.

You want GPIO.0 to charge the cap through the series resistor, go to input, and let the cap
discharge through the internal current sink. Kind of defeats the purpose if you have the pin
held high via the internal pull-up.

And, if your sensor outputs logic 1 when active, you should probably avoid the while GPIO.4
since it's detecting something when GPIO.4 = 1.

A better approach might be to read the port immediately on wake-up, find out which pin
caused the interrupt on change wake up, then jump to a routine to handle it.

Maybe something like this?


@ __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _BOD_OFF & _CPD_ON & _IESO_OFF & _FCMEN_ON & _WUREN_OFF

Include "modedefs.bas"

OSCCON = %01100000 ' Internal 4MHz select
OPTION_REG.7 = 1 ' turn off current hog internal pull-ups
CMCON0 = 7 ' disable comparator
VRCON = 0 ' disable internal Vref
GPIO = %00000000 ' LED off on boot
TRISIO = %011000 ' GPIO.0 / 3,4= input, rest outputs
PIR1 = 0 ' clear peripheral int flags
IOCA.0= 1 ' int on change enabled for GPIO.0
IOCA.4=1 ' int on change enabled for sensor @ GPIO.4

Main:
IF GPIO.4 THEN HandlePIR ' goto PIR detect routine
GPIO.0= 1 ' set data latch on GPIO.0
TRISIO.0= 0 ' GPIO.0 = output (charging cap)
PAUSEUS 100 ' charge cap for 1
PCON.5 = 1 ' ultra low power wakeup enabled
TRISIO.0= 1 ' GPIO.0 = input to discharge cap
INTCON= %00001000 ' globals disabled, int on change enabled, clear wake up int flag bit
@ SLEEP ' put PIC to sleep
IF GPIO.4 THEN
PCON.5 = 0 ' disable current sink on ultra low power wakeup
GOTO HandlePIR ' if PIR sensor woke us up, handle it
ELSE
GOSUB Test ' go test for under voltage condition AND send data if pin is made high by
ENDIF
GOTO Main

FromTheCockpit
- 5th November 2009, 05:01
Thanks Bruce. I am going to take your advice as it exactly was my aim towards increasing battery life. Thanks again

Bruce
- 5th November 2009, 05:26
You're welcome, and good luck. Have a look at this when you have time.

It has several good tips on power savings for battery apps:
http://ww1.microchip.com/downloads/en/devicedoc/41200B.pdf

And this one too: http://www.ac-limoges.fr/sti_ge/IMG/pdf/Using_ULPWU_module_on_PIC_nanowatt.pdf

Also take a peek in the Electrical Specifications section of the data sheet.

It shows current required for various peripherals, oscillators, etc..

FromTheCockpit
- 15th November 2009, 14:58
Hello Bruce, can you tell me what is the lowest current consumption you have achieved with 12F635?
The minimum I have is 320uA, using external 4MHz resonator. which I don't know is a lot or reasonable? Thanks

Bruce
- 15th November 2009, 20:03
I've never actually tested current consumption on anything I've done with a 12F635, but if
you post your circuit & code I'm sure someone could help you get it below 320uA if it's
sleeping during the time you're measuring current draw.

Dennis
- 24th November 2009, 01:07
Any chance I can send you a PM or email ?

Bruce
- 24th November 2009, 01:38
Sure. tech at rentron.com