Multiplexing with SN74LS47N

nerdegutta

Senior Member
Hi.

I'm trying to learn how to multiplex a 2-digit 7 segment display. Do anyone have any links or, tutorials on this?
This is my schematic, it's on a breadboard - for now...

14m2-7447-7seg_sch.png

This is my code:

Code:
#no_data

symbol lDelay = 200

symbol digit1 = c.0
symbol digit2 = c.1

let dirsb = %111111


main:
high digit1
for b2 = 0 to 9
	gosub lookuproutine
	inc b0
	let pinsb = b1: pause lDelay
	if b0 = 9 then
	endif
next b2
let b0 = 0
let b2=0

goto main

lookuproutine:
	lookup b0,(0,2,4,6,8,10,12,14,16,18), b1
	return
This is working on one of the digits, but I cannot get my head around, to get the other...

I know I have to

- set pins to output
- set pinsc low
- determin pinsb value
- set digit1 high
- send values to pinsb
- set digit1 low and set digit2 high
- send values to pinsb
- and repeat

First I want to make a counter that counts from 00 to 99.

Anyone?

- nerdegutta
 

AllyCat

Senior Member
Hi,

You need to use two "nested" loops, the outer loop counting through the displayed digits (0 - 99) and the inner loop repeatedly showing the two digits faster than the "persistence of vision" (i.e. looping faster than 50 Hz, or a 20 ms period).

If we assume that you want the digits to increment at 5 Hz (perhaps rather fast) and the inner loop is 50 Hz then you could make the inner loop a FOR .. 0 TO 9 : <multiplexer code> : NEXT structure

Your pseudocode is reasonably correct, but can be improved. The first line only needs to be executed once so can be outside the main loop(s). Then note my modified sequence below (not tested) to avoid "ghost" segments being lit, but to maximise the segments' on time :

- set pins to output
FOR digits = 0 TO 99
FOR multi = 0 TO 9
- determine pinsb value ; e.g. LET value = digits / 10 (i.e. the "tens" digit)
- set pinsc low
- send value to pinsb
- set digit1 high
PAUSE 3
- determine pinsb value ; e.g. LET value = digits // 10 (i.e. the "units" digit)
- set digit1 low
- send value to pinsb
- set digit2 high
PAUSE 2
NEXT multi
NEXT digits
- set pinsc low

Generally, you don't need to use both a LOOKUP command and an external decoder/driver chip. The driver may give more current, saves 3 PICAXE pins and may simplify the code with a 14M2. But a "minimal hardware" solution could use 7 PICAXE pins to drive the segments directly, and a suitable segment LOOKUP command (i.e. not the values you've shown).

Cheers, Alan.
 

nerdegutta

Senior Member
Thanks, Alan.

I can see it in my head,but when I sit down in front of the screen, my head goes blank.

I'll refine the pseudocode and will come back.

I learned sometime about something called "stepwise refinement"...

- nerdegutta
 

AllyCat

Senior Member
Hi,

Probably, each line of pseudocode will convert to a single PICaxe command line, with just a few extra Symbol declarations at the start. But I don't like to offer "real" code without thoroughly chcking its syntax and functionality.

Since there are only two "digit" pins, IMHO the code might be (slightly) more readable by replacing the "set pinsc ..." commands with simple "High" and "Low" instructions.

Cheers and good luck, Alan.
 

nerdegutta

Senior Member
Since there are only two "digit" pins, IMHO the code might be (slightly) more readable by replacing the "set pinsc ..." commands with simple "High" and "Low" instructions.
OK, I'll try that too, but I read somewhere that you could do the same as with a stepper. Controlling all pins at once, instead of seperate.

- nerdegutta
 

nerdegutta

Senior Member
Now, I've tried this code, among other, but I think I'm getting blind.

Code:
' Learning multiplexing code with 14m2
#no_data

symbol digits = b0
symbol multi = b1
symbol value = b2
symbol showdigit = b3 ' not in use right now

symbol d1 = c.0
symbol d2 = c.1

let pinsb = %011110
let pinsc = %011110

main:
for digits = 0 to 99
for multi = 0 to 9
	let value = digits / 10
	low d1: low d2
	let pinsb = value
		' Tried this but nothing
		' lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit
	let pinsb = showdigit
	high d1
pause 3
	let value = digits // 10
	low d1: low d2
	let pinsb = value
		' Tried this but nothing
		' lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit	
	let pinsb = showdigit
	high d2
pause 2
next multi
next digits
low d1: low d2
	
goto main
This code shows noting on the 7 seg.

- nerdegutta

EDIT: Found an error in the code: pins instead of dirs
 
Last edited:

nerdegutta

Senior Member
Progress. This code counst from 00 to 99, and repeats.

Code:
' Learning multiplexing code with 14m2
#no_data

symbol digits = b0
symbol multi = b1
symbol value = b2
symbol showdigit = b3

symbol d1 = c.1
symbol d2 = c.0

let dirsb = %011110
let dirsc = %011110

main:
for digits = 0 to 99
for multi = 0 to 9
	let value = digits / 10
	low d1: low d2
	 lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit
	let pinsb = showdigit
	high d1
pause 3
	let value = digits // 10
	low d1: low d2
	 lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit	
	let pinsb = showdigit
	high d2
pause 2
next multi
next digits
low d1: low d2
	
goto main
Thanks for tips and pointers!!

- nerdegutta
 

AllyCat

Senior Member
Hi,

Yes, you can use DIRSC to control the digit (common anode) pins, but as you only need to change one pin at a time (to avoid a potential "ghosting" problem that you may not yet be aware of) then it's simpler and clearer to control the pin explicitly.

low d1: low d2
lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit
You don't need both the "low d1" and "low d2" because one of them should be already low !

The LOOKUP is only required if the "mapping" of the data bits to the pins is not "tidy". In this case you can simply use "LET showdigit = value * 2 ". That is significantly faster and you might then need to increase the PAUSEs to perhaps 5 or more.

Cheers, Alan.
 

nerdegutta

Senior Member
OK...

I feel that this code is a lot smoother and runs better in the PICAXE.

Code:
' Learning multiplexing code with 14m2
#no_data

symbol digits = b0
symbol multi = b1
symbol value = b2
symbol showdigit = b3

symbol d1 = c.0
symbol d2 = c.1

let dirsb = %011110
let dirsc = %011110

main:
do
for digits = 0 to 99
for multi = 0 to 9
	let value = digits / 10
	low d1:low d2
	 'lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit
	 let showdigit = value * 2 
	let pinsb = showdigit
	high d1
pause 15
	let value = digits // 10
	low d2: low d1
	 'lookup value,(0,2,4,6,8,10,12,14,16,18), showdigit	
	 let showdigit = value * 2
	let pinsb = showdigit
	high d2
pause 3
next multi
next digits

loop
- nerdegutta
 

AllyCat

Senior Member
Hi,

Isn't the second digit rather dimmer than the first with those PAUSEs ?

Here's some slightly modified code (untested) which should count directly in seconds:

Code:
#no_data

symbol digits = b0
symbol d1 = c.0
symbol d2 = c.1
dirsb = %011110

main:
do
	digits = time
	do 
		low d2
		pinsb = digits / 10 * 2
		high d1
		pause 5
		low d1	
		pinsb = digits // 10 * 2
		high d2
		pause 4
	loop until	digits <> time 
loop
Also see what happens if you make the high d2 immediately follow the low d1 (e.g. low d1 : high d2) as would happen if you used a single pinsc command.

If you swapped the connections to ports b and c then you could omit the need for the " *2 "s (i.e. with pinsc = %1111 and the decoder chip wired to c.0 ... c.3).

Cheers, Alan.
 

nerdegutta

Senior Member
Hi.

You are right, one digit is slightly dimmer than the other.

When I download your code, the counting start, but when it reach 99, it start to show some other characters.

7-seg-numericals.png

One digit shows the symbol for 10-15, from the above table.

Guess we have to insert an ifstatement?

- nerdegutta
 

AllyCat

Senior Member
Hi,

Ah yes, either something like IF time > 99 THEN : time = 0 : ENDIF , or wrap the tens digit result to 0 after 9 by using the remainder after dividing by 10. For example, change the (first pinsb) line to pinsb = digits / 10 // 10 * 2 .

For equal digit brightness, typically the second PAUSE should be about 1 (ms) less than the first, to compensate for the time it takes the program to jump back to the start of the loop. Perhaps an example where a simple GOTO shows more clearly where an execution delay actually occurs.

Cheers, Alan.
 

nerdegutta

Senior Member
Hi,

I changed the first pinsb line to your suggestion. Now it counts from 00 to 99, without any strange signs/symbols.

Thanks!

- nerdegutta
 
Top