Flashing lights for desk ornament based on 18M2+

DamonHD

Senior Member
#1
Hi

I promised my dad an ornament for this desk flashing 7 LEDs (6 in a ring with one in the centre) ... oh about 35 years ago! Yes, really.

Well today, with some consultancy from my 7yo daughter, I built it on breadboard. I will transfer it to strip-board in time for my dad's 70th!

Code is here:

https://sourceforge.net/p/picaxeplay/code/18/tree/trunk/7LEDs/18M2.bas

I can link to pics/videos if anyone is interested.

Rgds

Damon
 
Last edited:
#3
Yes, please post the circuit diagram and any photots on this forum and avoid the links to external site. (All too often I find broken links where folks link to their wown website with all good intentions but eventually after a few years the external website dissapears.

Well done on providing comemnts and use of indenting for looping and test structures :)

Here is the code to save folks going externally:
Code:
; n18M2.bas    234 lines (203 with data), 6.4 kB 
; *************************************************************
;
; Damon Hart-Davis licenses this file to you
; under the Apache Licence, Version 2.0 (the "Licence");
; you may not use this file except in compliance
; with the Licence. You may obtain a copy of the Licence at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the Licence is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the Licence for the
; specific language governing permissions and limitations
; under the Licence.
;
; *************************************************************
; Author(s) / Copyright (c): Damon Hart-Davis 2013

; Flashing 7 LEDs, a red/green bi-colour in the centre; 6 surrounding it in a circle.
; Bi-colour LED between B.3 and B.6 outputs (via 330R+).
; All other B.0 to B.7 outputs driving LEDs (connected to ground via 330R+) in clockwise order around the circle.


#picaxe 18m2 ; 18M2+ device.

#no_data ; Not using the EEPROM.

dirsB = %11111111 ; All outputs.

symbol LED_BI1_RED_C = B.3 ; Bi-colour LED red cathode (short leg), green anode.
symbol LED_BI1_RED_A = B.6 ; Bi-colour LED red anode (long leg), green cathode.

; C.0: LDR light sensor (ADC input); higher voltage indicates more ambient light.
; Should be pulled low externally whether LDR used or not, so can be left as input or set to low output.
symbol INPUT_LDR = C.0

; Light level (0 is dark, 255 is light).
symbol ambientLighting = B24
readadc INPUT_LDR, ambientLighting ; Take initial reading.
#rem
testPWM:
	readadc INPUT_LDR, ambientLighting ; Take initial reading.
	pinsB = $ff ; Everything on.
	gosub centreRedSet
	gosub pauseAndPWMLeds1s
	toggle LED_BI1_RED_C, LED_BI1_RED_A
	gosub pauseAndPWMLeds1s
	goto testPWM
#endrem


; Speed (and possibly brightness) settings.
symbol MAX_SPEED = 4
symbol MIN_SPEED = 0
symbol speed = B25 ; 0 is slowest (can be used with nap).


symbol randWord = W13 ; Random number store
symbol randB1 = B26
symbol randB2 = B27
; Initialise with bits from the internal temperature sensor.
readinternaltemp IT_RAW_L, 0, randWord

; Warm up with some spins...
	for speed = MIN_SPEED to MAX_SPEED
    	    gosub spinCW
    	    gosub spinCW
    	    gosub spinCCW
    	    gosub spinCCW
	next
	sleep 1

mainloop:
    readadc INPUT_LDR, ambientLighting
    W0 = ambientLighting * MAX_SPEED / 255
    speed = W0

    ; Maybe do some spinning...
    do while randB1 >= $40 ; 0 or more times, typically 2 or 3...
        random randWord
        if randB2 >= $80 then
            gosub spinCW
        else
            gosub spinCCW
        endif
    loop

    random randWord
    readadc INPUT_LDR, ambientLighting
    ; More likely to turn LEDs off and sleep here as ambient lighting falls.
    if ambientLighting < randB1 then
        pinsB = 0 ; All off...
        sleep 1
    else
        B12 = 255 - ambientLighting min 1
        gosub pauseAndPWMLeds
    endif

    ; Do some flashing...
    gosub briefRandomRound

    pinsB = 0 ; All off...
    sleep 1

    gosub reseed
    goto mainloop


; Stir a little entropy into the pool!
reseed:
    readinternaltemp IT_RAW_L, 0, W0
    randWord = randWord ^ W0
    random randWord
    randWord = randWord ^ time
    random randWord


; Pause for *nominally* 1s, matching LED output to ambient lighting.
; Destroys B11, B12, B13, B14, B15.
pauseAndPWMLeds1s:
    B12 = 100
; Pause in B12 units of *nominally* 10ms, matching LED output to ambient lighting.
; Destroys B11, B13, B14, B15.
pauseAndPWMLeds:
    B11 = pinsB ; Capture extant LED state.
    ; Software PWM on nominal 10ms cycle.
    B14 = ambientLighting / 25 min 1 max 10 ; On time: never 0.
    B15 = 10 - B14 min 1; Off time: nominally can be zero (for max brightness).
    for B13 = 1 to B12
       ; Aim for LED duty cycle to go down with the ambient light level.
       pause B14
       pinsB = 0 ; Turn all LEDs off.
       pause B15
       pinsB = B11 ; Restore state of LEDs.
    next
    return

; Pauses in inverse proportion to speed and may adjust brightness of LEDs to match (software PWM).
; Attempts to conserve energy too.
; Destroys B10, B11, B12, B13, B14, B15
pauseToMatchSpeed:
    B10 = MAX_SPEED - speed ; B10 is pause time on 'nap' (log) scale.
    B12 = 1
    if B10 > 0 then : for B13 = 1 to B10 : B12 = B12 + B12 : next : endif ; B12 is pause time on (linear) scale.
    gosub pauseAndPWMLeds
    return


; Spin clockwise at specified speed.
spinCW:
    pinsB = 0; All off...
    gosub centreRedSet
    high B.0
    gosub pauseToMatchSpeed
    high B.1
        low B.0
    gosub pauseToMatchSpeed
    high B.2
        low B.1
    gosub pauseToMatchSpeed
    high B.4
        low B.2
    gosub pauseToMatchSpeed
    high B.5
        low B.4
    gosub pauseToMatchSpeed
    high B.7
        low B.5
    gosub pauseToMatchSpeed
        low B.7
    return

; Spin counter-clockwise at specified speed.
spinCCW:
    pinsB = 0; All off...
    gosub centreGreenSet
    high B.7
    gosub pauseToMatchSpeed
    high B.5
        low B.7
    gosub pauseToMatchSpeed
    high B.4
        low B.5
    gosub pauseToMatchSpeed
    high B.2
        low B.4
    gosub pauseToMatchSpeed
    high B.1
        low B.2
    gosub pauseToMatchSpeed
    high B.0
        low B.1
    gosub pauseToMatchSpeed
        low B.0
    return

; Do brief round of random flashing at current speed, with fewer and dimmer LEDs on with lower ambient lighting.
; Destroys B0 and others.
briefRandomRound:
    random randWord
    B0 = randB2 & $3f + 32; Between ~32 and 95 rounds... 
    do while B0 > 0
        dec B0
        gosub allRandomSet
        if ambientLighting < $80 then
            random randWord
            pinsB = pinsB & randB1 ; For low light knock out about half the LEDs.
            if ambientLighting < $20 then
                pinsB = pinsB & time ; For very low light knock out about half of the remaining LEDs.
            endif
        endif
        gosub pauseToMatchSpeed
    loop
    return

; Randomise all the LED states, as normal (B) outputs, using randB2.
allRandomSet:
    random randWord
    dirsB = %11111111 ; All outputs.
    pinsB = randB2
    return

; Turn the centre LED red.
centreRedSet:
    low LED_BI1_RED_C
    high LED_BI1_RED_A
    return

; Turn the centre LED red.
centreGreenSet:
    high LED_BI1_RED_C
    low LED_BI1_RED_A
    return
 

DamonHD

Senior Member
#4
Photos/videos (none spectacular) start here (follow the next> links for more):

http://gallery.hd.org/_c/electronic...ng-7-LED-desk-ornament-closeup-1-DHD.jpg.html

And I attach one of the stills.

Note that the thing next to the LEDs is a resistor array rather than the PICAXE which is elsewhere on the AXE091 board!

Rgds

Damon

PS. No circuit diagram for this: recipe is in the opening comments in the code.

PPS. My sites have been up and running more or less without interruption since about 1993, so here is a link to the snapshot on my site: http://d.hd.org/PICAXE/7LEDs/ (with a slightly tweaked .bas file, as it happens).
 

Attachments

Last edited:
Top