16x32 RGB LED Matrix, Arduino Due

EL Wire/Tape/Panels, LEDs, pixels and strips, LCDs and TFTs, etc products from Adafruit

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
LXD
 
Posts: 2
Joined: Thu Feb 21, 2013 2:59 am

16x32 RGB LED Matrix, Arduino Due

Post by LXD »

Hi, I found less information about this.
Will the 16x32 or 32x32 RGB LED-Matrix work with the Arduino Due? Is someone porting the library for the Arduino Due.
Another Question will the library for the digitally controlled pwm led stripes, work with the Due?
Thanks in advance

MarkEMarkEMark
 
Posts: 33
Joined: Thu Dec 20, 2012 9:33 am

Re: 16x32 RGB LED Matrix, Arduino Due

Post by MarkEMarkEMark »

There doesn't seem to be many people here with Due's yet. There was a shortage, so hopefully now that is sorted out, more people here will get them.

I've ported Adafruit's WS2801 and LBD8806 libraries to the Due. There were quite a few things I needed to do, but it is possible.

I'd encourage you to try it yourself, if it doesn't work straight away.

User avatar
pburgess
 
Posts: 4161
Joined: Sun Oct 26, 2008 2:29 am

Re: 16x32 RGB LED Matrix, Arduino Due

Post by pburgess »

Hardwarily, there's no reason this couldn't work. The Due would be great for this.

Softwarily, the library hasn't been ported yet. There are some hardware differences that would need to be dealt with (timers, etc.) that make this a non-trivial effort. But it seems likely it'll happen...just no ETA right now.

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

Is there any eta on a port of the LED matrix library for the Due? I've got something mostly working, but there is a bit of ghosting going on so I thought I'd check in to see if anybody else is working on this. If not, I can post what I have if others have any ideas.

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

Since nobody has responded, I assume nobody has gotten further then my blundering about :)

So, this is as far as I've gotten with porting stuff from the Adafruit RGB library:

Code: Select all

#include <Arduino.h>


#define APIN     33
#define BPIN     34
#define CPIN     35
#define LAT   38
#define OE    36
#define CLK   37
#define R1    32
#define G1    29
#define B1    27
#define R2    30
#define G2    28
#define B2    26


#define PWMBITS 3      // 3 = 3 bit color per LED, 9-bit total pixel color
#define PWMMAX ((1 << PWMBITS) - 1)

#define WIDTH 96       // = 32 X number of panels
#define HEIGHT 16      //  = height of each panel

#define NUMBYTES (WIDTH * HEIGHT / 2) * 3  // use 1.5 bytes (12 bits) per pixel

#define maxScan 8 // number of sections that are scanned - 8 rows for each RGB-123

uint8_t matrixbuff[NUMBYTES];  // 768 bytes for 16x32

volatile uint8_t pwmcounter=0;
volatile uint8_t scansection=0;




//----------------------------
void matrix_begin() {

  pinMode(APIN, OUTPUT);
  digitalWrite(APIN, LOW); 
  pinMode(BPIN, OUTPUT);
  digitalWrite(BPIN, LOW); 
  pinMode(CPIN, OUTPUT);
  digitalWrite(CPIN, LOW); 
  pinMode(LAT, OUTPUT);
  digitalWrite(LAT, LOW); 
  pinMode(CLK, OUTPUT);
  digitalWrite(CLK, HIGH); 

  pinMode(OE, OUTPUT);
  digitalWrite(OE, LOW); 
  
  pinMode(R1,OUTPUT);
  pinMode(R2,OUTPUT);
  pinMode(G1,OUTPUT);
  pinMode(G2,OUTPUT);
  pinMode(B1,OUTPUT);
  pinMode(B2,OUTPUT);
  digitalWrite(R1,LOW);
  digitalWrite(R2,LOW);
  digitalWrite(G1,LOW);
  digitalWrite(G2,LOW);
  digitalWrite(B1,LOW);
  digitalWrite(B2,LOW);
}



// construct a color from an r,g,b value
uint16_t matrix_Color444(uint8_t r, uint8_t g, uint8_t b) {
  uint16_t c;
  
  c = r;
  c <<= 4;
  c |= g & 0xF;
  c <<= 4;
  c |= b & 0xF;
  return c;
}


