Time
I’ve built several timekeeping devices before, but the challenge here was to build one where the user doesn’t have to set the time. My logic was that allowing the user to set the time would give them the power to set whichever book they wanted to read, and part of the allure of this clock is how its progress is unstoppable. Besides, making a clock set its own time is harder more fun!
When thinking of a clock that sets its own time, my first thought was one of those fancy SkyMall clocks or wristwatches that set their own time using the radio broadcast from the National Institute of Standards and Technology (NIST). The NIST maintains a 70kW antenna array near Fort Collins, Colorado that broadcasts time and date information on a 60kHz wavelength. A little more research showed that they not only broadcast the time, but also the day of the year and year of the century. Perfect!
I’m no RF engineer (yet), so rather than trying to create a custom 60kHz radio receiver, I shopped around online to see what I could find in the way of 60kHz radio modules. I found a few options, but nothing was in stock, so I did the next best thing:
30.
Of course, connecting this antenna required me to build my first ever radio frequency circuit. SCARY!
Not so scary really. I just needed to provide a 50
trace from the module to the antenna connection. This involves matching the parasitic capacitance and inductance of the signal trace to prevent any reflections along the transmission line from causing problems. Considering how weak satellite GPS signals are coming in, I’m guessing this is pretty critical, but it worked on the first try, so I’ll never know if it was my excellent engineering or the design of the radio’s input circuit that was responsible.
I used an online trace impedance calculator to help design my circuit. I forgot to record the exact values and which calculator I used, but taking measurements from my PCB design file, I used a different calculator to reproduce my results:
The sizing values are pretty self-explanatory, but the
is a value I estimated from some search results for “dielectric of FR4”. It wasn’t exactly rocket-science, but it worked. When I do more complicated RF circuits in the future, I’ll have to be more precise, I’m sure.
I took into account other things too such as making the entire bottom of the board a ground plane, and peppering it with vias. I also made sure to keep the RF line as short as possible. The end result looked like this:
In order to keep the wire connections from shorting to the bottom ground plane, I drilled them out like this:
As it turns out, drilling into fiberglass with a general purpose drill bit is an excellent way to dull that drill bit.
The GPS module’s serial command set allows you to configure the frequency with which it reports and what information is in those reports. I set mine to output GPRMC (Recommended Minimum Specific GNSS Sentence) and GPGGA. As the manual specifies, GPRMC provides Day, Month, Year, Hour, Minute, and Second information. GPGGA provides information regarding the quality of the satellite lock. My code waits for the GPGGA data to report “GPS fix” before reading the time/date information from GPRMC.
The returning data looks something like this:
I used the Saleae to capture a single GPRMC packet which looked like this:
GPRMC,034244.000,A,4737.4663,N,12221.3078,W,0.03,244016,060514,,,D*72
This indicates that the date is currently June 5th, 2014 (060514), and the time is 8:42:44PM in Seattle (034244 UTC). As an added bonus, the GPS location data (47
37.4663’N 122
21.3078’W) also checks out:
I don’t really need position data, but it’s pretty cool how well it works. I might have to use one of these modules again for a future project.
Schematic (again)
Since there were no more surprises after this point, I’ll go ahead and reveal the schematic:
The green thing is the controller built into the display, and the cardboard is a high tech form of insulation.
There are still a bunch of vestigial elements on this schematic. The Output signal from the 60kHz radio module was repurposed to be the 1 Pulse Per Second output of the GPS module which I also didn’t end up using.
The display and GPS module are now both connected over the same serial bus. This is okay because both of these devices require their commands to be prefaced with addresses that are unique to each of them. Furthermore, because only the GPS module sends any kind of response, there’s no need to worry about a race condition where the GPS module and display might try to send messages at the same time. It’s just convenient that both of them accept 9600 baud serial.
That’s not to say I didn’t have any problems.
Serial problems
With the hardware finished, I set about writing some firmware. A few days into this, I noticed that sometimes data packets were getting corrupted when sent from the GPS radio to my AVR.
As a temporary fix, I used the internal framing error bit of the AVR to detect when data was coming in corrupt and wrote some code to just ignore it. While this more or less fixed the problem, I wasn’t content to just let it slide without finding a root cause. Here you can see a simple loopback script with a debugging bit indicating where the corrupt byte comes in (‘0’ turns into ‘.’):
I had a number of theories as to what was causing this problem:
- I measured the GPS module transmitting at 9607.69Hz while my AVR transmits at 9600.00Hz. Standard serial starts counting from when the first bit is set, so it’s possible that for long messages, this accumulated error causes bits to be missed. Seemed unlikely though because that’s less than 0.1% error.
- I thought my code might be taking too long to handle incoming data so that it can’t keep up. This was ruled out by some debugging where I established that my code spends a majority of its time in a tight loop waiting for data to come in.
- Noise? I don’t know. I probably had a thousand half-baked theories about what could be going on here, but nothing seemed particularly out of place, and I was going crazy.
One interesting thing I found is that it sometimes randomly did take slightly longer to read an incoming byte even if it was still a much smaller amount of time than the total serial transmit time. You can see this below where the orange trace indicates how long it took to read the incoming byte from a buffer and how that correlates to where the corruption starts.
The actual problem ended up being pretty interesting.
Because I’m lazy, I very rarely write code from scratch. A smart engineer tries to avoid duplicating work, so many good software engineers try to find libraries to do what they want or write their own libraries that they can pull into any future project that has similar requirements.
Unfortunately, I’m not a good software engineer.
I usually start a project by pulling in code from other similar projects. In the case of this project, I was going to use the code from my party lights which used the ATMega328 to communicate over serial, but that project only received serial. It had no code for transmitting it. Instead, I used the code from my beat tracking windshield wipers which maintained two-way communication with the PC controlling them.
What I didn’t seem to notice is that the wiper driver used the ATTiny2313 while my new circuit used the ATMega328. You can see below how my Gutenberg Clock code sort of resembles the Wiper code that it drew from.
Wipers
//config serial UCSRB = 0b10011000; //Transmitter enable, Receiver Enable, receiver interrupt enable UCSRC = 0b00000110; //8 bit, asynch, no parity, 1 stop bit UCSRA = 0b00000000; //Don't double trans speed UBRRH = 0; UBRRL = 64; //9600 baud
Gutenberg Clock
//config serial UCSR0A = 0x00; //no double trans speed UCSR0B = 0x08; //TX enable UCSR0C = 0x46; //8 bit, asynch, no parity, 1 stop bit UBRR0H = 0; UBRR0L = 71; //9600 baud
For some reason, I switched bit 6 of UCSRnC from a 0 to a 1. I’m not entirely certain why I did this, but if I had to guess, I’d say it has something to do with misinterpreting the changes added to this register in the ATMega328 to support more USART features.
I also could have temporarily mixed up “synchronous” and “asynchronous”. Asynchronous means that no clock pin is required, but counter-intuitively, it requires receiving and transmitting parties to be more “in synch”. That always confuses me.
Regardless of why I did this, the implications were pretty interesting.
I accidentally placed my UART into synchronous mode. This means that my AVR was providing a data clock that nobody was reading. What’s confusing is how well this actually worked. Transmission from the AVR was completely unaffected.
Asynchronous serial requires the receiving party to start a timer when the first bit gets set and then check back on the line at a regular interval (9600Hz) to see the following bits. This mode of communication can be severely impacted by unexpected delays between bits. Synchronous communication adds the clock pin which makes it more robust as the receiving party can be told by the sending party when the bit is ready and should be read.
In my case, I was lucky in that there were no unexpected delays between bits sent from the AVR. Although it isn’t required for synchronous communication, the AVR maintained a solid 9600kHz transmit rate with no delays. Ignoring the clock line, this looked exactly like a standard 9600 baud serial transmission. This worked 100% of the time.
This wasn’t the case on the receiving end though. As I said before, asynchronous communication requires a timer to be started when the first bit arrives. Because the AVR was under the impression that its clock pin was providing the timing, it read the incoming bits on its own schedule.
For the most part, this actually worked! Since both devices had such well tuned transmit/receive clocks, as long as the AVR started reading somewhere between the clock edges of the incoming signal, it would continue to do so without problems. Furthermore, since the baud rate is so slow compared to the rise and fall time of the signal, the bits are valid for a majority of the time.
Every once in a while though, there will be some small delay or change in clock speed that can make a data stream that was near a clock edge pass it and corrupt a bit. That’s where my problem was.
So, at 3AM (yes, Seattle time this time), I fixed the UCSRnC byte and had no more problems. It wasn’t entirely a waste of time though. I learned a lot about how the AVR’s USARTs work during my investigation and used the Frame Error detector for the first time.
Pingback: Gutenberg Clock Keeps Time by Reading Books
Pingback: Gutenberg Clock Keeps Time by Reading Books - Tech key | Techzone | Tech data
Pingback: Gutenberg Clock Keeps Time by Reading Books | Ad Pub
Pingback: Gutenberg Clock Keeps Time by Reading Books | Hack The Planet
Pingback: Nerdcore › Gutenberg Clock reads a Public Domain Library
Pingback: Auteursrechtvrije Gutenbergbibliotheek leest als een klok | Rafelranden
If you are interested in porting the Gutenberg clock to my Wise Clock 4, I could send you a kit (you would need to buy the displays from Sure Electronics). In the end, you could have a device with ATmega1284, SD card, GPS, bluetooth and 128×16 tri-color display,
Pingback: PrintSnap Instant Camera | ch00ftech Industries
Pingback: Electrical Hell and the apocalypse survival external phone battery | ch00ftech Industries
2lnmst6u
zfi5l0
io70li
el0w07
jijzb0
hhmsxv
jumrg4
q59fzb
9gl6tt
bv9yxq
xg87xp
umtdf1
63ghlk
5qgq22
p4v4ys
ialscr
k0dlib
k5m167
lo5fd2
p10yph
plte54
0cv99p
44refp
jqtuvs
5op7tx
rzxf8q
x9172r