Driving 132 LEDs

AllyCat

Senior Member
Hi,

Yes LOOKUP will be way too slow (for long blocks of data) because the PE effectively converts it to (always) a sequence of 126 IF..THENs , see #20 and #14 here.

But a lookup table in EEPROM should be fine.

Cheers, Alan.

PS: And yes, "ptr=LED+LED" is a little faster (about 20% IIRC) than "ptr=LED*2"
 
Last edited:

Buzby

Senior Member
Hi hippy,

Yes, I could combine the subs, and I keep forgetting about bit shifts being faster than multiply !.

But why is #MACRO faster ?. I thought a macro was expanded at compile time, and created the same code as if typed in.
Am I missing something ?

Cheers,

Buzby
 

Buzby

Senior Member
... but if a lookup is going to be too slow, then an I2C EEPROM will be way too slow...
Definately not !.

The orrery used an external I2C EEPROM and it worked a treat.

Regarding lots of variables, I used the #slot mechanism to put the 1056 variables in #slot1, as they were only needed once to populate the EEPROM
 

oracacle

Senior Member
my understanding of a macro is: write the code once and when it compiled the code is copied to every place you called the macro, saving typing more than anything.
its essentially the same idea as unrolling loops. if you run a loop 4 times it will be faster to for the processor to run 4 identical section of code instead of a single loop 4 times.
its a lazy way of coding, it fine for getting a proto type up and running fast, and OK if you have the space and don't want to type out the same body of code however many times you need to use it.
 

oracacle

Senior Member
Definately not !.

The orrery used an external I2C EEPROM and it worked a treat.

Regarding lots of variables, I used the #slot mechanism to put the 1056 variables in #slot1, as they were only needed once to populate the EEPROM
I was going to write the EEPROM and leave written, save the values in a spread sheet or something in case the worst should happen.
Although now that I think about it, if something happens and the EEPROM should need to be replaced it would be helpful if you could just re-write the data onto a blank replacement
 

Buzby

Senior Member
Hi oracacle,

In the start of my orrery code I test a few locations in the EEPROM to see if they already contain known values. If they are I assume the rest of the data is correct, then I just skip calling the code in #slot1.

For your clock I am certain you won't need an external EEPROM, you only have 272 values, and they will fit in the scratchpad easily. ( Assuming you are using a 28X2 ).

Cheers,

Buzby
 

hippy

Technical Support
Staff member
But why is #MACRO faster ?. I thought a macro was expanded at compile time, and created the same code as if typed in.
Am I missing something ?
It's not the #MACRO itself which is faster but it is a speed gain from not having to execute the GOSUB and related RETURN at runtime -

Code:
IncSub:                    Executed code
  b1 = b0 + 1
  Return

Main:
  b0 = 1                   b0 = 1
  Gosub IncSub             Gosub
                           b1 = b0 + 1
                           Return
  SerTxd( #b1 )            SerTxd
  b0 = 22                  b0 = 22
  Gosub IncSub             Gosub
                           b1 = b0 + 1
                           Return
  SerTxd( #b1 )            SerTxd
  End                      End
Code:
#Macro IncSub()            Executed code
  b1 = b0 + 1
#EndMacro

Main:
  b0 = 1                   b0 = 1
  IncSub                   b1 = b0 + 1
  SerTxd( #b1 )            SerTxd
  b0 = 22                  b0 = 22
  IncSub                   b1 = b0 + 1
  SerTxd( #b1 )            SerTxd
  End                      End
 

hippy

Technical Support
Staff member
my understanding of a macro is: write the code once and when it compiled the code is copied to every place you called the macro, saving typing more than anything.
That is correct; it saves typing, makes things more readable and also avoids errors where similar code is used in a number of places -

Code:
w0 = w0 * 512 + %1011010 : If w0 > 1021 Then : w0 = 0 : End If
w1 = w1 * 512 + %1011010 : If w1 > 1021 Then : w1 = 0 : End If
Code:
#Macro FixUp(var)
  var = var * 512 + %1011010 : If var > 1021 Then : var = 0 : End If
#EndMacro

FixUp(w0)
FixUp(w1)
In the top example, the temptation would be to copy the 'w0=' line and duplicate for the 'w1=' line, change all 'w0' to 'w1'. If one 'w0' gets overlooked that's a bug. If a '2' gets hit instead of a '1' that's a bug.

Get the FixUp(var) macro right and it can be used with any variable and it will always behave as expected.

If the 'fixup' calculation ever needs to change, it only needs the #MACRO changing, not every 'fixup' calculation within the code.
 

Buzby

Senior Member
Hi hippy,

I'm struggling with #macro. ( PE 6.0.8.9 )
I've tried it with and without () in the define and call.
Where am I going wrong ?

Cheers,

BuzbyMacroFail_1.PNG
 

hippy

Technical Support
Staff member
I believe that is a limitation of parsing macro calls; the macro has to be on a separate line -

Code:
For LED = 117 To 125 Step 3
  macShowLED
Next
You could create a #MACRO for the FOR-NEXT ...

Code:
#Macro macShowSequence( nFrom, nTo, nStep )
  For LED = nFrom To nTo Step nStep
    macShowLED
  Next
#EndMacro

macShowSequence( 117, 125,   3 )
macShowSequence( 116,   8, -27 )
[i]etc[/i]
If you go into File -> Options -> Diagnostics -> Pre-Processor and tick the "Display Pre-Processor Output" checkbox then click OK, on Syntax Check a pop-out will appear showing what the equivalent expanded source code generated is.

That is not that useful beyond diagnostics so you will probably want to turn that off again soon after you have turned it on, but it does let you confirm what you are getting is as expected.
 
Last edited:

Buzby

Senior Member
Hi hippy,

That's a bit of an obscure bug to find. It should be highlighted in the manual.
( The example shows macros called as single lines, but it doesn't say they must be on single lines. )

The For/Next loops are just for testing, they won't be there in the final version.

Cheers,

Buzby
 
Last edited:

hippy

Technical Support
Staff member
I'll make a note of that not being mentioned in the manual.

You can also probably optimise you 'macShowLED' macro, to increase speed, reduce memory size, and save variables ...

Code:
#Macro macShowLed()
  ptr = LED << 1
  dirsB = 0
  dirsC = 0
  Low   @ptrInc
  High  @ptr
  Pause LEDdelay
#EndMacro
 

Buzby

Senior Member
Hi hippy,

That optimised macro is good.
I was going to go down the 'dirs=0' route, but I never thought of the 'high @ptr'.
It saved a lot of code space.

Two heads are better than one !.

Cheers,

Buzby
 

Buzby

Senior Member
Hi oracacle,

Here is a video of the LOL shield in action.

The main loop spends most of its time lighting the LEDs, only dropping out to run the 'clockticked' subroutine when timer3 rolls over.
I used timer3, but a real clock could use the 1sec pulse from SQW/OUT on a DS1307 RTC.

All the LED 'movement' is coded in the 'clockticked' subroutine. The code shown here just makes some moving dots, mostly using lookup (ugh!) to determine which LEDs are lit on each clock tick. A real clock display would be quite easy to code here.

There are a few enhancements that could be added.

The scratchpad could be pre-loaded with 'images' ( lists of LEDs ) which would be pulled out at the relevant time using a simple for/next, putting the numbers directly into LED_0, LED_1 etc by using POKE. This would allow complex animations without hundred of lines of code.

The #macShowLed could be modified to pass both the LED number and its 'brightness' ( LEDdelay ). Now that I understand macros a bit better, I can see that passing parameters like this creates no overhead in either time or code size. I must use them more often !.

I think we can safely say that a single Picaxe can drive your 132 LED clock easily, with no need for an I2C EEPROM.

Cheers,

Buzby

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

symbol xx			= b0
symbol xxx			= b1
symbol xxxx			= b2
symbol xxxxx		= b3
symbol ticked		= b4
symbol timerLED		= b5
symbol timediv		= b6
symbol LED_0		= b7
symbol LED_1		= b8
symbol LED_2		= b9
symbol LED_3		= b10
symbol LED_4		= b11
symbol LED_5		= b12
symbol LED_6		= b13
symbol LED_7		= b14
symbol LED_8		= b15
symbol LED_9		= b16
symbol LED_10		= b17
symbol LED_11		= b18
symbol LED_12		= b19
symbol LED_13		= b20

symbol G			= b21
symbol H			= b22
symbol K			= b23

symbol LEDdelay		= w25
symbol oldtime          = w26
symbol newtime		= w27

symbol timedivrate	= 3

#Macro macShowLed(var)
  ptr = var << 1
  dirsB = 0
  dirsC = 0
  Low   @ptrInc
  High  @ptr
  Pause LEDdelay
#EndMacro

' **************************************************  ************************
' Code starts here
' **************************************************  ************************
setfreq em64
pause 1000	

LEDdelay = 5
timediv = timedivrate 

tmr3setup %00110011 '  1:8 prescaler, the slowest it will go !

' Copy LED data from LOOKUP to scratchpad RAM
ptr = 0		
for b2 = 0 to 125
	gosub look_up
	@ptrinc = b0 : @ptrinc = b1
next

b0 = 0 ' Reset b0, needed later


' Preset LED positions
	LED_0 = 0
	LED_1 = 10	
	LED_2 = 20	
	LED_3 = 30	
	LED_4 = 40
	LED_5 = 50
	LED_6 = 58	
	LED_7 = 66	
	LED_8 = 56	
	LED_9 = 46	
	LED_10 = 38
	LED_11 = 104	
	LED_12 = 112
	LED_13 = 120
	
	
' Main loop
' ---------
do
		' Light the LEDs
	 	macShowLED(LED_0)   
	 	macShowLED(LED_1)  
	'	macShowLED(LED_2) 
	 	macShowLED(LED_3)   
	 	macShowLED(LED_4)
		macShowLED(LED_5)
	 	macShowLED(LED_6)   
	 	macShowLED(LED_7)
	 	macShowLED(LED_8)  
	 	macShowLED(LED_9)   
	 	macShowLED(LED_10)
	'	macShowLED(LED_11)
	'	macShowLED(LED_12)   
	'	macShowLED(LED_13)
	
		' Flash activity LED on each clock tick
		if ticked = 1 then
			macShowLED(125)
		Endif
	
		' 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
' **************************************************  ***************************

look_up:  'lookup LED pins into b0, b1
	lookup b2,  ($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 _
			 ),w0
return

clockticked:
	
	ticked = ticked xor 1 ' Toggle activity LED

'	inc H : if H > 11 then : H = 0 : endif
'	lookup H, (88, 70, 52, 51, 49, 47, 46, 64, 82, 83, 85, 87), H_LED

 	inc K : if K > 41 then : K = 0 : endif
 	lookup K, (117, 108, 99, 90, 81, 72, 63, 54, 45, 36, 27, 18, 9, 0,_
	             1,2,3,4,5,6,7,8,_
			 17,26,35,44,53,62,71,80,89,98,107,116,125,_
			 124,123,122,121,120,119,118), LED_0
	xxx=41-K
	lookup xxx,(117, 108, 99, 90, 81, 72, 63, 54, 45, 36, 27, 18, 9, 0,_
	             1,2,3,4,5,6,7,8,_
			 17,26,35,44,53,62,71,80,89,98,107,116,125,_
			 124,123,122,121,120,119,118) , LED_1

	inc G : if G > 11 then : G = 0 : endif
	lookup G,(1,1,1,9,9,9,255,255,255,247,247,247),H
	
	
	
'	LED_0 = LED_0 + H
'	LED_1 = LED_1 - 10	
'	LED_2 = LED_2 - 10	
 	LED_3 = LED_3 + H	
 	LED_4 = LED_4 + H
 	LED_5 = LED_5 + H
 	LED_6 = LED_6 + H	
 	LED_7 = LED_7 + H	
 	LED_8 = LED_8 + H		
 	LED_9 = LED_9 + H		
 	LED_10 = LED_10 + H
'	LED_11 = LED_11 - 10	
'	LED_12 = LED_12 - 10	
'	LED_13 = LED_13 - 10

return



[video]https://youtu.be/PTmHXoxvEns[/video]
 

oracacle

Senior Member
Nice work, buzby

My plan to make the far from five identical board didn't go accordingly. So plan b is to use some press and peal iron on stuff from Maplin's to di the whole face in one hit. My UV light box is not big enough to do it in the uv exposure method. I am not going to be able to get to do it until next week how sure to work.

I did start to populate what I had which taught me his bit to go about getting this wired up
 

Buzby

Senior Member
Could you not design the board full size, then cut into 3 or 4 pieces that will fit into your UV box ?.
You could 'thicken up' the traces where you know you are going to have to join boards together.

Or optically mask the big board in sections, and expose it a section at a time ?.

I don't like press'n'peel, I'd do anything to avoid that route. :)
 

oracacle

Senior Member
That's how I did it. The problem isn't Su much the process but my inability ti cut a strait line, and circle are often not circular.
I ab still causing keeping ok with this one for the time being. I wo post a picture later and go into a bit more detail of what I learnt, I gotta set some more leccy for the meter first though
 

oracacle

Senior Member
The Tracks themselves aren't too far of from being circular, the out side and centre still need refining.
The biggest thing I found is that the default pad sizes are big enough really and the joins between the boards introduce and extra area fro things to go wrong - I have had a couple of issue with tiny shorts causing addition LEDs to come on faintly by the smallest of bridges and the continuity test didn't pick up when I put the boards together.

The other thing I found is: The LEDs should be installed with all the first pairs the next to the pins (1:2, 2:3, 3:4....) and then the next layer (1:3, 2:4), you get the idea, I think this would reduce the chances of a pair being missed and having to try and find which on you have done with 90 pairs of LEDs to go through could be very tedious.
 

Attachments

Buzby

Senior Member
Can you post a .pdf or gerber ( or big picture ) of your track layout ?.

I'd like to get a better idea of how you have connected the LEDs.

( Best to have another pair of eyes see it, before you solder in a hundred more LEDs :) )
 

oracacle

Senior Member
the LEDs aren't actually the same way round, when I placed them using your spread sheet co-ordinated they all oriented around the same way, I have installed them in alternate ways (IE anode to cathode) in each pair.
circle tracks are copper side circle shapes, jumpers are then used to go from each LED pair to hopefully the correct track, outer most being 0 and inner most being 13.
Hope that makes sense.
 

Attachments

Buzby

Senior Member
... jumpers are then used to go from each LED pair to hopefully the correct track, outer most being 0 and inner most being 13.
0 to 13 ?. That's 14 pins, giving a possibility of 182 LEDs. Have you moved up from 132 LEDs on 12 pins ?

Regarding your layout, I like the idea, it will be easy to ensure the wiring is correct.

However, I think you are going to need more pads on the circular tracks. SixLEDs.png ( Ignore the numbers on the left hand LEDs )
 

oracacle

Senior Member
Yes 180 (maybe 181 for am/pm), so that an aprox hour can be represented with LEDs slightly faded either side of the actual hour position. The hour "hand" (led full on, will be moved to the next representation every 12 minutes - see post 36).
that's the other problem, for the most part 2 pads per LED pair on the circular track is for the should be for the most part enough I thought. When you get to putting 12 LEDs on 4 pins 3 are needed one ring 3. the problem with more pads is space. there is currently 28 for each set of six 28*30=840, increasing to 3 per set of six is 1260 which is going to be hard to get on the inner more track.
I am not sure how am going to solve the issue, maybe having one of the wire split (ie another piece of wire solder to it) on the top side of the board. Or is smaller diameter wire so that 2 wires could share a whole.
 

Buzby

Senior Member
Add three extra tracks or wire links in each group of 6 LEDs.

The wiring within each group is always the same, and each group only needs 3 links to the circles, meaning you only need 1 pad per circle for each group.

( If you do multiple wires in one hole, or split wires, it will be difficult to plan, and horrendous to fault find. )

SixLEDs2.png
 

oracacle

Senior Member
Would it not be simpler to the less around a little di that they are numbered from top to bottom 1,2,2,0,0,1
 

Buzby

Senior Member
It doesn't matter which way the numbering goes, as long as only two LEDs anywhere in the matrix are connected to the same signal pair. You can make a different 3 links in the group, it doesn't have to be the way I showed. However, I would strongly suggest that you keep the same links for all the groups, it will make diagnostics easier.

Trying to arrange the wiring such that there is a meaningful correspondence between a pin-pair and the location of its two LEDs is both difficult and totally unnecessary.
The pin-pair for each of the LEDs is used in the lookup table, and it is the ordering of this table that determines how the software sees the matrix.
e.g. That LOL shield has a really messy layout, but the lookup translates it into a 9x14 XY grid. Your table will translate into 3 rings of 60 LEDs, numbered 0-59, 60-119, 120-179.
 

Buzby

Senior Member
I just got DesignSpark, here is what DS thinks is the best routing for the 6 LEDs.

I've put all the LEDs facing the same direction, much less chance of making an error when assembling the board.


SixLEDs3.png
 

oracacle

Senior Member
I bit of tweak to get to fit into the space of the clock face and things should be good.
It should make the circular bus look a little less like swiss cheese too as it will only need one pad/whole on each track for each set of six LEDs

All LEDs will face the same direction (ie cathode outwards)
 

Attachments

oracacle

Senior Member
Am I right in saying that there are 30 sets of 3 connection that need to be made (ie 30 set of six for 180 LEDs, with to extra LEDs to make the 182 possible with 14 pins).
I think I maybe having a slow brain day as drawing it/writing it out is making my head spin. I will gladly welcome any input on the best way to find the combinations that I miss.

In other news I now have an A4 capable PCB setup, some PCB that is 200*300mm. this will put the track incredibly close to edges of the board, much care is going to be needed when places the transparency.
 

Buzby

Senior Member
Yes, there will be thirty sets of three links.

Try using a spreadsheet to plot the links. It's easier than pen and paper.

SixLeds5.PNG

( Don't trust what I've put on this spreadsheet, it was just a first attempt. )
 

oracacle

Senior Member
can some one check this please. pins are on the left, each of the 3 way header represented by a 1, there should be no more than 3 in a column and there should never be more than 1 of each pair of connections.

so if 0-3-6 have one in one column, 1-3-6 would not be allowed as the 3-6 is repeated.

I don't wont to jump up and down with excitement just yet as it possible that I have made an error. Its taken a while between work and what have you but I think I may actually be there know.
 

Attachments

Buzby

Senior Member
Yes, it's real headache working out the LEDs as 30 groups of 6, it was so much easier as 180 individuals.

I've tried to write a VB macro to do it, but still haven't cracked it.

Just one thing with your chart, there should be a pin-pair extra. The 30x6 accounts for 180 of the LEDs, with the remaining 2 LEDs on the extra pin-pair.

It's looking good though, you'll get there soon.

Cheers,

Buzby
 

oracacle

Senior Member
extra set would be 0-13. I think pairs could have easier too.
I made the PCB up, however I think I may have overexposed it, the closer to the centre the tack at the less there are.
My small UV box needed about 8mins to expose correctly over A5 with 40 LEDs. Being that I used the same LEDs for the A4+ box I thought the same time would be fine, except I didn't take into account that it use 234 LEDs over little more than 4 time the area. Due to the face that there is 1.5x the LEDs per equivalent area the UV must be more intense.

Hopefully I will get to start construction tomorrow
 

Buzby

Senior Member
Columns 7, 10, and 26 all have the same pair 2-8.
Columns 6 and 24 have a common pair as well.
 

Attachments

Last edited:

hippy

Technical Support
Staff member
If I have understood it right; there are 14 control lines (0-13) and we have to find triplets which can not use more than one control line which has been used in any other triplet.

In which case it seems there are 28 possibilities. Sideways on to your diagram I am afraid -

Code:
               1111
     01234567890123

 1 : ABC-----------
 2 : A--BC---------
 3 : A----BC-------
 4 : A------BC-----
 5 : A--------BC---
 6 : A----------BC-
 7 : -A-B-C--------
 8 : -A--B-C-------
 9 : -A-----B-C----
10 : -A------B-C---
11 : -A---------B-C
12 : --AB--C-------
13 : --A-BC--------
14 : --A----B--C---
15 : --A-----BC----
16 : --A---------BC
17 : ---A---B---C--
18 : ---A----B---C-
19 : ---A-----B---C
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---BC--
 

Buzby

Senior Member
Hi hippy,

Not sure that's quite right, but let's see.

14 lines gives 182 LEDs, and a group of 6 LEDs needs 3 lines.

So 30 groups should be driveable with 3 lines per group, giving 180 LEDs, and 2 more in a group of 2.

If there are only 28 possible arrangement of the triplet then you could only drive 6x28, i.e. 168 LEDs.

My brain is hurting again !!!.


Edit : Maybe its easier to plot on a standard Charliplex grid ....

SixLeds8.PNGSixLeds9.PNG

( Those are not 'real' plots, just 3 sets of numbers I chose at random. 0,1,2 and 3,6,9 and 2,4,8 )
 
Last edited:

hippy

Technical Support
Staff member
My brain is hurting again !!!.
Me too. I agree standard charlieplexing individual LED's with 14 controil lines gives 14*(14-1) = 182 LED's.

But with 14 control lines used as triplets that is only 28 sets of triplets. 28 x 6 = 168.

So where's Wally the missing 14 LED's ?

I suspect it's something to do with going from singular control to triplet control but I can't figure it out. But I can't see any error anywhere. I would be impressed to see anyone manage to squeeze another triplet in there which doesn't conflict.
 
Top