Thursday, July 5, 2012

Implementing Artcfox's TLC5940 code on an Arduino, Part 2

In my last post I detailed the basic hardware and software setup for getting Matt's TLC5940 chapter 3 code working on an Arduino. The the code doesn't do too much, but with the hardware and software working we can start to explore later chapters (where the interesting stuff happens).

At this point there is one more hardware obstacle to overcome. Matt makes use of an interesting feature of the Atmega328p called CKOUT. This is a chip level setting that can (according to the 328p datasheet) "output the system clock on the CLKO pin". Matt uses this to drive the TLC5940's GSCLK pin, a very clever way of handling the timing between the two chips.

Unfortunately the Arduino is not configured to support this by default and in order to switch on this feature, special configuration values in the 328p's flash known as "fuses" need to be be set. To do that, you need a chip level programmer.

The programmer I use is an USBtiny2 clone that I got off eBay for about 10 USD (search for "usbtiny" or "usbtinyasp" and you should get many results). Alternatively you can use a second Arduino to accomplish the same thing as per this link. Lastly, if you want to support a really fantastic company and get a great programmer with a nice case, please consider this one from Adafruit.
From this point on I will be assuming that you are using the USBtiny programmer, are on a Windows machine and are intending to program the fuses of an Arduino UNO.

At this point I am assuming that you have managed to install the drivers for your programmer. If you are using the USBtiny and are on Windows7 64-bit, this link may be helpful. If not, visit this excellent tutorial at Adafruit and get the drivers installed.


Once you have the hardware, you need to get hold of AVRDUDE. This is the software that will talk to your programmer and allow you to set the fuse bits. As of this article the latest AVRDUDE version is 5.1.1 and can be found here. If you are using an alternative programmer, please check compatibility with AVRDUDE at this page (look for the "-c programmer-id" reference).

Grab the windows archive (avrdude-5.11-Patch7610-win32.zip) and extract to a convenient location. I used "C:\temp\avrdude". Now you will need to connect your programmer to your Arduino.

Arduino ICSP port

Using the supplied 6 pin cable connect the programmer to the ICSP port on your Arduino, making sure you have:

  • disconnected your Arduino from USB and any other circuitry.
  • correctly identified the polarity and orientation of the programming cable and pin 1 on the ICSP port of the Arduino.

Once you have the cable correctly connected, connect the programmer to usb and the Arduino should power on.

Assuming everything is good to go: open a command prompt, change to the directory you extracted the AVRDUDE software into earlier ("c:\temp\avrdude" for me) and type:

avrdude -p m328p -c usbtiny 

See the advanced notes for additional information.

This command should print out something pretty much like this:

AVRDUDE basic output

If you get this result, add a "-v" to the command:

avrdude -p m328p -c usbtiny -v

which should spew out a whole load of text ending in something that looks like this:

Standard Arduino UNO fuse settings

What we want to do is to change the value of the lfuse from 0xFF to 0xBF to enable CKOUT.

To verify this, open this awesome AVR fuse calculator in another tab / window and check the lfuse checkbox that reads "Clock output on PORTB0; [CKOUT=0]". You should see the calculated value for lfuse change from 0xFF to 0xBF (and back when you uncheck the option).

Before we proceed any further, a word of caution:

Incorrect fuse settings can brick your Arduino!!!

If your fuse settings are not the same as the screenshot above you probably shouldn't proceed unless you are sure you know what you are doing.

Some clarification: You need to know that you have a good fuse read at this point. Your values may be different to mine but as long as they are good values you'll be okay.

Thanks to +Al McElmon who reported his hfuse value as D6 not DE. In the fuse calculator you can see that this is because EESAVE has been enabled. This could possibly be a setting on later Arduino Models?

Finally, if everything checks out and you are 100% sure of this, we are one command away from completion:
avrdude -p m328p -c usbtiny -U lfuse:w:0xBF:m -u

This command will write the value 0xBF to the lfuse and set CKOUT.
For a breakdown the "-U" command above, the command:
  • selects the lfuse memory for the operation
  • writes (use r for read and v for verify)
  • the value 0xBF
  • in immediate mode (i.e. write the value specified directly)
"-u" turns off safe mode which should enable the actual write.

And there we have it. Your Arduino should now be in a state where we can move onto the more advanced chapters of Matt's book.

Next time we are going to do exactly that, I hope you've enjoyed this post.
Until then, happy hacking!
-(e)

p.s. If you get stuck, I can attempt to help you out, circle me on G+ and send me a message via Messenger, or post a comment and I'll see what I can do.


Advanced Notes:

Perhaps you have a different model of Arduino? (e.g. ATMega168 e.t.c.):

The "-p m328p" switch for AVRDUDE specifies what chip your Arduino has. The "m328p" value is valid for the Arduino UNO and several other models, but will have to be changed for alternative models.

In this case, when using the fuse calculator please input your values for lfuse, hfuse and efuse into the fuse calculator, ensure that you have the correct AVR chip selected and note the change in the lfuse value when CKOUT is selected. The point here is that we wish to change ONLY this value. You can also confirm default board fuse settings in the "boards.txt" file located in the "hardware\arduino" directory of the Arduino IDE installation.

AVRDUDE has many other switches and supports many other programmers. I would suggest that you check out the command line in the documentation.

13 comments:

  1. I have sent several emails and non of them appear to have reached you. If you get this let me know

    ReplyDelete
    Replies
    1. Got it! Circle me on G+ and I'll get in direct contact with you.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hey Peter, right now my G+ is a circle of 1.... It does not exist. I could contact you later if and when I add this functionality. The TLC5940 does have a great deal of potential to go way beyond the conventional R,G,B applications, which, quite frankly are really old news.

    Still not yet at the point where I have set up the second microcontroller with the reprogrammed CLKO pin... but this will be one of my next steps, and your site is very helpful to getting to this point. I am interested in algorythms for imaging using this chipset.

    If there is a way to communicate using my gmail account I would be interested in a dialog and discussion about some of the other possibilities using this chipset.
    Also happy to share the results.

    Hope you are also thinking about possibilities for this enhanced functionality as well.

    Have you given much thought to how the Dot correction and Gray scale might be used for say calibration??? Or tuning a light source????

    Best Mark

    ReplyDelete
    Replies
    1. Hi, what is your Gmail? I only get some no-reply address from comments. Mine is sweetlilmre at gmail dot com.

      Delete
  4. Hi Peter,
    I'm playing with the TLC5940 as well for a little logger project, so thanks for this detailed information.
    I am now contemplating how to minimize current draw from this chip when it's not in use (i.e., when I send the Arduino/Atmega to sleep)?
    One thought is to use a load switch/transistor to control the supply voltage itself on the TLC5940, but I wonder if the power-on initialization time would be small enough (if it's on the order of microseconds, should be fine).
    Any thoughts, or alternate ideas?
    Cheers,
    Anders

    ReplyDelete
  5. Mr Edwards, thanks for the info on the fuse setting I have reprogrammed the chip to the new setting and have ordered 4 colors of leds red green blue and white. there are four of each = all 16 channels. Are you yet at a point where all 16 channels all operating in concert. I would like to try to set the PWM and DC separately. There are 192 bits for the PWM and 96 bits for the GS... Whats next in terms of getting the lights turned on and manipulating them.

    Thanks Photon144

    ReplyDelete
    Replies
    1. Hi,

      I've been working on the CH9 samples and have the code working. With the current code all 16 channels will work, you'll just need to fiddle with the code to set whatever values you'd like. The new code will do DC and gamma on RGB values. I am writing the code to initially use direct connections to RGB leds and will look into the the multiplexing stuff when I can get hold of some appropriate transistors. Hopefully I will have some time to put together a post this week.

      Delete
  6. Peter, The Output current is not high enough to drive the leds to thier full potential.

    Everything is running but you may be experiencing a lower than adequate output on your set up as well. I have been through the datasheets and set the limiting resistor at 2.2k, however, when I measure the current on each led, they are only outputting a bit more than 1mA.

    This is 20 times less than what they should be outputting. Otherwise the DC annd GS functions are both working fine. I set everything high to check first. The 6 bits of DC are high and the 12 of GS are high.... still only 1 mA output each channel.

    Not sure what the issue is but if this bug can be figured out it will be much more spectacular when it is all working.....

    Any thoughts? Have you checked your current to each led??? The problem might be with the artcfox setup Did either of you check the output current on this configuration?

    Are you worjking on chapter 9 ????

    Best Photon 144

    ReplyDelete
    Replies
    1. Hi,

      I haven't experienced this at all. The LEDs on my setup (running 4 simultaneously) are blindingly bright. I'll try and get some time to look at the output on each line. It sounds like you have a fault in the circuit or a damaged chip?

      CH9 is effectively done. I wrote some basic rainbow generation code around it. The only missing bit is multiplexing support (its there, I just don't have the HW to test with). Maybe this weekend, though I am so damn busy at the moment I hardly have time to sleep :)

      -(e)

      Delete
  7. Hi Peter, first of all, thanks for your afford! I'm just working on a LED chandelier and have choosen the TLC5940 long before I fell over Matt's and and your page. While I have a Freaduino Leonardo here to control it, I ended up at you blog here. Now I started to do the wiring and I have a question. While my Leonardo has the "Clock Out" on port C7 you were writing about B0 on our Uno. I took a look at the datasheet from arduino.cc and found port B0 not connected to anything? From your connection diagram I would guess that it is Output 13 on your Uno, am I right?

    Regards, Marcus

    ReplyDelete
    Replies
    1. Hi,

      If you look at this: http://arduino.cc/en/Hacking/PinMapping
      You'll see that for the 328P, B0 is mapped to digital pin 8.
      The Leonardo is a 32U4 based board so the pin mapping is different, see:
      http://arduino.cc/en/Hacking/PinMapping32u4

      So for my Uno, it would be pin 8, pin 13 is SCK for SPI.
      It would seem that you would have to map to 13 for clock (and change the SPI mappings accordingly). It seems your board has a separate SPI breakout bus:

      http://www.elecfreaks.com/wiki/index.php?title=Freaduino_Leonardo

      HTH
      -(e)

      Delete