# LED Ladder game on instrucables- PICAXE conversion?

#### chlgibbons

##### New Member
Has anyone spotted this game on instructables? If so, how hard would it be to convert to BASIC for Picaxe08M?
I am a secondary teacher and think this would be a good little product to make for the kids.
Any suggestions into the coding would be great.

#### Goeytex

##### Senior Member
If so, how hard would it be to convert to BASIC for Picaxe08M?
All that you need is to do is to study, and become proficient in both Arduino C and Picaxe BASIC so that you can do the translation.

Unless some kind soul comes along with the necessary skillset and does it for you, it could be quite a challenge.

#### hippy

##### Senior Member
Probably easier to code from scratch rather than try and convert. It doesn't seem it would be too difficult; the hardest part figuring out how the LED's are driven from just the 4 I/O pins. It seems to use charlieplexing but it's a bit hard to figure out the matrix without studying it. Not sure how the PICAXE 08M2 having pin 0 only High or Low would affect things.

#### rjandsam

##### Member
Hi just knocked this code up for you to play with in the simulator it should give you a small start.

Rich

#picaxe 18m2
let w5=300
symbol ontime=w5
symbol led1=b.0
symbol led2=b.1
symbol led3=b.2
symbol led4=b.3
symbol led5=b.4
symbol led6=b.5
symbol led7=b.6
symbol led8=b.7
symbol led9=c.6
symbol led10=c.7
symbol led11=c.0
symbol led12=c.1

symbol led=b.1
setint %00000100,%00000100

Main:
let b20=1
step1:
pause ontime
let bit15=1 high led1
pause ontime
let bit15=0 low led1
if b20=2 then let ontime=ontime-15 goto step2
endif
goto step1
step2:
pause ontime
let bit15=1 high led2
pause ontime
let bit15=0 low led2
if b20=3 then let ontime=ontime-15 goto step3
endif
goto step2
step3:
pause ontime
let bit15=1 high led3
pause ontime
let bit15=0 low led3
if b20=4 then let ontime=ontime-15 goto step4
endif
goto step3
step4:
pause ontime
let bit15=1 high led4
pause ontime
let bit15=0 low led4
if b20=5 then let ontime=ontime-15 goto step5
endif
goto step4
step5:
pause ontime
let bit15=1 high led5
pause ontime
let bit15=0 low led5
if b20=6 then let ontime=ontime-15 goto step6
endif
goto step5
step6:
pause ontime
let bit15=1 high led6
pause ontime
let bit15=0 low led6
if b20=7 then let ontime=ontime-15 goto step7
endif
goto step6
step7:
pause ontime
let bit15=1 high led7
pause ontime
let bit15=0 low led7
if b20=8 then let ontime=ontime-15 goto step8
endif
goto step7
step8:
pause ontime
let bit15=1 high led8
pause ontime
let bit15=0 low led8
if b20=9 then let ontime=ontime-15 goto step9
endif
goto step8
step9:
pause ontime
let bit15=1 high led9
pause ontime
let bit15=0 low led9
if b20=10 then let ontime=ontime-15 goto step10
endif
goto step9
step10:
pause ontime
let bit15=1 high led10
pause ontime
let bit15=0 low led10
if b20=11 then let ontime=ontime-15 goto step11
endif
goto step10
step11:
pause ontime
let bit15=1 high led11
pause ontime
let bit15=0 low led11
if b20=12 then let ontime=ontime-15 goto step12
endif
goto step11
step12:
pause ontime
let bit15=1 high led12
pause ontime
let bit15=0 low led12
if b20=13 then won
goto step12

won:
high led1,led2,led3,led4,led5,led6,led7,led8,led9,led10,led11,led12
pause 10000
reset

interrupt:
if input2=1 and bit15=1 then inc b20 goto release
elseif input2=1 and bit15=0 then goto cascade
endif

if b20=12 then decled12
if b20=11 then decled11
if b20=10 then decled10
if b20=9 then decled9
if b20=8 then decled8
if b20=7 then decled7
if b20=6 then decled6
if b20=5 then decled5
if b20=4 then decled4
if b20=3 then decled3
if b20=2 then decled2
if b20=1 then decled1

decled12:
high led12 pause 250
low led12
decled11:
high led11 pause 250
low led11
decled10:
high led10 pause 250
low led10
decled9:
high led9 pause 250
low led9
decled8:
high led8 pause 250
low led8
decled7:
high led7 pause 250
low led7
decled6:
high led6 pause 250
low led6
decled5:
high led5 pause 250
low led5
decled4:
high led4 pause 250
low led4
decled3:
high led3 pause 250
low led3
decled2:
high led2 pause 250
low led2
decled1:
high led1 pause 250
low led1
reset

release:
if input2=1 then release
pause 2000 setint %00000100,%00000100 return

Last edited:

#### AllyCat

##### Senior Member
Hi,

You can "tri-state" C.0 (Leg 7) of an 08M2 by setting it to be the DAC output. Maybe not quite "floating" but around 150 kohms by using the appropriate commands.

However, the OP has specified an 08M (by mistake, or because the PICaxe Store has them at a "Clearance" price?) which I believe has only 256 bytes of Program memory. That could make it a real challenge.

Cheers, Alan.

#### hippy

##### Senior Member
It might be possible in 256 bytes, but I wouldn't bet on it. One trick for saving memory would be in using a word variable to map the 12 LED's onto, just shift a bit up or down in sequence. That should be fairly compact.

#### techElder

##### Well-known member
Here's a drawing of the LED matrix that was referenced in some of the links via that Instructable.

Original matrix:

Revised matrix:

Last edited:

#### Buzby

##### Senior Member
Here is a completely untested attempt at the Ladder Game using an 08M. ( In a lot less than 256 bytes of memory ! )

I won't have a chance to do any more with it for a day or two, so if anyone wants to take up the torch here it is.

Cheers,

Buzby

Code:
#picaxe 08M

' Ver 3

' 12 LEDs Charlieplexed from pins C.0, C.1, C.2, C.4 ( Legs 7,6,5,3 )
' In Charlieplexing each pin has three states: High, Low, Tristate
' On the 08M pin C.0 is 'output only', so a pseudo-PWM trick is used to make it 'Tristate'.
' See http://www.user.dccnet.com/wrigter/picaxe/12LEDpyramid2.gif

symbol Eaddr	 = b0	' Pointer into EEPROM
symbol LEDanode	 = b1	' Pin number for Anode of lit LED
symbol LEDcathode	 = b2	' Pin number for Cathode of lit LED
symbol BPressed	 = b3	' Button pressed flag
symbol Height	 = b4	' Number of current step
symbol LEDduration = b5	' Duration of LED lit time
symbol LEDtimer    = b6	' Timer for LEDduration

symbol Pbutton 	 = pinC.3	' Push button ( Leg 4 ) pulled low, switched to high

' Store pin numbers for Anodes and Cathodes of each LED
EEPROM 0,(0,1, 0,2, 0,4, 1,0, 1,2, 1,4, 2,0, 2,1, 2,4, 4,0, 4,1, 4,2 )

' Store flash durations for each rung.
EEPROM 24, (250,250,250,200,200,200,150,150,150,100,100,100)

' Code starts here
' ----------------

Height = 0	' Start at first LED

' Main loop
do
' Wait for button not pressed
do
BPressed = Pbutton
loop until	BPressed = 0

' Get flash duration for this rung
Eaddr = Height + 24		' Make pointer to duration

' Flash LED	until button pressed
do

gosub LightLED

if BPressed > 0 then exit	' Exit flash loop if button was pressed

gosub BlankLED

if BPressed > 0 then exit	' Exit flash loop if button was pressed

loop ' End of flash loop

' Was button pressed while LED off ?
if Bpressed = 2 then
gosub DisplayFailed
Height = 0	' Go to lowest rung
endif

' Was button pressed while LED on ?
if Bpressed = 1 then
inc Height	' Go to next rung
endif

' Made it to the top !
if Height > 11 then
Height = 0	' Go to lowest rung
endif

loop ' Loop forever

' ---------------------------------------------------------------------
' Subroutines
' ---------------------------------------------------------------------

LightLED:	' Lights LED for time set by LEDduration, scans for Pbutton

Eaddr = Height * 2	' Make pointer to pin numbers

dirs = %00000000	' Switch off any previous LEDs

high LEDanode : low  LEDcathode	' Switch on current LED

LEDtimer = LEDduration	' Set timer

do
if LEDanode > 0 and LEDcathode > 0 then	' LED does not need C.0, so 'tristate' it

toggle 0	' Make square wave on C.0

endif

' Check if button pressed
if Pbutton = 1 then
BPressed = 1	' 1 means button was pressed when LED on
endif

dec LEDtimer

loop until LEDtimer = 0

return

BlankLED:	' Blanks LEDs for time set by LEDduration, scans for Pbutton

LEDtimer = LEDduration	' Set timer

dirs = %00000000	' Switch off any previous LEDs

do
toggle 0	' LED does not need C.0, so 'tristate' it

' Check if button pressed
if Pbutton = 1 then
BPressed = 2	' 2 means button was pressed when LED off
endif

dec LEDtimer

loop until LEDtimer = 0

return

' Put victory display routine here

return

DisplayFailed:
' Put failed display routine here

return

Last edited:

#### chlgibbons

##### New Member
Thanks for having a look at it and setting the ball rolling with it Buzby. I've had a quick play with it on a breadboard and it looks looks its on its way there.
Chris

#### Buzby

##### Senior Member
Hi Chris,

I've managed to get to a PC, but not a PE, so I can't try anymore coding, but if you need any help with understanding the code I'll try to answer.

Good Luck,

Buzby

#### AllyCat

##### Senior Member
Hi Chris,

But are you actually using an 08M (or is it a current 08M2), and do you want to copy the mixed range of LED colours used in the instructable? Both the hardware and software need to be more complex if using the older, non-M2 device (or the PWM method in general). Also, a "PULLUP 8" can't be used to save a resistor for the pushbutton.

The "trick" of using 50% PWM to emulate a tri-state output requires more careful slectiion of the supply voltage, particularly if using mixed LED colours (which have different forward voltage drops). With mixed LED colours, make sure that the Blue (or white) and preferably green LEDs are driven by the c.0 pin (which will require a software change if replicating the instructables version).

Also, you will need to modify the LED drives so that the resistors are in series with the PICaxe pins, not just on the LED anode side as shown in the instructable. This means that two resistors are in series with each LED, which may need to be of a lower value (for a particular LED brightness).

The PWM filtering capacitor probably needs to be at least 100 uF, even with a setfreq m8 (which as as high as an 08M can go). Buzby's PWM software PWM loop looks quite "tight" at around 5 ms, but the filter will need a time constant several times longer than that (perhaps 100 uF x 150 ohms = 15 ms).

But I do see that Buzby's edit now avoids the "Cheat" in his original code, that you could win by holding the button in continuously.

Cheers, Alan.

#### Buzby

##### Senior Member
Hi Alan & Chris,

I've not got access to hardware at the moment, so I'm grateful that you can run the code on a real chip.

As you can see, the 'PWM' works by toggling C.0 each time round the tight loop in the 'LightLED' routine. I couldn't determine exactly what frequency this would run at, so your testing is very helpful.

The waveform is currently fixed at 50/50, but it looks reasonably easy to change the code so that each LED can have it's own 'PWM' duty. This may help with different colour LEDs in different positions.

The matrix I envisaged was the one linked to in the code, not the Instructables one.

Regarding the 'BlankLED' loop, does it even need the toggle in there ?. All the other pins will be at real tristate, so it shouldn't matter if C.0 is high or low, no current will flow anyway.

Also, a small pause in BlankLED will equalise the on/off times of the flash rate, or even make it less 'on than 'off', which will make it more challenging, or even make it erratic, which will be really fun !.

Cheers,

Buzby

Last edited:

#### AllyCat

##### Senior Member
Hi Buzby,

I'm grateful that you can run the code on a real chip.
I don't know about Chris, but I'm only using the simulator and my knowledge of hardware design and of the approximate PICaxe instruction timings at 4 MHz (HIGH/LOW = 400 us, IF .. THEN (true) = 1.2 ms, etc.). I had also written similar code, but mine was no better than your edited version, so I didn't bother to post it.

Even I was surprised that a reasonable "game" could be written for a PICaxe in less than 100 bytes. But perhaps a "playable" version needs the addition of a random element (to the LED flash starting phase) because I believe it's currently possible to cheat by holding in the button and just releasing it briefly (I haven't checked if the instructables code is similar).

I suspect that a 50:50 duty cycle is (nearly) always the optimum, because some of the "low forward voltage" LEDs will be pulled high and others low for most output states. So I certainly wouldn't bother to modify the code until we know that an 08M is actually to be used with multiple-coloured LEDs. With an 08M2 a DACLEVEL 16 and a DACSETUP var should be better and more economical.

Cheers, Alan.

#### Buzby

##### Senior Member
... I'm only using the simulator ...
Lucky you !. I can't even get at PE till the weekend.
.. I had also written similar code, but mine was no better than your edited version, so I didn't bother to post it. ...
Please post, it's always instructive to see how someone else targets the same problem.
... Even I was surprised that a reasonable "game" could be written for a PICaxe in less than 100 bytes.
So was I.
... I certainly wouldn't bother to modify the code until we know that an 08M is actually to be used with multiple-coloured LEDs.
Fully in agreement there, trying to remotely program with no feedback is no fun !

Cheers,

Buzby

#### chlgibbons

##### New Member
Thanks guys. Its on my list of 'to do's' to get a bunch of LEDs tomorrow and give it a run using different colour combinations with a 08M2. I will let you know how I get on with it.
Thanks
Chris

#### Buzby

##### Senior Member
Given that we we quite surprised at getting a reasonable game into just a few bytes, I've thought up another.

Hardware is 12 Charlieplexed red LEDs arranged in a circle, and a pushbutton.

The game starts with a short 'block' of lit LEDs moving slowly round the circle. The aim is to press the button when the 'block' passes a fixed marker. As the game progresses the 'block' get shorter and the speed gets faster.

Should be easy to program, and no voltage difficulties because all LEDs are the same.

What else could we build with 12 LEDs and a pushbutton ?

##### Senior Member
What else could we build with 12 LEDs and a pushbutton ?
I constructed a game (from Electronics Today International IIRC) similar to Buzby's idea about three decades ago using a couple of 74LS96, a 74LS86 and a bit more glue logic.
10 LEDs circling, starting in a random pattern and you had to hit a button when a lit LED passed a set point, the idea being to hit all the LEDs and turn them off. However, the button was XORed with the set point so if you missed then the LED would turn on. Holding down the button down longer would invert subsequent LEDs as they passed the marker, which could be to your advantage or otherwise.

The trouble with simple Charlieplexing is that although you can select any one LED to be on, you can't select any combination of LEDs to be on at once. A way around this would be to time multiplex the LEDs as well, but code would start getting 'orrible.

Last edited:

#### Buzby

##### Senior Member
... The trouble with simple Charlieplexing is that although you can select any one LED to be on, you can't select any combination of LEDs to be on at once. ...
Not quite as difficult as you think it might be. My Charlieplexed Orrery lit 9 LEDs at once ( from a pool of 528 ), and experiments showed that upto about 15 LEDs at once still gave a good display.

#### chlgibbons

##### New Member

Hi Buzby. I have managed to try the game on a breadboard. As you can see it is a bit glitchy with some of the outputs still on. This is what it looks like:

http://youtu.be/C5MX_QDKzYM

#### Buzby

##### Senior Member
Hi Chris,

It's great that you've got some thing working, but it looks a bit odd. There should never be more than one LED on at once.

Are you absolutely sure the matrix is wired properly ?.

Put this piece of code in place of the "Was button pressed while LED off ?" test :

Code:
' Was button pressed while LED off ? ****** Ignore failures *****
if Bpressed = 2 then
'	gosub DisplayFailed
'     Height = 0	' Go to lowest rung

inc height
endif
This should step up the ladder each time the button is pressed. This will test the matrix properly.

This weekend I should be able to try the code on a real chip, so I'll be able to help a bit more then.

Cheers,

Buzby

#### chlgibbons

##### New Member
I tried the piece of code "Was button pressed while LED off ?" test and had no effect.

I think that when the LEDs contain an output 0 they work correctly, hence step 1,2,3,4,7 and 10 being single LEDs as required. I think that output 0 is not turning to the tristate position that you mentioned and hence is allowing other LEDs to turn on in the other states as below.

EEPROM 0,(0,1, 0,2, 0,4, 1,0, 1,2, 1,4, 2,0, 2,1, 2,4, 4,0, 4,1, 4,2 )

Cheers-Chris

#### AllyCat

##### Senior Member
Hi Chris,

Did you rewire the LEDs as I described in para 3 of post #12 ? If not, the PWM filter can only work for half of the LEDs.

But with a 5 volt rail (or even one just high enough to illuminate blue LEDs) then even half of the supply voltage may be enough to drive the Red LEDs. That's why I suggested the pins/code needed to be re-arranged so that only the blue and green LEDs are connected to the pseudo tri-state pin (c.0).

However, IMHO using the DAC to emulate a Tri-state is far better, because not only can it give an accurate, ripple-free level (and save a capacitor), but the output impedance is around 40 kohms, so at worst the "unselected" LEDs can only illuminate very dimly.

Cheers, Alan.

#### Buzby

##### Senior Member
Finally got to my hardware !.

This is just a demo of the 12 LEDs flashing. The virtual tristate from C.0 works fine. There is no ghosting on the unlit LEDs.

( The chip is actually an 08M2, but the code is working as if it was an 08M, i.e. not using the DAC idea. )

I've got some more work to do with the game code, will take another video when it's done.

#### JimPerry

##### Senior Member
Finally got to my hardware !.

This is just a demo of the 12 LEDs flashing. The virtual tristate from C.0 works fine. There is no ghosting on the unlit LEDs.

( The chip is actually an 08M2, but the code is working as if it was an 08M, i.e. not using the DAC idea. )

I've got some more work to do with the game code, will take another video when it's done.

Video is flagged as Private

Still no luck

#### Attachments

• 30.7 KB Views: 9

#### Buzby

##### Senior Member
One more attempt !

Code:
#picaxe 08M2

' Ver 4, nearly there !

' 12 LEDs Charlieplexed from pins C.0, C.1, C.2, C.4 ( Legs 7,6,5,3 )
' In Charlieplexing each pin has three states: High, Low, Tristate
' On the 08M pin C.0 is 'output only', so a pseudo-PWM trick is used to make it 'Tristate'.

' See http://www.user.dccnet.com/wrigter/picaxe/12LEDpyramid2.gif

symbol Eaddr	 = b0	' Pointer into EEPROM
symbol LEDanode	 = b1	' Pin number for Anode of lit LED
symbol LEDcathode	 = b2	' Pin number for Cathode of lit LED
symbol BPressed	 = b3	' Button pressed flag
symbol Height	 = b4	' Number of current step
symbol LEDduration = b5	' Duration of LED lit time
symbol LEDtimer    = b6	' Timer for LEDduration
symbol PBenable    = b7 ' Enables button if > 0
symbol temp        = b8

symbol Pbutton 	 = pinC.3	' Push button ( Leg 4 ) pulled low, switched to high

' Store pin numbers for Anodes and Cathodes of each LED
'          0    1    2    3    4    5    6    7    8    9    10   11
EEPROM 0,(4,0, 4,1, 4,2, 0,4, 0,1, 0,2, 1,4, 1,0, 1,2, 2,4, 2,0, 2,1 )

' Store flash durations for each rung.
EEPROM 24, (250,250,250,250,250,250,250,250,250,250,250,250)

' Code starts here
' ----------------

' Main loop
do
' Wait for button not pressed
do
PBenable = 0	' Disable PB detection during LightLED routine
gosub LightLED

BPressed = Pbutton
loop until	BPressed = 0

' Get flash duration for this rung
Eaddr = Height + 24		' Make pointer to duration

PBenable = 1	' Re-enable PB

' Flash LED	until button pressed
do
gosub LightLED

if BPressed > 0 then exit	' Exit flash loop if button was pressed

gosub BlankLED

if BPressed > 0 then exit	' Exit flash loop if button was pressed

loop ' End of flash loop

PBenable = 0

' Was button pressed while LED off ?
if Bpressed = 2 then
gosub DisplayFailed
Height = 0	' Go to lowest rung
endif

' Was button pressed while LED on ?
if Bpressed = 1 then
inc Height	' Go to next rung
endif

' Made it to the top !
if Height > 11 then
Height = 0	' Go to lowest rung
endif

loop ' Loop forever

' ---------------------------------------------------------------------
' Subroutines
' ---------------------------------------------------------------------

LightLED:	' Lights LED for time set by LEDduration, scans for Pbutton if enabled

Eaddr = Height * 2 	' Make pointer to pin numbers

dirs = %00000000	' Switch off any previous LEDs

high LEDanode : low  LEDcathode	' Switch on current LED

LEDtimer = LEDduration	' Set timer

do
if LEDanode > 0 and LEDcathode > 0 then	' LED does not need C.0, so 'tristate' it

toggle 0	' Make square wave on C.0

endif

' Check if button pressed
if Pbutton = 1 and PBenable > 0 then
BPressed = 1	' 1 means button was pressed when LED on
endif

dec LEDtimer

loop until LEDtimer = 0

return

BlankLED:	' Blanks LEDs for time set by LEDduration, scans for Pbutton if enabled

LEDtimer = LEDduration	' Set timer

dirs = %00000000	' Switch off any previous LEDs

do
toggle 0	' LED does not need C.0, so 'tristate' it

' Check if button pressed
if Pbutton = 1 and PBenable > 0 then
BPressed = 2	' 2 means button was pressed when LED off
endif

dec LEDtimer

pause 3

loop until LEDtimer = 0

return

' Put victory display routine here
LEDduration = 10
for temp = 0 to 5
for height = 0 to 11
gosub lightLED
next
next
return

DisplayFailed:
' Put failed display routine here
LEDduration = 10
for temp = 0 to 3
for height = 11 to 0 step -1
gosub lightLED
next
next
return
This is the latest code, but it seems to miss some button presses. I'll not have much time to fix it today.

#### JimPerry

##### Senior Member
Nope - copied the URL and pasted into a new frame and managed to see it though

#### Buzby

##### Senior Member
I can't see why the video is not visible, I've set it to 'Public'.
I'll delete it and try again if it's not working for anyone.

#### AllyCat

##### Senior Member
Hi Buzby,

Yes, the same here (it only works when the URL is pasted into a browser).

BTW what supply voltage are you using and do you have the "normal" Charlieplex arrangement with resistors in series with the pins (i.e. two in series with each LED) or the configuration in #8 above with the LED anodes directly to the PICaxe pins?

Cheers, Alan.

#### Buzby

##### Senior Member
Hi Alan,

Power is 5v, and the four outputs each have a 470 ohm resistor in series, so effectively an illuminated LED has a 5v supply and a 940 ohm resistor.

The 'tristate' capacitor is 100uF, connected at the junction where the C.0 resistor meets the LEDs.
( See http://www.user.dccnet.com/wrigter/picaxe/12LEDpyramid2.gif. )

Cheers,

Buzby

Last edited:

#### chlgibbons

##### New Member

The code now works well with 08M and 08M2 and I have had a play with the speeds of the LED to get more challenging. Probably 75 with increments of 3 down to 45ish may be the one I go for. I used 1K series resistors( as they were available) for the outputs and 100uF capacitor for output 0 and I can't fault. Over the next week or so I will draw up the artwork for a PCB and get some etched and show them on here. My kids have played it and are addicted. Many thanks Buzby it's a cracking job. The only thing that would improve the game is some sound/tune from a piezo for the victory/fail unless anyone knows how to squeeze that out of it.

http://youtu.be/v-VjDsAi_hE

#### Buzby

##### Senior Member
... The only thing that would improve the game is some sound/tune from a piezo for the victory/fail unless anyone knows how to squeeze that out of it.
Now that is a challenge !.
I did try putting a piezo from 0v to C.4. It gives a 'tick' each time an LED flashes, and a bit of a buzz when the game ends, but it's too quiet and not musical at all.

I'm really pleased you've got it working. I hope your students like building it as well as playing.

The 08M2 can run much faster than the 08M, and I've been trying lighting multiple LEDs at once. It's looking promising, and opens up the possibilities of what can be built with 12 LEDs and a 8 pin chip. ( I'm working on seeing if we could make a shooting gallery game ! )

Cheers,

Buzby