sync your microcontroller to the diurnal cycle using sensor data

Similar projects worth following
RTCs, TXCOs, GPS and atomic clocks are all great in their own ways. But if you have lots of devices you need to have a rough handle on time and will be in a lit place (like outside or near a window) you may like to develop something based on dayTime. This is Work In Progress - and progress looks slow when you need to stop for a year to collect readings!

dayTime started when I had a project that involved deploying many identical devices with no communication function and no ability for the deploying user to easily set the time on an RTC. The microcontroller involved had no special abilities when it came to timekeeping and its low power oscillator used for sleeping was even worse. But as long as I could keep the devices roughly in time (ie within a few hours of accurate time) the features would work fine.

I cannot believe this work is original as people have been synchronising things to the sun for eons but I genuinely struggled to find anything analogous to it when I started out.

Wouldn't it be cool to sync a project to the rotation of our planet with respect to its star? Of course! But it turns out it could also be useful, from a timekeeping perspective in cheap, low power electronic systems.

The devices I was using had the option of running a separate real time clock (RTC) on them, and they also had a light dependent resistor (LDR) voltage divider attached to the analogue to digital converter ADC. Although the RTC was accurate (DS3231) and attractive, the inability to easily let a user who was changing the batteries set the time (and a battery backup wasn't an option I entertained for long) meant I was very keen to explore rough time sync with the LDR. It was also much cheaper, on a tight BOM cost.

Thus began my search for a way to keep my microcontrollers from drifting off after days, weeks or months deployed, using daylight as the synchronising signal.

This project is a summary of my progress so far, links to useful resources and an introduction to some of the challenges, concepts and terms encountered along the way.


These are the readings from a 20kOhm (nominal) Light Dependent Resistor taken simultaneously with a TSL2591 light sensor using various configuration settings and then used to map Lux levels to anticipated ADC readings, if the LDR were installed in a voltage divider. Used to simulate a year of ADC readings using solar radiation data as the input.

sheet - 196.37 kB - 04/25/2021 at 16:03


This is an "as-is" Arduino project zipped file. Unzip and make sure all files are in the same folder. There is a sketch which implements some test functions to filter the simulated ADC data (converted from actual solar radiation measurements).

x-zip-compressed - 12.35 kB - 04/25/2021 at 15:58



This is an "as-is" spreadsheet of the solar radiation (W/m2) data from the London photovoltaic study dataset, with conversion to simulated LDR voltage divider readings to process with a microcontroller. There are also tabs/sheets to try different averaging filters etc to try and normalise/find phase markers in the data. There are graphs to help visualise where these points are.

sheet - 4.44 MB - 04/25/2021 at 15:45


  • Getting to grips with some real ADC readings

    Simon Merrett04/25/2021 at 21:31 0 comments

    This is a placeholder log which I promise to expand on later. For anyone keen to get their hands on the data now, please find it at:

    Where you can find RAW 8 bit ADC readings from my Itsybitsy M4 datalogger. I have a year of readings but they are not all nicely spliced together - yet. That will come. 

    For now, you can see from this graph that we have some lovely data with the days and nights clearly differentiable:

    The real world response of the LDR voltage divider turned out to be much better than the simulated ADC (well, converted from solar radiation data)! 

    A couple of other notable observations until I come back and expand this log:

    • You can clearly see the changing length of days in the data - so the algorithm will still have to handle that.
    • You can see rare measurements where we had the light on in that room after dark  - and it doesn't seem to be an insurmountable outlier, which is reassuring!

    Back soon to expand on this data and the implications for syncing our microcontrollers to the rotation of our planet!

  • Reading a real sensor

    Simon Merrett04/25/2021 at 17:45 0 comments

    While converting to simulated LDR/ADC readings and playing round with different algorithms to find the daily period and current phase from the simulated readings is OK, it would be good to check that a real sensor and ADC would yield the same data. We need to validate the conversion from W/m2 -> ADC counts we conducted in the log Algo's First Dataset

    It has taken me several logs to set the scene, but we are finally about to log some of our own data! Almost any microcontroller has an ADC and could be used to measure a voltage divider between a fixed resistor and an LDR. However, I wanted one that would be able to store the data for me reliably and allow almost continual logging for a year. I could have used an SD card connected over SPI to record data, and perhaps I should have done that  - you certainly could if you want to record your own data. 

    However, I had an Adafruit Itsybitsy M4 on hand and it has a nice QSPI flash memory chip onboard that plays very nicely with the Adafruit spiflash library. It is very much overkill for this application but it would be powered from a mains supply and the convenience made it worth it. I used it to make a small sketch that saves LDR readings to flash every 10 minutes, after waiting an initial period to see if you want to download data from it. If you plug it in to a PC and start a serial terminal within 20 seconds, it pauses readings and you can use a few single letter key commands to get it to print out all the readings in your serial monitor. You can also key a command to delete readings after you have copied and pasted them out of your serial terminal. If you choose to leave the readings on the flash chip, the next time the board powers up and does not detect a serial connection (ie it is expected to start logging again) it will record a "new session" line in the file record to hopefully help you keep track and not double count readings at the next download event. That said, my readings are not quite aligned/trimmed for any recording overlap so please forgive that - I do intend to clean them up. 

    Here is the simple LDR-10k resistor divider:

    And how it looks on it's sunny windowsill:

    As you can see - it has all the dusty hallmarks of having been sat there for a year!

    The overall setup is coarse but I will show you anyway. You do not need much to get going with dataloggin'!

    The Itsybitsy has seen better days!

    I have uploaded the sketch for this datalogger in the files area for this project. Please use as-is or as a basis for your own simple light logger. 

    We will look at the readings this logger took over a 12 month period in a future log.

  • Looking for the dawn in simulated ADC readings

    Simon Merrett04/25/2021 at 16:08 0 comments

    In the previous log we looked at how I attempted to simulate the ADC readings from an LDR by taking a year of solar radiation data from a photovoltaic study, converting coarsely from W/m2 to Lux, characterising an LDR against the TSL2591 and then using that to convert to the expected ADC readings under the sun on those days recorded in the photovoltaic study.

    In this log, I will show you how I started to apply filters to try and pick out data phenomenon that would be easy for a microcontroller to discern as a particular phase point in the day.

    For our first graph, we're looking at W/m2 values on the left side - we are still in Excel here, not on the microcontroller. This is a plot of a week in Jan 2014 in London, with the raw readings in blue and then increasing windows over which the readings were averaged, for 3 hours, 6 hours and 12 hours. 

    As might be expected, averaging smooths out the double peak seen during the first day on the left side of the graph, although it introduces a phase shift and reduces the magnitude of the peaks. 

    You can even apply a basic threshold, such as checking the previous reading was below the last 24 hours median and this reading is over it:

    But as you can see, there will be times when a dull day does not get a trigger if the day before was bright and some days apparently double trigger (probably due to bright then dark then bright again spells).

    So averaging on its own is of limited use.

    Next I looked at measuring the steepness and direction of the slope - is it getting brighter or dimmer? After all we are looking for things like dusk/dawn as markers of the time of day. This is effectively a measure of the curve's derivative but for a time unit of 1, we don't need to divide anything:

    This is the same first week's data from the first graph - including 3, 6, 12hr averaged values -  in derivative form. Nice - looks like some zero crossing we could exploit. But there is some double zero crossing for 3hr filtered values and we still have lag. Not saying something else will fix lag but we should not forget it is there.

    I need to pause this log here and will return to add details and graphs of some more promising looking filters, as well show how some filters look good at one point in the year but seem not to work the whole year round.

  • Algo's first dataset

    Simon Merrett04/25/2021 at 10:47 0 comments

    So far in this project I have touched on the requirements, initial challenges and potential algorithms for synchronising a basic microcontroller's time to the 24 hour clock, based on daylight cycles. What I have not yet done is shown any data. And that's because, at the point in this story we have arrived at, I didn't have any....

    I tried to get some data, I really did. But daylight data that you can use to test a synching algorithm with isn't quite as easy to come across as it sounds like it would be. I set myself the target of a year's worth of data, so that I could check this algorithm would work on short, dull winter days as well as it would on long bright summer ones. I trawled for open datasets of daylight readings but could not find anything which would give lux at a reasonable resolution - I considered 10 - 30 minute intervals to be a reasonable resolution so that intermittent cloud/precipitation had sufficient chance to introduce noise. And a 10+ minute wake-up interval would be reasonable for microcontrollers to perform to take light readings. 

    Sure, you can find out the average number of sunshine hours on a given day of the year at a given meteorological location, but I came up short for actual readings with all the noise and variability that a real system would have to dredge through to find the signal. By the way, I was focused on UK so if you have that data for other places, please link it in the comments here - hopefully it will help someone, if not me.

    What to do?

    Getting slightly desperate, I wondered if solar photovoltaic power production could be used as a proxy for light readings. I found that people were much keener to write and publish reports with supporting data on photovoltaic domestic electricity generation than they were about general light levels. And so it was I ended up downloading a dataset of insolation (solar radiation power) at half hourly intervals from a study of domestic photovoltaic installations in the UK (London) in 2014. Here is a link to the source:

    What I like about this is that it gives solar radiation in W/m2 - great stuff. However, I needed to approximate ADC readings from this - ie what an LDR voltage divider would produce as a response to these power (power density?) levels. I could not think of a good way to approximate from W/m2 -> 10 bit ADC counts from a non-linear sensor like a CdS LDR voltage divider, so I took an intermediate step (read - rabbit hole) and attempted to convert W/m2 to Lux before approximating Lux to ADC counts.  

    Converting to Lux

    There is a not a straightforward conversion factor - ie linear proportional relationship - between W/m2 and Lux. However, I settled upon using one for my first run at this. I apologise that I cannot provide the source after a year has passed but I used 0.0079 W/m2 per Lux.

    Once I had W/m2 in terms of Lux, I needed to know what my LDR voltage divider "would have been" reading if it had been out in the sun at the YMCA in London in 2014!

    Converting to Volts

    The best light sensor I had access to at the time was the TSL2591. To put it mildly, this is not the simplest sensor to derive a reliable Lux reading from. You will see much discussion on the Adafruit library repo issue about how to get a reliable Lux reading from it. 

    I decided to take matters into my own hands and characterised the TSL2591 sensor against formal photometric standards :

    Essentially we are trying to take the datasheet's sensor characteristics and map the sensor's response to known brightness values. I used the awesome to perform this conversion of datasheet curves. Big thanks to @Jenny List for her article bringing...

    Read more »

  • Kalman filters are overkill?

    Simon Merrett04/24/2021 at 18:50 0 comments

    I saved this for a separate log because I would like to return to this topic once I have brought the rest of the project up to date. 

    Kalman filters are well known and regarded for their ability to quickly adapt state estimations (ie the filter output) to legitimate signal, amongst noise. I had been wondering about this for some time when I posted a .stack entry to solicit input from the community over a year ago:

    For now, I will leave you with that exchange of thoughts and promise that I will return to the topic - when I do, any further wisdom from you in the comments here would be most welcome!

  • What options are there for synchronising a clock with sensor data?

    Simon Merrett04/24/2021 at 11:21 5 comments

    Once I had decided I wanted to synchronise my microcontroller with daylight levels as a proxy for the 24 hour clock, I needed to find a technique to get from sensor readings to a time of day.

    Initially, this may seem like a problem of frequency measurement - we just need to measure how many microcontroller "periods", such as wake ups / timeouts / timer interrupts occur in a single cycle of daylight. But it is not quite that easy and I'll come back to this. 

    Pattern matching for basic microcontrollers

    Before I get back to the main story, I want to cover some of the interesting "dead ends" I found while doing my initial searches for techniques to synchronise my data, which I anticipated would have clear periodic trends, using a microcontroller. If you are doing something similar or slightly different, this may be of interest. 

    Firstly, I looked for frequency detection/measurement on basic microcontrollers (by which I mean something like the ATMEGA328P would be a typical example). Loads of audio applications want to do something like this for instrument tuning or spectrum analyser and cool visual effects to accompany the music. Here are the sort of progressions you may find useful:

    But none of those seemed quite right when I dug deeper into dayTime.

    The first issue is that we are not just measuring frequency of the daily light cycle. We want to synchronise, or lock-in to the phase of the cycle too. So this is one task or feature we need. The frequency detection didn't do this out of the box and the FFT did not do this at all. Autocorrelation and frequency detection might have been able to to phase lock with some more work.

    The second challenge is that our readings are not going to produce nice regular patterns. This is obvious from the fact that we get dull and bright periods within each day (noise) and that the overall proportion of daylight in a 24 hour period varies from winter to summer in most parts of the world (seasonal). It is akin to a varying pulse width modulation duty, where the duty represents the hours of daylight and the fixed frequency represents our 24 hours:

    Source: By Eighthave, modified by Teslaton - Modification of Image:Pwm duty cycle.gif, Public Domain,

    With wildly varying levels of light (large dynamic range) between winter/summer and within clear and stormy days, none of the options above looked like they would reliably identify daily periods and phase points.

    Looking for something which would provide a phase locked loop, I found the wonderful #Software Phase Locked Loop project by @agp.cooper . Although I did not go through with a build based on this, I learned a great deal and would recommend you check out this project.  Top tip: another helpful search term for you - "product detector" might be something you want for fast locking/correlation.

    As I was researching all this, I...

    Read more »

  • What's the problem with microcontroller time-keeping?

    Simon Merrett04/24/2021 at 01:29 0 comments

    Low cost microcontrollers rarely have good enough built-in timekeeping clocks/oscillators/peripherals to keep a system within a few hours after many months in the field. You often find comparisons of the clock drift for a given microcontroller. Discussion will be about how many parts per million accuracy the clock/oscillator has. 

    The bottom line is that whether you use an internal clock, an external ceramic resonator or an external crystal, the accuracy is not going to work for this. For example, in Jeremy Cook's simple and clear explainer, a standard Arduino UNO would drift by up to 7 minutes per day. After a month we could be well out of the "few hours" I would have liked to keep within*. There is more to clock accuracy, and you can make some educated guesses to minimise the effect of drift if you keep track of temperature and maybe supply voltage but it won't improve the accuracy by the orders of magnitude I am looking for.

    Even if those sources were accurate enough, there would not be an easy way to sync them to the time of day (waterproof enclosures, no buttons etc). That said, you could "prime" a technique like dayTime by ensuring that power was only applied within a certain window of  time within a day. That would seed the system with a "certainty head-start" but nothing that wouldn't be negligible after a day or few.

    Just to quickly justify why GPS wasn't considered: unit cost and power budget. My devices often have to sleep for long periods, and I expect many of your dataloggers or sensor nodes have to do the same. This brings me to the conclusion of "What's the problem with microcontroller time-keeping?"; if you thought main clocks were poor time keepers after reading the above, wait until you see the specs for the low speed oscillators the sleep modes rely on...

    * Please don't ask - I can't really say what the application was. Suffice to say that the project went ahead without dayTime built in and the idea has outlived the project which conceived it!

View all 7 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates