Friday, April 1, 2016

Retro Radio


My husband inherited this early 1950's vintage Motorola AM radio from his grandfather. I've always thought it was really beautiful radio, but it spent 17 years sitting on our shelves as nothing more than a conversation piece. Recently, I decided I wanted to get it playing again.

This type of radio is called an All-American Five, so named because it uses five vacuum tubes, and American manufacturers mass-produced millions of radios based on the same basic design from the mid-1930s until the early 1960s.  The radio was physically in pretty good shape before I started restoring it. It has always been kept indoors and never subjected to any abuse. However, I would soon learn that 60+ year-old radios that have been sitting idle for 20 years still require a lot of TLC to get them working again.

I read all the restoration advice from Phil's Old Radios and read a lot more about the All-American Five on Fun With Tubes before I got started. I also found the schematics for my radio (Model 5X12U) on a site called Nostalgia Air that provides PDF scans of the schematics and service manuals for antique radios.  When restoring an old radio the schematics are nearly mandatory.

In my initial assessment of the radio, I found that the power cord's insulation was crumbling, it was missing two vacuum tubes, and it still had all the original wax paper and electrolytic capacitors. Capacitors are typically the least reliable parts of any  electronic circuit, and most restoration experts recommend replacing them before you even try power on an old radio.  I had already replaced one of the capacitors (the orange one) before it occurred to me to take a "before" picture, but you can still see most of the original components in the picture below.


I replaced all the paper and electrolytic caps, the power cord, and ordered replacement tubes for the rectifier (35W4) and the IF amplifier (12BA6) that were missing. I believe the remaining tubes (12BE6, 12AT6, and 50C5) were original to the radio. I checked them visually for oxidized getters and tested continuity their heaters, and everything checked out, so I decided they didn't need to be replaced. 

Before powering up the radio for the first time, I built a dim bulb tester. The basic idea is that you wire a light bulb in series with the radio, and if anything is shorted out, the light bulb limits the amount of current that can flow through the radio and prevents any major fireworks.  If the radio does short out, the bulb will glow brightly, but if everything is OK, it will be dim--hence the name.

Awash with anticipation, I hooked the radio up to the tester and powered it on.  The the bulb glowed dimly--a good sign that I hadn't botched anything--but then... nothing.  All the tubes lit up but I got no audio--no static, no hum, just silence. This was a major disappointment and it took me a few days to figure out what to do next.  Then I discovered that the 22 ohm series resistor in the B+ line had drifted up to around 70 ohms, which meant that the radio was getting less than a third of the current it was supposed to.

After replacing this, I tried again and the radio slowly crackled to life.  But something was wrong... it definitely worked, but it was temperamental. The station would play for a while and then suddenly the volume would cut out to  almost nothing.




I checked all the other resistors and found several more out of spec, so I decided to replace them and ended up replacing all the other resistors while I was at it, but there was no appreciable difference afterwards. I tested the voltages at all the points indicated in the schematic, and most of them are within a few percent of the specified voltages. Unsure what to do next, I turned to the Antique Radio Forums for help.  I made a several videos showing the audio problems I was having and folks from the forums took a listen and offered their guesses as to what could be wrong.  I owe a great deal to the friendly folks on the forum for all their guidance and encouragement, especially Peter Balazsy and Tom Bryant. 

Peter identified the true culprit--the dreaded silver migration disease. Radios of this vintage contain RF transformers with integrated silver mica capacitors in the bottom of them. Together with the coils, these form a tuned circuit that filters out the other stations and helps the radio amplify the one you've tuned in.  Over time, unfortunately, the voltage difference between the primary and secondary coils causes the silver on the capacitors to slowly migrate from one side to the other until it eventually shorts out. This causes what's often described as a "crashing" sound.  Fixing the problem requires disassembling the delicate transformers and removing the damaged capacitors, then wiring in external replacements. 

I watched several videos about this, and came away quite intimidated. I held out hope that something else would fix it. I tried several suggestions, first replacing the strange ceramic capacitor combo pack that contained 5 capacitors in one with individual capacitors, then blowing out the tuning capacitor with compressed air and cleaning the tubes sockets with contact cleaner. Sometimes the radio would play beautifully for quite a while and then refuse to play at all. During its good periods, I preoccupied myself with taking photos and videos of the radio, including this beautiful footage of the tubes glowing and the tuning capacitor moving while I tuned the dial.




