Sure Electronics new 32x16 bi-color display: 3216 RG -Cont. from read only forum

Here is the "old" read only forum link to be used as reference to continue discussions about the Sure Electronics 3216 RG display (both 3 and 5 mm versions):

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1292604415/0

Here are the Sure Electronic links on where to purchase them:

3mm: http://www.sureelectronics.net/goods.php?id=1095

5mm: http://www.sureelectronics.net/goods.php?id=1122

I ordered the remaining 6 additional P7 (5mm LED version) 3216 RG displays this week to complete my 2 sets of 4 (8 total) display. I hope that a single Arduino can handle this many displays.

[1][2][3][4]
[5][6][7][8]

How do I program in a configuration like this with 2 sets of 4 displays (as far as the clocking, etc.)?

Is the library for the green version fully working?

Federico:
Is the library for the green version fully working?

I don't know! We are using a different type of LED Matrix that has dual-color leds.

Wagner,

Can you look over the latest code again? As you stated earlier, I did make the change here: #define X_MAX 32*Number_of_Displays -1

I have added 2 additional displays (total of 4) and if I set #define Number_of_Displays 6 I can sort of see the display on all four of them but the scrolling routine is spliting the message in half. The bottom half of the message is scrolling across the top of the displays while the top half of the message is scrolling across the bottom of the displays. Something is wrong with the clocking or something and it is messed up with any displays more than 2 connected. If I use, #define Number_of_Displays 4 or #define Number_of_Displays 3 the 4th display is not even turned on.

Here is the non-working code for 4 displays: http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=973058#post973058

Tim,

I looked to your code but I didn't see anything unusual. It's very difficult to debug without 4 displays here(I have only 2).

So, I'm figuring out. This code:

if (x>=32) {
    nChip = 3 + x/16 + (y>7?2:0);
  } else {
    nChip = 1 + x/16 + (y>7?2:0);
  }

has to be tweeked as you have more chips on 4 displays and you have to calculate nChip for x>=64 and x>=96.

Wagner and others,

I have the code working for 3 and 4 displays EXCEPT I see some random pixels in the last collumn of the first quadrant of displays 3 and 4.

http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=973708#post973708

#define Number_of_Displays 4
#define CHIP_MAX 4*Number_of_Displays //Four HT1632Cs on one board
#define X_MAX 32*Number_of_Displays -1
#define Y_MAX 15
//if (x>=32) {
//  nChip = 3 + x/16 + (y>7?2:0);
//} else {
//  nChip = 1 + x/16 + (y>7?2:0);
//} 
  
  if (x>=96) {
    nChip = 7 + x/16 + (y>7?2:0);
  } 
  else if (x>=64) {
    nChip = 5 + x/16 + (y>7?2:0);
  }    
   else if (x>=32) {
    nChip = 3 + x/16 + (y>7?2:0);
  }  
  else {
    nChip = 1 + x/16 + (y>7?2:0);
  }

Any ideass on what to do about the random pixels ?

Wagner and others,

I found another bug but this did not fix the random pixel issue but did somewhat clear up some clearing issues better than before.

When the Number_of_Displays was 2, it was ok but if Number_of_Displays increases then it affects the value of CHIP_MAX:

#define Number_of_Displays 4
#define CHIP_MAX 4*Number_of_Displays //Four HT1632Cs on one board
#define X_MAX 32*Number_of_Displays -1
#define Y_MAX 15

CHIP_MAX was used as a value of 8 (when you have 2 displays), but with 4 displays, then the value of CHIP_MAX increases to 16.

/*
 * ht1632_clear
 * clear the display, and the shadow memory, and the snapshot
 * memory.  This uses the "write multiple words" capability of
 * the chipset by writing all 96 words of memory without raising
 * the chipselect signal.
 */
void ht1632_clear()
{
  char i;
  //for (int i=1; i<=CHIP_MAX; i++)
  for (int i=1; i<=8; i++)
  {
    ChipSelect(-1);
    ht1632_writebits(HT1632_ID_WR, 1<<2);  // send ID: WRITE to RAM
    ht1632_writebits(0, 1<<6); // Send address
    for (i = 0; i < 96/2; i++) // Clear entire display
      ht1632_writebits(0, 1<<7); // send 8 bits of data
    ChipSelect(0);

    for (int j=0; j < 64; j++)
      ht1632_shadowram[j][i] = 0;
  }
}

However, Shadowram cant be higher than 64 x 8 but this would make it 64x16 causing issues.

byte ht1632_shadowram[64][4*2] = {0};

What do you think?

What do you think?

I really don't know. shadowRam is a "copy" of ht1632c memory. maybe the code is not working as expected, you need to debug and understand better how the bitwise operations work and simmulate on paper to see what's wrong.

I'm telling to you but I have this difficult too. It's very, VERY hard to me to find out what's happening with these bitwise operations on shadowRam.

@Tim Gilmore,

Did you try to change data type from byte to int, i.e. int ht1632_shadowram.., because byte is only until 255 and you would have higher values with 64x16. Maybe you should change all values from byte to int.

