Have you ever wished that you had an alarm clock that would wake you up every few minutes so you could do something quick and then go back to sleep? Nope, me either. But in the microcontroller world, such a feature can be very handy. We know the PIC has timers and that we can program delays in software but we can’t really get very long timeouts without a lot of delay loops or some external help. In this post we will see how we can use a simple feature of the PIC, and minimal external parts, to get those long timeouts.
Pardon My Interruption
In a couple of previous posts we saw how we could use interrupts to let us know specifically when some event occurred. The PICs have all kinds of interrupts, mostly having to do with internal things like a serial port, timers, A/D converters, etc. There’s even an External Interrupt input that we took advantage of in previous episodes. But there are also special external interrupts on many of the I/O pins that we can put to good use. This special I/O pin function allows us to receive an interrupt whenever there is a logic change (0 to 1, or 1 to 0) on the pin. That feature is cleverly called “interrupt on change”. Even better is the fact that this interrupt can be used to wake up the PIC after it has been put into sleep mode. For instance a key press or a light sensor, etc. could be used to wake up the PIC. But wait, there’s more! On many PICs one of the I/O pins is designated as an Ultra Low-Power Wake-Up function. That can be particularly useful if you want to run your circuit on batteries and that is the option we will be exploring in this episode.
The diagram shows the 12F683 that we have used in some of the previous posts but this circuit will work equally as well with many other PIC versions. You just need to connect to the equivalent pins if you use a different PIC version. The only required components to create long timeouts are the components connected to pin 7. The LEDs and their current limiting resistors were added just to give us a visual indication of the time between wake-ups. Microchip Application Note AN879 provides tons of good information on the hardware and software for using this feature. The 220 ohm resistor is used to limit the peak current sourced from the PIC when charging the capacitor. AN879 recommends at least 200 ohms when using capacitors larger than 50pf.
The 220 ohm resistor has an insignificant impact on the delay timing because of the ultra-high equivalent resistance internal to the PIC. In reality, the PIC has an internal current sink of about 140nA so the timeout can be calculated as roughly 30ms per nano-farad at 5 volts. Because the characteristics of the chosen capacitor will vary over time and temperature, we can’t get highly precise timeouts. Then again, our goal is to get long timeouts so any inaccuracy is probably not critical. One of the things you should consider is the leakage current (self-discharge) of the capacitor, especially if you pick a value greater than 1uf. As a rule of thumb, ceramic capacitors have the lowest leakage current, tantalums the next lowest, and electrolytics are the worst. In my experiments I used ceramics for values under 1uf and tantalums for values 1uf and higher. The 47uf capacitor I show in the diagram is the largest I have tried, simply because that is the largest tantalum I found in my junk box. If you run the calculations, it should provide a 23.5 minute timeout but mine actual went about 26 minutes. A 10uf capacitor gave me 5.5 minutes (estimated 5 minutes), a 1uf gave me 32 seconds (estimated 30 seconds) and a 0.1uf gave me just over 3 seconds (estimated 3 seconds).
As mentioned earlier, the two LEDs in the diagram give a visual indication in case you want to time the delay. I used one red and one green so it was highly obvious when the switch had occurred. That came in handy on the very long timeout because I could just sneak an occasional peek from across the room.
The software link is listed below. While it is targeted for the 12F683, it is easily ported to other versions of the PIC. You will need to change the line that identifies the PIC version (LIST=) and the INCLUDE file but those are intuitive changes. The __CONFIG line may also need tweaking just because one or two of the labels used are spelled differently in some of the INCLUDE files.
Normally we would define an I/O pin as either an input or an output for whatever function we were using. In this case, however, we have the requirement to charge up the capacitor and then turn around and simultaneously drain and monitor the capacitor voltage. The TRISIO register controls the direction of the I/O pins so that needs to be modified every timeout cycle. Also, since the TRISIO and GPIO registers are in different banks, we need to make sure we issue the correct BANKSEL command each time.
The charge time required for the capacitor is dictated by the formula T=R*C where T is in seconds, R is in ohms, and C is in farads. For the example values in the diagram, that means a minimum of 11ms. The code I started with had a 100ms delay routine so I just left that instead of trimming it down closer to the minimum required. If you are really looking to minimize overall power usage, then you could easily reduce that delay. Frankly, it wouldn’t result in much savings because most of the time is spent in sleep mode. What does help for power savings is to reduce the clock speed so in this example we set the internal clock to its lowest rate (31-kHz) by clearing the frequency control bits in OSCCON. OSCCON normally defaults to use the 4-MHz internal clock rate. One other power savings tip is to configure all of the unused GPIO pins as outputs.
Obviously this example will not be a power saver because we are lighting one of the LEDs all of the time, even during sleep mode. Without the LEDs I measured sleep mode current of just a few micro amps. If we don’t care about power savings or if we need to do something in the code during the timeout period, then we can delete the SLEEP instruction. In either case, the timeout will generate an interrupt. In our example the interrupt handler simply recharges the capacitor, toggles the LEDs, and then clears GPIF (GPIO Interrupt Flag). The exit from the interrupt handler automatically resets the GIE (General Interrupt Enable) flag. That’s it for this post. Check out my other electronics projects.