However, the truth was inevitable and the radio never played well for long.  Finally, I worked up the courage, de-soldered the transformers, and took off their metal covers.  The most intimidating part of the operation is removing the rivet on the bottom of the transformer to expose the silver mica capacitor. In most of the videos I found, people used drills or dremels to grind out the rivet, which in my hands, seemed destined to destroy the fragile plastic frame or the hair-thin wires.  After spending weeks scouring the forums for a better way, I came across the simple suggestion to use an Xcelite flush cutter to snip off the top of the rivet.



I have to say, for anyone contemplating this surgery, that this is the way to go.  The top of the rivet easily came off without even shooting off as the shears went through it. No fuss, no muss, far less drama than breaking out the power tools!  Once the capacitor was removed, it showed a clear case of SMD.  Note the black trail of silver oxide going from the capacitor on one side to the other.



After removing the capacitors, I snipped the contacts on each side so they wouldn't touch each other, and then glued them back in place with a hot glue gun.  I put the transformers back in the radio and soldered replacement silver mica capacitors across the contacts on the bottom.  This picture shows the bottom of the radio with all the capacitors and resistors replaced.



After getting the radio back together, was relieved  to hear that it still played although it was badly out of alignment.  Only the two strongest stations were audible and even they were quiet. This was to be expected though, since the replacement silver mica caps I used were 100pf and the original ones measured closer to 120 pf.  Properly realigning the a radio is a fairly complex procedure that involves using a signal generator to inject a signal of a known frequency and measuring the voltages while turning the tuning slugs in the transformers until the peak voltage is found.

Fortunately, after some feedback from the guys on the forum, I learned that you can mostly align a radio by ear just by tuning in a weak station and listening for improvements as you twiddle the adjustments on the transformers.  I played with it for a few hours and got it aligned pretty well. However, I noticed that one of the tuning slugs was hitting the stop at the top of its range, so I  decided to order some 120pf capacitors so I was able to align the radio more precisely.  

At this point, the radio played great for about a week, but then it developed another problem. The audio got really scratchy and distorted but this time it sounded much more like an amplification problem than a reception problem.  I initially blamed the problem on the el-cheapo 50V capacitors I had used to replace the ceramic combo pack.  The members of the antique radio forum had warned me 50V was barely adequate for this application and  that I should replace them when I got a chance.  I put in some 1kV rated ceramics and I was convinced for a while that the radio was fixed, but the problem came back.  My next suspect was the amplifier or the detector tube.  Tom, who had also been helping me on the forums graciously sent me a few spare tubes he had on hand and I tried them, but the problem was still there.

The problem turned out to be the speaker itself.  The paper of the cone was very brittle, and I think the new activity after 70 years was more than it could handle.  With the cone warped, the voice coil rubbed against the pole of the magnet and shorted out.  One suggestion from the antique radio forum was to dampen the speaker and leave it overnight to dry, which can cause it to straighten out and resolve the issue with the misaligned voice coil.  Unfortunately the cone was so brittle that it basically disintegrated once I got it wet.

I searched Digi-Key and Mouser to find a replacement speaker that would fit and ultimately settled on the CUI GF1003M, which is a 4 inch speaker with a clear mylar cone.  There were a few other 4 inch speakers available, most of them also from CUI, but this was the only one that I was sure would fit. After replacing the speaker, the radio sounded great again, but the new speaker looks a little out of place since it is so obviously not from the 50s.



Also, after putting the speaker in, the dust cap was touching the tuning dial assembly in front of it. To solve this, I pushed the dust cap in slightly to create a dent and prevent it from rattling when the speaker played.  It looks a little ugly but you can't tell when the radio is inside its case.

It's a little disappointing that I couldn't salvage keep the original speaker or find one that looked closer to the original.  I found a few services on the internet that will recone vintage radio speakers, so I've kept the metal basket from the original speaker and I may try to have it re-coned at some point so I can keep the radio a little more authentic.

Here's the radio scanning the dial in its permanent home after recovering from the surgery.



There's also some bonus footage at the end of my newly acquired Commodore 64 and some breadboards I'm working on.  More on those projects in a later post!

Safety warning: there are voltages inside these old radios that can kill you. Before taking on a project like this yourself, please educate yourself, understand the risks and know how to mitigate them.

Friday, February 6, 2015

Meet Elbert

And now, for something completely different.  Lest you think my interest in electronics begins and ends with blinkenlights, I'd like to introduce you to Elbert.


The Elbert V2 from Numato is an entry-level FPGA board.  The best way to explain it for someone new to the game is that while you tell a CPU what to do, you tell an FPGA what to be.  The FPGA is basically a blank slate of basic logic elements which can be wired together to create almost anything. Video cards, CPUs, digital signal processors, you name it.  Your imagination--and the size of the FPGA you can afford--are the only limits.

I have been interested in FPGAs for quite some time, but until recently, the barrier to entry has been pretty high, and there hasn't been much information available for the hobbyist. Several enterprising makers are committed to bringing FPGAs to the masses with projects like the Papilio and the Mojo which sell for around $75 and provide a lot of hobbyist-friendly projects and tutorials.

Unfortunately, neither of the above boards includes any peripherals beyond some basic buttons and LEDs.  To add peripherals, you must buy an external add-on board that plugs into the FPGA board's headers. Generally, these peripheral boards cost $40 or more, depending on the peripherals. This adds quite a bit to the price of entry, and was a little more than I wanted to pay for something I was still unsure if I would get into.

When I found the Elbert V2 FPGA board from Numato Lab for only $30, it seemed like a safe jumping off point.  The board includes a number of built-in peripherals and connectors, including dip switches, push buttons, seven segment displays, VGA and audio output, and an SD card slot. The XC3S50A FPGA in the Elbert is tiny; probably one of the most basic chips you can buy. However, I would argue that's a not a bad thing because you need to learn the basics before you take off on any really ambitious projects, and having a limited platform forces you to do that.

The low price plus built-in peripherals make Numato's products an excellent value, and I have had a great experience so far with their tech support.

Elbert's Big Brother

Once you've exhausted the capabilities of the Elbert, Numato has the next step up the FPGA food chain waiting in the wings: the Mimas V2, which is only $50.  The Spartan 6  FPGA in the Mimas has over 5X the available logic elements and 10X the built-in memory of the Elbert. It also comes with a 64MB external DRAM chip, which vastly expands its potential.  It should be possible to recreate a lot of famous 8-bit and even 16-bit computers and video game consoles on this board.

Honestly since the Mimas is only $20 more than the Elbert, it might make sense to go ahead and buy it to begin with since it's a much more capable board.

Github Repository

I have checked my code for the various peripherals supported by the Elbert and Mimas into the numatolib Github repository.  Also check out the wiki on the same repository, which has a lot of resources and notes for using the Numato FPGAs.

The Matrix Gets Smart

In my search for a better LED matrix, I've finally arrived at what actually feels like a finished product: the SmartMatrix from PixelMatix.  This comes in a complete kit for $130 with everything that you need to build a nicely finished project. The only thing you have to add is an 8x8 shadowbox frame that sells for less than $10 on Amazon. Since I have sold off my soldering equipment during my move, I opted to order the pre-assembled kit for an additional $20.

With all the hardware taken care of for me, I could focus on the software to make interesting displays, which is what I've really wanted to do all along. The SmartMatrix is driven by a Teensy 3.1 from PRJC, which is a tiny ARM microcontroller board that can be programmed with Arduino. It comes with some really nice software called Aurora that has lots of interesting visual displays.  I have made my own fork of it to which I've added several features.

TPM2 Streaming Mode

One of the first things I wanted to do was add TPM2 streaming over the Teensy's serial USB connection.  This allows the matrix to be controlled from PC software such as Jinx!, PixelController, and Glediator.  I made a YouTube video showing off the results:


Instructions for using Streaming Mode are on the Aurora wiki.

The Game of Life

Finally I come full circle to the goal I had stated for myself in my very first LED Matrix post: to run Conway's Game of Life.  Aurora came with a basic game of life implementation that only had one color that cycled through as the generations progressed.  I decided I could make it more colorful so I tweaked the algorithm a bit.  Each cells is colored according to the number of times it has come to life.  Also, as a cell dies, it slowly fades into darkness instead of immediately disappearing.   It's definitely more colorful and feels more, well, organic.  I find the effect quite mesmerizing.

Munching Squares

After I was satisfied with my changes to the game of life, I went on to implement what is perhaps the original display hack, Munching Squares.  This interesting pattern is simply the result of applying the XOR operator to the X and Y coordinates on the grid.  It was discovered by the O.G. Hackers at MIT who were programming the PDP-1 in the 60's. 



Coincidentally, these same hackers went on to become obsessed with Conway's Game of Life and discovered and cataloged many of the interesting emergent patterns that the Game of Life produces.

Gifs

There is an alternative LED Matrix Kit called PIXEL, which has a lot of really cool animated gifs that were designed by artists especially for a 32x32 LED Matrix.  I loaded up my SD card with these so now I have a lot more animations to look at.

Troubleshooting

At one point, I had a scare while uploading a new Aurora sketch and thought my Teensy had bricked itself during reprogramming, but I was eventually able to revive it.  Being a tech support engineer by day, my natural instinct is to share my experience in case it helps anyone else out with a similar problem.

When I hit program on the Arduino UI, it encountered a program error, and went completely unresponsive. The matrix wouldn't light up, Windows said I had connected a USB device that had malfunctioned, and the COM port no longer shows up. I tried disconnecting the power and USB, reconnecting it, reconnecting only the power without USB, hitting the program button multiple times, switching to a different USB port and nothing worked.

I went to the PJRC Teensy forum and found this thread.  It seems to be a fairly common problem. Some of the people on the board suggested to either "double-click" the programming button or hold down the button while plugging in the USB cable. I'm not quite sure which, but one of these worked.

When I did it, Windows no longer showed the "one of your USB devices has malfunctioned and is not recognized" error, but I still didn't see it show up as a COM port.  However, I noticed that device manager was refreshing when it loaded so I dug around elsewhere and found it was showing up as an extra "HID-compliant device" under the "Human Interface Devices" tree, but Windows showed no apparent way to distinguish the 3 identically named devices. 

I rebooted my computer into Linux and ran lsusb and was relieved to see that Teensyduino was listed as one of the devices. I installed Arduino and Teensyduino and successfully programmed the blink sketch and confirmed the light on the back of the Teensy was blinking.  I'm not sure if booting into Linux was really necessary--maybe it would have worked if I had tried to program in Windows immediately after the Teensy showed up as a HID device.  

At this point, I didn't really want to go through the trouble of installing all the Aurora library dependencies, so I booted back into Windows. The Teensy showed up again as a COM port, so I went into Arduino and re-flashed Aurora.

Future Plans

I'm working on a heuristic to determine when the game of life has reached convergence.  Currently, Aurora resets the world after a fixed number of generations, and sometimes it cuts off the game while interesting things are still happening.  My idea is to detect when the universe has devolved to a steady state containing only still life, or simple oscillators. I have come up with a pretty good algorithm, but it still gets tripped up occasionally, usually when the only thing left is a glider that circles the screen and never runs into anything.

Additionally, I'd like to implement the ability to send the Aurora software commands over the serial interface to do things like switch the display mode or offer more customization for the patterns with settings would be too difficult to adjust using the IR remote.  I would eventually like to extend this with a mobile web interface that will allow you to connect to your computer and control the settings from your smart phone.

LEDs, Take Two

This blog post has been languishing half-written in my blogger account for a long time. I have since found an even better solution for driving a 32x32 LED matrix called SmartMatrix (more on that later), but I wanted to share what I had already written about my second attempt along the way.

With the red/green matrix I shared in my last post, I never got past the single 8x8 prototype that I demonstrated in my video.  I eventually tired of the tedium of endless soldering and the frustration of trying to find a way to route all the wires required to connect the 216 pins of the 9 8x8 panels together.

I had taken a break from electronics for a while, but was looking for an excuse to dive back in.  Then I found this video made by Henner Zeller, who has written some software to drive an RGB matrix from the Raspberry Pi.




After seeing this, I ordered the Raspberry Pi Starter Pack along with a 32x32 RGB LED Matrix from Adafruit.  At the time I bought it, the matrix was pretty pricey at $120, so I only opted to get one instead of the four that are chained together in the video above. The price has come down to around $40 since then.

Wiring

This matrix is already fully assembled so the only wiring required is a power cable and 16-pin data cable. The pins were not labelled on the matrix I got, so I looked at Adafruit's instructions to get the pinout for the matrix.  I found the GPIO pinout of the Raspberry Pi on the eLinux wiki, which is a great resource for all kinds of information about the Pi.

With this information in hand, I wired up a prototype using breadboard jumper wire to connect the appropriate pins on the Raspberry Pi's 26-pin ribbon cable to those on the 16-pin ribbon cable provided with the matrix. I connected each pin from the matrix's cable to the corresponding pin on the Raspberry Pi's cable as documented in the software's README. The important thing to remember when making these connections is that the pinout is flipped when looking at the connectors of the ribbon cables.

Once I had the prototype working, I wanted something a little more permanent, so I got some female to female pre-crimped wires plus some 2x8 and 2x12 connector housings from Pololu.  To make a custom cable, you just snap the end of the wire into the appropriate place in the housing.  Before doing this, I decided to move OE- from pin 2 to 27 on the Pi and CLK from pin 3 to 11 so that pins 2 and 3 remain free for the I2C expansion bus.

Adafruit now offers a Raspberry Pi LED Matrix Hat that is a much tidier solution, but if you don't like to solder, you may find the technique I used above more to your liking.

Software

