loading

Step 5: Code

The Arduino sketch draws the screen scanning row by row from top to bottom, much like a CRT-based TV screen.  It has the added complexity that in order to keep our current within the limits that the Atmega328P can handle, we can only light at most 2 LED's at a time.   Therefore, we also scan from left to right.  Even though only 2 LED's at a time are lit, to our eye, they appear to all be lit at the same time due to a phenomenon called persistence of vision.

The display code is interrupt driven, and uses the Timer1 library .  Timer1 isn't bundled in the Arduino software installation.  Therefore, to install it, you must download TimerOne.zip , and unzip its contents into your sketchbook/libraries/TimerOne.

A Frame is a screenful of data. A very straightforward and common way of storing the data would be to use a byte for each LED.  This would use 25 bytes per frame.   To save memory, we define it as an array of 5 bytes.  Each byte represents an entire row of our display.  Since a byte is composed of 8 bits, and we only have 5 LED's per row, we only use the bottom 5 bits, and the top 3 bits are ignored.  There are 5 bytes because we have 5 rows.  We could save another byte by packing 25 bits into 4 bytes, but that complicates the code unnecessarily, and makes it impossible to graphically view the frame declarations in frames.h.

  #define DIM 5 // x/y dimension - 5x5 matrix
  typedef byte Frame[DIM];


The column LED pins are defined in the cols array.

  int cols[DIM] = {12,11,10,9,8};


The row LED pins are defined in the rows array.

  int rows[DIM] = {7,6,5,4,3};

To turn on a particular LED, we set its cols pin HIGH and its rows pin LOW.  This causes current to flow through the selected LED.  The most straightforward way to do this would be to use the digitalWrite() function on each LED in sequence.  So to turn on the top left LED, we could use

  digitalWrite(cols[0],HIGH);
  digitalWrite(rows[0],LOW);

and do that for each LED.  However, that's not very efficient.   Instead we use direct port manipulation to turn on the columns.  The PORTB register corresponds to digital pins 8 to 13.
Note the ordering which we used in our declaration of the cols array above:  12,11,10,9,8.  This way, bit0 of PORTB corresponds to the far right column, bit1 corresponds to the next column to the left, until bit4, which corresponds to the far left column.  If we set a particular bit to 1, it's the same as calling digitalWrite() with HIGH, and setting a bit to 0 is equivalent to calling digitalWrite() with LOW.   Therefore, we could theoretically replace calling digitalWrite() 5 times to set all 5 columns with one write to PORTB.  But since we are allowed to turn on at most only 2 LED's at a time, we have to loop 3 times for each column, scanning 2 bits at a time.

// Interrupt routine
// each time display() is called, it turns off the previous row
// and turns on the next row
byte bitMask = B00000011;
void display() {
  digitalWrite(rows[row], HIGH); // Turn whole previous row off

  if (bitMask == B00010000) {
    bitMask = B00000011; // light the right 2 columns (pins 9,8)
    // increment row and wrap if necessary
    if (++row == DIM) {
      row = 0;
    }
  }
  else if (bitMask == B00000011) {
    bitMask = B00001100; // light the middle 2 columns (pins 11,10)
  }
  else { // bitMaskIdx == B00001100
    bitMask = B00010000; // light the leftmost column (pin 12)
  }

  // direct port manipulation.
  // PORTB is a pseudo variable for digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
  // the bottom 5 bits are our columns. We don't want to change the other bits,
  // so we first mask the bits we ignore, and then set the bits we want to light
  PORTB &= B11100000;
  PORTB |= curFrame[row] & bitMask;

  digitalWrite(rows[row], LOW); // turn on the row
}

Note that our comment above says that display() is an interrupt routine.  This is because instead of handling the scanning in our loop() function, we call it in the background via the Timer1 library.

  // interrupt interval in uSec
  // this determines how long to keep each row turned on
  // so if we have 5 rows, we redraw the whole screen
  // once every 5 rows * 3 cycles per row * 1000 usec = .015 sec -> 66.67Hz
  // if you perceive flickering you can decrease to 500 for a 133.33Hz rate
  Timer1.initialize(1000); // fire the interrupt every 1000 microseconds
  Timer1.attachInterrupt(display); // call display() at every interrupt.

The main loop simply steps through all of our animation frames.

  void loop() {
    // increment the frame index and wrap if necessary
    if (++curFrameIdx == FRAMECNT) {
      curFrameIdx = 0;
    }

    // select frame for display
    setFrame(curFrameIdx);

    delay(400); // wait time between frames in ms - reduce this value to speed up the animation, increase it to slow it down
  }

The entire sketch is attached below.
 
<p>Is it possible to fry arduino when all leds is in high state? i am planning to put a transistor and external powersupply to drive the leds, but is it practical to use? thanks anyway! ^_^<br><br><br>--------------</p><p><br>ah okay i got it, POV fix this problem (y)</p>
<p>Hi All; Is there somelimit to the number of frames? I have a big bunch but when I get to 13K bytes the code functions erratically. Can someone help? Lincomatic?</p>
<p>i wired up everything and used the same code as you did but ALL of my leds are on and wont do the pattern. help!</p>
<p>With just that explanation its very difficult to diagnose but if you uploaed the codeyou problem should be your wiring. Start over again and double check each connection.</p>
I already changed them in the code. Your cols looks like this <br>int cols[DIM] = {12,11,10,9,8}; <br>Mine is: <br>int cols[DIM] = {13,12,11,10,9}; <br> <br>Your rows <br>int rows[DIM] = {7,6,5,4,3}; <br>Mine <br>int rows[DIM] = {8,7,6,4,3}; <br> <br>I got your other message about replacing the &quot;// direct port manipulation&quot; I apologize I don't really know what that means.
<p>I suppose you want to change pins to make the board easier. I used</p><p>int cols[DIM] = {13,12,11,10,9}; and A0,A1,A2,A3,A4 for ROWS. </p><p>But that needs changes in software and could really complicate your life.</p>
Look at the code in the article. There is a section:<br><br> // direct port manipulation.<br> // PORTB is a pseudo variable for digital pins 8 to 13 The two high bits (6 &amp; 7) map to the crystal pins and are not usable<br> // the bottom 5 bits are our columns. We don't want to change the other bits,<br> // so we first mask the bits we ignore, and then set the bits we want to light<br> PORTB &amp;= B11100000;<br> PORTB |= curFrame[row] &amp; bitMask;<br><br>replace the two PORTB lines with <br><br> digitalWrite(cols[0],HIGH);<br> digitalWrite(rows[0],LOW);<br><br>The code will run slower, though. My code was optimized for the pins that I used. There's no way to optimize for random pins.
<p>guys i'm getting this.. any idea how to fix this ?</p><p>In file included from daftpunk.ino:1:0:</p><p>C:\Users\Tanzeem\Documents\Arduino\libraries\TimerOne/TimerOne.h:19:7: error: previous definition of 'class TimerOne'</p><p> class TimerOne</p><p> ^</p><p>Error compiling.</p>
<p>Thanks for this,lincomatic. Ive read and understand almost everthing but as Im still new to Arduino, I cant figure out how to run this onArduino IDE.</p><p>I dont see any .pde .ino files. Can somebody HELP, please.</p>
<p>I made the 5x5 led matrix but I'm having a hard time with the code. Instead of your pins I used the ones that was the easiest to get to for the atmega328 for and anodes I used pins 13,12,11,10,9 and for the cathodes I used 3,4,6,7,8. I changed them in the code but nothing comes out of pin 13 but when I do the test it works fine. I create a design I like put it seems it shifts to the right What do I need to do to the code so it all works.</p>
Change the numbers in the rows[] and cols[] arrays
also, as I explained in the instructable, you need to replace<br><br> // direct port manipulation.<br> // PORTB is a pseudo variable for digital pins 8 to 13 The two high bits (6 &amp; 7) map to the crystal pins and are not usable<br> // the bottom 5 bits are our columns. We don't want to change the other bits,<br> // so we first mask the bits we ignore, and then set the bits we want to light<br> PORTB &amp;= B11100000;<br> PORTB |= curFrame[row] &amp; bitMask;<br><br>with <br><br> digitalWrite(cols[0],HIGH);<br> digitalWrite(rows[0],LOW);<br>
Hello <br>I plan to do this project using 3w leds, so I know I need to place some transistores in the circuit. But using transistores for all pins I need to change the code right. <br>In you case to turn a certain led on you would put one port high and another low, but using transistors I need to put both ports on. <br>I am thinking correctly ? <br>If yes where do I change the code in order to be able to use transistors ? <br>Thanks <br> <br>Jos&eacute; <br>
<p><a href="http://www.instructables.com/id/Yet-Another-Daft-Punk-Coffee-TableDisplay/" rel="nofollow">http://www.instructables.com/id/Yet-Another-Daft-P...</a></p><p>The daft punk is a great instrucatble. I saw you had the same question as mine. Were you able to solve it. If yes, I am curious to know how you did it. <br></p><p>I have been planning to do the same thing with 3W LED's. How shall I go about it. I do know that I would perhaps need transistors for them. <br></p><p>What I do not know as of now is how would the circuit look like once I have made the required changes. The transistors would only be placed where you have the current limiting resistors placed ?</p><p>I am having a feeling I need 5 circuits similar to diagram #5 in <a href="http://www.instructables.com/id/Circuits-for-using-High-Power-LED-s/" rel="nofollow">http://www.instructables.com/id/Circuits-for-using...</a></p><p>Do you think the same ? I just want to be sure I do not burn my UNO in the process</p><p>Thanks in advance</p>
It's been a while since I wrote this code, but I think all you have to do is change the line at the top of display() from <br> digitalWrite(rows[row], HIGH); // Turn whole previous row off <br>to <br> digitalWrite(rows[row], LOW); // Turn whole previous row off <br> <br>and the bottom line from <br> digitalWrite(rows[row], LOW); // Turn whole row on at once (for equal lighting times) <br>to <br> digitalWrite(rows[row], HIGH); // Turn whole row on at once (for equal lighting times) <br> <br>Also, you don't need to light only 2 LED's at a time like I did, since you'll be able to handle the current of a whole row at a time. So your display() function should look like this: <br> <br>// Interrupt routine <br>// each time display() is called, it turns off the previous row <br>// and turns on the next row <br>byte bitMask = B00011111; <br>void display() { <br> digitalWrite(rows[row], LOW); // Turn whole previous row off <br> <br> // increment row and wrap if necessary <br> if (++row == DIM) { <br> row = 0; <br> } <br> <br> // direct port manipulation. <br> // PORTB is a pseudo variable for digital pins 8 to 13 The two high bits (6 &amp; 7) map to the crystal pins and are not usable <br> // the bottom 5 bits are our columns. We don't want to change the other bits, <br> // so we first mask the bits we ignore, and then set the bits we want to light <br> PORTB &amp;= B11100000; <br> PORTB |= curFrame[row] &amp; bitMask; <br> <br> digitalWrite(rows[row], HIGH); // Turn whole row on at once (for equal lighting times) <br>} <br> <br>
Thanks for your reply. <br>regarding the transistor do you have any sugestion ? <br>Yesterday I got some BUZ12 but I dont think it will do the trick. <br> <br>Jos&eacute; <br>
I think it will work OK w/ your BUZ12. It handles 12A and you only need to sink about 5A per row.
I need the buz12 to control both the cathods and anoths. <br>I did some testing and it seams to work with only one of them. <br>Only when I put the negativ trough the buz12 works, if I change it it stays always on. <br>What the hell am I doing wrong ? <br> <br>Jos&eacute; <br> <br>
<p>This is a great instructable. I am done with the sort of LEDs you have described and looks just awesome.</p><p>I have been planning to do the same thing with 3W LED's. How shall I go about it. I do know that I would perhaps need transistors for them. </p><p>What I do not know as of now is how would the circuit look like once I have made the required changes. The transistors would only be placed where you have the current limiting resistors placed ? </p><p>It would be great if you could give me the right pointers on the same. I could also see that some of the other guys also had the same query as well. </p><p>Thanks in advance</p>
<p>Hey, I have been following your instructions, i've got the matrix to work, and all the frames play out without music sync. However when I try to use the music sync with adafruits eletrect mic all i get is the LEDs (Col 0, Row 0) and (Col 4, Row 4) constantly on. Any idea why this is happening? *Disclaimer* Newby Alert**</p>
Hey : ) <br /> <br />i built your table with some large blue leds but they did not make bright enough light so i went for straw hat leds which seemed to be fine. For testing purposes i put one of them on a cr2032 battery with 3 V and it worked fine. I replaced one of the leds in my arduino driven matrix with one of the new red leds and was disappointed: It seems that it does only glow with much less intensity than it did before on the battery. Did i do something wrong or does the matrix work this way and there is not enough power for the maximum brightness of the leds? <br /> <br />thank you so much, <br />tm <br />p.S: I currently use a 91 Ohm resistor which should be even lower than the one it would need for the red ones
In order to keep the current within the alllowed levels on the Arduino, the current is limited. If you want to drive your LED's with more current, you will have to either use transistors, or add a driver IC
thank you for your answer! Oh thats bad. I have no idea how to do this. Do you know an instructable or other tutorial for a 5x5 arduino matrix like yours withh drivers or transistors? maybe i can upgrade my matrix..<br /><br />thank you very much<br />tm
Did you ever figured out how to do this project with transistors ? <br>
Hello <br>I plan to do this project using 3w leds, so I know I need to place some transistores in the circuit. But using transistores for all pins I need to change the code right. <br>In you case to turn a certain led on you would put one port high and another low, but using transistors I need to put both ports on. <br>I am thinking correctly ? <br>If yes where do I change the code in order to be able to use transistors ? <br>Thanks <br> <br>Jos&eacute; <br>
Hey is the TRS jack here male or female? It looks like like a female trs jack in the photo you posted but you linked male phone audio connectors in the comment below this.
female
Hey There, <br>I have built a 5x5 matrix and it seems to be working great in test mode. The LEDs are bright and fill the 2&quot; squares they are in. However, when I leave test mode and go into the animation frames the brightness of the LEDs greatly diminishes. Is this due to the current limitation on the Arduino or is there something else going on within the code that does this? Any help or insight anyone could provide would be much appreciated. <br>Thanks.
is the trs jack an auxillary wire? can you post a picture of it? (i would really appreciate it if you replied to this ASAP because we are doing this for school)
have you heard of google?<br>http://en.wikipedia.org/wiki/Phone_connector_(audio)
Great Instructable. I've wired it up and it is working great in test mode. As soon as I turn off test mode however, none of my LEDs will light up. I have installed TimerOne in the correct location, and the compiler does not indicate any errors, so I don't think the issue lies there. Any other ideas where I should be looking for the issue?
It sounds like the timer isn't working. Are you using one of the newer Arduinos like the Leonardo? If so, I'm not sure if Timer1 will work.
I'm using an Uno. A problem with Timer1 makes sense since test mode works. I'm not getting any code errors though, which I get if I remove the library. Would the IDE version matter at all? I'm using 1.0.
I did a little more digging and discovered that Timer1 only works with certain pins. I had been using 3-7 for anodes and 8-12 for cathodes. Reversing this fixed the issue. Working great now, thanks again!
I really don't understand what this piece of code does. I'm trying to make a 3x3 matrix but the first column is on all the time.<br> <br> if (bitMask == B00010000) {<br> &nbsp;&nbsp;&nbsp; bitMask = B00000011; // light the right 2 columns (pins 9,8)<br> &nbsp;&nbsp;&nbsp; // increment row and wrap if necessary<br> &nbsp;&nbsp;&nbsp; if (++row == DIM) {<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; row = 0;<br> &nbsp;&nbsp;&nbsp; }<br> &nbsp; }<br> &nbsp; else if (bitMask == B00000011) {<br> &nbsp;&nbsp;&nbsp; bitMask = B00001100; // light the middle 2 columns (pins 11,10)<br> &nbsp; }<br> &nbsp; else { // bitMaskIdx == B00001100<br> &nbsp;&nbsp;&nbsp; bitMask = B00010000; // light the leftmost column (pin 12)<br> &nbsp; }<br> <br> what do i have to do to fade the leds instead blink them?
the bits that are set to one are the columns that will light. since this is 5x5 the 5th bit is the leftmost column.<br>If you need to figure out what's going on w/ a column staying on all the time, try TESTMODE... it will light up the LED's in sequence. You might have a wiring error.<br><br>You have to use PWM to fade them. I don't have time to write the code for you
First off - thanks for the awesome Instructable! I've managed to build the display and get it running.<br> <br> I'm working on a version that uses random numbers instead of pre-defined values in frames.h. However, I'm running into a snag and perhaps you can help me to figure out why.<br> <br> Whenever I call random(), the display freaks out and flickers. Everything works find when that statement is REM'd. Is this a problem with the random number generator used in conjunction with the interrupt library?<br> <br> Thanks!
I don't know. You shouldn't call random() from withing the ISR. Maybe it's taking too long. Try to find a simple random number generator that doesn't use floats. You don't need anything fancy to just pick random frames.
Thanks for the tip! I've found an example that uses an analogRead on a pin with nothing attached to get a 0 or 1. Seems to work Ok. I've also found that I can call random() from inside the main loop() but when I call it from a function, it's too slow.
I'm building this as a table for an engineering project. I put all three files (frames, daftpunk, and timerone) into my sketchbook but when I try to upload it to my board it says &quot;Timer1 was not declared in this scope.&quot; Help?
it goes into sketchbook\libraries\TimerOne, not sketchbook\TimerOne
I asked my professor and he said the same, thanks! Also, if I want to make my LEDs brighter, how bad of an idea is it to add another 120ohm resistor to each existing resistor in parallel to only have 60ohms of resistance? How much chance am I taking as far as burning my LEDs out?
You really need to figure out how much current your LEDs are rated for, and set the resistance accordingly. The main problem with brightness is the limitation on how much current the Arduino can dissipate without getting burned out, since for simplicity, the LED's are being driven directly by the Arduino. If you change the circuit to use transistors to drive the LED's instead, you can put more current through. And then you can change my sketch to drive a whole row at a time, which will increase the duty cycle so the LED's will be brighter.
hi there, <br>i want to built the 5x5-matrix too, but first i wanted to try the animationbuilder, unfortunately the link doesn't work. can anyone tell me, if i can download it elsewehere. would be really nice to have it. thanks in advance! <br> <br>and great tutorial!!! after this i'll maybe try the lampduino ;). <br> <br>
Sorry, it seems they don't let me upload HTML files anymore. I put it into a zip file. Please download daftpunkanimationbuilder.zip. Unzip it to daftpunkanimationbuilder.html, and load it into your web browser
thank you for the super fast reply and the upload of the zipfile!!! works great. <br> <br>next step is to sand + paint the table and to find the right leds. the table already has a 5x5 grid built in, but the &quot;pixels&quot; are quite big. i'm going to buy a few leds and try, if i can find one, that has the right angle to light the hole pixel. <br> <br>i'm going to post some pictures or maybe a video of the final result. <br> <br>thanks again!!!
Cool, looking forward to seeing your build when it's done.
Hi, I finally got around to building your ible with a mod <a href="http://www.instructables.com/id/Daft-Punk-LED-Matrix-Breakout-Board/" rel="nofollow">http://www.instructables.com/id/Daft-Punk-LED-Matrix-Breakout-Board/</a><br /> <br /> Your animation builder html leads to a 403 forbidden error, maybe a bug?
Sorry, it seems they don't let me upload HTML files anymore. I put it into a zip file. Please download daftpunkanimationbuilder.zip. Unzip it to daftpunkanimationbuilder.html, and load it into your web browser

About This Instructable

120,902views

334favorites

License:

Bio: For more information on my projects as they develop, visit my blog: http://blog.lincomatic.com
More by lincomatic:Turn Your Bike Into a Party MachineLampduino - an 8x8 RGB Floor LampYet Another Daft Punk Coffee Table (5x5 LED Matrix)
Add instructable to: