Sunday, March 28, 2010

ATtiny2313 Four Digit Clock

After my foray into TTL logic, I feel like I've earned back the right to start using a C compiler again.  I've already done enough clock builds based on the Arduino environment, so I figured it was time to go another layer down, and toss all the nice Arduino libraries out the window.  Spring break left me with plenty of time to work only on software, since I left all of my tools and parts in Davis.  The hardware for the clock was finished during finals week, with meant I only had to take it and my laptop home for the break.

This clock reads just as a normal digital clock does: hours and minutes, with a PM indicator.  The brains of the clock is the ATtiny2313, which comes in at 2kB of flash program space, and 128 bytes of RAM.  This is plenty for this application, since it only needs to download three bytes worth of time from the real time clock chip, and then display them on the seven segment displays.


Note that flicker on the display in the video is an artifact of the video, and isn't visible in person.

Source code.
 From a software side, the first challenge was multiplexing the four digits of the display.  This was the first time I have done anything with interrupts, but once I got an LED to blink, extending it to switch digits on and off 300 times a second was fairly trivial.

Next was talking to an RTC.  I originally tried using a DS1306 SPI RTC, since SPI is a significantly simpler protocol to implement in software.  For some reason beyond me, I couldn't get my DS1306 to talk to me, so I downloaded Atmel application note AVR310, "Using the USI module as a I2C master."  This comes with a complete I2C library, which meant I could use my trusty DS1307 once again, but left me unsatisfied with reusing someone else's code.  This meant I spent most of my time on this project simply reimplementing their library how I wanted it.  My version does seem to compile to a few dozen bytes larger than theirs, but I feel like the code is much easier to read.  The entire program comes in under 1300 bytes anyways, so it all fits on the ATtiny2313 in the end.

Nothing too exciting from a hardware side.  I used a 7447 BCD to seven segment decoder because I was quickly running out of pins on the ATtiny2313.  I also got tired of swapping the 2313s from the breadboard to my miniPOV3 for reprogramming, so I scrounged a serial port to break out the pins I needed for my DASA programmer.  I have a real programmer in the mail, so these problems are soon to be a thing of the past.

Parts list:
  • 1 ATtiny2313 ($2.47 Digikey)
  • 1 momentary push button($0.23 Digikey)
  • 1 74LS47 BCD to seven segment decoder (Good luck finding somewhere to buy that)
  • 1 DS1307 RTC ($3.74 Digikey)
  • 1 32.768kHz quartz crystal ($0.32 Digikey)
  • 1 4 DIP switch
  • 4 2N3906 PNP transistors ($0.36 Digikey)
  • 4 1k resistors
  • 8 100Ω resistors
  • 2 4.7k resistors for the I2C lines
  • 1 3.5 digit 7 segment display (Bought mine locally at Halted)
  • Optional serial port and 3 4.7k resistors for in circuit programming

Monday, March 15, 2010

Pure TTL Clock

The second half of my circuits and systems lab class this quarter has been an introduction to digital logic.  Unfortunately, over winter break my dad gave me the TTL Cookbook by Lancaster, which I then read a few times, so I've been spending the last four weeks of lecture catching up on my pleasure reading.  The lab projects for the class have been pretty rudimentary (compared to my other projects), so I've had quite a bit of free time in lab to help other groups and work on my own projects.

Flipping through the TTL Cookbook a few weeks ago, I found a schematic for a crystal oscillator (page 170), and it hit me: Once you get a crystal to oscillate, it isn't much more to get it to count time, WITHOUT using a microcontroller!  All of my clocks so far have essentially been a real time clock chip (eg DS1307) connected to a controller (eg ATMega168) which is then connected to a bunch of LEDs of some creative configuration to show time [1] [2] [3] [4].  You do that enough times, and it stops being all that challenging, and easy hobbies are boring hobbies, right?

So what's the challenge?  7400 series digital logic consists of a couple hundred different integrated circuit chips, starting from 7400 and counting up (highest I've seen in real life is 74595).  Each chip does a single logical operation, so one may output the logical AND of two inputs (output HIGH if both inputs are HIGH), where another is 4 flip flops chained together to make a divide by 16 counter.  Before the era of the PC, it wasn't uncommon for a hobbyist to buy a bag full of TTL gates and build himself a nice little computer.  Unfortunately, when each individual IC only does one thing, doing anything useful generally takes quite a few ICs, and you'll need a pretty good collection of them before trying to do anything doesn't consist of buying every single part you need (25-70 cents a piece isn't much, but does add up).  Comparing this project to your typical 8 pin RTC chip, I'd say this implements 5% of the functionality (no calendar functionality, no I2C, etc) at the cost of a few orders of magnitude more board space (6 columns vs half an inch), and a few orders of magnitude in power requirements (600mA vs less than 1.5mA).

Reading this clock is relatively easy, compared to most of my other clocks.  It's in 24 hour time, and seconds, minutes, and the 1's of hours are all decoded nicely by 7 segment displays.  Unfortunately, I ran out of breadboard space, so the 10's of hours had to settle for a pair of LEDs: One LED is lit for 10 + n hours past midnight, and both LEDs are lit for 20 + n hours past midnight (The schematic below shows the little bit of cleverness that I did with a pair of diodes to make that happen).  This means the picture above reads 16:36:39 (4:36PM).

Power consumption for the entire clock is relatively high, which is expected for this many TTL gates.  At 5V, it draws somewhere between 550mA and 650mA, depending on how many LED segments are lit, so plan on running it with a pretty stiff power supply.

Click any of the pictures to enlarge.

  • I did a surprising good job in the video of rattling off part numbers, with the one exception of the 1's digit of the minutes.  The counter is not a 7493 or the 74120 which I corrected myself with, but is actually the 74160 divide-by-10 counter, which is the same as for the second's 1's place.
  • With the button debouncers, the RC response times were calculated for use with 555s, but when I switched to a 74123 I just used the same values without recalculating it.  I think it's quite a bit faster than a quarter second now.
  • I live next to the railroad tracks; I'm sorry.

Working from right to left in the pictures:
On the top right is a 32.768kHz quartz crystal.  This is a convenient frequency because it is a power of 2 (215, for those of you reading at home).  This means that if you divide the output of this crystal by two 15 times, you get down to a relatively stable 1Hz signal (The crystal is spec'd for 20ppm, and the measured drift on it is at least on that order of magnitude).  The amplification of the crystal is done by a 4001 CMOS NOR gate (Not technically TTL, I'm sorry!), which then feeds a chain of three 74161 divide-by-16 gates, and half of a 7493, which divides it by another eight.

Once divided down to 1Hz, the rest of the clock is simply a matter of counting seconds, minutes, and hours, and displaying them.  The seconds stage consists of nothing more than a 74160 divide-by-10 and a 7493 wired as a divide-by-6, which feed a pair of 7447 BCD to seven segment decoders for display.  The 7493 normally divides by 16, but I used a 7408 AND gate between the 2 and 4 output lines, such that when the counter (which signifies the tens of seconds digit) reaches six, the AND gate goes high, resets the counter, and pulses the carry line to the minutes stage.

The minutes stage is just like the seconds stage, with the singular complication that most clock users have this almost indecent expectation that they can plug in a clock all willy-nilly any time of day, and then expect to have some ability to change the time on the clock to the current time.  What nerve, right? That means we have to like, have buttons and stuff...

Unfortunately, TTL counters and buttons don't mix very well.  You don't realize it, but when you push a button, it will sit there and bounce a couple times before it settles down and looks like a single voltage to the counter.  This is a problem, because instead of advancing the clock one minute every time you press the minute button, it can advance two, eight, twenty, or even forty times.  This is a real drag, and needs to be fixed.  To fix this, I used a 74123 dual monostable multivibrator.  Monostable multivibrators are useful because you can kick it once (or a whole bunch of times, in this case), and it will output a single, clean, square pulse for a defined amount of time (defined by the resistors and capacitors connected to it).  This means it can debounce the messy button presses, and turn them into clean square waves to advance the minutes and hour counters.  The 74123 output is combined with the carry signal from the seconds stage by a 7432 OR gate.  I originally had the debouncing implemented by a pair of 555s, which probably made more sense than the 74123, but I had never used a 74123 before, so I decided to have some fun (pretty sick idea of fun, right?).

The hours stage is unfortunately an entirely different bucket of fish.  Not only do we have to use the other half of the 74123 and another 7432 OR gate to let the user advance the hours, and have the first counter carry and reset at 10, but we want both 7493 counters to reset when the clock reaches the end of the day (at 24 hours).  This means another AND gate connected to the 20 and 4 lines, fed to the reset on the 10's counter, and combined with the 1's reset signal through another OR gate.  Pile on top of all of this the fact that I was quickly running out of breadboard space, and you can see my problem.

So there it is.  An entire clock, built from little more than AND & OR gates, flip-flops, and BCD to seven segment decoders.  It was a fun little project, but now that I've proven that I can do it, I think I'm going to go back to my nice little DS1307 RTCs and AVR microcontrollers, thank you very much.

Sunday, March 14, 2010

TTL Frequency Counter

Things have been a little crazy as of late, with finals coming up, so I figured I'd post something I had to do for class to give ya'll a break from all of my clocks.  The final lab project for my circuits and systems class this quarter consisted of designing a two digit frequency counter, which we then used to measure the rotational speed of a motor with an LED and phototransistor.  The design is rather rudimentary, since we use a 555 timer for the time standard, but after putting enough effort into getting the pulse width calibrated, it does a pretty good job of getting within a few hertz of the actual frequency.

The two 7493 counters are wired with AND gates to reset when they reach 10, making them divide by 10 instead of 16.  The output of these counters are fed into a pair of 74174 flipflops, which save the current output when the 555 fires every second, which means it only displays the final result, instead of showing the counters count up from zero to the final count.  The 74174s then feed into 7447 decoders, which decode the binary coded decimal into 7 segment displays.