I hope this helps.

Wagner,

Thanks for your help on this. All I was saying about the shadowram was that their was an inconsistancy I saw if the value of Number_of_Displays gets changed from 2 to something else.

If Number_of_Displays was to stay at 2, then the following would occur:

#define Number_of_Displays 2
#define CHIP_MAX 4*Number_of_Displays //Four HT1632Cs on one board
#define X_MAX 32*Number_of_Displays -1
#define Y_MAX 15

CHIP_MAX would have a value of 4*Number_of_Displays being 8.

But later in the program Shadowram is a 2 dimensional array of [64][4*2].

byte ht1632_shadowram[64][4*2] = {0};

Further in the program in the HT1632_Clear routine, Shadowram is now set by the value of CHIP_MAX and if CHIP_MAX is 8 then the 2nd array [42] is ok but if CHIP_MAX gets changed to 16 because the Number_of_Displays get's is now 4, this will make CHIP_MAX's value 44 or 16. 16 does not match up to the original byte declaration of

byte ht1632_shadowram[64][4*2] = {0};

as seen below in CHIP_MAX. I hope this makes sense. So all I am saying is that in the HT1632_Clear routine, that it needs not to use the value of CHIP_MAX in the counter routine of 'i'.

void ht1632_clear()
{
  char i;
  //for (int i=1; i<=CHIP_MAX; i++) COMMENT OUT THIS LINE AND REPLACE WITH LINE BELOW SO i GOES to 8 and not the CHANGED VALUE OF CHIP_MAX WHICH COULD BE 16 NOW
  for (int i=1; i<=8; i++)
  {
    ChipSelect(-1);
    ht1632_writebits(HT1632_ID_WR, 1<<2);  // send ID: WRITE to RAM
    ht1632_writebits(0, 1<<6); // Send address
    for (i = 0; i < 96/2; i++) // Clear entire display
      ht1632_writebits(0, 1<<7); // send 8 bits of data
    ChipSelect(0);

    for (int j=0; j < 64; j++)
      ht1632_shadowram[j][i] = 0;
  }
}

Just a small point I wanted to make, thats is all.

Thanks.

My real issue with with the random pixels.

Tim.

I did not have a chance to play with 2 displays yet, maybe this weekend.

This is the idea behind the shadow ram data structure: you need 64 bytes for each individual HT1632 chip, used as a duplicate of the "video" memory of the chip (to get easier and faster access to the video memory, basically).

byte ht1632_shadowram[64][4] = {0};

defines the shadow ram for one 3216 display (with 4 chips).

To define the shadow ram for 2 displays, I would use either something like Tim's definition

byte ht1632_shadowram[64][4*2] = {0};

or

byte ht1632_shadowram[64][4][2] = {0};

For 8 displays, this would extend to:

byte ht1632_shadowram[64][4][8] = {0};

florinc,

I'm reading the ht1632c datasheet http://www.holtek.com/pdf/consumer/1632cv100.pdf and on display memory(page 5) you can see that it only has 32 x 8 bytes, so why are you using [64][4]?

I saw on previous codes that they double to 64 to make a "snapshot" memory to manipulate before send all to display but if you do not use the matrix this way you can save half of your RAM memory.

From what I remember, the lower 4 bits are used for the actual shadow ram. The upper 4 bits are (sometimes, when you need it, like in the game of life for example) used as a "snapshot" (copy) of the shadow ram.
Put together, as a quantity, you would have 32 full bytes, but for easier addressing you use this structure of 64 half-bytes.
Confusing, I know :slight_smile:

florinc,

Thanks so much for your help in this forum especially along with Wagner and others. So shadowram should be:

byte ht1632_shadowram[64][4][8] = {0};

because I think it should just be:

byte ht1632_shadowram[64][4*Number_of_Displays] = {0};

which works now with no random pixel errors (as modified from my last posted code).

I also found a couple of small issues in the h1632_putchar routine that works much better now. Before I would have left over random colored LEDs in the last row of the text messages displayed. Now they are correct.

This

for (char row=0; row <7; row++) {

was changed to this: for (char row=0; row <=7; row++) {

Also in the void line, it had byte declarations for x and y which caused displaying issues especially in the scrolling routine. However, changing it to integer fixed this (as changed previously in past coding).

However, I would like some assistance in cleaning up the coding for char c as my bitwise coding is lacking (as there has to be a cleaner way for this).

//void ht1632_putchar(byte x, byte y, char c, byte color=GREEN)
void ht1632_putchar(int x, int y, char c, byte color=GREEN)
{
  byte dots;
  //if (c >= 'A' && c <= 'Z' ||
  //  (c >= 'a' && c <= 'z') ) {
  //  c &= 0x1F;   // A-Z maps to 1-26
  //} 
  //else if (c >= '0' && c <= '9') {
  //  c = (c - '0') + 27;
  //} 
  //else if (c == ' ') {
  //  c = 0; // space
  //}
  
  if (c == ' ') {c = 0;}
  else if (c == '!') {c = 1;}
  else if (c == '"') {c = 2;}
  else if (c == '#') {c = 3;}
  else if (c == '

Overall the coding is working very well (except for the scrolling is still a bit slow even with the digitalwritefast routines) now thanks to everyones help.

Here is the latest code for up to 4 working displays:

http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=974131#post974131) {c = 4;}
 else if (c == '%') {c = 5;}
 else if (c == '&') {c = 6;}
 //else if (c == ''') {c = 7;}
 else if (c == '(') {c = 8;}
 else if (c == ')') {c = 9;}
 else if (c == '*') {c = 10;}
 else if (c == '+') {c = 11;}
 else if (c == ',') {c = 12;}
 else if (c == '-') {c = 13;}
 else if (c == '.') {c = 14;}
 else if (c == '/') {c = 15;}  
 
 else if (c >= '0' && c <= '9') {
   c = (c - '0') + 16;
 }
 
 else if (c == ':') {c = 26;}
 else if (c == ';') {c = 27;}
 else if (c == '<') {c = 28;}
 else if (c == '=') {c = 29;}
 else if (c == '>') {c = 30;}
 else if (c == '?') {c = 31;}
 else if (c == '@') {c = 32;}  
 
 else if (c >= 'A' && c <= 'Z') {
   c = (c - 'A') + 33;
 }
 
 else if (c == '[') {c = 59;}
 //else if (c == '') {c = 60;}
 else if (c == ']') {c = 61;}
 else if (c == '^') {c = 62;}
 else if (c == '_') {c = 63;}
 else if (c == '`') {c = 64;}
 
 else if (c >= 'a' && c <= 'z') {
   c = (c - 'a') + 65;
 }
 
 else if (c == '{') {c = 91;}
 else if (c == '|') {c = 92;}
 else if (c == '}') {c = 93;}
 
 for (char col=0; col< 6; col++) {
   dots = pgm_read_byte_near(&my3font[c][col]);
   for (char row=0; row <=7; row++) {
     if (dots & (64>>row))       // only 7 rows.
       plot(x+col, y+row, color);
     else
       plot(x+col, y+row, 0);
   }
 }
}


Overall the coding is working very well (except for the scrolling is still a bit slow even with the digitalwritefast routines) now thanks to everyones help. 

Here is the latest code for up to 4 working displays:

http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=974131#post974131

I was slightly mistaken about having no random pixels. The display first starts with a scrolling of text from right to left and then displays the multicolored larger sized "2011" in the first display. It then displays multicolored inidividual lettered static text message. This is pretty good other than I would like to see a faster scroll but it is not too bad.

The problem with the random pixels comes out when the program is looped and it runs again. First the scrolling message runs and no problems there. Then the display of the multicolored larger size "2011" causes some pixels to be off. Then the multicolored individual lettered static text message shows some letters to be missing some LEDs. It always has the same LEDs off everytime.

As a test, I ran the large "Arduino rocks" scroll across the 4 displays (and then the normal other scrolling message, 2011 message and colored text)... This time the "Arduino rocks" scroll (although somewhat slow but reasonably ok), is good until you see a couple of LEDs turn on on the 1st and 2nd display on the very top row. However, after this is done, the normal sized other scrolling message comes out fine with no pixel issues, and the 2011 message is GOOD this time as well as the colored text display (no missing LED pixels). I don't quite understand what is happening here but could be related to the shaddow ram.

I created another version of the program with the 'DigitalWriteFast' library routines commented out and used direct port access to digital pins 6,7,8,9 and it worked to see if this would caused the scrolling message to be any faster. Unfortunately, it was not any noticibly faster and the work based off of this link: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=706055 was used to figure out how to do the direct port access.

The new code is listed here:

http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=974440#post974440

Since, it did not show much of an improvement, I think I may just go back to the easier to use 'DigitalWriteFast' library routines. We'll see.

Let me know what you think.

Thanks,

Tim

Tim,
I looked briefly at the code you posted and noticed that you can still improve on the speed by adding a few lines in function ht1632_plot:

  if (x<0 || x>=X_MAX || y<0 || y>=Y_MAX)
    return;
  
  if (color != BLACK && color != GREEN && color != RED && color != ORANGE)
    return;
  
  byte existingPixel = get_shadowram(x, y);
  if (existingPixel == color)
    return;		// nothing to change;
...

Florinc,

Im not a good C programmer yet and did not quite follow the example. However, I wanted to post my latest accomplishments of the 3216 RG with 8 displays running on a Teensy++2.0 (www.pjrc.com/teensy) with the code: http://forums.parallax.com/showthread.php?128037-Sure-Electronics-new-32x16-bi-color-display-3216-RG&p=976869#post976869

and YouTube video: Teensy++2.0 driving (8) 3216 RG 5mm LED Displays - YouTube

Now if I we can figure out how to clear all of those LEDs that turn back on after they have been cleared.

Thanks for all of your help and to everyone!

More to come...