I started with Henner Zeller's original code is on Github.  I have forked his code on Github and made a few changes:


  • Swap blue and green pins so they match wiring shown in Adafruit's documentation
  • Changed OE- from pin 2 to 27 on the Pi and CLK from pin 3 to 11 so that pins 2 and 3 remain free for the I2C expansion bus.
  • Added support for the TPM2.net protocol for streaming video from your PC to the matrix over UDP.
  • Compiled against the Xenomai real-time kernel. Instructions for building a Raspberry Pi linux kernel with Xenomai support are here. There is also a Github repository with some helpful scripts here.


Results

It works pretty well, but because Linux is a multitasking operating system, getting precise timings is not always possible, and when the loop gets preempted, it causes noticeable flicker on the display. Compiling with Xenomai helps this somewhat but it's still noticeable at times.  Also, a bare Raspberry Pi with a wire connected to a bare matrix doesn't really feel like a finished project; however, it's a lost farther than I ever got with my last attempt.

Eventually, I found a better solution the SmartMatrix kit that I mentioned at the beginning of the post. I'll talk more about that in my next post.

Tuesday, August 14, 2012

My Adventures Are Over for Now

I've started a new job and no longer have the time or mental space to devote to electronics, and now that I'm moving to a new house, I no longer have the physical space either. I've sold off my electronic components and I'm taking a hiatus. I'll leave up the blog in case someone finds my TLC5940 Matrix project useful.

Sunday, February 26, 2012

My LED Matrix Needs a Little TLC


I picked up a set of 10 Sure Electronics 8x8 red/green LED matrices for about $13 on eBay.  I figured I could build an Arduino-powered 24x24 LED sign to show messages, run Conway's Game of Life, and play simple games, and still have one more 8x8 matrix left over to experiment with.  I did eventually get a working prototype, but I had no idea of the rabbit hole that it would take me down.




False Starts

The easiest way to get a matrix running on an Arduino is to drive the rows and columns directly from its I/O pins. For a quick introduction on how this works, refer to the Arduino row-column scanning tutorial. Although it's very straightforward, this approach has two major deal breakers:
  1. The LEDs in a typical matrix are rated at 20 mA, so if all the LEDs in a row are on at once, the pin attached to the row would have to supply 160 mA to light the LEDs at full brightness.  The Arduino can only source 40 mA per pin, so this limits us to 5 mA per LED, resulting in a dim display.  Since only one row is lit at a time, the display is even dimmer.  
  2. It requires 16 I/O pins just to drive a single color 8x8 matrix, so forget about driving multiple colors or scaling up to multiple matrices using this approach.  
Another approach I investigated was to use the Maxim MAX7219 or MAX7221 LED display driver chips. The chip was originally intended to drive an eight digit, seven segment display, but can also drive an 8x8 matrix. Both Beginning Arduino and Arduino Cookbook cover this technique in depth. Arduino inherited a library from Wiring to drive matrices using these chips, so getting it working was very easy. Since these chips are purpose built for driving LEDs, they also provide plenty of current to drive the matrix at full brightness.  Unfortunately, they also have several drawbacks:
  1. They're expensive--the cheapest I found the MAX7219 was for $5.25 at Digi-Key. 
  2. The chips were originally designed to drive eight digits on a seven segment display, so scaling up to multiple matrices is awkward.  Driving multicolor matrices likewise requires multiple chips and is not straightforward.  
  3. Each LED is either on or off using this chip, so it's not possible to have multiple shades of color.

The Hardware

This brings me approach I finally settled on. I'm using a Texas Instruments TLC5940 16-channel LED sink driver for the columns and a Micrel MIC5891 8-bit serial input latched source driver for the rows. The TLC5940 has a number of advantages that sold me on it:
  1. This chip is a current sink, meaning that it attaches to the LED's cathode and lights the LED by pulling the cathode toward ground.  Since it can drive 16 channels, it is a perfect fit for an 8x8 bi-color common anode matrix like the ones I am using.
  2. It supports greyscale control using PWM, so the brightness of the red and green LEDs can be finely tuned to produce red, green, or any shade in between.
  3. It's not exactly cheap, but it only requires three TLC5940s ($4.20 each) and six MIC5891s ($2.50 each) to drive a 24x24 bi-color matrix versus eighteen MAX7221s ($5.25 each). Therefore, at the best prices I could find we're looking at a total of $27.60 for the driver chips with the TLC5940/MIC5891 combo versus $94.50 for the MAX7221s.

The MIC5891 is basically a standard shift register (a la 74HC595) which has PNP Darlington transistors built into its output stages, allowing it to source up to 500 mA per output. A standard 74HC595 could be substituted, but each of the eight outputs would need to be attached to an external PNP Darlington or P-channel MOSFET in order to source enough current for the rows.

One TLC5940 and one MIC5891 can drive one 8x8 red/green matrix or two 8x8 single-color matrices side-by-side. It is possible to add an arbitrary number of columns and rows by chaining together additional TLC5940s and MIC5891s.  Eventually, my plan is to scale up to a single 8x8 matrix to a 24x24 matrix composed of nine individual 8x8 tiles.



To build a 24x24 matrix out of nine individual 8x8 matrices, the common columns and rows of each matrix must be tied together.  As you can see in the picture below, I've got a lot of soldering to do.


As the number of columns increases, current demands for the rows will increase proportionally, so multiple outputs of the MIC5891 must be tied together to provide sufficient current. Each row in a 24 column red-green matrix requires approximately 960 mA if all 48 LEDs are on at full brightness.  Therefore three TLC5940s and six MIC5891s should be sufficient to drive it.

I started out driving the chips using a Solarbotics Ardweeny, which is basically just a bare ATmega328 chip with a backpack PCB containing a ceramic oscillator, an FTDI-compatible header, some reset circuitry, and an LED attached to pin 13. It sells for $9 directly from Solarbotics.

However, the ATmega328 will not have enough SRAM to hold a 12-bit 48x24 frame buffer when I scale my matrix up. I also got tired of manually wiring up my AVR programmer each time I wanted to program it since the Ardweeny doesn't have a 6-pin header for it.  When I burned up one of my Ardweenies by accidentally wiring up the wrong pins to an external power supply, this was the last straw.

My search for a better alternative lead me to the Sanguino which sells for $25 from MakerBot Industries. It is a breadboardable Arduino-compatible ATmega644 board with a built-in regulated power supply as well as ISP, JTAG, and FTDI headers. The ATmega644 has more I/O pins, an extra timer, two USARTs, twice the SRAM and 4x the Flash of the ATmega328 used on standard Arduinos.

For even more horsepower, I upgraded the Sanguino's MCU from a stock 644 to a 1284 and replaced the 16MHz crystal with a 20MHz crystal. The 1284 is the most powerful non-SMT AVR chip that you can buy.  Compared to the 644, it has 4x the SRAM at 16K and twice the flash at 128K.  This should provide enough room for the frame buffer with plenty of space left over to write interesting programs to use it.  The 1284 is a drop-in replacement for the 644, so using it in the Sanguino did not require any special considerations.

The Software

As it turns out, finding the right hardware was the easy part.  Driving the TLC5940 is not exactly simple. I first came across the TLC5940 Arduino Library by Alex Leone, but this library is not intended to drive a multiplexed matrix. There is an alpha-quality version of the library that does multiplexing, but it's poorly documented and the example code uses a 74LS138 3:8 line decoder to control the rows instead of the shift register I had decided on. I tried to read the library's code but it left me mystified.

Luckily, Matt Pandina has written a mini-book called--appropriately enough--Demystifying the TLC5940.  Matt takes an iterative approach to developing a library for the TLC5940.  First he implements a verbatim translation of the TLC5940 programming flow chart.  Then he gradually improves the library, adding features such as hardware-driven clock output, timer-based interrupts, and SPI communication. This was exactly what I needed to understand the hardware and the code well enough to make the necessary changes to get my matrix working.  I based my initial code on the final library from Chapter 7 of his book and got a prototype 8x8 matrix working.

Matt has done some really interesting work on his library since writing the tutorial. He's improved the performance of the library by 1.75x using the AVR's built-in USART and implemented multiplexing for use with an RGB POV toy that he's blogging about on Google+. He hasn't gotten around to updating the book to cover his latest changes, but he has released the new source code on the book's website.  It is in the ch9 subdirectory of src.zip. 

The new code is multiplexing the anodes of his RGB LEDs using some P-channel MOSFETs attached directly to the pins of the AVR, while the cathodes are attached to the TLC5940. This is fine for his purposes since he's only multiplexing three anodes, but it won't work for me since my matrix will eventually have 24 common-anode rows. Therefore, I needed to adapt his code to use a shift register to drive the rows instead.

When I e-mailed Matt about the new code, he pointed me towards the following line in the ISR in tlc5940.c which directly toggles the pins on the AVR that are attached to the rows:

MULTIPLEX_PIN = toggleRows[row]; // toggle two pins at once

I've changed that line to the following block of code, which will drive the rows using the shift register instead of directly:

#if (TLC5940_USE_ROW_SHIFT_REGISTER)
   if (row == 0)
     setHigh(ROW_SIN_PORT, ROW_SIN_PIN);
   else
     setLow(ROW_SIN_PORT, ROW_SIN_PIN);
   pulse(ROW_SCLK_PORT, ROW_SCLK_PIN);
#else
   MULTIPLEX_PIN = toggleRows[row]; // toggle two pins at once
#endif

Since the TLC5940 is handling the latching and blanking on the columns, I simplified the operation of the shift register by tying the latch and blank pins high and low, respectively.  That means that all my code has to do is toggle the shift register's serial data and clock pins in such a way that the shift register lights one row at a time.  When the ISR is handling row 0, I set the shift register's serial data pin high so that it will turn on the first row when the clock pin is pulsed.  On all the subsequent rows I set the serial data pin low and send out a clock pulse, causing the lighted row to shift down one. When the ISR cycles back around to row 0, I repeat the process.

Next, I added the following block to TLC5940_Init which sets up the output pins for the shift register and shifts out any garbage the shift register may contain when it is powered up:

#if (TLC5940_USE_ROW_SHIFT_REGISTER)
 setOutput(ROW_SCLK_DDR, ROW_SCLK_PIN);
 setOutput(ROW_SIN_DDR, ROW_SIN_PIN);

 // Clear row shift registers
 setLow(ROW_SIN_PORT, ROW_SIN_PIN);
 for (int i = 0; i < TLC5940_MULTIPLEX_N; i++)
   pulse(ROW_SCLK_PORT, ROW_SCLK_PIN);
#endif

I also added #if (!TLC5940_USE_ROW_SHIFT_REGISTER) to the declaration of toggleRows in tlc5940.c and tlc5940.h, so the variable doesn't take up memory if it's not needed.

Finally, when I moved to the ATmega1284, I discovered that the ports and pins used by SPI and USART are different than on the 328.  Therefore, I have conditionalized the code in  tlc5940.h that defines these pins so that they are defined appropriately depending on which chip the code is being compiled for.

I've conditionalized my code so that the use of the shift register is configurable.  The TLC5940_USE_ROW_SHIFT_REGISTER define controls whether the library uses the shift register or directly toggles the anodes using the pins on the AVR.  The ROW_SCLK_DDR, ROW_SCLK_PIN, ROW_SCLK_PORT, ROW_SIN_DDR, ROW_SIN_PIN, and ROW_SIN_PORT defines configure which pins are used to drive the shift register. All of these defines have been added to the Makefile.

These were the only changes necessary to get the library working with my matrix.  I have committed the code that I derived Matt's optimized ch9 library to GitHub.  


Arduino Compatibility

Matt's library was not written with Arduino in mind, so I have been using AVR Studio to program my matrix, and I have not tested any of my recent code with the Arduino IDE, bootloader, or libraries.  Eventually, I would like to make the library as Arduino-compatible as possible, but this is not currently my top priority.

The library now optionally uses the AVR's USART to drive the TLC5940 up to 1.75x faster. When this option is enabled, it is definitely not Arduino-compatible since Arduino needs control of the USART to load code via the bootloader.  With the USART option disabled, the code should still be marginally compatible with Arduino, subject to the following caveats.  I have not tested it, but if you are the adventurous type, feel free to give it a shot and let me know if it works for you.  I'll try to help with any issues you encounter.

The library requires the CKOUT fuse bit to be enabled so that the clock signal is output on digital pin 8 (pin 14 of the ATmega328). This requires re-burning the bootloader on your Arduino with a different set of fuse bits. You will need an ISP or a second Arduino programmed as an ISP to burn the bootloader.