// draw a pixel at the x & y coords with a specific color
void  matrix_drawPixel(uint8_t x, uint8_t y, uint16_t c) {
  uint16_t index = 0;
  uint8_t old;
  uint8_t red, green, blue, panel, ysave, ii;
  
  // extract the 12 bits of color
  red = (c >> 8) & 0xF;
  green = (c >> 4) & 0xF;
  blue = c & 0xF;
  
  panel = (y - y%16)/16;

  // both top and bottom are stored in same byte
  if (y%16 < 8) 
    index = y%16;
  else 
  index = y%16-8;
  // now multiply this y by the # of pixels in a row
  index *= WIDTH;
  index += 32*panel;
  // now, add the x value of the row
  index += x;
  // then multiply by 3 bytes per color (12 bit * High and Low = 24 bit = 3 byte)
  index *= 3;

  old = matrixbuff[index];
  if (y%16 < 8) {
    // we're going to replace the high nybbles only
    // red first!
    matrixbuff[index] &= ~0xF0;  // mask off top 4 bits
    matrixbuff[index] |= (red << 4);
    index++;
    // then green
    matrixbuff[index] &= ~0xF0;  // mask off top 4 bits
    matrixbuff[index] |= (green << 4);
    index++;
    // finally blue
    matrixbuff[index] &= ~0xF0;  // mask off top 4 bits
    matrixbuff[index] |= (blue << 4);
  } else {
    // we're going to replace the low nybbles only
    // red first!
    matrixbuff[index] &= ~0x0F;  // mask off bottom 4 bits
    matrixbuff[index] |= red;
    index++;
    // then green
    matrixbuff[index] &= ~0x0F;  // mask off bottom 4 bits
    matrixbuff[index] |= green;
    index++;
    // finally blue
    matrixbuff[index] &= ~0x0F;  // mask off bottom 4 bits
    matrixbuff[index] |= blue;
  }
}


// output your filled matrix
void matrix_writeSection(uint8_t secn, uint8_t *buffptr) {
  
  //digitalWrite(OE, HIGH);
  uint16_t portCstatus_nonclk = 0x0080; // CLK = low
  uint16_t portCstatus = 0x0080; // OE = HIGH
  portCstatus |= 0x0020; // clk is high here too
  REG_PIOC_ODSR = portCstatus; // set OE, CLK to high
  
  // set A, B, C pins
  if (secn & 0x1){  // Apin
    portCstatus |= 0x0002;
    portCstatus_nonclk |= 0x0002;
  }
  if (secn & 0x2){ // Bpin
    portCstatus |= 0x0004;
    portCstatus_nonclk |= 0x0004;
  }
  if (secn & 0x4){ // Cpin
    portCstatus |= 0x0008;
    portCstatus_nonclk |= 0x0008;
  }
  REG_PIOC_ODSR = portCstatus; // set A, B, C pins

//  if (secn & 0x1) {
//    digitalWrite(APIN, HIGH);
//  } else {
//    digitalWrite(APIN, LOW);
//  }
//  if (secn & 0x2) {
//    digitalWrite(BPIN, HIGH);
//  } else {
//    digitalWrite(BPIN, LOW);
//  }
//  if (secn & 0x4) {
//    digitalWrite(CPIN, HIGH);
//  } else {
//    digitalWrite(CPIN, LOW);
//  } 
 
  uint8_t  low, high;
  uint16_t out = 0x0000;
  
  uint8_t i;
  for ( i=0; i<WIDTH; i++) {

    out = 0x0000;
   
    // red
   low = *buffptr++;
   high = low >> 4;
   low &= 0x0F;
   //if (low > pwmcounter) {
   //   digitalWrite(R2,HIGH);
   //} else {
   //   digitalWrite(R2,LOW);
   //}
   if (low > pwmcounter) out |= 0x0200; // R2, pin 30, PD9
   //if (high > pwmcounter){
   //  digitalWrite(R1,HIGH);
   //} else {
   //  digitalWrite(R1,LOW);
   //}
   if (high > pwmcounter) out |= 0x0400; // R1, pin 32, PD10

   // green
   low = *buffptr++;
   high = low >> 4;
   low &= 0x0F;
   //if (low > pwmcounter) {
   //   digitalWrite(G2,HIGH);
   //} else {
   //   digitalWrite(G2,LOW);
   //}
   if (low > pwmcounter) out |= 0x0008; // G2, pin 28, PD3
   //if (high > pwmcounter){
   //  digitalWrite(G1,HIGH);
   //} else {
   //  digitalWrite(G1,LOW);
   //}
   if (high > pwmcounter) out |= 0x0040; // G1, pin 29, PD6

   // blue
   low = *buffptr++;
   high = low >> 4;
   low &= 0x0F;
   //if (low > pwmcounter) {
   //   digitalWrite(B2,HIGH);
   //} else {
   //   digitalWrite(B2,LOW);
   //}
  if (low > pwmcounter) out |= 0x0002; // B2, pin 26, PD1

   //if (high > pwmcounter){
   //  digitalWrite(B1,HIGH);
   //} else {
   //  digitalWrite(B1,LOW);
   // }
    if (high > pwmcounter) out |= 0x0004; // B1, pin 27, PD2
   
    
   //digitalWrite(CLK, LOW);
   REG_PIOC_ODSR = portCstatus_nonclk; // set clock to low, OE, A, B, C stay the same

   REG_PIOD_ODSR = out;

   //digitalWrite(CLK, HIGH);
   REG_PIOC_ODSR = portCstatus; // set clock to high, OE, A, B, C stay the same
   
  } 

  // latch it!
  
  //digitalWrite(LAT, HIGH);
  REG_PIOC_ODSR = 0x0070;  // LAT = HIGH, OE = HIGH, CLK = HIGH, A, B, C = LOW

  //digitalWrite(LAT, LOW);  
  REG_PIOC_ODSR = 0x0030;    // only OE = HIGH and CLK = HIGH, LAT = LOW, A, B, C = LOW  
  
  // digitalWrite(OE, LOW);
  REG_PIOC_ODSR = 0x0020; // only clk is high, OE, LAT, A, B, C are low

}


