This project aims to implement Light-level geolocation method into small unit, capable of running and logging for months or years from single coin cell, like CR2032.
Years ago I stumbled upon article describing geolocation logger for animals, allowing biologists to track their position. The device was self-sustained, logging into its memory, available to be downloaded after retrieval.
As usual, no details were released, I just remember method of determining position from time of dawn and dusk - it certainly piqued my interest. I decided to investigate more into this method... one day. And coin cell contest gave me good reason to start it.
This project ran in two phases, with two different hardware variants built:
1, At first I have no single clear idea how to turn light input data into geolocation output - though I had partial ideas that can be employed. In order to make the decision easier, I built simple and "disposable" loggers I sent around the world to see and log as many sunsets/sunrises as possible. Those loggers were designed to not make any geolocation output, just logging light levels; and were of no use after the mission is done.
2, Once the geolocation algorithm was clear, I made the final LLG hardware, providing geolocation output on display, also with logging capability.
The accuracy of geolocation seems to be in order of dozens of kilometers. It depends strongly on surroundings, though in really unsuitable conditions it can provide valid results within few hundred of kilometers.
The LLG has calculated run-time of nearly 10 years with LCD permanently on, or over 30 years with LCD off. EEPROM capacity is for more than 22 years worth of logging.
Apart from Sun light geolocation, I have two more options to passively resolve geographic location on small low-power device.
1, Watching the light output from Moon, as @Ted Yapo suggested in one of previous logs. It's almost the same as geolocation by Sun, just it's by Moon :-)
2, Watching the inclination of geomagnetic field against center of gravity. The map is known and looking just like this
Using 3-axis accelerometer and 3-axis sensitive magnetic field detector should be able to uncover relation between the two variables and it will provide me another point to resolve geographical latitude.
I can build minimal version - without display and buttons, just with logging option. Time setting/readout of logged data would be done via serial interface. The minimal option can be done very small and lightweight. There is also option of using larger photodiodes to generate not just measurement input, but also power to the logger. I wonder if it's possible to power logger from harvested sun energy without any other power source. Accumulator of some kind would be probably needed, though - at least to backup RTC.
To make longer term logs, more precise RTC is needed. RTC drift causes mainly geographical longitude to drift (latitude is less affected), slowly.
The accuracy of LLG changes over the year, especially for latitude. As shown here, day length for zero declination is nearly equal for all over the world (with exception of polar areas, not shown in graphs), that happens at spring/autumn equinoxes. In such condition, LLG is almost unable to determine its position and accuracy is bad. Fortunately, it's easy to predict when this does happen and filter out wrong results. Accuracy of longitude is more-less constant all over the year.
I didn't fully explore the blue filters idea. Filters I employed are probably not the best choice and I need something better.
I wonder if LDR is good light detection device. Photodiode with TIA is better option in terms of accuracy (it can be done linear over many orders of magnitude of photocurrent), not that much in terms of component count and probably current consumption. The advantage of LDR is that it produces roughly exponential output, but I've been unable to properly use data measured by @Ted Yapo as his logger has different "gain" compared to my combination of LDR/47kOhm resistor. Maybe I need LDR with more than one resistor to achieve different "gain levels". Also, currently there is a few manufacturers of integrated devices photodiode+TIA+ADC in single package, this is also viable alternative. LDR with fixed resistor was simplest and easiest way to do it in short timeframe of contest, and provides quite good results, though.
Though started 12th of December - less than month ago - this project was funny a rewarding one. From beginning I knew there will be a few weak spots I have to addres:
I have to make two hardware variants, one just for collectnig data, another one being the final product
I have to transfer the loggers to its destination as fast as possible at reasonable price, while dealing with overloaded post offices during pre-christmas time
Light level geologging is not very well known and sources of information are scarce
Despite that, I've been able to make 6 light loggers, five of them being sent across the Europe, being ready to collect data which served as basis of my geolocation algorithm setup. After I succesfully received four of them I honed the algorithm, discovered some peculiarities making my life harder, but at the end I validated my ideas and established approach to use on real LLG.
In the meantime, I designed and made the LLG hardware. Because I had no time to wait days or weeks to collect reasonable amount of results from LLG measurement, I implanted data previously measured by simple loggers into LLG as if it were measured by LLG and observed results, being surprisingly good considering how trivial is the measurement method, even proving some degree of robustness against unsuitable conditions.
At the end I calculated projected battery life, being 10 years with display on and 30 years with display off - just running geolocation and logging the location points.
Firmware, PCB files and 3D files are available on github.
LLG has error of, say 100km versus 10m for GPS, ie. four orders of magnitude worse accuracy. On the other hand, commonly available GPS units have consumption in order of tens miliwatts, while LLG can track and log its position with consumption of microwatts, that is four orders of magnitude less.
LLG was built with lowest possible current consumption in mind right from its inception, see my one of my previous project logs. I expected 2,5uA with LCD on, 0,7uA with LCD off; and 9 or 23 years battery life. Let's check it against reality.
Device works in three modes
High-power mode, when ADC acquisition and calculations do take place. In this mode LLG takes approximately 400uA
Mid-power mode, when LLG is brought out of sleep and interacts with user; scanning buttons, refreshing LCD. This takes approximately 25uA and after a few seconds falls to low-power mode.
Low power mode, when LLG is idle and waits for user interaction or RTC to wake up and take measurement. In this mode, LLG takes 2,55uA with LCD on or 570nA with LCD off.
When I took video in previous project log, the 2,55uA and 25uA figures are obvious, but at the time I didn't have LCD-off mode yet. In order to measure it more precisely I had to use some older, heavy stuff
The logger spend different time in those power managed modes. Vast majority of time is spend in low-power modes. Let's say user spends one minute per day checking the LLG results - that is mid-power mode. High power modes are ran automatically - 1440 times per day for light measurements (each one takes less than 5ms) and once per day to analyze the data, calculate geographical location and save one log into EEPROM (that takes roughly 150ms).
It draws 60uAs (microampere-seconds) in high calculations, 3,24mAs in measurement mode, 1,5mAs in mid-power mode and 220mAs per day in low-power mode with LCD on. That is roughly 225mAs per day or 22,8mAh of capacity consumed by the logger. Self discharge is usually defined as 1% per year - leaving us with a bit of doubt what it does mean, as @Ted Yapo discusses here, but if I assume it's 1% of nominal 240mAh capacity, that adds another 2,4mAh of capacity per year, giving total 25,2mAh per year. This yields to 9,5 years of lifetime on average usage and LCD on.
With LCD off the idle-mode figure goes roughly five times lower, in total 54mAs per day, or 5,48mAh per year, plus 2,4mAh self-discharge, that is 7,88mAh per year. Given the same capacity, runtime could be 30,5 years for one CR2032.
Yesterday I designed enclosure for my LLG in FreeCad
and printed it in two parts
After a few strokes with sandpaper it fitted nicely together, bottom part first, with standoffs
and top cover
While case was being printed, I made final touches to my firmware I was working on for last three days. As this project reaches to completely new filed to me, at least 95% of code was freshly written, with little code reuse. User interface of the LLG is being built around four key switches and LCD. The switches are numbered K1, K2, K3 and surprisingly K4; left to right. In general, K1 changes current display content, K2 selects what to change, K3 does the change and K4 is here to confirm the change. Flow diagram of the UI logic is as follows:
Here is video of LLG (without case) in action.
The video is 12 hours old, what unfortunately means it doesn't have display on/off feature captured. The switching sound of switches is actually quite modest, but the automatic gain control of camera microphone channel made it loud as if my bones were cracking or something.
I have to record another video, probably, and also make some battery life estimation.
Also, I setup github repository with various bits regarding LLG, I'm filling it on the fly.
I finally made the reverse sunrise equation to work. As usual, it wasn't that hard, but it took another one great input from @Ted Yapo to get there. The equation
can be expressed as
with substitution of
from now it's just matter of applying some standard high-school math to solve the equation for L into form that can be easily calculated on MCU. That is for calculating latitude.
I thought calculating longitude is trivial, but as usual it's not quite like that. When oversimplifying reality, it's just counting how many hours of difference is between local noon and noon at Greenwich; being roughly at 12:00 UTC and multiply this number by 15 degrees for every hour. The key word here is the 'roughly' word. Trying to synchronize clock to sun over the length of year is a bit more complicated, because simple looking movement of Earth versus the Sun is somehow more complicated by axial tilt and its eccentricity, bringing error of a few minutes into the sync. This doesn't look like too much, but it can mean a few hundred of kilometers error for longitude calculation. So, I have to take this effect, named equation of time into account. Fortunately, it can be calculated as sum of two sine functions with different periods as
where is d is day of year, starting at 1 at first of January. This difference should be subtracted from measured local solar noon and then scaled to 15 degrees per hour. This is quite good approximation for my needs, so I decided to move on.
I did some more work on LLG hardware, got myself to implement proper segment mapping table, so I'm finally able to display some meaningful messages.
Above that, I reorganized my measured data so I can import it into my source files for LLG and adjusted the sources so that LLG calculates the geographical position from the data - is if the LLG would sit at the place and capturing data on its own. The calculations ran on real hardware, being outputted via serial link from MCU.
At first I imported daylight data from my own place, got set of latitude/longitude pairs, entered them into custom map at google maps and here is how it looks. I started with my own place, as this is where I have the most of data
The orange home icon is where the logger really was, the blue points are determined locations from LLG. I can see the latitude to be more dispersed than longitude, but otherwise half of the measurements got into 75km circle, average accuracy being around 100km.
The logger on another side of my country was somehow worse, especially in determining the longitude. I assume that's because it was placed on window of tall building, casting shadows during phases of day, shifting the results.
Interesting is what happed to measurement from Spain.
The three results are almost perfectly aligned, with differences within a few kilometers. Though all being shifted from real location - that is probably due to sunrise/sunset zenith angle being determined slightly wrong, but I didn't want to change the algorithm to fit the data, that would be cheating. The error in zenith angle didn't show in other examples, as those had much less repeatability due to suboptimal logger placement.
The difference between the last result and the previous two is that measurement in Spain took place in minimal light smog, open view to sky; unlike the previous ones, with buildings, trees and other obstacles in view. Even worse were measurement made by valuable contributor @davedarko in Germany
Both longitudes and latitudes quite far away from original place, but consider conditions where the measurement was done:
I hope @oshpark will not mind abusing their motto for the PCBs not made by them, but the color is a bit similar.
I asked friend of mine to produce a few boards for me, as I know he is making some PCBs for himself, occasionally. He agreed and asked me what color of soldermask I want - I didn't care much, answering - "I don't know, let it be pink.". - "Say no more."
Searching for proper shade of the pink color.
Already drilled and etched PCB is covered by pink soldermask
White on pink, nice combo
And detail to my little PCBs
One PCB populated
The red and black wires are for powering the board during development.
So far so good, now I'm going to transcribe the sunrise/sunset detection algorithms, as well as reverse sunrise equation for use with the MCU, do some minor tasks, like user interface and logging - and LLG is done!
The key part of this project is determining location through known date/time and light levels.
Determining geographical longitude from light levels data is relatively straightforward. Take the time of solar noon and compare it to 12:00 of Greenwich time. If it's 12:00, then you are (approximately though) at Greenwich, if not, you are 15 degrees farther to East for each hour.
I played with it a bit, discovering relations between the variables. At first I was curious how does look the relationship between latitude and day length at different solar declinations, as those are the the main variables that come into game.
Expectedly, I can see strong relationship of day length and latitude when solar declination hits its extremes (winter and summer solstices) and very weak relationship at zero declination (spring/autumn equinoxes).
Change of day length over the changes of solar declination (= throughout the year) is almost linear, for -48, -22, 0, 22 and 48 degrees of latitude.
I was interested also how much the day length is changing when taking into account different solar zenith angles; the previous ones being at -0,83 degrees; being standard for sunrise/sunset tables. Though my detection algorithm triggers at slightly different angle, shifting the measured day length to somehow longer times. Here are day lengths at different sun zenith angles, for three different latitudes (48, 0, -48 degrees)
and here are just the differences
The differences are almost linear, with change rate slightly being dependent on latitude.
My problem with this equation is it's reverse of what I need - it gives me length of day from latitude, while I have the day length known, with latitude unknown. It looks like there isn't analytical solution to this equation. For now I have plan of having huge precomputed tables in FLASH memory of MCU and doing lookup, but I can't say I'm happy with it, though it can be quite effective when it comes to power consumption.
Today was really nice day with lots of sunshine, melting the snow - and freezing right now during the night, so walking on ice covered sidewalks will be fun game - so skies were clear blue. I know explanation why the sky is blue belongs to kids textbooks, but it's relevant here.
Earth atmosphere does a lot of things to light incoming from outer space, one of them is dispersion. The shorter is the wavelength, the stronger is the dispersion and shortest of visible wavelength is blue light, so the blue light we see overhead is actually a dispersion happening everywhere in atmosphere around, especially when Sun is high above horizon. When it's low, sky is somehow more colorful.
During sunrise (and during sunset too, from the same reason), sun is low above horizon, light from Sun has to travel long distance through atmosphere, where a lot of diffraction happens (and people in "higher" timezones see this light as their blue sky), so Sun looks orange or red, as its light is stripped of shorter wavelenghts. As the solar elevation angle is getting higher, the path through atmosphere is getting shorter, lose of short wavelength is decreasing and sun appears more "white", see on picture taken from here:
and set cone made of blue plastic sheet on top of it, secured by obligatory hot melt glue
and let run for a few days. Here is the logs look like
A is unmodified channel, B is blue channel. The output from blue channel is much lower, probably due to thick and opaque filter. I made also derivation of the output. Blue line is clean channel, red is derivative of filtered channel. It was quite noisy, so I cut down when intensity from filtered output is above 50%. The peaks, corresponding to highest change of blue filtered channel do happen later on sunset and earlier on sunrise as opposed to clean channel - that is, the same algorithm on blue filtered LDR outputs events on higher solar elevation angle than unfiltered. The result is quite noisy, though, due to the opaque filter.
By now I have measurement data from four places - two from Slovakia, one from Spain and one from US; those are the green ones. The orange points are from places where loggers finished their job, but I still haven't them at home.
The loggers doesn't have internal RTC, just timer set to 6 minutes to wake up and perform light measurement, so I had to note the time when the loggers were started before packing, in order to assign timestamps to measurements. Typical record from logger looks like this
This is raw ADC count from LDR channel. The peak at the beginning is light at my desktop in Bratislava when I packed it, the minor light levels measured around points 100, 230 470 and 560 is light leaking into paper envelope during transport, finally around point 1200 the package was open and manipulated; at point 1400 there is first sunrise in Galapagar, Spain. After adding timestamps I blended all available data into single graph, looking like this
This is starting to look interestin. Firstly, the data look reasonable; the loggers were not extensively tested and all it could return with could be all zeroes or some other rubbish. This was not the case, so I could go on. I zoomed at 19th-20th of December:
Comparing to blue line (my hometown), I can make following observations:
1, The sun in Presov, Slovakia (red line) rises earlier and the day is a bit shorter. As it's located slightly northern and approximately 320km eastern, it's quite expected.
2, Galapagar, Spain (yellow line ) has later sunrise and longer daylight. Again, that is not surprising, being ~1500km on west and ~900km southern compared to Bratislava.
3, Clifton park in NY, US: daylight something between Spain and Slovakia, local noon shifted rather right (later), being roughly another 5200km more on west than Galapagar.
So far, so good. Reality is checked, loggers seem to do the job correctly, Earth doesn't seem to be flat. Now I need to dissect the data some more, in order to obtain sunrise and sunset time. This is how single day looks like, blue line is raw value from ADC channel where LDR is connected (right axis), red line is resistance in kiloOhms (left axis, logarithmic scale):
Interesting enough, illumination of LDR in lux is inversely proportional to log of its resistance, meaning the graph of illumination in logarithmic values would look very similar to the blue graph (raw ADC value), just with different scale. For now I won't bother with converting ADC values to resistance of LDR and then illumination, I assume I can use ADC values directly with good accuracy for the purpose of dusk/dawn identification. Because those events are easily identified as change in illumination due to particular place on Earth moving from/to its own shadow, it looks logical to me to search for major changes in illumination, that is performing numerical derivation.
Though this may be nice exercise for machine learning and artificial neural networks, keep in mind I have to choose algorithms that are easy to perform on low-frequency clocked microcontroller.
At first I applied one of simplest FIR filters on input data - running average filter, with 7 samples around midpoint. The difference doesn't look very convincing at first
Differences starts to appear as soon as differentiation is applied:
The blue graph is from filtered data, providing much more stable identification of illumination changes. Previous data combined into single graph:
Blue line is raw ADC count (right axis), red line is difference from previous sample (left axis). I also added "wide" difference, where N-th result is difference between N+1th and N-1th member of input data. I was curious whether this will make any impact on sunrise/sunset resolving accuracy.
Then I "manually" identified all peaks from input data, calculated...