Just how low-power can an Arduino based circuit go? I found that it can go low, very low! So why not apply this in a cool project. Source files are linked at the bottom.
The simplest way to make a solar jar light is to disassemble one of those solar garden lamps and fix it into a glass jar. As an engineer I need something more sophisticated. At least it must have colors. But how to change them? The choices are slim: buttons are too complicated to water-proof, hall sensors have been done before so I decided to use an accelerometer. I used an ADXL345 in a similar project before and it has some cool features like tap and double-tap detection which I am using to switch control modes. The color can be changed by simply tilting the light.
Technical design details
I want the light to automatically switch on when it gets dark so I need to tap into the solar panel voltage. To store the solar energy a lithium battery is used. Also its voltage has to be monitored to know approximately how much juice is left and when to go into power saving mode to protect the battery from dying. These voltages have to be sensed with a high impedance voltage divider: to actually make sense of a voltage, the Arduino’s internal voltage reference is used and that is just at 1.1V. Since the voltage divider is permanently drawing current from the battery (and the solar panel) the current has to be low or it will dominate standby current. I used a 10M and a 1M resistor to make a 1:11 voltage divider for each of the voltages. The current draw of the divider is only 0.35µA and thus negligible. The 10bit ADC resolution is good enough to get an accurate voltage reading and we do not need a high precision value: anything within 0.1V is fine. To lower the output impedance of the divider for accurate ADC conversions a capacitor is added which also acts as a low pass filter, reducing noise spikes on the readings. I found the readings to be surprisingly accurate. On the prototyping circuit it was less than 50mV off compared to the mutimeter value.
There is a whole variety of small solar modules available on Aliexpress nicely encapsulated in epoxy with solderable output pads. To be able to charge a lithium battery it needs an output voltage of at least 4.5V. For a solar cell to run at maximum power efficiency the output voltage should be between 0.4V and 0.45V, see the graph below (source: wikipedia). The best choice is a 5V panel: it has 10 solar cells wired in series so with an output voltage of about 4V when charging the battery it runs close to the maximum power point. I ordered two different sizes: a 60x60mm and a 45x45mm version. The claimed output current is 80mA for the bigger one and 50mA for the smaller one. Taking half that value to make a more realistic assumption a 500mAh battery would take about two to three days to fully charge when placed at a more or less sunny spot during summertime. Since the LEDs do not fully drain the battery in one evening the light will switch on almost every day for a few hours.
To charge the battery from the solar cell I used the same IC I used before, for example in the line follower robot: the cheap TP4054 with an input voltage range up to 9V is just about perfect for this.
The Accelerometer is tiny and very hard to solder by hand so I used a finished module to make it possible for a wider range of people to make one of these. The 3.3V LDO voltage regulator on the module is drawing about 0.2mA even when the accelerometer is set to power down mode. Since the accelerometer itself uses less than that in full operation the module has quite a poor design for low power applications but this is fixed easily: the power is simply supplied through one of the GPIO pins of the Arduino so it can be deactivated during standby periods.
As for the WS2812 color LEDs: these are not particularly hard to solder but are very sensitive to the heat of a soldering iron and can easily be destroyed. I chose to use the ones that are pre-soldered on a strip. I found in other projects that these LEDs draw quite a lot of quiescent current. In fact I just checked: 3 WS2812 draw 2mA when off. This is unacceptable for a low power circuit so I added a p-channel MOSFET to be able to completely switch them off.
This is all there is as far as the circuit design goes. I built a prototype to test the functionality of the circuit and to be able to write the code while I was waiting for the PCBs to arrive.
Time to do some coding and measurements
The light has to have three basic modes: static light, flickering light imitating a candle and standby with low current draw.
The first two were easy to do since I did these things before and was able to re-use most of the code. Low power on the other hand was something I never did with the Arduino hardware. To start off I found some instructions online and even a low power library that worked quite well. Removing the voltage regulator and the power LED from the arduino board I got the current draw down to just 5µA during standby periods. To my surprise the ATmega holds all ram content during these periods and does not even need to be reset to exit the low power mode which really handy: no backup registers are required like it has to be done on the STM32F0.
I later found a major drawback of using the low power library: it only works on the ATmega328p and I already ordered a whole bunch of Arduino Pro-Minis with the cheaper ATmega168P. A quick checking of the datasheet of said micro controller revealed that the ‘P’ version also supports the low power modes so it is just the library. There is a pull request on github fixing that problem but I could not get the extended power save to work which allows the brown out detector to be suspended. Without it, the standby current is three times higher. The extended standby mode does not work because the Arduino IDE does not have the option to select the ‘P’ version of the ATmega168 and I did not want to edit the hardware definition files so the code can be compiled by others without having to change any external files. I abandoned the library and turned to the lower level AVR library, adding all the functions and defines needed to access the registers directly, even if the wrong micro controller info is provided by the Arduino IDE. The extra power saved is not huge and it would not really have been necessary to do all the extra work but it just bothered me too much to leave it half-baked.
To have the circuit turn on at dawn I quickly measured the solar panel voltage one evening and it was around 1V when it was getting dark and only 0.5V half an hour later. I set the limit to 1V. If the voltage is lower, a counter starts incrementing every minute and the light switches on if the darkness persists for more than about 10 minutes. This prevents the light from switching on if there is a bad voltage reading due to noise. When the sun comes back up in the morning the counter is decremented to zero within an hour so if a car or something happens to pass during the night it is not enough to reset the counter and the light stays off. Oh I forgot to mention that the light will turn off on two conditions: if the battery voltage is lower than a threshold where it still has enough power to run the light for a few hours if it is manually switched on or if the light has been running for over 5 hours. Also it does not automatically switch on if the battery is not (almost) fully charged at dawn.
I am using a 500mAh lithium battery which can run the light easily for 10 hours. Even when going to white light and full brightness the current draw is in the range of 120mA so the fully charged battery will still last for four hours and there is always the option of using a bigger battery.
When the light is switched off the code to check the accelerometer for any movement runs about once per second. In between the microcontroller is put into its lowest power mode and the watchdog timer is used to trigger the wake-up. When the sleep bit is set in the low power control register of the ATmega the watchdog timer does not reset the system automatically when it expires so it can be used to time the duration of the low power modes. Checking the accelerometer is done by using its ability to check for any activity without constantly having to read the values. A threshold in any of the three sensor axes can be set to. If the acceleration force exceeds the threshold an interrupt flag is set. When waking up, the accelerometer is powered on and configured. Then the interrupt register of the accelerometer cleared and the microcontroller is put back to sleep for 250ms. After that the interrupts are checked and if the activity interrupt flag is set the light is switched on. The threshold is set such that shaking it or tapping on it will switch it on.
Initially I planned on using the interrupt output pin to wake the Arduino if an interrupt happens. This would work fine but I did not test it yet. With the Arduino in sleep mode and just the accelerometer running the current is at 250µA which is higher than what it is with the polling method. Most of that current is drawn by the LDO of the accelerometer module.
To measure the current during the wake-up period I used my current sensing amplifier I made last year. It uses a transimpedance amplifier to have zero burde voltage current sensing. Its documentation is on my long todo list but before I do I need to improve its very noisy output signal and find a more suitable opamp for it. With the amplification set to 100x (40dB) the current draw looks like this:
The first spike is from charging the bypass capacitor of the accelerometer after waking up. During the longer spike the accelerometer is configured over I2C at 400kHz clock frequency. During the long period that follows the microcontroller is in sleep mode and the accelerometer is watching out for any movement. The current draw during this period is 250µA. The current during the one second low power sleep of the finished circuit is just 8.5µA! We can now calculate the average current per cycle:
9.5ms*8.5mA+250ms*0.25mA+1000*0.0085mA = 152mAms
Therefore the average current is 152mAms/1259.5 = 120µA. Over one day this results in just 2.9mAh if the light is off. The little solar panel will produce this amount of energy in less than five minutes!
The Arduino Pro-Mini with some modifications is well suited for low power applications in combination with a solar panel and a lithium battery for energy storage. The circuit and the software are running smoothly for over a week now: the jar lights in my back yard turn on every night and light up in beautiful colors. Of course there were some initial software bugs and one of the lamps broke down after heavy rain – one of the Ikea jars was not waterproof so the moisture got in and got to the accelerometer, so be careful when building your own.
If you want to buy a kit with all components or even a fully soldered PCB feel free to contact me. You have to provide and solder your own battery though, they are a pain to ship internationally. You can find full assembly instructions in german here or in english here.