void  matrix_updateDisplay(void) {
  matrix_writeSection(scansection, matrixbuff + (3*WIDTH*scansection));  
  scansection++;
  if (scansection == maxScan) { 
    scansection = 0;
    pwmcounter++;
    if (pwmcounter == PWMMAX) { pwmcounter = 0; }
  }
}

//TC1 ch 0
void TC3_Handler()
{
        TC_GetStatus(TC1, 0);
        matrix_updateDisplay();
}

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {
        pmc_set_writeprotect(false);
        pmc_enable_periph_clk((uint32_t)irq);
        TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
        uint32_t rc = VARIANT_MCK/2/frequency; //2 because we selected TIMER_CLOCK1 above
        //TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
        //// VARIANT_MCK = 84000000, I guess timer4 is every 1/4 or something?
        //uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above
        TC_SetRA(tc, channel, rc/2); //50% high, 50% low
        TC_SetRC(tc, channel, rc);
        TC_Start(tc, channel);
        tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
        tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
        NVIC_EnableIRQ(irq);
}



void setup(){
  matrix_begin();
  startTimer(TC1, 0, TC3_IRQn, 150000); //TC1 channel 0, the IRQ for that channel and the desired frequency
}

void loop(){

  matrix_drawPixel(0, 2, matrix_Color444(2, 0, 0));
  matrix_drawPixel(1, 2, matrix_Color444(2, 0, 0));
  matrix_drawPixel(2, 2, matrix_Color444(2, 0, 0));
  matrix_drawPixel(3, 2, matrix_Color444(2, 0, 0));
  matrix_drawPixel(4, 2, matrix_Color444(2, 0, 0));

}

It works mostly, but I get ghosties:
Image

One thing I can think of is a a possible misunderstanding about how the timer interrupts work. I grabbed code from http://forum.arduino.cc/index.php?topic=130423.0 which seemed to work ok, but I'm a bit confused. Specifically, about these few lines:

Code: Select all

        TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
        uint32_t rc = VARIANT_MCK/2/frequency; //2 because we selected TIMER_CLOCK1 above
and

Code: Select all

  startTimer(TC1, 0, TC3_IRQn, 80000); //TC1 channel 0, the IRQ for that channel and the desired frequency
I'm using this combo because any higher frequency and not all the points are plotted, but any lower frequency, and the ghosties get worse. I would think this combo would lead to an interrupt at (84 Mhz)/2/80000 = 525 Hz or clock cycles (which would be 0.16 Hz)? Either way, it is way lower than the 40-50 Mhz I would need. It is possible that I'm just not understanding how all of the variables work, but I've played with different values of the "frequency" and its hard to find a sweet spot.

Furthermore, if I do other things in the code, like update the display based on input from an analog pin or two, then the value of the optimum frequency changes.

So, any ideas on this would be thankfully appreciated!

Edit: Also, I realized I'm also a little fishy on the setting of the registers (so, basically, the whole code! :) ), as in, how the toggling of bits in the original Arduino code translates to simply setting registers in the new Due code (for example: do A, B, C pins need to be low when the clock is toggled or their original values?)

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

Ok, so, I've narrowed down one problem which is basically a typo * looks sheepish *

Changing the lines:

Code: Select all

  
uint16_t portCstatus_nonclk = 0x0080; // OE high, CLK = low
uint16_t portCstatus = 0x0080; // OE = HIGH
to

Code: Select all

  
uint16_t portCstatus_nonclk = 0x0010; // OE high, CLK = low
uint16_t portCstatus = 0x0010; // OE = HIGH
leads me to actually set the OE on the right pin and removes the ghosting. Hurray!

I still don't quite get the timer update frequency as it seems to be very low numbers still, and I still can't get exactly the pattern I want to print out... but one crisis at a time... sigh. :)

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

So, I do feel a little silly posting again since I think I'm just talking to myself (Hi self! *waves*). But, on the off chance that someone else wants to try to drive more panels with a Due some time in the future, I've managed to get a little library working with a few standard examples. Link is found in this post: http://avriot.com/?p=393. Right now I've just got the library doing the math for 1 panel, but the Due can definitely drive more. On that blog post I show a pic of 3 panels which don't flicker in the slightest, but there are some funny lines in the 2 trailing panels because of poor math. More info can be found at that page, since I think I've blathered on and on enough here :)

User avatar
hiduino
 
Posts: 862
Joined: Sat Sep 01, 2012 7:05 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by hiduino »

I've been wanting to try using my Due also, but just haven't the time. But I'll take a look at what you have and see if I can make a go of it also. I have 4 panels to play with so we'll see how well it can do or not.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 16x32 RGB LED Matrix, Arduino Due

Post by adafruit_support_rick »

avriot wrote:Since nobody has responded, I assume nobody has gotten further then my blundering about
My apologies. We in support usually look for unanswered topics. When you tag on to an old thread, it often goes unnoticed. It usually better to start a new topic than resurrect an old one.

We aren't really doing much work on porting libraries to the Due. A major reason for this is that Arduino 1.5.2 is quite incomplete and unstable, and it hasn't been updated for over 6 months. We have decided to focus our efforts elsewhere until such time as a usable version of Arduino for the Due is released.

That said, we don't discourage our customers from making their own attempts at porting our libraries! :D

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

My apologies. We in support usually look for unanswered topics. When you tag on to an old thread, it often goes unnoticed. It usually better to start a new topic than resurrect an old one.
No worries! I'll know better next time. In the end, it worked out well since I just had to work on it a bit more myself and I learned something new. Got some new brain folds. :)
We aren't really doing much work on porting libraries to the Due. A major reason for this is that Arduino 1.5.2 is quite incomplete and unstable, and it hasn't been updated for over 6 months. We have decided to focus our efforts elsewhere until such time as a usable version of Arduino for the Due is released.
Now that you mention it, I did have to make a few changes to the hardware stuff for Arduino 1.5.2, but I think it was all for another application. If anybody has issues with the matrix library I posted, please let me know and I'll post the hardware changes I made.

User avatar
avriot
 
Posts: 15
Joined: Tue Nov 15, 2011 4:55 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by avriot »

Hi all! Just wanted to give you a quick update that a new library with multiple panel support and examples has been posted. I was able to do 6 panels with some simple animations, but had to play around a bit with the "frequency" input in matrix.begin. The character writing isn't working at the moment with multiple y-panels, but other stuff is. Also, seems like the plasma example has a slow refresh rate do draw new pixels, which I'll hopefully get around to checking up with in the next few weeks, but probably not until then. Check out some of the examples for a better idea of how to implement different panels, and there is a diagram of different panel layouts on the website.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 16x32 RGB LED Matrix, Arduino Due

Post by adafruit_support_rick »

Cool - We'll have to give it a try :D

djdanielb
 
Posts: 15
Joined: Tue Apr 23, 2013 6:19 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by djdanielb »

I've bought the same display. Could you post you working library to try something ? I've 2 display

Thank you so much
Daniele

kirberich
 
Posts: 2
Joined: Sun Jan 12, 2014 11:12 am

Re: 16x32 RGB LED Matrix, Arduino Due

Post by kirberich »

I've expanded avriot's library a bit to work with the 32x32 matrix as well as the 16x32 one.

It works pretty well, but I too am having some timing troubles stemming, I think, from using SerialUSB on the native port. I'm pushing frames to the panel over serial, which works nicely in about 30fps with 16bit colors, but I think the timers for usb and the matrix interfere with each other. (I'm using SerialUSB because as far as I can tell using hardware serial through the programming port is basically impossible over 200,000 kbaud.)

As long as I'm pushing new data, the display flickers randomly, resulting in some lines being brighter than other lines. If I set the matrix frequency to something ludicrously high (like 20,000), the problem goes away, but unsurprisingly the frame rate goes down. As soon as I stop sending new frames, the matrix displays the last frame completely flicker-free. Maybe somebody here who understands these timers properly has some idea.

Side note: If I do use serial via the programming port the flicker completely goes away, but I can't get more than about 9fps. So that's not a solution, but it does lead me to think the issue must be timer/interrupt-related.

I've put my changes to the library on github at https://github.com/kirberich/RGBmatrixPanelDue
The python module and arduino sketches for sending frames over serial is here: https://github.com/kirberich/matrix-controller

tuckenstein
 
Posts: 6
Joined: Tue Jun 14, 2011 12:06 pm

Re: 16x32 RGB LED Matrix, Arduino Due

Post by tuckenstein »

Just wanted to say thanks for all the hard work! I have this panel and Due and I've been waiting for someone smarter than me to put all the pieces together! Thanks for all your hard work!

Locked
Please be positive and constructive with your questions and comments.

Return to “Glowy things (LCD, LED, TFT, EL) purchased at Adafruit”