Once you have your hardware wired up to reburn the bootloader, find the file hardware\arduino\boards.txt in your Arduino directory and edit it as follows:
  1. Find the section like the one below that corresponds to your Arduino and paste a copy of it at the top of the file (don't change the original section).
  2. Add clko to the first part of each line.  In this example, I have changed atmega328 to atmega328clko on each line.
  3. Change the name of the section to indicate CLKO is enabled as I have on the atmega328clko.name line below.
  4. Change the line containing bootloader.low_fuses from 0xFF to 0xBF as shown below.
atmega328clko.name=Arduino Duemilanove w/ ATmega328 (CLKO enabled)

atmega328clko.upload.protocol=arduino
atmega328clko.upload.maximum_size=30720
atmega328clko.upload.speed=57600

atmega328clko.bootloader.low_fuses=0xBF
atmega328clko.bootloader.high_fuses=0xDA
atmega328clko.bootloader.extended_fuses=0x05
atmega328clko.bootloader.path=atmega
atmega328clko.bootloader.file=ATmegaBOOT_168_atmega328.hex
atmega328clko.bootloader.unlock_bits=0x3F
atmega328clko.bootloader.lock_bits=0x0F

atmega328clko.build.mcu=atmega328p
atmega328clko.build.f_cpu=16000000L
atmega328clko.build.core=arduino
atmega328clko.build.variant=standard

Save the file. Now open Arduino, and under Tools>Board, select the entry that you just created (e.g., "Arduino Duemilanove w/ ATmega328 (CLKO enabled)").  Select Tools>Burn Bootloader and wait for the process to complete.  The CKOUT fuse bit will now be set on your Arduino.  After doing this, you will no longer have control over digital pin 8.  If you want to return pin 8 to normal operation, you will need to select your original board from Tools>Board and burn the bootloader again.

Once you have finished reprogramming your Arduino's fuse bits, make the following connections between the Arduino and the TLC5940/MIC5891:

Arduino     TLC5940     MIC5891
Digital 2*               2 SERIAL DATA IN
Digital 3*               3 CLOCK
Digital 8   18 GSCLK
Digital 9*  24 XLAT
Digital 10  23 BLANK
Digital 11  26 SIN
Digital 13  25 SCLK

Also, due to this library's use of Timer 0, it will interfere with the millis(), micros(), delay(), and delayMicros() functions in Arduino.  The library could probably be modified to use a different timer, but I have not tried yet.

Once I get my full 24x24 matrix working with the library in it's current form, I will evaluate changes to further improve compatibility with Arduino.

Friday, February 24, 2012

Make: Electronics

This Christmas, I received a copy of Make: Electronics by Charles Platt, along with the accompanying Make: Electronics Components Pack 1a from Maker Shed.  Just like that, I had a new obses^H^H^H^H^H hobby.

The book can be divided into three parts of roughly equal length. The parts in the first kit correspond to the first two chapters of the book. The kit comes with batteries, a solderless breadboard, hookup wire, a DC power supply and the various electronic components covered by the first section of the book.  This part of the book covers batteries, switches, relays, resistors, capacitors, LEDs, transistors, and other fundamental components. The kit and the first two chapters culminate in a siren circuit made only from transistors, resistors and capacitors.



I completed the projects covered by Component Pack 1 in about a week and ordered Component Pack 2a.  The second kit, consisting mostly of soldering supplies and integrated circuits, includes the all the parts necessary for the next two chapters of the book. The third chapter starts by covering basic soldering skills. It then builds upon the siren circuit from the first section, eventually building it out into a full-fledged burglar alarm with magnetic window/door switches.  Unfortunately, the burglar alarm did not survive the transition into a permanent project--a victim of my fledgling soldering skills.  The lead-free solder in the kit may be the environmentally correct choice, but it didn't make learning to solder very easy.

The fourth chapter delves into integrated circuits in the form of timers and discrete logic. It guides the reader through several projects including a reaction timer, a combination lock, a game show buzzer, and an electronic dice roller.  All in all, the second kit took me another two weeks to complete. My favorite project from this section was the reaction timer, built from 555 timers, 4026 counters, and a seven-segment display.  I'm pretty sure my partner thought I was building a bomb.


I really didn't enjoy building the electronic dice out of 74LS TTL chips.  The circuit was very flaky and I had to alter the resistor values given by the book to make it work.  Maybe the point of this project is that TTL sucks (sorry old-timers).

The fifth chapter starts by giving advice on how to set up an electronics workshop and suggests some additional books for further reading.  It then covers an eclectic variety of topics including electromagnets, motors, generators, audio electronics, robotics, and microcontrollers.   Maker Shed does not offer a kit to go along with this part of the book, but by this point, I felt confident enough in my skills to branch out on my own without slavishly completing the remaining projects in the book.

Overall I recommend both the book and the kits highly.  The book provided a great hands-on introduction to hobby electronics by walking me through fun experiments without getting bogged down in theory, and the kits saved me the intimidation of placing my first order to Digi-Key or Mouser before I knew anything about the components I was ordering.  While Make: Electronics definitely left me with some fundamental gaps in my understanding of electronics theory, it kept my interest long enough to get me hooked, and I believe that was precisely Mr. Platt's goal.

Epilogue

With this blog, my aim is to bring you along on my journey as I learn electronics and share the interesting projects that I work on along the way.  I have been working on a lot of great stuff since completing this book, and I hope to share more with you soon. I hope that others who are starting out will find my experience useful as my understanding grows.