Please, do not post elsewhere the code found here.
– The code should reside in one place and people should use links to my site instead. I have a hard time browsing the Internet for pieces of code sometimes, and finding old or obsolete code instead of links to the original developer is always a pain in the ass.
– I expect people to comment on the code and make optimizations/new developments, especially for student usage. Having this in mind, the code itself is an ongoing process which can be followed by students, from its first state (intelligible, but unoptimized) to its latest state (optimized, but unintelligible). Many people asked me how the code becomes awful and almost impossible to understand. It is my chance to show that I always start from a human approach and I am ending to a computer approach, and that this is always an endeavour that takes time and patience and endless computations and verifications, it doesn’t just come from thin air.
– the last reason is that I collect stats on page visits and downloads, which show me where to insist with open source development and where not to. I cannot collect stats from foreign sites, nor do I wish or have the time to do so.
I have bought 3 pieces of SKU14220 – DIY 4 Digit LED Electronic Clock Kit Large Screen Red Blue Green LED from banggood. At ~ US$12, it seemed a good deal and most interesting. Following my experience with the EC1204B clock, I was almost sure the firmware was going to be bad.
Bad is a nice thing to say. The firmware was horrible:
– it doesn’t show day/month/year;
– the setup is tricky and not easy to remember/understand;
– it lacks temperature;
– many people comment it is too bright during the night.
– the STC 15F204EA processor was a bad choice. 4K of flash do not suffice to build a nice and comfortable firmware for the end user, in my experience this design needs an processor with at least 8k flash.
So I decided to modify the latest firmware for the EC1204B clock and make it available for this version, with the necessary modifications.
Figure 2 – SKU142210 clock assembled – top view
The software/firmware presented here is a complete rewrite from scratch, just by observing the schematic and by understanding the way it works. It did not involve any kind of disassembly of the original firmware, reverse engineering or other similar stuff.
I do not condone copying the work of others in any way. However, progress is difficult to achieve these days from zero and it is easier to build up on something that already exists, while respecting the original work and effort.
I advice my readers to buy Banggood kits, the PCB has an excellent quality and all the parts delivered will be used, even with the modifications I suggest in this post. The idea is to start learning soldering and coding using affordable ressources.
2. Hardware modifications
Video 1: The modified clock
After studying the schematic, it became obvious the only thing that needed to be replaced was the processor itself, with another firmware.
I couldn’t find any Atmel processor compatible pin to pin with the original, STC 15F204EA processor. The available place to insert a custom PCB in the processor’s slot is also narrow, so space would be of the essence in choosing a replacement processor.
This is why I have decided to use an ATmega8 AU, which is the smd version of the ATmega8.
Supplementary, a DS18B20 was added to measure temperature along with a photo-transistor, to implement automatic dimming of the display.
From a mechanical point of view, the programming pins were designed to go through the plexiglass wall, in order to allow programming of the device even when it is fully enclosed, without the need to disassemble the enclosure (see Figure 3 above).
2.3 The actual PCB
Figure 5. The bottom side of the PCB
Figure 6. The top side of the PCB
The software, or firmware, is a variation of the software used for the EC1204B clock, in a previous post of mine.
Disregarding the process of eliminating pieces of code that did not apply to this particular clock, the two main additions are:
-the implementation of analog reading from a photo-diode, quite straightforward process;
– the implementation of digital dimming a multiplexed display.
A few words about the latter. The problem was to dim the display without having disturbing light shifts.
How it was done: In a multiplexed display, only one digit is lit a a time, with the specific data for that digit. Then, we go to the second digit and so on until the last. Basically we have an eternal cycle of lighting each digit at a time, cycle equal to the number of digits to be lit. What if we would add to this cycle “dead” times, when we don’t lit any digit? The result will be a software pwm on the multiplexed digits, up to the point when all the digits start to tremble. After a few trials, I have discovered that this has to stop at around 50 cycles. After 50 cycles, the dimming process isn’t perceived by the human eye, but it inserts this trembling of the digits.
The relationship between the level of light and the dimming is a simple transformation of the first degree, where dimming is inversely proportional to the level of light. The actual parameters are decided by experimenting. In this particular case, I had:
0 light -> 50 dimming cycles
50 light -> 4 dimming cycles.
The transformation became : cycles = (54-light), which is a rough approximation of the hypothesis above. A supplementary condition is also in effect, after reading the light value:
if (light>50) light=50;
This was necessary from direct observation: at 50 light, the display was too dimmed and the light value (0-100) didn’t correspond well with the dimming if it was to be used full scale.
Feel free to play with the code and try to modify and optimize it. I hope it is easy enough to understand after 1-2 hours of study, in its most intimate details.
4. How it works
The upper button is the “set” button. The lower button is the “select” button.
- Pressing the Set button will cycle between the DS18B20 temperature sensors present at start up. On the board there is only one sensor, but you may solder several other sensors, all connected in parallel, and the device detects them at start up.
- Pressing the Select button will enable you to program the microcontroller:
- A short press (less than 5s) will show the date and month. Pressing it again will show the year. One more press reverts to clock display.
- A longer press (6-10s) will enter the alarm set mode. Press set to cycle between alarm hour, minutes, alarm enable and memory storage. Press select at each stage to cycle possible values (0-23 for hours, 0-59 for minutes, on/off for enable);
- A longer press (11-15s) will enter the clock set mode. Press set to cycle between year, month, day, minutes, hours and memory storage. Press select at each stage to cycle possible values;
- A longer press (16-20s) will enter display mode. Press set to cycle between on, off and memory storage. Press select at each stage to cycle possible values;
- A longer press (21-25s) will enter the temperature unit select mode. Press set to cycle between C,F and memory storage. Press select at each stage to cycle possible values;
At each stage, the last select key press is the memory storage. After storing selected parameters, the clock will beep. If you fail to store parameters (i.e. you do not press the button), the parameters will be in effect until the next reset of the clock.
All the project for Atmel Studio 4, including a PDF with the PCB printout and necessary datasheets for parts (DS1302, DS18B20) can be downloaded here.
Following Bob Pike’s request to have the firmware show temperatures in F instead of C, the code was modified with the possibility to program the temperature display unit. The latest version can be downloaded here.
Last edit: 18.04.2015
6. Semi-automatic software drift compensation
Many people (including me) complain about the DS1302 drift, related to badly manufactured quartz resonators that do not offer a real 32 kHz (32768 Hz) clock.
The drift may become so big, a clock can have easily +- 10 minutes drift in a matter of months. Having two or more clocks in different rooms may easily lead to headaches in the morning when the decision to leave for work becomes a growing pain week after week.
The best practice would be to insert a trimmer capacitor in series with the quartz and set it to obtain a 32768 Hz clock. Even this practice is prone to errors due to:
– bringing a metallic screwdriver next to the trimmer alters its capacity. After setting the trimmer it would change its capacity again, hence the clock;
– normal trimmers are influenced by temperature. Just a little, but enough to generate a 1-minute drift every month or so;
– usually there is no or very little space on the PCB to insert a trimmer properly;
– the DS1302 clock could stop if a trimmer inserted in the circuit.
I have imagined a software solution to the drift, by calculating it in between two clock settings.
I began by asking myself what would be a disturbing drift, and I came with 5 minutes per year at a minimum, as being disturbing. However, setting the clock every year wouldn’t be too much to do, since I already set the clock twice a year when the daylight saving time appears and disappears.
5 minutes per year would mean a drift of roughly 5*60/12=25 seconds a month, less than 1 second per day.
Since the setting is done manually and one could press the set button with a 1 second drift, if the setting would be done after 20 days, it would lead to a supplementary error drift of 365/20=18.25 seconds a year, which is less than a minute per year: it wouldn’t even be noticeable.
The whole idea is to set the clock twice in the same month from a good time source (like your PC, after synchronizing its time with a time server). Why during the same month? Just to make the subroutine that computes time difference easier and less flash consuming. Anyway, there’s less than 1K of flash available for this with this project.
So: you set the clock on the 1st of the month and then you set it again on the 20th or 30th of the month.
The software computes the time difference from the two settings, which were made using a good time source and it will also compute the time difference the DS1302 has run, thus determining the time drift in a given period of time (let’s say 34 seconds in 28 days).
28 days equal 28*24*60=40320 seconds
So we have a drift of 34 seconds every 40320 seconds, which means a drift of 1 second every 1185(.88) seconds.
The clock will remember this drift and the processor will either add or subtract (depending on whether the drift is positive or negative) one second every 1185 seconds, by reading and rewriting the seconds in the DS1302.
Two errors are now in place:
– a 0.88 second (from rounding 1185.88 to 1185) every 40320 seconds, leading to roughly 12 seconds a year: almost non existent;
– a supplementary error drift from manipulation of the setting button of 365/20=18.25 seconds a year: almost non existent either;
In fact, this kind of semi-automatic drift compensation can lead to an error of at most 30 seconds a year, much lower than we could obtain by inserting a trimmer and setting it to achieve a 32kHz clock for the DS1302. We would experience annoying drifts in 10 years of non-stop operation of the clock.
What if we set the clock in different months? The software compares the month and the year of the last setting and the previous one. If these do not match, the clock drift is set to zero and there is no automatic drift compensation. A new clock setting in the same month would trigger a new drift computation and automatic drift compensation.
What if we set the time more than once during the same month? The software would take into consideration the last interval between two settings. If the interval is too low (e.g. 3 days) it could lead to a wrong computation of the drift compensation.
In order to set the drift compensation to zero, please operate two consecutive settings one after the other or by changing the month or year.
This version of the firmware can be downloaded here.
7. Bug fixes, additions and optimizations
While working on my other project, the EC1204B Led rotating clock and implementing some requests from my readers, I have discovered ways to improve the code and also minor bugs that were addressed.
- the code to multiplex the data on the display was optimized;
- there was a bug while displaying temperatures over 100. It was fixed.
- the colon display was modified. Now the colon displays whenever a second starts instead of displaying it on odd seconds only.
- Peter Casper had a request to alternatively show the clock and the temperature, for he wishes to use the clock in an infrared-heated room.I thought using the same idea as above, so a new EEMEM variable was defined and if at programming time it is equal to 1, it fires a condition in the main loop that shows the temperature for 1 second every 10 seconds. It displays just with one (or the first) temperature sensor.Some optimizations to the display routine were also made.Because this firmware is about to hit the available flash memory in the mega8515, I had to look closely of the size of the binary data that was about to be burned into the MCU. How to do this, since the HEX file size has nothing to do with the size of the binary code? I have written this morning a Windows tool that converts Intel HEX files to binary and viceversa + it allows for automation…well, silent repetition of a load and save operations. I know, I am lazy, that’s why I wished for automation. Find what it is all about in this post.This version of the firmware can be downloaded here.
8. Combining all latest developments in one and allowing for setup without the need to reprogram the flash
While working on the latest requests for US mode (12H display and Fahnrenheit instead of Celsius), I used EEPROM variables to shorten the code and allow for its implementation. Unfortunately, to change these modes, the clock needed to be reprogrammed.
After many optimizations, I have succeeded to implement a way to set these modes without the need for a programmer.
Toggle between US and EU mode is now done from the menu itself:
- EU mode displays 24H and Celsius. Setting the clock and alarm shows 24H.
- US mode displays 12H and Fahnrenheit. Setting the clock and alarm shows 12H with A or P indicator for AM/PM.
Resetting the clock while pressing the SET key will toggle between regular clock display and clock/temperature display (temperature is displayes for 1 second every 10 seconds).
Enjoy downloading the latest firmware, datasheets etc, here.
At this moment, the firmware has 8160 bytes, further development on this firware being almost impossible, at least with the ATmega8.
9. It becomes a never ending story, huh?
Following the latest developments on the EC1204B clock, a new set of improvements to the code were added:
- the code was optimized, again, to lower its size;
- the ghost digit disappeared;
- the clock can measure now negative temperatures on both C and F;
- toggling between EU and US modes may also be done by keeping SET pressed at startup. It can also be changed from the menu.
Enjoy downloading the latest firmware, datasheets etc, here.
Last edited 17/01/2017