Tutorial 7 - All the info you need is right here!

Post here to discuss the PIC microcontroller tutorials.

Moderators: Chuckt, Garth, bitfogav

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Tutorial 7 - All the info you need is right here!

Post by brad » Sat Sep 04, 2010 6:07 pm

Throughout this tutorial, we will be looking at interfacing an 8x8 LED Matrix to the microcontroller.
 
Now first things first, I don't recommend making your own 8x8 LED matrix out of individual LED's (because it is very time consuming!) I do recommend purchasing yourself one (or more) of the 8x8 Bi-colour LED matrix displays off ebay. they are incredibly cheap and are very easy to use.
I buy mine from sure electronics. make sure you check out their website.

Also, if you are interested in buying in bulk from sure electronics, make sure you email them because when I made the 8x8 game system kit, i ordered 50 of the 8x8 matrix's and all up it cost me $50 including postage!
 
And now into the lesson...

 
The 8x8 LED matrix display's are (believe it or not) connected in a matrix. This means that you don't just have 2 connections for each led (of which there are 64 LED's) instead, the LED's are connected in such a way that we can light up every LED in the matrix and to do this, we only require 16 connections (rather than 128 doing it individually)
Here is a diagram showing you how the LED's are connected together to form the matrix.

Image

You will notice the image on the left has 64 LED's connected in an 8x8 LED matrix. There are 8 Columns where the cathodes are all connected together and also 8 Rows where the anodes are all connected together. The image on the right will be used to demonstrate how we get the matrix to do what we want.
 
Le's start out nice and simple. What if we wanted to turn on just the top right LED. Well. we would need to ground the right most cathode and then connect the top Anode to our power supply (+5v) through a resistor, just like this next picture:

Image

You may also have guessed that if we connect +5v to the top row of anodes then EVERY anode up the top will have +5v connected to it. The reason that only the top right LED turns on is because we have only connected ground to the right most column of cathodes. We need the combination of +5v AND ground in order to complete the circuit to turn on whatever LED or LED's that we want.
 
What about if we wanted to turn on an entire Column of LED's? We'll you would connect your matrix as follows:

Image

Or perhaps an entire row?

Image

Now, having finished the introduction, this is the circuit that we are going to be working with when experimenting with our matrix.

Image

We are using a helper chip in this excercise - the 7442 ( 1 of 10 decoder) this is going to help us with 'scanning' the cathodes. Let's have a look at how the 7442 works:

Image

This is a 16 pin chip, of course it has a +5v connection and ground in order to power it up. It also has four inputs namely A, B, C and D. lastly, it has 10 outputs - 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9. It is quite a simple chip to work with. The outputs will vary depending on what combination of 1's and 0's are on the inputs. All outputs of this chip will be a logic high EXCEPT for one. That one will depend on the input. Here is a chart showing you what the output will be for all combinations of inputs:

Image

So anyway, having a look at the 7442 output, we can make any one of the outputs low (or pretty much connect it to ground) by giving a certain combination on the input. If we wanted output 0 to be low then we would input 0000 OR if we wanted output 6 to be low then we would input 0110 etc...
We only require 8 (of the 10) outputs from this chip therefor we use these 8 combinations on the input:

000

001

010

011

100

101

110

111

This means that we don't need to use the fourth input line (D) so that is why I have connected it straight to ground and only the first three inputs (A, B and C) are connected to the microcontroller so we can control them. So this means that we will have any one of these eight combinations on the inputs:

0000

0001

0010

0011

0100

0101

0110

0111

So hopefully you can see that by using this chip, we can 'Activate' one column of Cathodes at a time by connecting one column at a time to ground (logic 0) and to do this it only required 3 I/O lines from the microcontroller - whereas without the 7442, we would have required 8 I/O lines and we only have seven to spare (because PORTB is used for the anodes and PORTA pin 5 cannot be an output)
 
So now we are working towards drawing a picture on the screen. Here is what we want to draw:

Image

Now you may very well be asking "That's a pretty picture, BUT how do we draw a picture with all of those LED's lit up at once if we can only 'activate' one column at a time?"
We'll I am glad that you asked that question! there is a little bit of a trick to it.
What you see on the 8x8 matrix is a face. BUT not all columns are on at the same time - infact only one column is drawn at any one time but we 'scan' through the columns so fast, that to the human eye it just looks like one steady image.
 
Download this piece of source code and see for yourself:

http://www.bradsprojects.com/phpBB2/upl ... ix_104.asm
 
PLEASE NOTE: I HAVE NOT TESTED THIS SOURCECODE! IT SHOULD WORK FINE THOUGH. I WILL GET AROUND TO TESTING IT WHEN I BUILD THE CIRCUIT :)
 
