Driving 132 LEDs

hippy

Technical Support
Staff member
Thanks for posting that grid. It made it obvious where the discrepency is.

Normal charlieplexing with 6 contol lines, 6 * (6-1) = 30. Note the six # marked LED's ...

Code:
- X X # X X
X - X X # X
X X - X X #
# X X - X X
X # X X - X
X X # X X -
But, when we group them up into sets, those six hash marked LED's become unavailable, we only have 24 LED's ...

Code:
- X X   - X X
X - X   X - X
X X -   X X -

- X X   - X X
X - X   X - X
X X -   X X -
And we still need six control lines to control those ...

Code:
1 : ABC---
2 : A--BC-
3 : -A-B-C
4 : --A-BC
 

hippy

Technical Support
Staff member
Cracked the maths. We are used to thinking of LED capacity as N * (N-1) but in fact it's better to think of it as below, N = number of control lines -

For traditional charlieplexing : capacity = ( N * N ) - N

For triplet charlieplexing : capacity = ( N * N ) - ( N * 2 )

And that gives 182 and 168 respectively for our 14 control lines, and also verifies for the 30 and 24 example above with 6 control lines.

Control lines, single capacity, triplet capacity ..

Code:
 3 :   6   3
 4 :  12   8
 5 :  20  15
 6 :  30  24
 7 :  42  35
 8 :  56  48
 9 :  72  63
10 :  90  80
11 : 110  99
12 : 132 120
13 : 156 143
14 : 182 168
15 : 210 195
16 : 240 224
17 : 272 255
18 : 306 288
19 : 342 323
20 : 380 360
 

Buzby

Senior Member
Hi hippy,

Just goes to show, two heads are better than one !. I knew we'd get to the bottom of it eventually.

Bad news for oracacle, he can't do his clock with 30 identical groups as we thought.

Good news is he can now process big boards, so it won't really matter about the groups of 6.

Cheers,

Buzby
 

oracacle

Senior Member
So it looks like I will make up another board. Plus side I will reduce the exposure time for the new board.
Can't believe i missed those repeats
 

oracacle

Senior Member
So seeing as we can agree that all the LEDs are in pairs, I went back to that, here's would should be hopefully the final board.
I have some bits too add as that I can line it up on the PCB more easily (another lesson learned from the previous one). I have widened the gaps in between the bus track as well.
Just need to wait for the PCB to arrive. On the subject of PCB, has anyone tried that iron UV film that makes any copper clad board into photoresist. From what I can tell it come in large rolls and would make making large board a cheaper and easier to source the large board sizes. Maplin stock some larger board sizes but they are not photoresist.
 

Attachments

hippy

Technical Support
Staff member
Bad news for oracacle, he can't do his clock with 30 identical groups as we thought.
He can if he adds an extra control line, has 15 instead of 14 -

Code:
               11111
     012345678901234

 1 : ABC------------
 2 : A--BC----------
 3 : A----BC--------
 4 : A------BC------
 5 : A--------BC----
 6 : A----------BC--
 7 : A------------BC
 8 : -A-B-C---------
 9 : -A--B-C--------
10 : -A-----B-C-----
11 : -A------B-C----
12 : -A---------B-C-
13 : -A----------B-C
14 : --AB--C--------
15 : --A-BC---------
16 : --A----B--C----
17 : --A-----BC-----
18 : --A--------B--C
19 : --A---------BC-
20 : ---A---B---C---
21 : ---A----B---C--
22 : ---A-----B---C-
23 : ---A------B---C
24 : ----A--B----C--
25 : ----A---B--C---
26 : ----A----B----C
27 : ----A-----B--C-
28 : -----A-B-----C-
29 : -----A--B-----C
30 : -----A---B-C---
31 : -----A----B-C--
32 : ------AB------C
33 : ------A-B----C-
34 : ------A--B--C--
35 : ------A---BC---
 

oracacle

Senior Member
Its been a couple of weeks, and there has been progress. It been a bit tight on time to fit everything in but alas,


and the code
Code:
#no_data
#no_table
setfreq em64

'symbol					= w0
	'symbol				= b0
		symbol high_flag		= bit0
		symbol half_flag		= bit1
		symbol third_flag		= bit2
symbol led_word				= w1
	symbol high_pin			= b2
	symbol low_pin			= b3
'symbol					= w2
	symbol loop_number		= b4
	symbol LED				= b5
'symbol					= w3
	symbol temp_led			= b6
	symbol sec				= b7
	symbol mins				= b8
	symbol hour				= b9
	symbol pause_time			= b10
	symbol hour_2			= b11

symbol com			= 44
symbol col			= 58
symbol ret			= 13
symbol lfeed		= 10

init:
	let ptr = 0
	for led = 0 to 179
		lookup LED, (770,515,1541,1286,2312,2057,3597,3342,1026,516,25  68,2058,1283,773,3337,2317,1539,774,1025,260,3850,  2575,3336,2061,3592,2062,3849,2319,1795,775,1280,5  ,3334,1549,2051,776,1793,263,2049,264,2307,777,333  3,1293,2305,265,2561,266,2562,522,3330,525,3588,10  38,3587,782,3844,1039,3845,1295,513,258,1284,1029,  2055,1800,3338,2573,512,2,2054,1544,769,259,2311,1  801,768,3,3593,2318,2567,1802,2053,1288,2052,1032,  2309,1289,2566,1546,2308,1033,1537,262,3591,1806,3  590,1550,1792,7,2306,521,2564,1034,2048,8,2560,10,  3329,269,270,3585,3331,781,3842,527,3843,783,3846,  1551,256,1,1027,772,1798,1543,2569,2314,3854,3599,  1540,1030,3594,2574,1797,1287,3853,3343,2310,1545,  1796,1031,1282,517,1024,4,1281,261,1538,518,3335,1  805,2565,1290,1794,519,1536,6,3847,1807,2050,520,2  563,778,3332,1037,2304,9,3328,13,3584,14,3586,526,  3841,271,2063,3848,3589,1294),led_word
		@ptrinc = high_pin
		@ptrinc = low_pin
	next led
	led = 179
	pause_time = 100
	
main:
	for loop_number = 0 to led
		ptr = loop_number	
		gosub display_address
	next loop_number
	goto main
		
		
display_address:				'display hour with dimmed LEDs either side
	ptr = ptr *2			'correct pointer address for display
	high_pin = @ptrinc
	low_pin = @ptr	
display:						'show LED
	low low_pin
	high high_pin
	pause pause_time
	input low_pin
	input high_pin
	'pause_time = 10
	return
I managed to duplicate one pair of LEDs, and some how use the pair that I was planning on leaving out, but not to worry everything is in working order now.
I have the DS3231 to learn how to use and incorporate into the project, hopefully more progress can be made in the next few days
 
Last edited:

oracacle

Senior Member
Thanks, made a start on getting it to display the time. I have seconds and minutes. Next I have to figure out how to calculate the required address for each hour on the fly, but that a problem for tomorrow.
 

Buzby

Senior Member
Here is one way to structure the code for your clock.

If you want to try it on your matrix you will need to tweak the min/max values, and select the correct lookup gosub.

There is more code to write regarding calculating the dim LEDs at the beginning and end of the range, but that can be added later.

This video doesn't show the difference between dim and bright very well. I found dim/bright works best with bigger LEDs, not these tiny SMD devices.

https://youtu.be/__x5qHPLS_4

Code:
#picaxe 28x2
#no_data
#no_table
'#terminal 76800

symbol LED_pins		= w1
symbol high_Pin		= b2
symbol low_pin		= b3
symbol ticked		= b4	' value toggles on each clock tick

symbol LEDdelay		= b6	' Brightness control
symbol LED_Sec		= b7	' Seconds LED
symbol LED_Min		= b8	' Minutes LED
symbol LED_Hour		= b9	' Hours LED
symbol LED_Hd1		= b10	' Dim LED 1 
symbol LED_Hd2		= b11	' Dim LED 2
symbol LED_Hd3		= b12	' Dim LED 3
symbol LED_Hd4		= b13	' Dim LED 4

symbol TimeDiv		= b14 ' only used in demo to simulate RTC
symbol oldtime		= b15 ' only used in demo to simulate RTC
symbol newtime		= b16 ' only used in demo to simulate RTC

' Constants
' ---------

'( Define the min and max values to match the LED arrangement )
#define Hourminval	54
#define Hourmaxval	62
#define Minuteminval	63
#define Minutemaxval	71
#define Secondminval	72
#define Secondmaxval	80

'( Define the brightness levels )
#define LEDdelayDim	1
#define LEDdelayBright	100


#define TimeDivRate	1	' only used in demo to simulate RTC


' Define macros
' -------------
#Macro macShowLed(var)
b0 = var	' see http://www.picaxeforum.co.uk/showthread.php?29354 
if b0 <> 255 then ' if LED = 255 then don't light it
  ptr = b0 << 1
  Low   @ptrInc
  High  @ptr
  PauseUS LEDdelay
  dirsB = 0
  dirsC = 0
 endif
#EndMacro

' ---------------------------------------------------------------------------
' Code starts here
' ---------------------------------------------------------------------------
setfreq em64
pause 8000

sertxd(cr,lf,ppp_filename," ",PPP_DateTime,cr,lf)

tmr3setup %00110011 ' tmr3 only used in demo to simulate RTC

' copy lookup data to ram
' -----------------------
'  gosub lookup_oracacle
 gosub lookup_buzby

' Preset intial LED positions 
LED_Hour = Hourminval + 3
LED_Min  = Minuteminval + 3
LED_Sec  = Secondminval + 3
LED_hd1  = LED_hour - 2  
LED_hd2  = LED_hour - 1 
LED_hd3  = LED_hour + 1
LED_hd4  = LED_hour + 2

timediv = TimeDivRate ' only used in demo to simulate RTC

' Main loop
' ---------
do
	' Light the bright LEDs
	LEDdelay = LEDdelayBright
	
	' Flash hour LED at tick rate
 	if ticked = 1 then
		macShowLED(LED_Hour) 
 	endif	 
 	macShowLED(LED_Min)  
 	macShowLED(LED_Sec) 

	' Light the dim LEDs
 	LEDdelay = LEDdelayDim
	
   	macShowLED(LED_Hd1)   
   	macShowLED(LED_hd2)  
   	macShowLED(LED_Hd3) 		
   	macShowLED(LED_Hd4) 	
	
	' Detect time change
	newtime = timer3
	if newtime <> oldtime then
		oldtime = newtime
		dec timediv
		if timediv = 0 then
			timediv = timedivrate ' Reset time divider
			gosub clockticked ' Go do stuff 
		endif
	endif
		
loop ' End of main loop


' *****************************************************************************
' Subroutines
' *****************************************************************************
clockticked:
	ticked = ticked xor 1 ' Toggle activity flag

	inc LED_Sec 
	if LED_Sec > Secondmaxval then
		LED_Sec = Secondminval
	 	inc LED_Min
	 	if LED_Min > Minutemaxval then
	 		LED_Min = Minuteminval
	 		inc LED_Hour
	 		if LED_Hour > Hourmaxval then
	 			LED_Hour = Hourminval
			endif
		
			' Calculate positions of dim LEDs
			LED_hd1 = LED_Hour - 2
			if LED_hd1 < Hourminval then
				LED_hd1 = 255
			endif	
			LED_hd2 = LED_Hour - 1
			if LED_hd2 < Hourminval then
				LED_hd2 = 255
			endif		
			LED_hd3 = LED_Hour + 1
			if LED_hd3 > Hourmaxval then
				LED_hd3 = 255
			endif	
			LED_hd4 = LED_Hour + 2
			if LED_hd4 > Hourmaxval then
				LED_hd4 = 255
			endif		
		
	 	endif
	endif
return	

lookup_oracacle: 'lookup LED pins( Used once to populate scratch ram. )
let ptr = 0
for b0 = 0 to 179
	lookup b0, (770,515,1541,1286,2312,2057,3597,3342,1026,516,2568,2058,1283,_
			773,3337,2317,1539,774,1025,260,3850,2575,3336,2061,3592,2062,_
			3849,2319,1795,775,1280,5,3334,1549,2051,776,1793,263,2049,_
			264,2307,777,3333,1293,2305,265,2561,266,2562,522,3330,525,_
			3588,1038,3587,782,3844,1039,3845,1295,513,258,1284,1029,_
			2055,1800,3338,2573,512,2,2054,1544,769,259,2311,1801,768,_
			3,3593,2318,2567,1802,2053,1288,2052,1032,2309,1289,2566,_
			1546,2308,1033,1537,262,3591,1806,3590,1550,1792,7,2306,_
			521,2564,1034,2048,8,2560,10,3329,269,270,3585,3331,_
			781,3842,527,3843,783,3846,1551,256,1,1027,772,1798,_
			1543,2569,2314,3854,3599,1540,1030,3594,2574,1797,1287,3853,_
			3343,2310,1545,1796,1031,1282,517,1024,4,1281,261,1538,_
			518,3335,1805,2565,1290,1794,519,1536,6,3847,1807,2050,_
			520,2563,778,3332,1037,2304,9,3328,13,3584,14,3586,_
			526,3841,271,2063,3848,3589,1294),LED_pins
	@ptrinc = high_pin
	@ptrinc = low_pin
next b0
return

lookup_buzby:  'lookup LED pins( Used once to populate scratch ram. )
let ptr = 0
for b0 = 0 to 125
	lookup b0,  ($205, $206, $207, $208, $209, $20A, $20D, $20C, $20B,_
			 $502, $602, $702, $802, $902, $A02, $D02, $C02, $B02,_
			 $005, $006, $007, $008, $009, $00A, $00D, $00C, $00B,_
			 $500, $600, $700, $800, $900, $A00, $D00, $C00, $B00,_
			 $105, $106, $107, $108, $109, $10A, $10D, $10C, $10B,_
			 $501, $601, $701, $801, $901, $A01, $D01, $C01, $B01,_
			 $50B, $60B, $70B, $80B, $90B, $A0B, $D0B, $C0B, $B0C,_
			 $50C, $60C, $70C, $80C, $90C, $A0C, $D0C, $C0D, $B0D,_
			 $50D, $60D, $70D, $80D, $90D, $A0D, $D0A, $C0A, $B0A,_
			 $50A, $60A, $70A, $80A, $90A, $A09, $D09, $C09, $B09,_
			 $509, $609, $709, $809, $908, $A08, $D08, $C08, $B08,_
			 $508, $608, $708, $807, $907, $A07, $D07, $C07, $B07,_
			 $507, $607, $706, $806, $906, $A06, $D06, $C06, $B06,_
			 $506, $605, $705, $805, $905, $A05, $D05, $C05, $B05 _
			 ),LED_pins
	@ptrinc = high_pin
	@ptrinc = low_pin
next b0			 
return
 

oracacle

Senior Member
while that's an impressive bit of code, it rather other complicated, possible caused by using timer 3
second led = seconds
mins led = mins + 60

the RTC produces the addresses needed for those 2 at least

here is what I have, it a modified version of the code that marks produced
Code:
main:     
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231

	if sec <> temp_sec then
		'setfreq m8
			AM_PM = "A" : IF hour >$60 THEN : AM_PM ="P": ENDIF  ' 12 hour format   PM 
		D5 = hour  &$10 /$10 +$30 : IF D5 = "0" THEN : D5 = " " : ENDIF 'Zero blanking
		D4 = hour //$10
		D3 = mins   /$10
		D2 = mins  //$10
		D1 = sec   /$10
		D0 = sec  //$10
	   	dis_sec = d1 *10 + d0
		dis_mins = d3 * 10 + d2 + 60
		'sertxd (cr,lf,D5,#D4,".",#D3,#D2,".",#D1,#D0," ",AM_PM,"M  ") 
		D5 = date   /$10
		D4 = date  //$10
		D3 = month  /$10
		D2 = month //$10
		D1 = year   /$10
		D0 = year  //$10
	      '(11.59.00 PM )
		
		'sertxd (#D5,#D4,"/",#D3,#D2,"/20",#D1,#D0)        '(11/01/2015)
		setfreq em64
		let temp_sec = sec
		end if
	for loop_number = 0 to 50
		let ptr = dis_sec
		gosub display_address
		let ptr = dis_mins
		gosub display_address
	next loop_number	
	goto main
 

oracacle

Senior Member
this shows the LED on the hour correctly

Code:
[color=Purple]D4 [/color][color=DarkCyan]= [/color][color=Purple]hour [/color][color=DarkCyan]//[/color][color=Navy]$10
            [/color][color=Purple]D3 [/color][color=DarkCyan]= [/color][color=Purple]mins   [/color][color=DarkCyan]/[/color][color=Navy]$10
            [/color][color=Purple]D2 [/color][color=DarkCyan]= [/color][color=Purple]mins  [/color][color=DarkCyan]//[/color][color=Navy]$10
            [/color][color=Purple]D1 [/color][color=DarkCyan]= [/color][color=Purple]sec   [/color][color=DarkCyan]/[/color][color=Navy]$10
            [/color][color=Purple]D0 [/color][color=DarkCyan]= [/color][color=Purple]sec  [/color][color=DarkCyan]//[/color][color=Navy]$10
            [/color][color=Purple]dis_sec [/color][color=DarkCyan]= [/color][color=Purple]d1 [/color][color=DarkCyan]*[/color][color=Navy]10 [/color][color=DarkCyan]+ [/color][color=Purple]d0
            dis_mins [/color][color=DarkCyan]= [/color][color=Purple]d3 [/color][color=DarkCyan]* [/color][color=Navy]10 [/color][color=DarkCyan]+ [/color][color=Purple]d2 [/color][color=DarkCyan]+ [/color][color=Navy]60
            [/color][color=Purple]dis_hour [/color][color=DarkCyan]= [/color][color=Purple]d4
            [/color][color=Blue]if [/color][color=Purple]dis_hour [/color][color=DarkCyan]= [/color][color=Navy]12 [/color][color=Blue]then
                  [/color][color=Purple]dis_hour [/color][color=DarkCyan]= [/color][color=Navy]0
            [/color][color=Blue]end if
            [/color][color=Purple]dis_hour [/color][color=DarkCyan]= [/color][color=Purple]dis_hour [/color][color=DarkCyan]*[/color][color=Navy]5[/color][color=DarkCyan]+[/color][color=Navy]120[/color]
this means that the correct hour can be displayed at startup.
 

oracacle

Senior Member
a quick question about hex - I am not good with it, makes my head hurt a little

is this correct assuming b0 hold a hexadecimal character

Code:
      [color=Green]'convert from hex
      [/color][color=Blue]let [/color][color=Purple]b1 [/color][color=DarkCyan]= [/color][color=Purple]b0 [/color][color=DarkCyan]/ [/color][color=Navy]16 [/color][color=DarkCyan]*[/color][color=Navy]10
      [/color][color=Blue]let [/color][color=Purple]b2 [/color][color=DarkCyan]= [/color][color=Purple]b0 [/color][color=DarkCyan]// [/color][color=Navy]16 [/color][color=DarkCyan]+ [/color][color=Purple]b1        [/color][color=Green]'b2 no hold decimal
      
      'convert back to hex
      [/color][color=Blue]let [/color][color=Purple]b3 [/color][color=DarkCyan]= [/color][color=Purple]b2 [/color][color=DarkCyan]/ [/color][color=Navy]10 [/color][color=DarkCyan]*[/color][color=Navy]16
      [/color][color=Blue]let [/color][color=Purple]b4 [/color][color=DarkCyan]= [/color][color=Purple]b2 [/color][color=DarkCyan]// [/color][color=Navy]10 [/color][color=DarkCyan]+ [/color][color=Purple]b3        [/color][color=Green]'b4 now hold hexidecimal[/color]
 

Buzby

Senior Member
while that's an impressive bit of code, it rather other complicated, possible caused by using timer 3
Hi oracacle,

The code was written to test the display method, and to experiment with what the dim LEDs would look like. I agree it's a bit complicated due to using timer3 in the way I did. The timer is used to simulate 1s pulses, then the code in 'clockticked' subroutine counts those pulses to determine LED positions.

With hindsight I should have used the timer to generate three HMS numbers, which would replicate what you would get from the RTC.
To do that it's only the code in the 'Detect time change' region and the 'clockticked' subroutine that need replacing.

Anyway, it was fun to do, and you are making good progress as it is.

Looking forward to seeing the final result.

Cheers,

Buzby
 

oracacle

Senior Member
Thanks Hippy, I will incorporate that into my code later.
In other news I found that just reducing the display time does not make that much difference to the brightness of the LEDs. So queue what is quite complex code for making the inner 2 LEDs show every after 2 passes of the loop pass and the outer 2 every 5th pass, and only on the 5 pass

its still got some major work to be done to it so that I am happy. I also think that if I can get this to work in a subroutine (maybe even I cant) it would be cool to have an option to do the same to the minutes and seconds too
Code:
if dimmed_led => 2 then
			'do inner LEDs
			let temp_byte_0 = led + inner_led
			let temp_byte_1 = led - inner_led
			if temp_byte_0 > 179 then     		'check for leading LED overflow
				temp_byte_0 = temp_byte_0 - 60
			end if
			if temp_byte_1 < 120 then     		'check for trailing LED underflow
				temp_byte_1 = led + 59
			end if
			let pause_time = 10
			let led = temp_byte_0
			gosub display_address
			let led = temp_byte_1
			gosub display_address
				led = dis_hour
			if dimmed_led = 5 then
				let temp_byte_0 = led + outter_led
				let temp_byte_1 = led - outter_led
				if temp_byte_0 > 179 then			'check for leading LED overflow
					temp_byte_0 = temp_byte_0 - 60
				end if
				if temp_byte_1 < 120 then			'check for trailing LED underflow
					temp_byte_1 = led + 58
				end if
				let pause_time = 2
				let led = temp_byte_0
				gosub display_address
				let led = temp_byte_1
				gosub display_address
			end if
			inc dimmed_led
			if dimmed_led = 6 then
				dimmed_led = 0
			end if
		else
			inc dimmed_led
		end if
			let pause_time = normal_led
its getting there, I should be showing current progress to the prospective owner of this tomorrow.
I am having a small op on Thursday resulting in no work and no lifting so I should be able to plough some serious time into this. tune the code up and finalise the control circuit for designing and making the PCB - the quandary at the moment is how many buttons and switches to use for user input, 3 buttons should be enough but wondering if having the facility for 4 on the board maybe handy down the line
 

Attachments

oracacle

Senior Member
so heres some more.

not happy with things as they stand

main code body
Code:
main:     
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231

	if sec <> temp_sec then
		AM_PM = "A" : IF hour >$60 THEN : AM_PM ="P" : AM_PM_flag = 1 : ENDIF  ' 12 hour format   PM 
		temp_byte_0 = sec // $10
		dis_sec = sec / $10 * 10 + temp_byte_0
		temp_byte_0 = mins // $10
		dis_mins = mins / $10 * 10 + temp_byte_0 + 60
		
		if dis_mins = 60 then				'check for zero minute
			gosub hour_address
			let store_hour_led = dis_mins + 12
		end if
		'setfreq m8
		'sertxd (cr,lf,#dis_mins,44,#store_hour_led)
		'setfreq em64
		if dis_mins = store_hour_led then 'and bit4 = 0 then
			inc dis_hour
			store_hour_led = store_hour_led + 12
		end if
		
#rem
		setfreq m8
		'sertxd (cr,lf,#dis_hour,":",#dis_mins,":",#dis_sec," ",AM_PM,"M  ")
		D5 = hour  &$10 /$10
		D4 = hour //$10
		D3 = mins   /$10
		D2 = mins  //$10
		D1 = sec   /$10
		D0 = sec  //$10
	      sertxd (cr,lf,#d5,#D4,".",#D3,#D2,".",#D1,#D0," ",AM_PM,"M  ",44,#am_pm_flag)
		D5 = date   /$10
		D4 = date  //$10
		D3 = month  /$10
		D2 = month //$10
		D1 = year   /$10
		D0 = year  //$10
	      '(11.59.00 PM )
		
		'sertxd (#D5,#D4,"/",#D3,#D2,"/20",#D1,#D0)        '(11/01/2015)
		'setfreq em64
#endrem	
		let temp_sec = sec
		end if
	
	for loop_number = 0 to 25
		let led = dis_sec
		gosub display_address
		min_led_val = 0
		max_led_val = 59
		dimmed_led = b29
		'gosub faded_leds
		b29 = dimmed_led
		
		let led = dis_mins
		gosub display_address
		min_led_val = 60
		max_led_val = 119
		dimmed_led = b30
		'gosub faded_leds
		b30 = dimmed_led
		
		let led = dis_hour
		gosub display_address
		min_led_val	= 120
		max_led_val = 179
		dimmed_led = b31
		gosub faded_leds
		b31 = dimmed_led
			
		if am_pm_flag = 1 then
			low_pin = 15
			high_pin = 0
			gosub display
		end if
	next loop_number	
	goto main
		
		
display_address:				'display hour with dimmed LEDs either side
	ptr = led <<1			'correct pointer address for display
	high_pin = @ptrinc
	low_pin = @ptr	
display:						'show LED
	low low_pin
	high high_pin
	pauseus pause_time
	dirsb = 0
	dirsc = 0
	'input low_pin
	'input high_pin
	return
hour_address:
	temp_byte_0 = hour & $10 / $10 *10
	dis_hour = hour // $10 + temp_byte_0
	if dis_hour = 12 then
		dis_hour = 0
	end if
	dis_hour = dis_hour *5+120
	return
	
faded_leds:
	if dimmed_led => 2 then
		LED_hold = LED
		'do inner LEDs
		let temp_byte_0 = led + inner_led
		let temp_byte_1 = led - inner_led
		if temp_byte_0 > max_led_val then     		'check for leading LED overflow
			temp_byte_0 = temp_byte_0 - 60
		end if
		if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
			temp_byte_1 = led + 59
		end if
		if temp_byte_1 < min_led_val then     		'check for trailing LED underflow
			temp_byte_1 = led + 59
		end if
		let pause_time = 0
		let led = temp_byte_0
		gosub display_address
		let led = temp_byte_1
		gosub display_address
			led = LED_hold
		if dimmed_led = 3 then
			let temp_byte_0 = led + outter_led
			let temp_byte_1 = led - outter_led
			if temp_byte_0 > max_led_val then			'check for leading LED overflow
				temp_byte_0 = temp_byte_0 - 60
			end if
			if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
			temp_byte_1 = led + 58
			end if
			if temp_byte_1 < min_led_val then			'check for trailing LED underflow
				temp_byte_1 = led + 58
			end if
			let pause_time = 0
			let led = temp_byte_0
			gosub display_address
			let led = temp_byte_1
			gosub display_address
		end if
		inc dimmed_led
		if dimmed_led = 5 then
			dimmed_led = 0
		end if
	else
		inc dimmed_led
	end if
	let pause_time = normal_led
	return

so I managed to get the faded LEDs sequence into a sub procedure, I am not sure if its just the number of LEDs or and issue with the way I have thing being done at the moment. Having just one set of 5 LEDs is fine, 2 sets introduces a little flickering and 3 sets is quite noticeable.

I am going to look for way of streamlining things, and put some annotation on what I have now. I have tried repeating the faded_leds routine in 3 separate times for each of SMH to no difference which would infer its no the calling of the sub-procedure that's the issue. This is more of a how far can I push this, and hopefully have this as an optional display.

Other than this I only have the interface to adjust time to work on
 

Buzby

Senior Member
15 LEDs is not too many to Charlieplex when running at 64Mhz.

Please post your full code and we'll have a look.

Cheers,

Buzby
 

oracacle

Senior Member
fading call on seconds and minutes is commented out
Code:
#no_data
#no_table
setfreq em64

'symbol					= w0
	'symbol				= b0
		symbol AM_PM_flag		= bit0
symbol led_word				= w2
	symbol high_pin			= b4
	symbol low_pin			= b5
'symbol					= w3
	symbol loop_number		= b6
	symbol LED				= b7
'symbol					= w4
	symbol temp_led			= b8
	symbol sec				= b9

	symbol mins				= b10
	symbol hour				= b11

	symbol pause_time			= b12
	symbol LED_hold			= b13

	symbol day				= b14
	symbol date          		= b15

	symbol month         		= b16
	symbol year          		= b17

	symbol AM_PM         		= b18
	symbol temp_sec			= b19

	symbol dis_sec			= b20
	symbol dis_mins			= b21

	symbol dis_hour			= b22
	symbol store_hour_led		= b23
symbol temp_word_0			= w12
	symbol temp_byte_0		= b24
	symbol temp_byte_1		= b25
	
	symbol dimmed_LED			= b26
	symbol min_led_val		= b27
	
	symbol max_led_val		= b28
	
	symbol D0            		= b50
	symbol D1            		= b51
	symbol D2            		= b52
	symbol D3            		= b53
	symbol D4           		= b54
	symbol D5            		= b55

symbol com			= 44
symbol col			= 58
symbol ret			= 13
symbol lfeed		= 10
symbol outter_led		= 2
symbol inner_led		= 1
symbol dim_led		= 60
symbol dimmer_led		= 25
symbol normal_led		= 50

init:
	let ptr = 0
	for led = 0 to 179
		lookup LED, (770,515,1541,1286,2312,2057,3597,3342,1026,516,2568,2058,1283,773,3337,2317,1539,774,1025,260,3850,2575,3336,2061,3592,2062,3849,2319,1795,775,1280,5,3334,1549,2051,776,1793,263,2049,264,2307,777,3333,1293,2305,265,2561,266,2562,522,3330,525,3588,1038,3587,782,3844,1039,3845,1295,513,258,1284,1029,2055,1800,3338,2573,512,2,2054,1544,769,259,2311,1801,768,3,3593,2318,2567,1802,2053,1288,2052,1032,2309,1289,2566,1546,2308,1033,1537,262,3591,1806,3590,1550,1792,7,2306,521,2564,1034,2048,8,2560,10,3329,269,270,3585,3331,781,3842,527,3843,783,3846,1551,256,1,1027,772,1798,1543,2569,2314,3854,3599,1540,1030,3594,2574,1797,1287,3853,3343,2310,1545,1796,1031,1282,517,1024,4,1281,261,1538,518,3335,1805,2565,1290,1794,519,1536,6,3847,1807,2050,520,2563,778,3332,1037,2304,9,3328,13,3584,14,3586,526,3841,271,2063,3848,3589,1294),led_word
		@ptrinc = high_pin
		@ptrinc = low_pin
	next led
	HI2Csetup I2Cmaster, %11010000, I2Cfast_64, I2Cbyte       ' Set to 100kbps
	if pina.0 = 1 then
		
		'bin = bcd / 16 * $FA + bcd
		'bcd = bin / 10 * 6 + bin
		'if pm hour = hour + 40, if am hour = hour + 60 before converting to bcd
		'testing in PM so set for 60 got time being
		temp_byte_0 = 12 + 40		'hour + pm setting
		hour = temp_byte_0 / 10 * 6 + temp_byte_0 
		temp_byte_0 = 1
		mins = temp_byte_0 / 10 * 6 + temp_byte_0
		sec = $00
		
		HI2Cout $0 , ( sec, mins, hour ,day, $21, $11 , $16)
	end if
	
	pause_time = normal_led
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231
	gosub hour_address
	if mins > 0 then						'check and find part hout at startup
		'temp_byte_0 = mins / 12
		'dis_hour = dis_hour + temp_byte_0
		'store_hour_led = dis_hour
		'#rem
		temp_byte_0 = mins // $10
		dis_mins = mins / $10 * 10 + temp_byte_0
		temp_byte_0 = 0
		do
			temp_byte_0 = temp_byte_0 + 12
			if temp_byte_0 > dis_mins then
				store_hour_led = temp_byte_0 +60
				exit
			else
				inc dis_hour
				
			end if
		loop	
		'#endrem
	end if
main:     
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231

	if sec <> temp_sec then
		am_pm_flag = 0 : if hour > $60 then : am_pm_flag = 1
		
		'bin = bcd / 16 * $FA + bcd
		'bcd = bin / 10 * 6 + bin
		
		dis_sec = sec / 16 * $FA + sec		'convert BCD to decimal for LED address
		dis_sec = mins / 16 * $FA + mins + 60
		'temp_byte_0 = sec // $10
		'dis_sec = sec / $10 * 10 + temp_byte_0
		'temp_byte_0 = mins // $10
		'dis_mins = mins / $10 * 10 + temp_byte_0 + 60
		
		if dis_mins = 60 then				'check for zero minute - 0+60=60 so make sure hour LED is correct
			gosub hour_address
			let store_hour_led = dis_mins + 12
		end if
		if dis_mins = store_hour_led then		'check to see if 12 minutes has elapsed
			inc dis_hour
			store_hour_led = store_hour_led + 12
		end if
		
#rem
		setfreq m8						'send deubging info
		AM_PM = "A" : IF hour >$60 THEN : AM_PM ="P" : ENDIF  ' 12 hour format   PM 
		'sertxd (cr,lf,#dis_hour,":",#dis_mins,":",#dis_sec," ",AM_PM,"M  ")
		D5 = hour  &$10 /$10
		D4 = hour //$10
		D3 = mins   /$10
		D2 = mins  //$10
		D1 = sec   /$10
		D0 = sec  //$10
	      sertxd (cr,lf,#d5,#D4,".",#D3,#D2,".",#D1,#D0," ",AM_PM,"M  ",44,#am_pm_flag)
		D5 = date   /$10
		D4 = date  //$10
		D3 = month  /$10
		D2 = month //$10
		D1 = year   /$10
		D0 = year  //$10
	      '(11.59.00 PM )
		
		'sertxd (#D5,#D4,"/",#D3,#D2,"/20",#D1,#D0)
		'setfreq em64
#endrem	
		let temp_sec = sec
		end if
	
	for loop_number = 0 to 25					'loop 25 times before checking time again
		let led = dis_sec						'led address = seconds
		gosub display_address
		min_led_val = 0						'set min value for faded LEDs - this will be an error due to 0 - n overflow variable
		max_led_val = 59						'set max value for faded LEDs
		dimmed_led = b29						'get stored loop value of faded LEDs
		'gosub faded_leds
		b29 = dimmed_led						'store faded LED loop value
		'each part of the display needs to maintain it own loop count of the fadded LEDs
		
		let led = dis_mins
		gosub display_address
		min_led_val = 60
		max_led_val = 119
		dimmed_led = b30
		'gosub faded_leds
		b30 = dimmed_led
		
		let led = dis_hour
		gosub display_address
		min_led_val	= 120
		max_led_val = 179
		dimmed_led = b31
		gosub faded_leds
		b31 = dimmed_led
			
		if am_pm_flag = 1 then					'check AM PM flag and set LED if PM
			low_pin = 15
			high_pin = 0
			gosub display
		end if
	next loop_number	
	goto main
		
		
display_address:				'display hour with dimmed LEDs either side
	ptr = led <<1			'correct pointer address for display
	high_pin = @ptrinc
	low_pin = @ptr	
display:						'show LED
	low low_pin
	high high_pin
	pauseus pause_time
	dirsb = 0
	dirsc = 0
	'input low_pin
	'input high_pin
	return
hour_address:
	temp_byte_0 = hour & $10 / $10 *10
	dis_hour = hour // $10 + temp_byte_0
	if dis_hour = 12 then
		dis_hour = 0
	end if
	dis_hour = dis_hour *5+120
	return
	
faded_leds:
	if dimmed_led => 2 then
		LED_hold = LED
		'do inner LEDs
		let temp_byte_0 = led + inner_led
		let temp_byte_1 = led - inner_led
		if temp_byte_0 > max_led_val then     		'check for leading LED overflow
			temp_byte_0 = temp_byte_0 - 60
		end if
		if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
			temp_byte_1 = led + 59
		end if
		if temp_byte_1 < min_led_val then     		'check for trailing LED underflow
			temp_byte_1 = led + 59
		end if
		let pause_time = 0
		let led = temp_byte_0
		gosub display_address
		let led = temp_byte_1
		gosub display_address
			led = LED_hold
		'do outter LEDs
		if dimmed_led = 3 then
			let temp_byte_0 = led + outter_led
			let temp_byte_1 = led - outter_led
			if temp_byte_0 > max_led_val then			'check for leading LED overflow
				temp_byte_0 = temp_byte_0 - 60
			end if
			if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
			temp_byte_1 = led + 58
			end if
			if temp_byte_1 < min_led_val then			'check for trailing LED underflow
				temp_byte_1 = led + 58
			end if
			let pause_time = 0
			let led = temp_byte_0
			gosub display_address
			let led = temp_byte_1
			gosub display_address
		end if
		inc dimmed_led
		if dimmed_led = 4 then
			dimmed_led = 0
		end if
	else
		inc dimmed_led
	end if
	let pause_time = normal_led
	return
 

oracacle

Senior Member
I don't know if it completely solved but, I don't get any flickering if I set a 20us show time for the inner 2 LEDs, 0 for the outer 2, and adjust the number of times each is displayed to >=1 and 2 respectively.
 

Buzby

Senior Member
I would suggest you re-structure your code so that the LEDs are lit during all the time the RTC has not changed, and only calculate changes when necessary.

Something like this ...

Code:
init:
' Do initialisation
.
.
' Main loop
do
	Set brightness high
	Display LED hours
	Display LED minutes
	etc
	.
	.
	Set brightness low
	Display dim LED 1
	Display dim LED 2
	etc
	.
	.
	Read RTC
	if RTC seconds changed
		gosub Calc_new_LED_positions
	endif
	
loop ' End of main loop

' Subroutine
Calc_new_LED_positions:
	Make new seconds LED
	Make new dim LEDs for seconds
	if minutes changed then
		Make new minutes LED
		Make new dim LEDs for minutes
			if hours changed then 
				Make new hours LED
				Make new dim LEDs for hours
			endif
       endif
return
I just coded a demo based on this structure, and its displaying 3 bright and 12 dim with no flicker at all, absolutely rock steady.

Edit : If you make the code to display a LED into a macro, like 'macShowLed(var)' in my previous programme, the code will be easier to read, and it runs a little bit faster as well !.
 
Last edited:

oracacle

Senior Member
seems we had similar ideas

this actually has 16 LEDs as there is one off shot to indicate PM
moving to macros for the fade display is next on the list, however I am reasonably happy with the results of this, currently sat at 1071 byte so the macro would be the first thing to go if I were to run out of space
Think its a little heavy on variables, but that should allow for faster display. Each of the SMH have 5 variables that store the values for the 5 LEDs, the centre LED is first in the list with its associates in following variables which meant the @bptrinc can be used removing the need for handling variables with things like the let command. the byte pointer (and pointer for that matter) is a handy tool.

Code:
no_data
#no_table
setfreq em64

'symbol					= w0
	'symbol				= b0
		symbol AM_PM_flag		= bit0
symbol led_word				= w2
	symbol high_pin			= b4
	symbol low_pin			= b5
'symbol					= w3
	symbol loop_number		= b6
	symbol LED				= b7
'symbol					= w4
	symbol temp_led			= b8
	symbol sec				= b9

	symbol mins				= b10
	symbol hour				= b11

	symbol pause_time			= b12
	symbol LED_hold			= b13

	symbol day				= b14
	symbol date          		= b15

	symbol month         		= b16
	symbol year          		= b17

	symbol AM_PM         		= b18
	symbol store_sec			= b19

	symbol store_mins			= b20
	symbol store_hour			= b21

	'symbol dis_hour			= b22
	symbol store_hour_led		= b23
symbol temp_word_0			= w12
	symbol temp_byte_0		= b24
	symbol temp_byte_1		= b25
	
	symbol dimmed_LED			= b26
	symbol min_led_val		= b27
	
	symbol max_led_val		= b28
	symbol sec_loop_store		= b29
	
	symbol min_loop_store		= b30
	symbol hour_loop_store		= b31
	
	symbol dis_sec			= b32
	symbol sec_fade_1			= b33
	symbol sec_fade_2			= b34
	symbol sec_fade_3			= b35
	symbol sec_fade_4			= b36
	
	symbol dis_mins			= b37
	symbol mins_fade_1		= b38
	symbol mins_fade_2		= b39
	symbol mins_fade_3		= b40
	symbol mins_fade_4		= b41

	symbol dis_hour			= b42
	symbol hour_fade_1		= b43
	symbol hour_fade_2		= b44
	symbol hour_fade_3		= b45
	symbol hour_fade_4		= b46 

symbol com			= 44
symbol col			= 58
symbol ret			= 13
symbol lfeed		= 10
symbol outter_led		= 2
symbol inner_led		= 1
symbol dim_led		= 60
symbol dimmer_led		= 25
symbol normal_led		= 100

init:
	let ptr = 0
	for led = 0 to 179
		lookup LED, (770,515,1541,1286,2312,2057,3597,3342,1026,516,25  68,2058,1283,773,3337,2317,1539,774,1025,260,3850,  2575,3336,2061,3592,2062,3849,2319,1795,775,1280,5  ,3334,1549,2051,776,1793,263,2049,264,2307,777,333  3,1293,2305,265,2561,266,2562,522,3330,525,3588,10  38,3587,782,3844,1039,3845,1295,513,258,1284,1029,  2055,1800,3338,2573,512,2,2054,1544,769,259,2311,1  801,768,3,3593,2318,2567,1802,2053,1288,2052,1032,  2309,1289,2566,1546,2308,1033,1537,262,3591,1806,3  590,1550,1792,7,2306,521,2564,1034,2048,8,2560,10,  3329,269,270,3585,3331,781,3842,527,3843,783,3846,  1551,256,1,1027,772,1798,1543,2569,2314,3854,3599,  1540,1030,3594,2574,1797,1287,3853,3343,2310,1545,  1796,1031,1282,517,1024,4,1281,261,1538,518,3335,1  805,2565,1290,1794,519,1536,6,3847,1807,2050,520,2  563,778,3332,1037,2304,9,3328,13,3584,14,3586,526,  3841,271,2063,3848,3589,1294),led_word
		@ptrinc = high_pin
		@ptrinc = low_pin
	next led
	HI2Csetup I2Cmaster, %11010000, I2Cfast_64, I2Cbyte       ' Set to 100kbps
	if pina.0 = 1 then
		let bit1 = 1
		let bit2 = 1
		let bit3 = 1
		'bin = bcd / 16 * $FA + bcd
		'bcd = bin / 10 * 6 + bin
		'if pm hour = hour + 40, if am hour = hour + 60 before converting to bcd
		'testing in PM so set for 60 got time being
		temp_byte_0 = 6 + 60		'hour + pm setting
		hour = temp_byte_0 / 10 * 6 + temp_byte_0 
		temp_byte_0 = 30
		mins = temp_byte_0 / 10 * 6 + temp_byte_0
		sec = $00
		
		HI2Cout $0 , ( sec, mins, hour ,day, $21, $11 , $16)
	end if
	let bit1 = 1
		let bit2 = 1
		let bit3 = 1
	pause_time = normal_led
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231
	gosub hour_address
	if mins > 0 then						'check and find part hout at startup
		'temp_byte_0 = mins / 12
		'dis_hour = dis_hour + temp_byte_0
		'store_hour_led = dis_hour
		'#rem
		temp_byte_0 = mins // $10
		dis_mins = mins / $10 * 10 + temp_byte_0
		temp_byte_0 = 0
		do
			temp_byte_0 = temp_byte_0 + 12
			if temp_byte_0 > dis_mins then
				store_hour_led = temp_byte_0 +60
				exit
			else
				inc dis_hour
				
			end if
		loop	
		'#endrem
	end if
main:     
	HI2Cin $0  , (sec,mins,hour,day,date,month,year) ' Read from DS3231

	if sec <> store_sec then					'check for seconds change
		am_pm_flag = 0 : if hour > $60 then : am_pm_flag = 1 : end if
		
		'bin = bcd / 16 * $FA + bcd
		'bcd = bin / 10 * 6 + bin
		
		dis_sec = sec / 16 * $FA + sec		'convert BCD to decimal for LED address
		dis_mins = mins / 16 * $FA + mins + 60
		
		min_led_val = 0						'set min value for faded LEDs - this will be an error due to 0 - n overflow variable
		max_led_val = 59						'set max value for faded LEDs
		'now get dim LEDs
		let led_Hold = dis_sec
		gosub calc_dim_leds
		'on return save dim LEDs to variables
		sec_fade_1 = temp_byte_0
		sec_fade_2 = temp_byte_1
		gosub calc_dimmer_leds
		'on return save dim LEDs to variables
		sec_fade_3 = temp_byte_0
		sec_fade_4 = temp_byte_1
		
		'min
		if mins <> store_mins then
			min_led_val = 60
			max_led_val = 119
			let led_Hold = dis_mins
			gosub calc_dim_leds
			'on return save dim LEDs to variables
			mins_fade_1 = temp_byte_0
			mins_fade_2 = temp_byte_1
			gosub calc_dimmer_leds
			'on return save dim LEDs to variables
			mins_fade_3 = temp_byte_0
			mins_fade_4 = temp_byte_1
				if dis_mins = 60 then   			'check for zero minute - 0+60=60 so make sure hour LED is correct
					gosub hour_address
					let store_hour_led = dis_mins + 12
				end if
				if dis_mins = store_hour_led then   	'check to see if 12 minutes has elapsed
					inc dis_hour
					store_hour_led = store_hour_led + 12
				end if
				if store_hour_led <> store_hour then
					min_led_val = 120
					max_led_val = 179 
					let led_Hold = dis_hour
					gosub calc_dim_leds
					'on return save dim LEDs to variables
					hour_fade_1 = temp_byte_0
					hour_fade_2 = temp_byte_1
					gosub calc_dimmer_leds
					'on return save dim LEDs to variables
					hour_fade_3 = temp_byte_0
					hour_fade_4 = temp_byte_1
				end if
		end if
		
		let store_sec = sec
		let store_mins = mins
		let store_hour = store_hour_led
	end if
	
	'for loop_number = 0 to 25					'loop 25 times before checking time again
		bptr = 32	'find second LED
		let led = @bptrinc						'led address = seconds
		gosub display_address
		if bit2 = 1 then
			dimmed_led = b29						'get stored loop value of faded LEDs
			gosub faded_leds
			b29 = dimmed_led						'store faded LED loop value
		end if
		'each part of the display needs to maintain it own loop count of the fadded LEDs
		bptr = 37
		let led = @bptrinc
		gosub display_address
		if bit3 = 1 then
			dimmed_led = b30
			gosub faded_leds
			b30 = dimmed_led
		end if
		bptr = 42
		let led = @bptrinc
		gosub display_address
		if bit1 = 1 then
			dimmed_led = b31
			gosub faded_leds
			b31 = dimmed_led
		end if
		if am_pm_flag = 1 then					'check AM PM flag and set LED if PM
			low_pin = 15
			high_pin = 0
			gosub display
		end if
	'next loop_number	
	goto main
		
		
display_address:				'display hour with dimmed LEDs either side
	ptr = led <<1			'correct pointer address for display
	high_pin = @ptrinc
	low_pin = @ptr	
display:						'show LED
	low low_pin
	high high_pin
	pauseus pause_time
	dirsb = 0
	dirsc = 0
	'input low_pin
	'input high_pin
	return
hour_address:
	temp_byte_0 = hour & $10 / $10 *10
	dis_hour = hour // $10 + temp_byte_0
	if dis_hour = 12 then
		dis_hour = 0
	end if
	dis_hour = dis_hour *5+120
	return
	
calc_dim_leds:
	'LED_hold = LED
	'do inner LEDs
	let temp_byte_0 = led_hold + inner_led
	let temp_byte_1 = led_hold - inner_led
	if temp_byte_0 > max_led_val then     		'check for leading LED overflow
		temp_byte_0 = temp_byte_0 - 60
	end if
	if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
		temp_byte_1 = led_hold + 59
	end if
	if temp_byte_1 < min_led_val then     		'check for trailing LED underflow
		temp_byte_1 = led_hold + 59
	end if
	return
calc_dimmer_leds:
	let temp_byte_0 = led_hold + outter_led
	let temp_byte_1 = led_hold - outter_led
	if temp_byte_0 > max_led_val then			'check for leading LED overflow
		temp_byte_0 = temp_byte_0 - 60
	end if
	if temp_byte_1 > 200 then				'check for underflow on seconds displaiy
		temp_byte_1 = led_hold + 58
	end if
	if temp_byte_1 < min_led_val then			'check for trailing LED underflow
		temp_byte_1 = led_hold + 58
	end if
	return
	
faded_leds:
	if dimmed_led => 0 then
		
		let pause_time = 10
		let led = @bptrinc
		gosub display_address
		let led = @bptrinc
		gosub display_address
		'do outter LEDs
		if dimmed_led = 1 then
			let pause_time = 0
			let led = @bptrinc
			gosub display_address
			let led = @bptrinc
			gosub display_address
		end if
		inc dimmed_led
		if dimmed_led = 2 then
			dimmed_led = 0
		end if
	else
		inc dimmed_led
	end if
	
	let pause_time = normal_led
	return
 

oracacle

Senior Member
While this project as now pretty much done, with some tinkering left to do, a large request has come in.
Back lighting the thing 2 different colours depending on AM/PM.
I did bit of a head scratch. PM already has an indicator, and there is one spare address. the problem is it going to take more than the juice available from the 28X2 to drive enough LEDs for back lighting. Transistors would be the normal route, but keeping the tri-state is going to be a problem.

I think using 4 1N4001 diodes used in pairs to replace ach LED and taking the base from the middle of each pair wold do the job. I don't know how many LEDs are going to be need as yet, I don't even know what colours either, so the transistor are currently BC548. Although I am think of going something like a 2N7000 due to the possibility of high currents needing to be passed.

Any ideas on this would be highly appreciated. I am open to both component and circuit ideas
 

Attachments

Top