LED Matrix using µC

Thread Starter

VI ASI 1

Joined Dec 24, 2018
7
Hello everyone!
I'm working on a little project using led matrixs using 16F88 µController and shift registers (74HC595) and i want to know if there is a way to optimise my code,independent of the length of my message and the matrix size (kind of an autoscale) , what i want to achieve is to write directly a sentence in a variable and then display it, not writing down every line like i did (exemple: A : 0xe3,0xd7,0xe3) , should i create some sort of functions where i write all the letters (like i did pour A,L,O) then send the sentence i want to display and it will select each letter's code and display it? Or is there any other solution?
 

Attachments

dl324

Joined Mar 30, 2015
16,845
I see a lot of these LED matrix designs using 74HC595 shift registers and I don't get it.

The code can be simplified by using a little hardware.

I made a scrolling LED matrix display (currently a single 5x7 matrix). To scroll my message, I format the message in a 2D array with 7 rows and as many columns as the message requires. I drive the matrix a column at a time vs a single pixel. I did this because I was concerned about the speed I could get on the GPIOs (I'm using a ARM single board computer running Linux). Using bit band aliases, I can change all of the I/O's in the same register as fast as I can change 1.
 

JohnInTX

Joined Jun 26, 2012
4,787
what i want to achieve is to write directly a sentence in a variable and then display it, not writing down every line like i did (exemple: A : 0xe3,0xd7,0xe3) , should i create some sort of functions where i write all the letters (like i did pour A,L,O) then send the sentence i want to display and it will select each letter's code and display it? Or is there any other solution?
What you want, I think, is to add a character generator array containing the dot patterns of the character 'A', 'B', etc. 4 bytes per character if I read your code right? Then the characters in the message become the index into that array to find the first column of dots. Same with the digits 0-9

For example '0' is ASCII 30h, '1' is 31h etc. If your character generator array contains '0'-'9' and 'A' through 'Z', the first 4 byte entry would correspond to the dot pattern for '0', the next 4 bytes would describe the dot pattern for '1' etc. For any character in a text string, just use the character value as an index into the array:

index = (*BufferPointer -30h)*4;
Use that index to fetch the 4 byte dot pattern for that character.

Good luck!

EDIT: it looks like you are using MikroC (from the colors of the screen shot). If so, declare your array as 'const' to put it into ROM. MikroC likes to copy strings and the like to RAM for easy access and then complains when it runs out.

If you design the character generator array as a (2 dimensional) array of 4 character constant strings, then it will be easier to initialize with dot patterns.

Finally, use the 'Insert Code' button to insert your code in a text box here on the site. That way, members can load your code into our compilers and help with the debug. You can't do that with screen shots.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
@VI ASI 1
Something like this would do maybe:
C:
// ROM array of dot patterns for each character - only two shown
const unsigned char dots[][4] = {
  {0x11,0x12,0x13,0x14},  // '0'
  {0x21,0x22,0x23,0x24},  // '1'
  };  // first 2 character dot patterns - add the rest

unsigned char dotbuf[4];  // a place in RAM to put the 4 byte dot pattern for the selected character
unsigned char ch;  // the ASCII character fetched from a string etc.
unsigned char k;   // counter, index

main()
  ch = '1';  // character is ASCII '1'  // for test

  ch = ch -'0';  // convert ASCII ch to zero-offset by subtracting 30h

  for(k=0; k<4; k++)  // copy 4 byte character dot pattern to dot buf in RAM
     dotbuf[k] = dots[ch][k];
  send_dotbuf();  // send to displays
Have fun!
 

Thread Starter

VI ASI 1

Joined Dec 24, 2018
7
Code:
void Shout(unsigned char d)
{
short j;
for(j=0;j<8;j++) // Shift out 8 bits
{
PORTb.B0= d & 1 ; // test least significant bit if its 1
PORTb.B1=1;PORTb.B1=0; // clock
d=d >> 1; // shift bits to right by 1 to get next bit
}
}
char i,matrix1,matrix2,matrix3,sel,k;

//colomn selection sequence
char colomn[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

//Letters
char text[24]={0xe3,0xd7,0xe3,0xff,0xc3,0xfb,0xfb,0xff,0xc3,0xfb,0xfb,0xff,0xc3,0xdb,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
               //A              -  L                -  L                -  O                 -  8*0xff fill blank
void main() {
trisb=0x00;
portb=0x00;
sel=0;
while(1)

{
  //Stabilisation loop
for(k=0;k<7;k++)
{
//Display loop

for (i=0;i<24;i++)
{
  //colomn selection
if (sel<8)
{matrix1=colomn[sel];
matrix2=0x00;
matrix3=0x00;
}
else
{
if (sel<16)
{
  matrix2=colomn[sel-8];
  matrix1=0x00;
  matrix3=0x00;
}
else
{
  matrix3=colomn[Sel-16];
  matrix2=0x00;
  matrix1=0x00;
}
}
//Sending data;
Shout(matrix3);
Shout(matrix2);
Shout(matrix1);
Shout(text[i]);
//Display enable
PORTb.B2=1;
PORTb.B2=0;
//Variable incrementation for colomn selection
sel+=1;
if (sel>23)
  sel=0;
//Stabilisation delay
delay_ms(1);
}
}
//Shifting message
sel+=1;
if (sel>23)
sel=0;
}

}
Thank you guys!
@JohnInTX I like your idea, quite simple and effective, so first of all i should create all the patterns from 0-9,A-Z, 4 bytes for each in an array (Char const) and pick from it one by one, just one question about "*BufferPointer", how do i select the ascii code for the character i want to use?
For exemple i'll declare this message String msg="Hello world", how do i select the H for exemple, index = (msg[0] -30h)*4? I don't think that this is correct but just to point out what i didn't understand
 

JohnInTX

Joined Jun 26, 2012
4,787
A character string can be addressed with an index like [] or a pointer to char like *p. ASCII strings are terminated with a NUL character 00h. So to fetch and send a string just:
C:
unsigned char *p;
p = msg;  // p points to the first character in msg

while(*p)  // do while the character p points at is non-zero
  ch = *p;  // get the ASCII character
  // do the lookup as shown above, subtract 30h from ch, fill the 4 byte buffer with the dots for the character at *p

  ch = ch -'0';  // convert ASCII ch to zero-offset by subtracting 30h
  for(k=0; k<4; k++)  // copy 4 byte character dot pattern to dot buf in RAM
     dotbuf[k] = dots[ch][k]; 
// send the 4 byte dot pattern from the buffer
  p++;  // next character from the msg string
}//while


The string can now be an arbitrary length.
Note that this is a general idea. You'll have to plug it into your particular refresh code. I'd make it a callable function.

Have fun!
 
Last edited:
Top