In this first piece of sourcecode we are 'drawing' the face on the screen BUT the rate at which we scan the display is so slow that our brains can't put all of the eight columns together to make one complete image. So what you will infact see on your display is something like this:

Image

This animation hopefully will help you understand what is going on.
We first 'activate' the right most column by putting 000 on the 7442 input. This means that the first output is low and all other outputs are high. Now at the same time that we have activated the right most column - we also output 8-bits of data to PORTB. All LED anodes are connected to PORTB but only the right most column will do anything because that is the only column with a complete circuit connecting us to ground. This is how the beauty of multiplexing works.

So we want to output the first column of our face, in this case it is 00111100. so if you have a look at the animation, when the right most column is activated, we have 00111100 on PORTB and so those particular LED's light up. We hold that there for just a moment and then we turn off the LED's and then move onto the next column to the left by sending 001 to the 7442. We then output another 8-bits to PORTB but only the second column will light up with anything because this column is the only one connected to ground.  Then we repeat the process of activating the next column in sequence, and then sending the correct 8-bits that corresponds to that column in the picture to PORTB. once we have drawn the complete image, we just loop back to the begging and do it all again!
 
So now that you can see how one complete image is drawn, go back to the sourcecode and decrease the delay time. I.E it is set to 255, try changing it to 100 and then 50, 20, 10, 05, 02 etc... What happens?
We'll the lower your delay routine, the faster it will scan through drawining each column. You will notice that you will start to see the complete picture but it will be quick flickery. Then you will eventually get to a point where there is no longer any flicker - what is the delay set to in order to achieve this?
 
Homework:
1. I have purposely designed the sourcecode to be very basic and not efficient. Can you redesign the sourcode so that it does the same thing but in a more efficent manner? E.G use the incf instruction to increment PORTA instead of doing it by movlw.

2. Design your own piece of code so that you have one LED lit - starting at the top left and then the led will do laps around the outside edge of the display. I.E it goes from top left to top right, then down, then left again and then back up to the starting position.  
Attachments
matrix_pinout.PNG
matrix_pinout.PNG (10.87 KiB) Viewed 21457 times
top_right_led.PNG
top_right_led.PNG (4.29 KiB) Viewed 21457 times
led_column.PNG
led_column.PNG (4.94 KiB) Viewed 21457 times
led_row.PNG
led_row.PNG (4.32 KiB) Viewed 21457 times
8x8_led_schematic.PNG
8x8_led_schematic.PNG (14.44 KiB) Viewed 21457 times
7442.PNG
7442.PNG (2.99 KiB) Viewed 21457 times
7442_table.PNG
7442_table.PNG (7.87 KiB) Viewed 21457 times
8x8_face.GIF
8x8_face.GIF (10.07 KiB) Viewed 21457 times
smiley_face_8x8_matrix.asm
(8.67 KiB) Downloaded 638 times
8x8_anim_slow.gif
8x8_anim_slow.gif (73.74 KiB) Viewed 21457 times

tgraz34
decided to stick around...
decided to stick around...
Posts: 32
Joined: Tue Jun 08, 2010 12:14 pm

Post by tgraz34 » Mon Sep 06, 2010 4:51 am

Hey brad, thanks for that tutorial.
I do have a question about it though, how would you scroll an image (or sentence) across the matrix?

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Mon Sep 06, 2010 6:03 am

Here is some code from "The Great Race" game whereby the screen keeps scrolling:

Code: Select all

track_data		
	incf pc_track, f	
	movf pc_track, w	
	addwf PC				
	retlw b'10000001'	
	retlw b'10000001'	
	retlw b'11000001'	
	retlw b'11000001'
	retlw b'11100001'
	retlw b'11100001'
	retlw b'11110001'
	retlw b'11110001'
	retlw b'11111001'
	retlw b'11110001'
	retlw b'11100001'
	retlw b'11000011'
	retlw b'10000111'
	retlw b'10001111'
	retlw b'10000111'
	retlw b'10000011'
	retlw b'10110001'
	retlw b'10111001'
	retlw b'10111001'
	retlw b'10111001'
	retlw b'10010001'
	retlw b'10000001'
	retlw b'10000001'
	retlw b'11000011'
	retlw b'11100111'
	retlw b'11000011'
	retlw b'10000001'
	retlw b'10011001'
	retlw b'10011001'
	retlw b'10111101'
	retlw b'10111101'
	retlw b'10011001'
	retlw b'10011001'
	retlw b'10000001'
	retlw b'11000011'
	retlw b'11100111'
	retlw b'11000011'
	retlw b'10000001'
	retlw b'10000001'
	retlw b'10010001'
	retlw b'10110001'
	retlw b'10111001'
	retlw b'10111001'
	retlw b'10011001'
	retlw b'10000001'
	retlw b'10000011'
	retlw b'10000111'
	retlw b'10001111'
	retlw b'10000111'
	retlw b'11000001'
	retlw b'11100001'
	retlw b'11110001'
	retlw b'11111001'
	retlw b'11111101'
	retlw b'11111001'
	retlw b'11110001'
	retlw b'10000001'
	retlw b'10000001'
	retlw b'10110001'
	retlw b'10110001'
	retlw b'10110001'
	retlw b'10000001'
This first bit of code takes care of grabbing one byte of data at a time and returning with it to the routine that called it (using the retlw instruction) Each time it is called, it actually grabs the next successive byte of data in line because we keep incrementing our track counter by one each time.

In order to display the data on the screen and have it scrolling we need to map each column on the screen to a memory location. We then keep shifting the data from the first column, to the next column and then grab a new byte for the first column and keep repeating that process.

So here's the code to shift the data through these eight variables which then get sent to their own column on the screen. Notice how I first save what is in seven of the eight variables, then I grab one new byte of data from the data table above and this comes into the first variable location. Then variable 1 is moved to 2, 2 goes to 3, 3 goes to 4 etc...

If you want the full code then jump to the great race page in the projects section on the main site

Code: Select all

fill_vram
		movf vram_1, 0
		movwf vtemp_1
		movf vram_2, 0
		movwf vtemp_2
		movf vram_3, 0
		movwf vtemp_3
		movf vram_4, 0
		movwf vtemp_4	
		movf vram_5, 0		
		movwf vtemp_5		
		movf vram_6, 0		
		movwf vtemp_6		
		movf vram_7, 0		
		movwf vtemp_7		
		call track_data		
		movwf vram_1		
		movf vtemp_1, 0		
		movwf vram_2		
		movf vtemp_2, 0
		movwf vram_3		
		movf vtemp_3, 0		
		movwf vram_4		
		movf vtemp_4, 0	
		movwf vram_5	
		movf vtemp_5, 0	
		movwf vram_6	
		movf vtemp_6, 0		
		movwf vram_7		
		movf vtemp_7, 0	
		movwf vram_8	
	return
:D

tgraz34
decided to stick around...
decided to stick around...
Posts: 32
Joined: Tue Jun 08, 2010 12:14 pm

Post by tgraz34 » Wed Sep 08, 2010 12:03 pm

hey brad, i changed the delay to 03 and i cant tell a difference between that and 255.

what could be the problem?

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Post by brad » Wed Sep 08, 2010 12:22 pm

tgraz34 wrote:hey brad, i changed the delay to 03 and i cant tell a difference between that and 255.

what could be the problem?
Good question, It's because it is drawing one static image and even if you increase how fast you draw that image (by decreasing the delay) it still is the same image and won't look any different :)

How about you increase the delay like this:

Code: Select all

delay
	movlw d'255'			
	movwf delay_1			
	movwf delay_2
        movlw d'05'
	movwf delay_3	
delay_loop				
	decfsz delay_1, f		
		goto delay_loop		
	decfsz delay_2, f			
		goto delay_loop	
	decfsz delay_3, f			
		goto delay_loop			
	return
then experiment with different numbers in delay_3

tgraz34
decided to stick around...
decided to stick around...
Posts: 32
Joined: Tue Jun 08, 2010 12:14 pm

Post by tgraz34 » Tue Sep 14, 2010 10:52 pm

How do you access the 8th output on the 7442 if you have the input connected to ground?

The input requires the D colum to have a high instead of a low.

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Re: Tutorial 7 - All the info you need is right here!

Post by brad » Wed Oct 13, 2010 3:05 pm

Hi, sorry I must have missed this post!

you can still get 8 outputs because remember that 000 is your first output and it goes all the way to 111 which is your last.

io.
newbie
newbie
Posts: 7
Joined: Wed Feb 23, 2011 8:23 am

Re: Tutorial 7 - All the info you need is right here!

Post by io. » Sat Feb 26, 2011 8:00 pm

Hi,

Will it be a good idea to use 3 7442 ? One for grounds, one for greens and one for reds.

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Re: Tutorial 7 - All the info you need is right here!

Post by brad » Sun Feb 27, 2011 8:21 pm

io. wrote:Hi,

Will it be a good idea to use 3 7442 ? One for grounds, one for greens and one for reds.
Unfortunately that won't work.

The problem is that with the 7442, you can only activate ONE output at a time (it is a decoder)

What we need to do in this instance is activate just one line of cathodes, and then send in eight bits to the anodes. This will light up the respective LED's in that one line. We then turn them off, activate the next line of cathodes - send eight bits to the anodes and this has then drawn your second line.

Another problem with just using 7442 chips is that they are only designed to be used with the LED cathodes (because they output logic 0's) so they wouldn't work with anodes.

io.
newbie
newbie
Posts: 7
Joined: Wed Feb 23, 2011 8:23 am

Re: Tutorial 7 - All the info you need is right here!

Post by io. » Fri Mar 04, 2011 8:53 pm

My idea was to draw less current by controlling only one LED at time and to be able to use both colors of the LED Matrix with only one 16f628a.
Maybe can we use NOT gates to get logic 1 instead of logic 0 at anode pins ?

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Re: Tutorial 7 - All the info you need is right here!

Post by brad » Sat Mar 05, 2011 12:43 pm

Yep you are correct.

You could invert the output of one of the 7442 chips and then you would be able to turn on one pixel at a time.

Now the only other problem that you may face is the screen flickering due to only one pixel being lit up at a time (and it will need to do all 64 pixels to produce one picture) whereas if you light up a whole row at a time, you only need to draw eight rows to get one complete picture (so the refresh rate is a lot quicker)

If the microcontroller clock speed is fast enough, you won't have a flicker problem. But the screen will be very dim, because each LED will only be staying on for perhaps 1uS every 64uS (because it is scanning through each individual LED)

Having said that - it can be done!

io.
newbie
newbie
Posts: 7
Joined: Wed Feb 23, 2011 8:23 am

Re: Tutorial 7 - All the info you need is right here!

Post by io. » Sat Mar 05, 2011 6:58 pm

Oh yes of course, I don't have to only think about time to scan all the matrix but also about the time each LED have to stay on to be visible enough.
Or maybe, with a 16f628a at 20 MHz, I will have enough time to execute the code and to draw the same image several times to make it persistent enough.
I don't know yet 16f628a microcontroller, but seeing what yo do with it, I already like it.

I'm trying here to figure out a way to control red and green LED from 8x8 matrix (last year I bought several of the same matrix as yours from Sure Electronic), but only 5 pins are remaining on the microcontroller so it can't drive another color.

Or maybe with 16 AND gates and 1 (or 2) another output(s), we can alternatively draw reds then greens with the same pins from 6 to 13, and this way it could be done row by row.

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Re: Tutorial 7 - All the info you need is right here!

Post by brad » Sat Mar 05, 2011 11:15 pm

What you need is a way to expand your output ports.

The best way to do this (in my experience) is to get some 74373 chips.

They are 8-bit data latches with tri-state outputs.

What you can do with these is get three of them. connect the eight inputs of each one to PORTB of your microcontroller (so they all have exactly the same inputs)

Then connect the eight outputs of each chip to your eight red cathodes, your eight green cathodes and then your eight anodes. (one chip for each section)

Then, connect the latch enable pin of each chip to one of the pins on PORTA. So you could connect the latch enable of the red 74373 to PORTA pin 0, then green latch enable to PORTA pin 1 and then the anode latch enable to PORTA pin 2.

Then lastly, the 74373 chips have an output enable pin (because they have tri-state outputs) so you need to connect all three output enable pins of the three chips together, and then to PORTA pin 3.

So, to draw an image you need to send out three bytes of data (one for the red cathodes, one for green and one for the anodes. First send the red byte to PORTB, then enable the red 74373 latch by making PORTA pin 0 a logic 1, then 0 again. Then send the green byte to PORTB and then enable the latch by sending a logic 1 to PORTA pin 1, then make it a zero again. lastly - send out your anode data to PORTB and then send a logic 1 to PORTA pin 2 to enable the anode latch, then make it a logic 0 again.

Now we have three chips, each with their required data. We then make PORTA pin 3 (the output enable connection) a logic 0 (we need it to be a 0 because it has an inverted input at the 74373 for this connection)

This will allow all the data present in the 74373 chips to go out and be displayed on the LED matrix.

Have a look at the 8x8 game system page for full details and a schematic of how I made it all work.

io.
newbie
newbie
Posts: 7
Joined: Wed Feb 23, 2011 8:23 am

Re: Tutorial 7 - All the info you need is right here!

Post by io. » Sun Mar 06, 2011 7:32 am

Thanks a lot, I think I have understood the theory. I'm gonna do some reading about the subject :)

I'm about to buy some Motorola MC74F374N, they seem to do the same as 373.

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm

Re: Tutorial 7 - All the info you need is right here!

Post by brad » Sun Mar 06, 2011 11:44 am

Yep, they will do the trick. You will find different variations in the part number but as long as it has 74373 written in there, it will be fine.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest