Transistors for multiplexed display

oracacle

Senior Member
Its beena while, money is still pretty tight atm, so i have a few half finnished projects here, how ever using some hardware that i have but arent suitable for my other project i have another nice little project. A clock with the ability to displayd not just time, but date, day of week, year and tempurature


Circuit 2.0 by f2268d215cc925918731918f4efa0289, on Flickr

this is the circuit to date

the question is, should i run the cathodes of the 7 segments thought a transistor or strait to the picaxe, the sevent segment i am using are red one found here

http://www.maplin.co.uk/14mm-0.56-inch-double-digit-numeric-display-2166

I am unsure if the 28x1 i have will be OK sinking the amount current for up to 8 LEDs. I did try and read the PIC16F data sheet, but i coult not see the info i needed

I will post the programme i have been working on later.
I should also mention that this will be laying foundation for an idea using a large home made set of 7 segment displays (maybe 5 LEDs per segment), but that is just a pipe dream at the moment, depending on how my new job goes may come to fruition, along with other thing that sit semi complete on my desk
 

westaust55

Moderator
Each PICAXE IO pin is limited to an operating current of 20 mA (absolute max of 25 mA).
In addition there are port and total chip limits which for some of the later chips is around 95 mA.

If you are going to keep the 7-segment display current down to around 12 mA each (which is still quite visible) the. You will still need a transistor for the common side capable of at least 100mA.

BC548 is capable of 100 mA and BC338 is capable of 800 mA.
Drive these in saturation rather than linear to reduce the Vce and power losses in the transistors.

EDIT:
In the PIC Datasheet it is usually around section 30 for Electrical Characteristics ( not downloading a large Datasheet onto my iPhone).

Also make sure you earth/ground the gnd side of the 10 kOhm resistor in the programming circuit or your project will not work when unleashed from the AXE027 cable.
 
Last edited:

oracacle

Senior Member
handy, i have a miassive bag of 548s. but from the sounds of thing, to help increase the brightness of the display i should run both side throught transistors. however with that said, providing i have read the data sheet correctly, and a set of 330ohm resistor between the pins and LEDs the BC548 should reach saturation @ 5 volts, so s standard 1k resistor between the picaxe and transistor should be fine, and cause saturation.

also i just tryed to post the programme so far, but it is 10548 characters or something. i may have to break it into to to post it, will this be OK
 

westaust55

Moderator
If your BC548 is group B or C then the normal linear gain wll typically be 200 or better and the Hfe(sat) about one tenth of then in which case a 1 kOhm resistor will be the max value. Try say a 820 Ohm instead.

If the transistors are group A the normal linear gain will be around 100 so use a 470 Ohm resistor.
 

westaust55

Moderator
If your BC548 is group B or C then the normal linear gain wll typically be 200 or better and the Hfe(sat) about one tenth of then in which case a 1 kOhm resistor will be the max value. Try say a 820 Ohm instead.

If the transistors are group A the normal gain will be around 100 so use a 470 Ohm resistor.
 

oracacle

Senior Member
the are group be, i found some 670ohm resistors whcih seem to be doing the job. i was trying to do the maths but it made my head hurt a little.

here the first section of code

Code:
#rem
Segement - Picaxe Pin		A
   A----------2		     ---
   B----------1		    |   |
   C----------0		   F|   |B
   D----------6		    | G |
   E----------5		     ---
   F----------4		    |   |
   G----------3		   E|   |C
   DP---------7		    |   |
   				     ---
   				      D   oDP
#endrem

	#picaxe28x1
	let dirsc = %11100100
	setfreq m8
'pin outs for numbers	
symbol deci		= %10000000
symbol blank	= %00000000
symbol zero		= %01110111
symbol one		= %00000011
symbol two		= %01101110
symbol three	= %01001111
symbol four		= %00011011
symbol five		= %01011101
symbol six		= %01111101
symbol seven	= %00000111
symbol eight	= %01111111
symbol nine		= %00011111
'pinouts for days of week
symbol mon1		= %00110110
symbol mon2		= %00010111
symbol mon3		= %01101001
symbol mon4		= %00101001

symbol tue1		= %01111000
symbol tue2		= %01100001
symbol tue3		= %01111100
symbol tue4		= %01011101

symbol wed1		= %01110001
symbol wed2		= %01100011
symbol wed3		= %01111100
symbol wed4		= %01101011

symbol thu1		= %01111000
symbol thu2		= %00111001
symbol thu3		= %01100001
symbol thu4		= %00101000

symbol fri1		= %00111100
symbol fri2		= %00101000
symbol fri3		= %00000001
symbol fri4		= %01101011

symbol sat1		= %01011101
symbol sat2		= %00111111
symbol sat3		= %01111000
symbol sat4		= %00000000

symbol sun1		= %01011101
symbol sun2		= %01100001
symbol sun3		= %00101001
symbol sun4		= %00000000
'variables
symbol decimal	= b22
symbol units	= b23
symbol tens		= b24
symbol hundreds	= b25

symbol temp		= w0
symbol whole	= b2
symbol sign		= b3
symbol adjtemp	= w2
symbol display	= b6

symbol secs		= b7
symbol mins		= b8
symbol hour		= b9
symbol days 	= b10
symbol date 	= b11
symbol month 	= b12
symbol year 	= b13

symbol hten		= b14
symbol hunit	= b15
symbol mten		= b16
symbol munit	= b17

symbol loops	= w9

symbol tempbyte	= b20
symbol tempyear	= b21

'***main programme loop***
main:
	
	i2cslave %11010000, i2cslow, i2cbyte
	readi2c 0, (secs,mins,hour,days,date,month,year,b20)		'read clock data
	gosub bin									'goto sub-procedure
	let days = days - 1							'adjust days data for correct reading
	;the DS1307 considers sunday the first day of the week and is show as 1, correcting by -1 allow the table to read for 0 to 6
	if secs > 60 then setclock						'check for rtc battery faliure
	
	gosub getdata
	
	for tempbyte = 0 to 40							'set loop
	if porta pin0 = 1 then gosub get_temp				'check for user asking for tempurature
	if porta pin1 = 1 then gosub show_date				'check for user asking for date

	gosub show									'show time on displays
	next tempbyte								'go next loop
	let tempbyte = 0
	goto main


'********************
'***Sub procedures***
'********************	
get_temp:
	let loops = 0
	readtemp12 0, temp

	sign = 43					;"+"
		
	if temp > 2048 then 			;check for negative temp
	sign = 45					;"-"
	temp = - temp				;two's complement
	end if

	adjtemp = temp *10/16			;x10 for 0.1 resolution
	whole = adjtemp / 10
	decimal = adjtemp // 10
	
	gosub divide				;go to sub-procedure
		
	for loops = 0 to 2000			;set display time
	if sign = 45 then				;check for positive tempurature
	let pins = %00001000			;disply - if negative
	else
	let pins = blank				;otherwise display blank
	end if
	let pinsc = %10000000			'switch on first display
	let pinsc = %00000000			'switch off second display
	
	let pins = tens 				;load tens value to outpur bus
	let pinsc = %01000000			;switch on second display
	let pinsc = %00000000			;switch off second display
	
	
	let pins = units + %10000000			;load units into output bus, add 1 for DP
	let pinsc = %00100000			;switch on third display
	let pinsc = %00000000			;switch off third display
	
	let pins = decimal			;load decimal into output buffer
	let pinsc = %00000100			;switch on fourth display
	let pinsc = %00000000			;swtich off fourth display
	next loops
	let loops = 0
	return

divide:
	let tens = whole /10			;divide whole by 10 to give tens lookup value
	let units =  whole // 10		;divide whole by the remainder off 10 for units lookup value
	;now loop up values to define the output bus value
	lookup decimal, (zero, one, two, three, four, five, six, seven, eight, nine), decimal
	lookup tens, (zero, one, two, three, four, five, six, seven, eight, nine), tens
	lookup units, (zero, one, two, three, four, five, six, seven, eight, nine), units
	return



show_date:
	'lookup up day and display
	gosub lookday				;lookup day of week in tables
	for tempbyte = 40 to 50			;set varaible to loop amd remove deciaml point
	if porta pin0 = 1 then settime	;check for time update
	gosub show
	next tempbyte
	let tempbyte = 0
	'display month and date
	let hten = date/10
	let hunit = date//10
	
	let mten = month/10
	let munit = month //10
	gosub look					;look for disaply data in tables
	
	for tempbyte = 0 to 10
	gosub show					;show display
	next tempbyte
	tempbyte = 40
	;set year to 20--
	let hten = 2
	let hunit = 0
	
	let mten = year/10
	let munit = year//10
	;show year
	gosub look
	for tempbyte = 40 to 50
	gosub show
	next tempbyte
	reset	
	
;followinf proceedures are for updating the RTC
settime:
	gosub getdata
	gosub show
	loops = 0
	let tempbyte = 0
setmins:
	gosub show
		if porta pin0 = 1 then		;check for user incrementing mins
		let mins = mins + 1		;increment mins if needed
			if mins > 59 then		;check for overflow
			let mins = 0		;reset in case of overflow
			endif
		let mten= mins /10		;set variables for display
		let munit = mins //10
		let hten = hour /10
		let hunit = hour //10
		gosub look
		endif
		if porta pin1 = 0 then goto setmins	;check for user input, continue to hours
	pause 150

sethours:
	gosub show
		if porta pin0 = 1 then		;check for user input
		let hour = hour + 1		;add 1 hour
			if hour > 23 then		;check for overflow
			let hour = 0		;reset if overflow occours
			end if
		let hten = hour /10		;set variables for display
		let hunit = hour //10
		let mten= mins /10
		let munit = mins //10
		gosub look
		endif
	if porta pin1 = 0 then goto sethours	;check for iser input
	pause 150
	gosub lookday
		let tempbyte = 40			;set variable to remove deciaml place

setdays:
	gosub show
		if porta pin0 = 1 then		;check for user input
		let days = days + 1		;add 1 day
			if days > 6 then		;check for over flow
			let days = 0		;reset if overflow occours
			end if
		gosub lookday
		end if
	if porta pin1 = 0 then setdays	;check for user input
	let days = days + 1			;correct for writing to DS1307
	pause 150
	
		let hten = 2
		let hunit = 0
		let mten = year/10
		let munit = year//10
		gosub look
	
setyear:
	gosub show
		if porta pin0 = 1 then
		let year = year + 1
			if year > 99 then
			let year = 00
			end if
		let hten = 2
		let hunit = 0
		let mten = year/10
		let munit = year//10
	gosub look		
		end if

	if porta pin1 = 0 then goto setyear

	'put date variable into display variables
	let hten = date/10
	let hunit = date//10
	
	let mten = month/10
	let munit = month //10
	gosub look
	gosub show
	let tempbyte = 0

setmonth:
	gosub show
		if porta pin0 = 1 then
		let month = month + 1
			if month > 12 then
			let month = 1
			end if
		let mten = month /10
		let munit = month //10
		let hten= date /10
		let hunit = date //10
		gosub look
		endif
	if porta pin1 = 0 then goto setmonth
	pause 150

setdate:
	gosub show
	if porta pin0 = 1 then
	let date = date + 1
	let tempbyte = month -1							;correct month for lookup table
	lookup tempbyte, (31,28,31,30,31,30,31,31,30,31,30,31),tempbyte	;lookup days in each month
		if month = 2 then							;check for feburary
	#rem
	research showed the all leap years when divided by 4 were whole numbers, as the picaxe can not make use
	of deicimal place, shifting the decimal place by multipling by 10 and finding the remainder of divideing
	the result by 4 the piacxe can use a simple if statement to dtermine leap years and thus how many days
	in the second month
	#endrem
		let tempyear = year *10						;x10
		let tempyear = tempyear//4					;find remainder of dividing by 4
				if tempyear = 0 then 				;if the answer is 0, then its a leap year
				tempbyte = 29					;set number of day to 29
				end if
		end if	
		if date > tempbyte then
		let date = 1
		end if
		
	
		let hten= date /10
		let hunit = date //10
		let mten = month /10
		let munit = month //10
		gosub look
	endif
	if porta pin1 = 0 then goto setdate
	pause 150
	
write_time:
	gosub bcd									'goto sub procedure
	i2cslave %11010000, i2cslow,i2cbyte					
	writei2c 0, (secs,mins,hour,days,date,month,year,$10)		'write data to clock
	pause 1000									'wait while data is writen
	
	reset
	
	
show:
	for loops = 0 to 50
	let pins = hten
	let pinsc = %10000000
	let pinsc = %00000000
	
	
	let pins = hunit
	let pinsc = %01000000
	let pinsc = %00000000
	
	if tempbyte < 40 then
	let pins = deci
	let pinsc = %01000000
	let pinsc = %00000000
	end if
	
	let pins = mten
	let pinsc = %00100000
	let pinsc = %00000000
	
	let pins = munit
	let pinsc = %00000100
	let pinsc = %00000000
	next loops
	loops = 0
	return
	
lookday:
	lookup days, (mon1,tue1,wed1,thu1,fri1,sat1,sun1), hten
	lookup days, (mon2,tue2,wed2,thu2,fri2,sat2,sun2), hunit
	lookup days, (mon3,tue3,wed3,thu3,fri3,sat3,sun3), mten
	lookup days, (mon4,tue4,wed4,thu4,fri4,sat4,sun4), munit
	return
 

oracacle

Senior Member
and the rest of it

Code:
getdata:
	let hten = hour/10
	let hunit = hour//10
	
	let mten = mins/10
	let munit = mins//10
look:	
	lookup hten, (zero, one, two, three, four, five, six, seven, eight, nine), hten
	lookup hunit, (zero, one, two, three, four, five, six, seven, eight, nine), hunit
	lookup mten, (zero, one, two, three, four, five, six, seven, eight, nine), mten
	lookup munit, (zero, one, two, three, four, five, six, seven, eight, nine), munit
	return
	

'incase of complete power faliure clock will reset to zeros
setclock:
	i2cslave %11010000, i2cslow,i2cbyte					'address i2c clock
	writei2c 0, ($00,$00,$00,$01,$01,$01,$12,$10)			'defult clock settings
	pause 100									'wait for write
	reset

'***Convert BCD to binary with given commend***	
bin:
	let secs = bcdtobin secs
	let mins = bcdtobin mins
	let hour = bcdtobin hour
	let days = bcdtobin days
	let date = bcdtobin date
	let month = bcdtobin month
	let year = bcdtobin year
	return

'***Convert binary to BCD with given command***

bcd:
	let secs = bintobcd secs
	let mins = bintobcd mins
	let hour = bintobcd hour
	let days = bintobcd days
	let date = bintobcd date
	let month = bintobcd month
	let year = bintobcd year
	return
it not fully noted and formated yet but seem to work well enough, any suggested changed welcome
 
Top