Jump to content
43oh

Little 5x7 LED matrix project.


Recommended Posts

Here's my current progress on an LED matrix display. I'm using 4 outputs to control 35 LED's, which was the point of the whole exercise.

 

I've used 2 x 74HC595s, with the reset tied high and the Output Enabled tied low. I've tied the clocks together to reduce the number of outputs used, and used two pins for the data outputs to the shift registers.

 

Mostly done with trial and error (I've since found the 74HC595 isn't suitable for driving multiple LED's - but it can cope with individual ones). The code is below, and not the greatest, but it works! I'm just using an 8x8 output to the shift registers, but I'm sure it could be optimised for 7x5.

 

I'm going to add another shift register and make a little game of it later, but I'm happy with it for now.

 

Any comments/criticism welcomed, but be gentle, it's my first MCU project. Actually, it's my first ever project.

 

http://www.youtube.com/watch?v=RLsNdYr09qU

 

#include 

unsigned char COL[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
unsigned char ROW[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

//Does this below need declaring seperately to when it is declared by the function below?
int delayTime;
void delay(int delayTime);

//Serial function, adapted from wikipedia entry on bitbanging.
void sendSerial(unsigned char dataGreen, unsigned char dataColumn); 


void main(void) {
WDTCTL = WDTPW + WDTHOLD;		// Hold the WDT (WatchDog Timer)
P1DIR = 0xFF; 					//Set Port 1 as outputs

/*
 * p1.1 DS Serial data Row
 * p1.0 DS Serial data Column
 * p1.3 ST CP storage register clock input
 * P1.4	SH CP shift register clock
 */

	while(1){
		int x, y;

		unsigned char z=0x02;			//
		for	(x=1;x<8;x++){
			for(y=1;y<6;y++){
				sendSerial(z, COL[x]);
				z <<= 1;
				delay(10000);
			}
			z=0x02;
		}
	}
}

void delay(int delayTime){
int t1;
for (t1=0;t1		t1=t1*1;
}

}

//The following function is the code from the wikipedia entry on BitBanging, adapted for my specific application.

void sendSerial(unsigned char dataGreen, unsigned char dataColumn)
{
  int i;

  // send bits 7..0
  for (i = 0; i < 8; i++)
  {
      // consider leftmost bit
      // set line low if bit is 1, High if bit is 0
      if (dataGreen & 0x80){
          P1OUT &= ~BIT1;
      }
      else{
          P1OUT |= BIT1;
      }

      if (dataColumn & 0x80){
      	P1OUT |= BIT0;
      }

      else{
      	P1OUT &= ~BIT0;
      }
      delay(2);

      // pulse clock to indicate that bit value should be read
      	P1OUT |= BIT4;
		delay(2);
		P1OUT ^= BIT4;

      // shift byte left so next bit will be leftmost
      dataGreen <<= 1;
      dataColumn <<= 1;

  }

  // Set storage register.
 	P1OUT |= BIT3;
 	delay(2);
	P1OUT &= ~BIT3;

}

Link to post
Share on other sites

Yeah, I thought it's an oddball size, but I'd guess that 5x7 is used as it's good proportions for characters/numbers.

 

The one above is a red/green one, so I'm going to have to do something with an extra 595 (or appropriate shift register) to be able to control all 70 LED's with 5 outputs.

Link to post
Share on other sites

I connect the 74HC595 with three pins from the MSP430 Launchpad to drive up to 8 seven segment LED displays.

 

You only have a problem driving the LED's is if you turn on all of them at one time, I turn on each LED one row at a time. But I do it 100's of times a second, so you don't see them blink. But at the same time you don't draw more current then the IC can handle. My next project is using some 5X7 LED's I have laying around.

 

Here is how I have connected the 74HC595 to my MSP430.

 

See attachment

temp-led595.pdf

Link to post
Share on other sites

Thanks for that Nexus, looks very similar to how I've wired my set-up, but I hadn't thought of using the serial out (of the 595) to feed a second register - using that method, you could operate many outputs from just 3 pins (rather than my method of sending serial data to each 595 from it's own pin).

 

Regarding my inability to achieve sufficient brightness using the 595's - I have tried to strobe the LED's to take advantage of POV, but the brightness just isn't there. It's probably down to the fact that my LED matrix is CA, so I'm trying to source far too much current from the 595 - I think it would be much more capable if I were using a CC display.

 

I'm going to have a play with the timing, and see if I can make it work any better, but my results so far (just using alternate program cycles to alternate two LED's brings a noticeable drop in brightness) suggest I'm using the wrong tool for the job.

Link to post
Share on other sites

EngIP,

 

I'd like to apologize for forgetting to say congrats' on your first MSP430 project. You did a great job and it looks like it could be a good building block for bigger displays.

 

Regarding my inability to achieve sufficient brightness using the 595's - I have tried to strobe the LED's to take advantage of POV, but the brightness just isn't there. It's probably down to the fact that my LED matrix is CA, so I'm trying to source far too much current from the 595 - I think it would be much more capable if I were using a CC display.

 

May I ask why you think switching from common anode to common cathode displays might improve brightness? Wouldn't that still leave you with one '595 sourcing current and one '595 sinking current to the display?

 

Also, could you be more precise about the type of 5x7 displays you have? It would probably be more meaningful to describe them as "anode row" or "cathode row", depending of course on their orientation, 5 rows & 7 columns or 7 rows & 5 columns.

 

Cheerful regards, Mike

Link to post
Share on other sites
EngIP,

 

I'd like to apologize for forgetting to say congrats' on your first MSP430 project. You did a great job and it looks like it could be a good building block for bigger displays.

 

May I ask why you think switching from common anode to common cathode displays might improve brightness? Wouldn't that still leave you with one '595 sourcing current and one '595 sinking current to the display?

 

Cheerful regards, Mike

 

Thanks Mike, it's amazing the feeling of accomplishment you get when you figure something out yourself, no matter how simple it may be to others. I've wanted to do a matrix project for a while, as I "invented" the idea of sequentially illuminating row by row in order to create an image, before discovering it's been thought of (long) before :D .

 

You'll have to forgive my ignorance when it comes to electronics, my knowledge is very hotch-potch, and my MCU knowledge starts and ends with the launchpad I purchased about a month ago. Hopefully that will improve as a module of my degree next year is embedded systems.

 

The 5x7 displays are common anode on the 7 rows.

 

Regarding the CA/CC, my thinking was that should I try to illuminate 3 x LED's simultaneously, I would have the anode 595 trying to source enough current for 3x LED's (on one pin) whilst the cathode 595 would be sinking 3x LED's on individual pins. I'm assuming the 595's can sink much more current than they can source, so in the reverse of the previous example, the cathode 595 would be sinking 3x LED's from one pin, rather than sourcing.

 

My assumption is that a 595 (or any IC as a rule of thumb) will be able to sink more current than it can source.

 

Of course, illuminating LED's individually would mean CC/CA is irrelevant, as you have rightly said, the current is always being sourced/sink by a 595. The brightness drops when using this method still, but I think this is down to the speed of my code/the MCU.

 

I've made a little progress with the matrix, so I'll post up later how far I've got (and the source code), and hopefully I can get some pointers on how to improve it.

 

Edit: Just wanted to add, having re-read what I previously posted, I can see that I wasn't clear - sorry for any confusion. :oops:

Link to post
Share on other sites

Thanks for the additional info'. It seemed from your video and program that you were only lighting one LED at a time. And the delays seem long enough to give you an idea of the brightness you could expect when lighting an LED continuously through two '595 outputs.

 

So, what then could be the reason for the low brightness? With my school schedule (two spring semester classes) I haven't really had a chance to play with my LaunchPad and with LED displays so I can only guess. Are you running the '595s from the 3.6v source on the LaunchPad? Could the combined voltage drops of two '595 outputs be limiting the voltage and current to the LED? Are the displays of the "super bright" type which in my experience seem to throw off a lot of light even with very low (3-5 ma) current?

 

Some experiments might be in order. Try lighting one of the LEDs by sourcing it from a '595 output with the other end of the LED grounded, then try it the other way (sinking from '595 with opposite end of LED to Vcc).

 

If you're going to light multiple LEDs in columns or rows, depending on how you end up driving the matrix, you really should consider column or row driver transistors, or their serial-to-parallel IC counterparts.

 

Good luck in your classes. This semester only started Monday and I'm already swamped (grin).

 

Regards, Mike

Link to post
Share on other sites

With the project I'm working on now that uses 8x8 matrices, I've found that doing 1 led at a time does the best job for me... There is another way to source/sink if you don't mind adding some transisters/resistors to your circuit.

 

viewtopic.php?f=9&t=683

 

This way you can source/sink with whatever you want, with the correct resistor values for the brightness you want. Removes the 595 bottleneck.

Link to post
Share on other sites

Hi Mike,

 

I'm going to put my hands up and say I've not been very clear about what's going on with this. The video I posted shows my first success at multiplexing, which was indeed lighting up individual LED's one by one. I then moved on to characters and such, which is where the brightness issue comes to the fore.

 

I've pretty much figured it out now, with a bit of experimentation (and pointers from yourself and others) - the 595's are limiting current, but the refresh rate is the culprit when addressing individual LED's. Unfortunately, setting it to run at 16MHz is beyond my capabilities at the moment, so unless someone puts together an idiots guide, I'll just have to wait until I can set some time aside to dedicate myself to the task (like you, I'm currently swamped!).

 

SugarAddict - That's a nice PCB you've manufactured there! I've had a quick read through and noticed you've upped the MCU to 16MHz, which is something I think I'm going to have to do. I'm only doing this for the learning aspect, and If I were doing it for a finished project, I think dedicated driver IC's / transistors would definitely be used.

 

Now, on to my problems/questions. Any help or advice would be greatly appreciated. And Mods/Admin, sorry if this isn't the right place, but I didn't think it would be any more appropriate on a different board.

 

Question 1 - Why is addressing individual LED's faster?

 

I decided to write a little code to compare the brightness of addressing individual LED's Vs. addressing rows. Let's say I wanted to light Row 1:Column 1 and Row1:Column 2 for simplicity. The individual method would send 0x01 followed by 0x02 over and over (two instructions). The row method would send 0x03 over and over (one instruction). I put both methods in individual for loops (same number of iterations) and noticed the row method took longer to execute, despite there being significantly less instructions in the for loop. I can't understand how this can be, as they both use the same bitbanging function, but one uses it twice as much per cycle of the for loop, yet executes all cycles quicker than the short code.

 

Question 2 - Surely the following code doesn't exceed the limit for a G2231?

 

EDIT (edited then got a reply) - Simplified, my code is as follows, the error I get is run out of RAM.

 

#include 

//unsigned char PH[x] = {14, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

void main(void){
//Code goes here ~80 lines or so

}

 

Many thanks for any help, and thank you for the replies so far :)

Link to post
Share on other sites

What does the compiler say when you comment out the delays instead?

 

Are the values in your array changing or are they constant? If constant I think you can modify their declaration to get the compiler to stuff them into Flash memory rather than RAM. Someone help me out here. Is it const or static?

 

The code might look like this:

unsigned char const PH[14] = {14,5,4,3,5,2,5,2,5,4,3,5,5,5};

 

 

Oh, what are the compiler error messages? Are you out of RAM or FLASH?

Link to post
Share on other sites

Thanks Zeke, I got rid of the delay function as a function as it was only called once. The values in the array are constant, and I was thinking along the lines them being written to the wrong place.

 

The error message was out of RAM.

 

I've pretty much decimated the code now, but I'll rebuild it all tomorrow and will look into this const/static declaration. If someone could point me to some literature that covers this (I don't know if it's C specific or TI/MSP specific) that would be great.

 

Many thanks again,

 

Guy

Link to post
Share on other sites

I have the same problem if I use more than 1 led on a display. I attempted to use a refresh rate of 8 and the leds would be different brightnesses all over the place... Questions I would ask is...

 

What happens when you add a second LED to a sourcing 74HC595?

How about a second led to a sinking 74HC595? (One try with same source for both, second try with different sources)

Are these LEDs in parallel or series?

 

I found the simplest solution was to do them one at a time. The option to remove the 595 limitation on the board I linked you was something I haven't explored, but it may fix the issue to some degree, as you could source enough to cover more leds perhaps..

Link to post
Share on other sites

Update, it's now doing something a little bit more useful than chasing an LED 8-)

 

http://www.youtube.com/watch?v=WZNMLf6zzEU

 

Here's my code.

 

#include 

const unsigned char COL[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
const unsigned char ROW[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

//Letter format
//make first char in array = the length of the array,
//PV[n]= the nth LED in the sequence for that letter.
//PV = letter 'P' 'V'ertical
const unsigned char PH[14] = {13, 5, 4, 3, 5, 2, 5, 2, 5, 4, 3, 5, 5, 5};
const unsigned char PV[14] = {13, 1, 1, 1, 2,2,3,3,4,4,4,5,6,7};
const unsigned char AH[19] = {18, 4,3,2,5,1,5,1,5,4,3,2,1,5,1,5,1,5,1};
const unsigned char AV[19] = {18, 1,1,1,2,2,3,3,4,4,4,4,4,5,5,6,6,7,7};
const unsigned char MH[19] = {18, 5,1,5,4,2,1,5,3,1,5,3,1,5,1,5,1,5,1};
const unsigned char MV[19] = {18, 1,1,2,2,2,2,3,3,3,4,4,4,5,5,6,6,7,7};
const unsigned char SH[16] = {15, 4,3,2,5,1,5,4,3,2,1,5,1,4,3,2};
const unsigned char SV[16] = {15, 1,1,1,2,2,3,4,4,4,5,6,6,7,7,7};
const unsigned char FourH[14] = {13, 5,5,5,3,5,3,5,4,3,2,1,3,3};
const unsigned char FourV[14] = {13, 1,2,3,3,4,4,5,5,5,5,5,6,7};
const unsigned char ThreeH[16] = {15, 5,4,3,2,1,1,2,3,4,1,1,4,3,2,5};
const unsigned char ThreeV[16] = {15, 1,1,1,1,2,3,4,4,4,5,6,7,7,7,7};
const unsigned char ZeroH[17] = {16, 4,3,2,5,1,5,1,5,1,5,1,5,1,4,3,2};
const unsigned char ZeroV[17] = {16, 1,1,1,2,2,3,3,4,4,5,5,6,6,7,7,7};

//Serial function, adapted from wikipedia entry on bitbanging.
void sendSerial(unsigned char dataGreen, unsigned char dataColumn, unsigned char dataRed); 

void delay(unsigned int delayTime);

void main(void) {
WDTCTL = WDTPW + WDTHOLD;		// Hold the WDT (WatchDog Timer)
P1DIR = 0xFF; 					//Set Port 1 as outputs

/*
 * p1.1 DS Serial data Red Row
 * p1.0 DS Serial data Column
 * p1.5 DS Serial data Green Row
 * p1.3 ST CP storage register clock input
 * P1.4	SH CP shift register clock
 */

	while(1){

		int x,y;


		int loops;


		loops = 2000/MV[0];
		for(y=0;y 			for (x=(MV[0]);x>0;x--){
				sendSerial(0, COL[MV[x]],ROW[MH[x]]);
			}
		}

		loops = 2000/SV[0];
		for(y=0;y 			for (x=(SV[0]);x>0;x--){
				sendSerial(ROW[sH[x]], COL[sV[x]],0);
			}
		}

		loops = 2000/PV[0];
		for(y=0;y 			for (x=(PV[0]);x>0;x--){
				sendSerial(ROW[PH[x]], COL[PV[x]], ROW[PH[x]]);
			}
		}

		loops = 2000/FourV[0];
		for(y=0;y 			for (x=(FourV[0]);x>0;x--){
				sendSerial(ROW[FourH[x]], COL[FourV[x]],0);
			}
		}

		loops = 2000/ThreeV[0];
		for(y=0;y 			for (x=(ThreeV[0]);x>0;x--){
				sendSerial(0, COL[ThreeV[x]],ROW[ThreeH[x]]);
			}
		}

		loops = 2000/ZeroV[0];
		for(y=0;y 			for (x=(ZeroV[0]);x>0;x--){
				sendSerial(ROW[ZeroH[x]], COL[ZeroV[x]], ROW[ZeroH[x]]);
			}
		}



}

}



void delay(unsigned int delayTime){
  int t1;
  for (t1=0;t1      t1=t1*1;
  }

}


void sendSerial(unsigned char dataGreen, unsigned char dataColumn, unsigned char dataRed)
{
  int i;

  // send bits 7..0
  for (i = 0; i < 8; i++)
  {
      // consider leftmost bit
      // set P1.5 (Green cathode) low if bit is 1, High if bit is 0
      // set P1.1 (Red cathode) low if bit is 1, High if bit is 0
      // set P1.0 (Data column) low if bit is 1, High if bit is 0
      if (dataGreen & 0x80){
          P1OUT &= ~BIT5;
      }
      else{
          P1OUT |= BIT5;
      }


      if (dataRed & 0x80){
          P1OUT &= ~BIT1;
      }
      else{
          P1OUT |= BIT1;
      }


      if (dataColumn & 0x80){
      	P1OUT |= BIT0;
      }

      else{
      	P1OUT &= ~BIT0;
      }
      //Send Clk signal high to all shift registers.
      	P1OUT |= BIT4;
		//Then set it low again.
		P1OUT ^= BIT4;

		//Shift all the data and cycle through 8 times.
		dataGreen <<= 1;
		dataColumn <<= 1;
		dataRed <<=1;       
  }
   // Set storage register to update outputs of shift registers.
 	P1OUT |= BIT3;
 	P1OUT &= ~BIT3;

}

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...