Wednesday, February 18, 2015

NXP LPC8xx EEPROM emulation

Screen grab from terminal of demo showing
the reprogramming of a byte in 'EEPROM'
(actually a page in flash memory).
Summary: The NXP LPC8xx series of MCU lack traditional EEPROM capability to preserve settings across power cycles, but this functionality can be emulated using in-application flash programming. I've written a demo program to show this in operation.

The LPC8xx series is a popular range of of ARM Cortex-M0 MCUs from NXP. One feature that I find indispensable is the ability to preserve settings across power cycles.

Many MCUs feature a small EEPROM bank for this purpose. But the LPC8xx does not have EEPROM. However it does allow the flash memory to be reprogrammed in 64 byte pages from within the application. This can be used to emulate EEPROM functionality.

I found an example [1] which worked after some initial trouble [2]. The example however fails to address one important question: how to allocate a space in flash that's safe to read/write for this purpose.

I posted a query to stackexchange.com [3] and received a few good suggestions on how to achieve this. One suggestion was to use the uppermost flash page. However that required prior knowledge as to the particular part being used (LPC810 has 4kB flash, LPC812 16kB etc). An alternative suggestion which I preferred was to use this:

const uint8_t eeprom_flashpage[64] __attribute__ ((aligned (64))) = {0};

This is probably specific to the GCC compiler, but other compilers will have an equivalent for directing a 64 byte alignment of the allocation. I found the "={0}" assignment necessary, otherwise the array was allocated in RAM.

I implemented all this in a little demo program which has been tested on a LPC812, but should work on all LPC8xx series of MCU. You can find the code on GitHub: https://github.com/jdesbonnet/LPC8xx_Flash_EEPROM/

Flash vs EEPROM

There are some downsides to using flash. First, it does wear out eventually (as does EEPROM, but EEPROM endurance is typically an order of magnitude greater than flash: (in the order of 100 kcycles vs 10 kcycles). [4]

The other problem which can be seen in the screen shot above: a whopping 101ms to complete a write. That's forever! (typically EEPROMs have write times in the order of a few milliseconds). What happens if the power fails during a write? (I actually don't know!)

References:

[1]  http://www.lpcware.com/content/forum/eeprom-emulation

[2] I was initially attempting to test by writing some constants defined in the program (and therefore were stored in flash). The iap_copy_ram_to_flash() function must receive the source data from RAM. Flash to flash copy is not possible during this operation. Ref UM10601 22.5.2.2 Copy RAM to flash (IAP).

[3]  http://electronics.stackexchange.com/questions/153424/how-to-automatically-allocate-a-page-of-flash-for-in-application-storage-of-sett

[4] The LPC81XM datasheet, section 12.1 specifies flash endurance typically at 100 kcycles, erase time for 64 bytes typically 100ms and write time for 64 bytes typically 1ms.

Sunday, February 8, 2015

A hack to easily measure electrical current use of a battery powered device

This is a little hack to measure the current use of a battery powered device. I used this in a recent Lidl LED nightlight teardown. These nightlights came with plastic spacers which kept the battery disconnect until it was ready for use.

I covered both sides with copper foil tape, soldered wires each side and reinserted between the battery and battery contact. I then connected the two wires to an ammeter. Voila!


Lidl PIR nightlight teardown and hack

Summary: I picked up some low cost (E8) battery powered / PIR triggered nightlights that were on sale in Lidl. The heart of the device is a common PIR IC. One of the IC pins can be tapped to drive digital IO line for occupancy detection or an intruder alarm. Given that PIR sensors alone in small volumes can often exceed €10/$10 this represents good value for money.

The device (Livarno Lux brand (Lidl), model Z31685C)  comprises 8 white LEDs, a  PIR (Pyroelectric Infrared) sensor with a polyethylene plastic fresnel lens [1] and a photodiode (which suppresses the illumination of the LEDs during the day). It is powered by 8 x AAA alkaline cells (supplied) arranged in two sets of 4 in series.

The device can be mounted on a wall or ceiling by attaching a mounting plate with screws or an adhesive strip (also supplied).

Teardown:

The top cover comes off easily enough: seems to be held on by friction alone. Then an aluminiumized plastic reflector can be pulled of revealing a single sided PCB secured to the base with three screws. On the top surface of the PCB is the PIR sensor, a light sensing photodiode and two electrolytic caps.

Underside of nighlight PCB.
 (the thin red and yellow wires soldered to the main IC were
added by myself to facilitate interfacing with MCU).
Click to expand image.
The fun is on the underside. At the heart is a 16 pin PIR IC marked "HS0001". Googling this didn't yield any useful results, but I found several PIR ICs that had similar marking codes: LP0001 [3] and BISS0001 [4]. The datasheets for these have a reference design which look very similar to the layout of this PCB. After some probing, I can say with certainty that the HS0001 used on this board is functionally identical to the LP0001 and BISS0001.

The board is powered by the two parallel banks of 4 x AAA alkaline cells. Each bank supplies approx 5.5V. A diode in series with each bank prevents one bank from driving the other in reverse (which can cause alkaline cells to leak). A linear regulator provides a 3.3V rail to the PIR IC.
Reference design schematic from LP0001 datasheet.


Most of the passive components on the board are resistors and capacitors used to set various tunable parameters of this IC [list pins]

The VO (pin 2) line from the IC drives the gate of a (FET?) transistor which switches the lighting LEDs (driven by the 5.5V direct from the batteries).

So how power efficient is this? Using a little hack I measured the quiescent current at about 90uA and the current with LEDs on at 70mA. Unfortunately the supplied AAA cells don't have any product code, but typically AAA alkaline cells have capacities in the range from 800 - 1200 mAh. Let's say 1000mAh. And as there is two sets in parallel that's a total of 2000mAh capacity. If you assuming the LEDs are never triggered, that's an approximate battery lifetime of 2000mAh/90uA = 22222 hours or 2.5 years. In reality if the LEDs are on at least a few minutes a day so that brings the battery lifetime down to under a year.

Driving a MCU

So can this cheap nightlight be used as a PIR sensor for another application? 
So this is what the OUT2 (output of second stage opamp) pin of the PIR IC looks like on an oscilloscope when I walk into the room (about half way though the trace).  So it seems OUT2 tends to about half the supply voltage (1.6V) when there is no activity. Then when a person enters its field of view OUT2 oscillates between 0 and 3.3V.  So if you connect this directly to a digital IO input, all you need to do is detect a transition (high to low or low to high). Apply classic switch debounce logic (except on a multisecond time scale) and you have a occupancy / intruder detection mechanism!

To facilitate my hack, I soldered some think (30AWG) wire to OUT2 , GND / battern -ve and the 3.3V rail (to draw power for my MCU application).


Oscilloscope trace from the OUT2 pin showing a person enter the room at about the half way mark.

Conclusion:

If you can find these in Lidl (it's a very hit and miss thing with them) this can be converted into a nice neat PIR sensor for less money than ordering a dedicated PIR sensor [2]. Plus you get the LED night light functionality and 8 AAA alkaline cells!

References:

[1] Focusing devices for pyroelectric infrared sensors
http://www.glolab.com/focusdevices/focus.html

[2] Adafruit PIR (motion) sensor  ($10)
http://www.adafruit.com/products/189

[3] LP0001 datasheet
http://akizukidenshi.com/download/ds/sctech/LP0001.pdf

[4] BISS0001 datasheet
http://www.seeedstudio.com/wiki/images/2/2f/Twig_-_BISS0001.pdf