I have already made a lot of progress. Today I designed the following circuit to generate a 60 Hz square wave at a safe 5 V logic level:
I tried adding another transformer to the circuit above to serve as the power supply as well as the clock signal, but the two transformers are getting awfully hot. It seems dangerous, so it looks like I need to try something else for a power supply. But the good news is that I have finished building the low-order LED display digit.
The prototype with microcontroller, LED driver array, and the low-order numeral of the display.
|Closeup of the low-order LED numeral I have finished so far. I still need to figure out how to diffuse the light from each LED into a bar shape.|
|Microcontroller and LED driver boards.|
|60 Hz digital pulse generator.|
I have decided to post the source code for the digital clock firmware here:
I will keep this firmware up to date as I make changes and fixes. I know for sure I will need to make changes once I start adding push-buttons to the clock hardware.
Tonight I hooked up the completed LED numeral first to the outputs for the hours digits, and then to the tens of hours digits. I found a mistake in my wiring plan due to the fact that the digital outputs of the STP16C596 wrap counterclockwise around the chip. From left to right, one side of the chip has the pins going from 1 to 12, but on the other side they go 13 to 24 right-to-left.
I also modified the firmware tonight to actually render the digits other than the low-order seconds numeral. At first I was getting upset because I thought something was wrong with the circuit, but then I realized that it had to be firmware since the power-on test showed the numeral 8 (all LEDs turned on) as expected. I enhanced the power-on test to display the numeral 8 for two seconds, then count from 0 to 9 for half a second each. This way, not only can I tell that all the LEDs are working and connected, but that they are wired to the correct output pins.
Just to finish off the evening with something easy and mindless, I hammered in the nails for the tens-of-seconds numeral, or digit 1 as I call it. The digits are numbered as follows:
Tonight I printed out a copy of my LED mask (the same one seen glued to the board in the photo above) onto card stock. I chose a pastel blue color, but I glued it to another piece of card stock that is red, which will block a lot of the light from the green LEDs. I am experimenting with using an exacto knife to slice out the hexagonal holes. In hindsight, it is obvious to me now that the result will be very delicate, because there are two squares of paper each hanging by four thin tentrils of paper inside each numeral. I am going to try taping both sides of the result with clear plastic tape to reinforce this mask, and to scatter some of the light so people don't just see bright circular spots of light.
Here is a PNG version of the mask, which is not as good looking as the original SVG file, but a lot browsers (okay, I mean Internet Explorer) cannot display SVG files.
I just finished the first draft of the plan for the LED driver board, using the Radio Shack circuit board:
Below is my first revision of the CPU board. I still have plenty of space left over to add extra stuff. I am thinking of working in a speaker and oscillator for making audible tones.
Now I have gathered all the components I need for the CPU board and snapped them into a breadboard for prototyping. I have not yet wired up the connections, though. Once I do, I will burn in the bootloader. The sanity check will be seeing the green LED blink every time I press the reset button.
I have decided to try to use some of the space left on the CPU board for a simple audio oscillator. I want to allow the microcontroller to turn a 1 kHz tone on or off using one of its digital outputs. I know I could use a 555 timer chip for this purpose, but I thought it would be interesting to make this out of discrete components. I have the following as an idea, but I have not tested it yet:
I finally managed to get the bootloader burned into my four ATMEGA8 microcontrollers. I am using the Arduino home-made parallel port programmer hardware. I ran into some weird problems with the Arduino 11 software saying:
At first this forum post gave me hope. I applied the registry patch for Windows XP that is mentioned on that page, but to no avail. Then I found Dybkowski's ISP Programmer software and installed it. I noticed during the installation that it said something about installing giveio.sys, so on a hunch, I tried launching Aurdino again and lo and behold, the error had magically gone away and everything worked perfectly!avrdude: can't open device "giveio" avrdude: failed to open parallel port "lpt1"
Then I decided to go ahead and get the bootloader burned into the other 3 chips also, since I had finally got this thing to work after 2 hours of frustration. I learned something else in the process that is worth mentioning here: The avrdude program reported that I had the wrong chip version, the signature didn't match, blah blah blah. It turned out I was a bonehead and did not unplug the power and the parallel port before popping the new chip in. My heart sank, thinking I had fried the poor thing. But I soon found that all I needed to do was unplug the ground wire from the parallel port, along with the positive terminal from my battery, then reconnect the battery and then the parallel port ground. After this, the bootloader burned in without any errors!
Soon I had all 4 chips with bootloader burned in. As expected, after each burn I saw the LED pulse every 10 seconds, indicating that the ATMEGA8 is ready to download code from the serial port. This seems like a good stopping point for me to go to bed. Tomorrow morning, after the traditional Saturday bacon, eggs, and coffee, I will get the serial port hooked up and burn in some simple test code that turns the LED on and off in an infinite loop.
I did a lot of work on the project this weekend. I built out the new power supply, but I am still running into problems. There were a couple of times where the ATMEGA8 somehow lost its internal programming, and I lost a couple of hours when suddenly I could no longer upload new firmware via the serial port. First, the ground pin on my home-made serial cable suffered metal fatigue and broke off. Then, after fixing that, serial code still did not upload. I finally tracked it down to the 7404 hex inverter used for translating RS-232 data into logic levels suitable for the ATMEGA8: it was totally non-functional when I ran simple tests of feeding 0V and 5V into its inputs and probing the outputs with my multimeter.
I find it disturbing that I don't know what I did to fry this chip, or what other damage I might do. One theory is that my home-brew power supply is not handling transients properly when I plug or unplug the power cord. Another possibility is that I accidentally mashed some exposed resistor terminals together. I also believe I had some wires backward on the 7404 (had input and output swapped), but I don't see how this could have hurt anything.
Some friends from work are going to go to Skycraft with me on Wednesday afternoon. I will stock up on some more 7404 hex inverters, get myself a commercial wall adapter that outputs 12VDC at 2 amps, along with a low-voltage AC outputting adapter. The power supply isn't really the most interesting part of this project, and I don't feel like I really know what I'm doing in that regard. I don't want to ruin my whole project over something dumb like this, even if it means that I have to junk my second attempt at a power supply, find a new piece of wood to mount everything, and have 2 plugs to plug in.
On the side of good news, I did solder the CPU part of the CPU board: the processor and hex inverter are sitting snug in sockets (easy to replace in case I burn them out too). I was able to boot it up, see the green LED blink, then the red LED turned on, correctly indicating that there was no feedback from the LED driver board, since that wasn't hooked up. This red LED is something I added this weekend; I modified the hardware so that the serial data out (SDO) pin on LED driver chip #3 feeds the previous low-order LED bit back into the ATMEGA8. I modified the software to check to make sure this bit is what we know we sent in the previous display update. If there is a bit mismatch, I turn on the red LED and leave it on. Later on I will probably come up with distinct blink codes for different error conditions.
I still need to figure out a good way to mount connectors, especially for the LED driver board, because I don't want to have to solder nearly 50 wires into it. I would rather have pins sticking out of the board that I can snap connectors onto. This will also be handy for the 4 lines needed between the CPU board and the LED driver board, as well as the 3 lines needed for the serial port on the CPU board.
I started an experiment that will allow me to have a custom serial port design that places less mechanical stress on the digital clock when I am connecting/disconnecting the serial cable. Also, as mentioned before, I have had problems with my home-made connectors breaking due to metal fatigue. I found a 4-wire telephone plug and cable, and a standard 9-pin RS-232 cable. I cut both cables in half. I took the female end of the RS-232 cable (since it fits the male side on my laptop) and soldered the 3 relevant wires from it to 3 of the 4 wires on the phone cable. Because the wires in both cables are so delicate, and the solder joints would not withstand very much tension, I carefully taped up each solder joint with electrical tape, then taped the whole junction to a popsicle stick as a splint. It looks goofy, but it certainly protects the junction from coming apart. The two ends of this custom cable are factory made and are unlikely to have any mechanical problems. Tomorrow night I will try hooking it all up and making sure it can transfer data reliably.
I dug through some of my junk boxes last night and found two wall adapters that I can use instead of a home-made power supply. One outputs 9VDC at 1000mA, and the other outputs 9VAC. I can use the 9VDC for primary power, and the 9VAC one for the jiffy pulse. So this saved me about $20. I even found a power strip that can accomodate both adapters, allowing me to have a single plug going into the wall.
I started soldering together the permanent version of the CPU board. I am happy to report a successful power-on test and serial upload of firmware, and two-way serial communication with the software running on the board. I did not yet supply a timing signal, and the LED driver board was not connected, so the red error LED turned on as expected. I still need to add the circuitry for converting the AC timing signal into a digital pulse. Here is what it looks like so far:
|CPU board, partially assembled. More components will be added in open space to the left.|
|This is the updated board plan that matches the photo above.|
I left work early today and went to Skycraft, where I spent about $35 on lots of itsy bitsy parts. I bought a bunch of rectangular lens yellow LEDs, and I am thinking about switching over to using them for the LED display, but I am not sure yet. The bulk of my purchase was connectors of various kinds. Most pleasing were a bunch of 8-pin connectors and sockets that I can use for hooking up the LED drivers to the LEDs. This will allow me to test everything, then disconnect for final assembly, then reconnect.
Tonight I soldered together power connectors so that I can plug the AC and DC adapters into the digital clock. I did not get much sleep last night, so that's all I am going to try to do for now. It is a good enough, smart enough accomplishment, and gosh darn it, I like it!
In reading more about transistors, I learned that they can often have a reverse-bias breakdown voltage of 5V or so across the base-emitter junction. For this reason, I am going to try a slightly different approach in the jiffy pulse generator design. I am going to substitute a diode for one of the resistors, as shown in the schematic below. Note that I have also removed the step-down transformer, because I am using off-the-shelf wall adapters for all my power from now on. I am no longer in the power supply design business, thank you very much! Even though the adapter outputs a nominal 9VAC, that is its voltage rating at several hundred mA of current draw. I am going to draw less than 1 mA from it, and under such a small load, the multimeter shows over 11 volts. My change in the value of R1 allows the transistor Q1 to be switched on for a slightly wider duty cycle, i.e. closer to 50%. The diode limits the reverse bias voltage to about 0.6V.
|Jiffy digital pulse generator, now using diode to protect Q1 from excessive reverse bias on B-E junction.|
Now that I have all my fancy-pants connectors from Skycraft, I have modified the LED driver plan to use 8-pin connectors for all the LED numerals, and a 4-pin connector for the serial interface to the CPU board:
I got a lot done this weekend on the project:
|Digital clock motherboard. Three of the red connectors on the LED driver board are absent because they are currently connected to the LED display itself, which is still under construction and is not pictured here.|
The only odd problem I have run into is that occasionally my ATMEGA8 program memory gets corrupt sometimes when I turn the power off and back on. I did some reading in the ATMEGA8 data sheet, and it turns out that this can happen when the voltage gradually decreases from 5V to 0V. The processor can start executing instructions incorrectly, causing it to overwrite its own code. The ATMEGA8 has its own internal brownout detector, but to enable it requires re-burning the Arduino bootloader code with modifications to the fuse bits. I am a bit leery of making custom bootloader code, but it would have the benefit of working without any extra hardware. My other option is to build my own external brownout detector circuit, and have it pull the ATMEGA8 reset pin low when the supply voltage drops to a dangerously low value.
I think I found out how to enable the internal brownout detection with a 4V threshold on the ATMEGA8. I posted this message on the Arduino forum explaining what I did. So far it seems to work — I have turned the wall adapter on and off several times with no program corruption detected yet. To really test this, I will need to contrive a variable voltage source, start it out at 9V, and gradually decrease it until the output of the voltage regulator reaches 4V. At that point, the chip should immediate enter a RESET state and stay there until the voltage goes back up to a safe level, at which time it should reboot.
Tonight I experimented with what to do when the AC power goes out. This is an unfortunately common occurrence in the rural Florida town where I live. Every time there is a thunderstorm, you can count on several power outages lasting a good fraction of a second each. So I added a couple of diodes, one to allow current to flow out of the battery only, but not backward, and another to do the same for the wall adapter's positive supply line. When the wall power is available, I do not want it overpowering the battery and charging it up excessively. When the power goes out, I want the battery to take over instantly and keep the clock moving forward as accurately as possible. Later on, if I know what I'm doing, it would be nice to make this a safe battery charger.
More interesting to me is a change in the software to have an internal timer take over when the external 60 Hz timing signal is absent. I did some creative math with the Arduino timer overflow counter. It is a 32-bit signed integer that gets incremented on every timer overflow, which is exactly 1.024 ms. I worked out the math such that every time I see the timer overflow change, it means I have completed 1 timer tick, so I add 6144 to a counter. When that counter reaches or exceeds 100,000 (105), I fire a jiffy event and subtract 100,000 from the counter until it falls below 100,000. Whatever residue is left serves as something of a leap jiffy when it adds up over time.
It will be interesting when morning comes to evaluate how accurate the self-timing algorithm fares against the one that uses house current as a timing signal. If it is much more accurate over several trials, I think I will rework this project as not only a more accurate clock, but a means to measure the current power frequency being delivered to the home. Logging the frequency shifts every few minutes to the central computer via laptop could lead to interesting insights into the local power generation industry. Do they run the generator slow during high demand (hot days, lots of air conditioners running), or is there some other reason for the variation I have seen thus far?
Preliminary results from my internal timing experiment are that I seem to have comparable accuracy using the ATMEGA8 timer interrupt for timekeeping, as compared to using the 60 Hz signal from the AC power supply. With last night's run, the timer seems to have run slow by about 4.3 seconds per day. I already know that the 60 Hz AC fluctuates in unpredictable ways. Sometimes it would run 5 seconds fast per day, then 3 seconds slow the next day.
If I can compensate for the behavior of the 16 MHz quartz timing crystal (HC49US 16.000MABJ), I could potentially fine-tune the clock's accuracy. For example, if it turns out that there is a temperature dependence on the quartz oscillation rate, I could try adding a temperature sensor and compensate for temperature changes. This is a fanciful idea, but it could provide me with a lot of opportunities to experiment and learn.
I also learned last night that suddenly losing power from the DC wall adapter is not handled gracefully just by having diodes and a battery backup. The sudden power loss apparently leaks its way through the voltage regulator and causes a brownout condition that resets the chip. It looks like I may need a fairly large capacitor to help smooth out the abrupt transition between wall power and battery power.
The ATMEGA8 internal timer is still consistently running 5 seconds slow per day. If this continues for a day or two more, I will go ahead and rework the hardware and software to no longer use the unpredictable external 60 Hz timing signal, and tweak the internal timing logic to be as accurate as possible.
This morning it occurred to me that I can still use the transistor circuit currently dedicated to sensing 60 Hz. I can re-route it to sense the DC voltage coming in from the wall, before it crosses over the diode to be mixed with the battery backup. Then I will change the software to read this digital input to determine whether the display LEDs need to be turned off, so as to conserve backup battery power.
I still want to experiment with hooking up a capacitor to see if I can get the backup battery idea working. Right now the digital logic gets confused when I unplug the wall adapter. I wish I had some way of seeing what happens to the voltage when the wall power goes out, but my old vintage-1974 oscilloscope has no way of capturing and displaying such a quick event. This musing gave me the idea that maybe I could build a custom oscilloscope using another microcontroller circuit, making use of its analog input, but that is a project for another day!
I finished the unit hours LED numeral tonight. Only one more to go!
The power must have gone out today while I was at work, because the clock had reset itself when I got home. This messed up my attempt to get today's data about the accuracy of the clock. It also further motivates me to get the battery backup working this weekend!
Last night I configured the digital clock to run on internal timing. At 21:41:45 EDT, I synchronized it with WWV. This morning I took 9 time measurements, and calculated the drift rate in seconds per day, as compared to WWV. I discarded the 2 extreme drift rates (the largest and the smallest), and calculated an average of −5.352 seconds/day, and a standard deviation of 0.158 seconds/day.
The standard deviation is pretty good, considering that synchronizing consisted of me manually pushing a button at the same time I heard a click on WWV, and the measurements were done likewise.
I forgot to record the temperature last night in the office, but this morning it is 79.0°F (26.1°C). This data will be important in case I want to try to correct for temperature dependence. I would need to find a way to incorporate an electronic temperature sensor of some kind into the clock. Another possibility would be to have a thermostat-controlled heater and enclosure for the 16 MHz crystal, but that would also require a temperature sensor, plus a lot of extra hardware complications. My guess is that correcting for temperature would be a lot simpler than controlling it.
The drift rate was holding at about −5.3 seconds per day, so tonight I decided to tinker with the firmware and make it run at a correspondingly faster rate. I am running the experiment now and I will check on it in the morning. I was running at a rate of exactly 0.6144 jiffies per tick, but if my math is right, the adjustment to correct for the measured drift rate is 0.6144376889 jiffies per tick.
Keep in mind that I define a jiffy as 1/60 of a second, based on the original idea of using 60 Hz power as a timing signal, which I am soon to abandon. Yet the jiffy is still handy as a unit of time for things like blinking LEDs and such.
Today I finished building the final LED display numeral. I also mounted the LED display to the motherboard using wood screws. Everything was working fine...
But then I had a little setback. While experimenting with switchover to battery backup, I noticed that the top LED in numeral 5 (the one I just finished) would always stay on. At first I thought this was just a wiring problem, but I soon traced it to one of the LED driver chips. I even swapped the suspect chip with its neighbor, and the LED that was always on moved to the other position. This means I did something to fry the Output Enable (OE) functionality on just that one pin of the chip. I know it is OE because the LED stays on even when OE is disabled for all 3 driver chips. I have ordered three more LED driver chips so I can replace the one that is bad, and still have two spares in case I damage more.
I suspect the problem is caused by the abrupt change in current when the power outage detector turns off all the LEDs at once. I think perhaps the voltage regulator on the LED driver board does not react fast enough to the sudden drop in current it is delivering, and overdrives the voltage. Another possibility is that the chip just overheated; they do feel quite warm to the touch, though I believe I am running them within tolerances.
Today I finished the additional circuitry needed for battery backup. As planned, I switched the former 60 Hz detector over to a power sensor. Its job is to notice when power from the wall adapter has ceased, and to turn off the LED display to conserve power. If the battery backup is functioning, the battery will last much longer. If not, the whole clock is about to lose power anyway, so it doesn't matter what it does.
I went back and read the LM7805 voltage regulator data sheet, and now I am pretty sure I am operating it well within tolerances, so I am not sure what caused one of the LED driver chips to malfunction. Even still, I have added a 220μF capacitor to buffer the 5V output from the LM7805, along with the recommended 1N4002 diode to bypass any current surge that could happen if the 9V input got shorted to ground.
|The LED display. The red arrow points to the LED that should be turned off, but is always on, due to damage to one of the three STP16C596 LED drivers. The time reads 16:51:27. The numerals will be easier to read once I get the shadow mask working. (I hope!)|
|The motherboard with new battery backup circuitry. The tags labeled "AC" are obsolete; these are now used for the wall adapter power sensor.|
|A view of the entire clock from above, with an edge-on view of the LED display.|
This morning I made the disturbing discovery of another LED problem. This time, instead of an LED that was on when it should have been off, there was another LED that never turned on. It was 3B, meaning numeral 3 (the tens of minutes numeral), segment B (the upper-left vertical segment). Fortunately, I was quickly able to diagnose the problem as an unsoldered wire on the anode nail of that LED. Tonight I fixed it quite easily. As Douglas Adams would have said, "DON'T PANIC!"
Tonight I found a partial solution to what I have dubbed the "scattering problem". When I put the shadow mask in front of the LED display, it is hard to read because light scatters from each LED to unrelated nearby segments. I took a printout of the segment mask on card stock, and punched holes in it where each LED goes. With a little fiddling around, I was able to put just the tip of each LED through its respective hole. This has noticeably reduced scattering, and therefore increased contrast significantly.
|This is not a very good photograph (low light conditions, slow shutter, blurred image), but it shows the current level of display contrast I am getting, having put a hole punch mask between the LEDs and the shadow mask. The display reads 23:15:40. I hope to make more improvements by putting X-shaped paper slats perpendicular to the plane of the display. The theory is that this will keep each LED illuminating only its own segment, not other nearby segments.|
Today my replacement LED driver chips arrived from Digi-Key. While Tropical Storm Fay was howling outside and pelting my house with sideways sheets of rain, I swapped out the damaged chip with its replacement and everything is working perfectly now!
This storm has also been a good test of the clock's battery backup system, which has performed flawlessly so far, even though the power keeps going out for a few seconds every now and then.
Tonight I also worked on paper baffles to help improve contrast in the display. I can tell the small amount I did on digit 5 (the tens of hours digit) is helping significantly, but it is very difficult to figure out how to get this done in a consistent and efficient way.
Tonight I finished making the paper baffles to increase contrast in the display, and it really works! The clock is now working well enough that I can take it to work on Monday for its public debut.
I have had fun showing off the clock at work, both on Monday and today. However, I had another setback tonight. The same problem happened again with an LED that won't turn off. It happened when the adapter was attached, but had lost power. I got a brownout where the microcontroller rebooted. I realize the way I have been testing the power sensor is not quite correct. I was unplugging the adapter from the clock, not turning off the power to the adapter. Doing the latter is different because there is a capacitor inside the adapter that causes the power level to fade gradually.
As I was experimenting with this, I caused yet another problem: this time an LED that won't turn on at all! Even worse, this appears to be damage to a different LED driver. I have only 2 spare chips from my last order, so I need to really get this figured out before I do any more testing and cause damage to another good chip.
My best guess is that the gradual loss of power leaves the power sensor input in a high state for too long, leaving the LEDs turned on longer than the voltage regulators can sustain. I am measuring just over 10V across the 1.5K resistor that I was hoping would drain down the adapter capacitor fast enough. My best guess now is that I need to use a voltage divider to approach the threshold where the transistor turns off, which is about 0.67V, based on experiments I did earlier. I'm guessing something like 170Ω will be about right to bring the power sense input voltage down to 1V, while still draining the capacitor at about the same rate.
The part that really bugs me is I still don't really understand the reason for the chip damage. All I know is based on the fact that it always happens when the chip reboots due to a brownout. Even if I prevent this from happening by tweaking the hardware to cause the LEDs to turn off quickly when external power is lost, it may just be a band-aid that is covering over a fundamental design flaw that may still happen under other circumstances.
This whole episode is also unfortunate because it interrupted almost 3 days of continuous up-time for the clock. I was attempting to measure the accuracy of the clock. The best I have determined is that the clock is running fast at a rate of about half a second per week. It appeared to be about a quarter second fast this afternoon, before the malfunction occurred.
Tonight I went with the assumption that the damage to the clock was caused by taking too long for the power sense to fall to logic low, causing the current-hungry LED array browning out the digital logic. Based on theoretical calculations and experiments with resistors and alligator clips, I settled on a voltage divider configuration. I now have a 1.5K resistor in series with a 180Ω resistor. The top (figuratively) of the 1.5K is connected to the positive terminal of the wall adapter, the other side is connected to both the input of the power sensor and the 180Ω. The other side of the 180Ω is connected to ground.
When the LED display is on, the voltage measured at the wall adapter positive terminal is about +10V. (It fluctuates each second as different LEDs turn on or off.) When the LED display is forced off (say, by shunting across the 180Ω with an alligator clip to pull power sense low), the positive supply voltage jumps to 12.3V because of the sudden drop of current being pulled out of the adapter. Under normal (unshunted) operation, the voltage between the resistors is about 1.1V, which is fed into the base of the power sense transistor via a 10K resistor. This is just enough to hold the transistor base voltage at 0.66V, turning it on. Now when I unplug the adapter from the wall, the voltage falls slowly as before, but the transistor base falls below its switching level in about half a second. I have tested this about 30 times and have not seen any microcontroller reboots, LED damage, or other suspicious behavior. The green heartbeat LED on the CPU board keeps blinking once a second as if nothing happened, and the LEDs turn off cleanly.
The clock is back! It turns out that the LED that would not turn on was because the LED itself (digit 5, segment C) was burned out. Interestingly, because digit 5 is the tens-of-hours digit, segment C is always on when the display shows a valid time. This is because digit 5 can display 0, 1, or 2 only, on a 24-hour clock. It makes me wonder if this has any correlation with that particular LED getting burned out.
I still don't know whether there was corresponding damage to both LED driver chips. There definitely was damage to the chip that drives digits 2 and 3, because digit 3, segment A was always turned on, and when I swapped in a fresh chip, that problem went away.
After diagnosing 5C as an LED failure and 3A as chip damage, I repaired both problems and now the display is working perfectly. I just hope the power sense circuitry modifications I made last night are sufficient to keep the clock from damaging itself again!
I have also changed the software to wait about half a second before turning on the LEDs when it senses a resumption of wall power, though it still will turn off the LEDs 3 milliseconds after sensing loss of wall power. I just didn't like the idea of the LEDs being turned on and off rapidly if the power sense were to fluctuate erratically during a brownout.
I synchronized the clock with WWV at 07:45:00 EDT. If I can get a week or so of continuous up-time, I will have a better idea of what the drift rate is, so I can make another software correction.
I have had fun today upgrading the clock software to report time to the nearest millisecond, instead of just tenths of a second. This is another benefit of no longer using 60Hz timing. I also wrote C# code to read from the digital clock and compare it to system time, to help me calculate drift rates accurately.
Then I went a step further: I wrote NistClock.exe, a program to synchronize my system clock to the NIST atomic clocks. Putting both together, I have a very easy way to track my digital clock's drift rate.
|New and improved clock display, with internal baffles for enhanced contrast.|
Today I built a tone generator (beeper) with a digital input, for use with the clock. It turns out the tone generator circuit idea I had was not quite right. Apparently the 2N4009 transistors I used turn on too easily with the 700Ω resistors I was using, and would not oscillate. Also, I could not get nearly enough volume with the speaker placed in series with one of the capacitors. I experimented on the breadboard, then came up with a modified circuit that produces a nice tone with good volume, but uses very little power:
|Schematic for the working tone generator I actually built.|
I built this tone generator on a sawed-off piece of wood stake measuring 17.2cm × 3.4cm × 1.6cm. I found an 8Ω speaker that is only 3.6cm in diameter, and has a very flat profile: only 5mm off the surface of the wood. I glued the speaker to the wood with fabric glue.
As a test of the beeper, I connected its +5VDC to the LED array voltage regulator, the GND appropriately, and the digital input to the green LED on the CPU board, which already blinks once every second. The resulting sound is a nice little chirp every second, and a longer tone on the minute mark.
I did some cosmetic work on the clock today: I did the best I could to scrub out the ugly Sharpie marker labels from the wood, and glued on some nicer labels printed on card stock.
|Clock with printed labels.|
|Beeper mounted on back side of display board.|
|Waveform of beeper measured at positive speaker terminal. The oscilloscope was set for 0.1 ms per division. This was tested with a 8.56V supply, yielding an apparent period of 0.39 ms, i.e. a frequency of 2.56 kHz. The time-averaged current consumed by the beeper in this test was measured to be 80 mA. When I hook up the beeper to a 5V regulated power supply, I can't tell the difference in the audible tone it generates. In this case, the current drops to 50 mA.|
|This is the current layout of the CPU board, complete with H, M, S buttons to set the hour, minute, and second. Also included are the power sense circuitry and SDO check bit input.|
I have been using my NistClock program to syncrhonize my laptop to NIST atomic clocks, then comparing the laptop time against the home-made digital clock's time. So far I am getting erratic results. In reading the Wikipedia article about crystal oscillators, the example temperature dependence formula they give would account for only about 20 ms/day variability in drift, but that formula is for a 32 kHz crystal, not 16 MHz. The manufacturer's data sheet is not very helpful in this regard either. I have seen sudden shifts of ±170 ms/day, followed by steady increases of 20 ms/day. I tried graphing the incremental drift rate as a function of hour of day (thinking maybe there is a temperature correlation), but I can't see anything obvious.
Here is a graph of the drift data. It is becoming clearer that there is a real drift rate of about 0.034 seconds per day, though something flaky is happening with my method for measuring it. I will keep updating this graph as the data accumulates.
Once again the digital clock has suffered LED driver damage. This time it happened when I was unplugging the serial data interface between the CPU board and the LED driver board. However, I did notice that it takes about half a second after turning off the supply power before the battery backup switches over. I decided to decrease the effective resistance of the power sense resistor. By experimentation, I found two more resistors (1K and 0.666K) that I can put in parallel with the existing 180Ω to get a net resistance of 124Ω. The reduced the power sense voltage from 1.05V down to 0.76V, which is much closer to the cutoff voltage of 0.67V. Now when I turn off the power, the LEDs turn dark almost instantly, instead of half a second later.
I have also changed the software so that the power sense input is checked very quickly. No longer does it wait several milliseconds before turning the LEDs off. In addition, the software now waits for 5 seconds of steady power before turning the LEDs back on, instead of 0.5 seconds.
Even still, I notice it is possible to brown out the microcontroller when the power goes out. If the microcontroller gets browned out, I presume the LED drivers can be damaged by undervoltage as well. I am not sure how to handle this problem.
I have ordered more replacement LED drivers, and also three 2.85V voltage regulators and heat sinks. I think I want to try dedicating a 5V regulator and a bigger heat sink just to the LEDs, with a cascaded 2.85V regulator per LED driver chip. I am hoping to spread out the power and reduce the strain on the LED drivers.
On a more positive note, I have made a correction in the software to increase the clock's accuracy. It was running about 37 ms/day fast, which amounts to about 0.43 parts per million. I slowed down the clock by the corresponding amount. So far it seems to be working very well. Assuming I can keep the clock running over the next week, I should be able to tell how much an improvement I have made.
I received some advice from Ian Paterson about my LED controller burnout problems, and it looks like it is really going to pay off. Ian has done some really cool stuff with Persistence of Vision devices mounted on bicycle wheels using the Arduino architecture and the STP16C596 LED driver.
He reports that he used to have occasional problems with damaging these chips himself. He recommended that I power the LED common anodes separately from the battery backup part of the power supply. This means that the LEDs will automatically turn off when wall power ceases, so I won't need turn turn them off via software. I have already tried this experimentally with the help of a third 5V regulator on a breadboard. I connected the input of this regulator to the anode of the 1N4007 diode that is connected to the wall adapter positive terminal. I used the 5V output to power the LED common anode array. Now when I turn off the power, the LEDs turn off simply because of running out of power. The best news of all is that the CPU brownout problem has disappeared, at least as far as I can tell from testing it about 20 or 30 times. Before this change, flipping the power this many times would have certainly rebooted the CPU, or even worse, put it in a stuck state.
Also, Ian confirmed that it is desirable to run the LEDs at a lower voltage than the 5V supply used by all the digital logic, so as to reduce heat and strain suffered by the STP16C596 chips. The replacement chips and the new voltage regulators should arrive in the mail in a day or two.
As a minor note, it turns out I only have one damaged chip, not two. Segment F in digit 0 was not turning on, but I tracked that down to a loose wire on the corresponding connector to the LED driver board. All it took was some work with needle-nose pliers, and it's all better now!
I am excited that I think I am finally getting close to a stable, working design, with parts that won't burn my fingers, and that won't damage itself! I will be able to free up some room on the board by removing the power sense resistors, but then I will need some more space for the extra voltage regulators. I might be able to squeeze some of them onto the back of the display, below where the beeper module is mounted.
My shipment of parts arrived from Digi-Key today! Unfortunately, I was a bit surprised about the voltage regulators and heat sinks I ordered: they are not really compatible with each other. I'm still learning about all the varieties of component configurations. I think I can work around this though.
The 2.85V regulators are FAN1086M285-ND units in a TO-263 package. This means the pins are short and curved. Oddly, the heat sink tab is connected to the regulated output, not GND as in the case of the LM7805. It seems strange not to be GND, since the tab is a convenient place to bolt to a solid metal chassis for dissipating heat.
At any rate, I am going to have my hands full this weekend figuring out how to solder and mount these new components, and to provide sufficient heat sinking.
I have a functional clock again! I build the dual 2.85V power supply for the LEDs as planned. Each power supply drives three of the LED numerals, and each consists of one LM7805 (5V regulator) cascaded with one FAN1086 (2.85V regulator). Both reside on a single small printed circuit board.
I also replaced the damaged LED driver chip. I notice that all the chips are running cool to the touch. As far as I can tell, they feel like room temperature.
However, I am still having problems with the battery backup. Even with a fresh alkaline 9V battery (measuring 9.53V), I occasionally get CPU brownouts and/or LED driver SDO check bit errors when I turn off the wall power. But so long as the hardware isn't damaging itself, things are not so bad. This gives me something else to think about and experiment with.
This morning I am ignoring the power backup problems, in favor of something more fun. I have added an hourly chime functionality. Much like cuckoo clocks or clocks with bells, it is nice to have a clock that can count out the hours for you. I connected the beeper circuit to the red error LED, and between the hours of 8AM and 8PM, it now sounds out the hours. I use 12-hour counts for the tones, for the sake of tradition, and who really wants to count 20 tones to find out it's 8PM. Outside those hours, it is quiet, so people can we in my house can sleep undisturbed.
I have allowed the clock to run for 13 days uninterrupted, and here is a graph of the drift measurements I have taken.
In addition to the puzzling spikes of sudden drift that appear and vanish mysteriously, there is an overall trend toward accelerating drift. I am not sure, but it may be due to the decreasing average temperature as autumn sets in.
I continued allowing the clock to run and took more drift measurements. The accelerating clock rate has continued and has a surprisingly good fit to a parabola:
Clock drift in seconds (vertical axis) versus time in calendar days (horizontal axis).
The dark blue dots are actual measurements, and the magenta dots are a perfectly parabolic curve calculated to approximately fit the data.
I was wondering if there was some subtle flaw in my software, or if the quartz crystal oscillator is really speeding up. Yesterday I decided to test this by completely powering down and resetting the clock: I removed the backup battery and then unplugged the wall power, then reapplied both sources of power. After that, I resynchronized the clock to atomic clock time via serial port connection. By completely resetting the software state, I have virtually eliminated any cumulative error that could possibly be caused by software. And yet, over the span of the last 24 hours, the drift rate remains high: approximately 29 milliseconds per day (ms/day).
The rate of acceleration appears to be about 1.85 ms/day2. I have read about "aging" of crystal oscillators on the order of 3 parts per 10 million over a time span of a month. My observed rate works out to 55.5 ms/day/month, or 6.4 parts per 10 million per month, which is in the same order of magnitude. I am considering ways of using software to correct for this ever changing oscillation rate, even to the extent of storing in EEPROM how many hours the clock has been running. It is not clear how long this aging trend will continue. As they always say in grant-seeking academia, "more research is needed".
It has been quite a while since I updated this page, but I wanted to drop a note that the digital clock is still running fine. Over the past few weeks I have been measuring its drift rate. I determined that the clock was running 32.69 ms/day fast, so I slowed down the timing constant accordingly with a firmware revision. Instead of 0.06144372316 jiffies/tick, it will now run at 0.06144369991 jiffies/tick. I have also updated the firmware to print the existing timing constant when the "v" command is received on the serial port, along with the firmware build date like it always did. This way I can make sure any future corrections are based on the correct starting values for what is actually running inside the microcontroller.
Contact me (Don Cross) :
Visits to this page since 10 September 2008: