Halloween LED lights on a plastic trick or treat cauldron

Halloween has past but it wasn’t uneventful. My two year old daughter went trick or treating for the first time and it was all so exciting!

When i saw the plastic cauldron she was carrying as a trick or treat bag i had an idea. I could use an arduino to operate red LEDs and make the cauldron flash on and off like little evil eyes. I knew she would love it!




Once I drilled the holes and got all the pieces I needed:

2 red LEDs soldered in series with a resistor.

I connected those to a breadboard arduino I had spare. (See my blog post on making a breadboard arduino.) You can just use a normal Arduino UNO here instead if you prefer. My reasons are because they're cheaper, and also because a breadboard Arduino uses less power and I wanted this to be battery powered.

I'm powering the whole thing with 3 AA batteries in a battery case. Because Maplin has shut down in the UK :((( I will have to wait for the battery holder to be delivered... no more weekend fun popping down the shop for parts. So for now I powered it with a bench power supply. You can see how much she loved it though. :)

Good, alkaline AA batteries have a capacity about 2000mAh, with three of them, that's about 6000mAh. If you look closely you'll see the project uses about 20-25mAh (depending how much light the LED is putting out at that point), so three AA cells should last about a week or two. Compare that to 600mAh for a good, alkaline 9v battery and you can see that battery choice is important! Plus a 9v battery would lose about half it's energy to the voltage controller... it would probably last less than a day! Finally, a full Arduino UNO board uses about 40-50mAh even without the LEDs (it has two microcontrollers on it, one atmega328p and one that just does the USB<->Serial interface). That would halve the battery life for no real benefit.







I proceeded to the programming.  The nice thing is that's now the easy bit thanks to S4A. :)

I opened the IDE and started with some of the code from the fade example in the community website.

https://github.com/swiftforarduino/community/tree/master/learning%20examples

So if you haven't looked over that example yet and gotten to know it, it's really simple. You declare a variable that will be the brightness of the LED:

var brightness: Int16 = 0

That's starting at zero (off) and going up to 255 (on at full brightness). In your loop you then use the magic function

analogWrite

...to set one of the arduino pins to that brightness value. You can see my youtube video on how it works if you're interested. There's a gotcha! Only pins 3, 5, 6, 9, 10 and 11 have this capability, all the other pins can only be full off or full on (this is a limitation of the underlying atmega328p chip).

Luckily in the IDE, when you drag out the code snippet for Analog Write, it already has a comment in there to remind you of this. You'll be scratching your head a lot if you forget and use a pin that doesn't have this capability!

So, back to the program. The next thing is after setting the brightness, I wait a little bit using

delay(milliseconds: ...)

Now, I change the brightness and go back and repeat the loop again. The next trick is once we have reached full brightness, we start going back in the other direction!

To make that work I have another top level variable:

var brightStep: Int16 = 1

This is the amount we will add to the brightness on each cycle.  Once we reach maximum brightness, we change it to -1.

Here's the loop:

while(true) {
brightness = brightness &+ brightStep
if brightness == 255 {
brightStep = -1
} else if brightness == -50 {
brightStep = 1
}
let realBrightness: Int16 = brightness > 0 ? brightness : 0
analogWrite(pin: 9, value: UInt8(truncatingBitPattern: realBrightness))
delay(milliseconds: 9)
}

So why do we use Int16 for the numbers? And what is this truncatingBitPattern nonsense?

Well S4A is built on safety, like all Swift, so that means types are really strict. AnalogWrite takes a UInt8 for the value so it cannot go outside of its defined range. But, unlike C, you can't just throw a UInt into an Int or an Int16 into an Int8 without clearly specifying what you're doing and how to handle all the edge cases where C might do something not explained or undefined. And we need to use Ints for the brightStep, so it can be negative. Int8 is too limiting so we use Int16.

And that's about it.  I wrote the above program, then tweaked things like the maximum and minimum brightness, delays, etc. until I got an effect I considered "spooky" enough.

And my daughter absolutely loved it!

You should have heard her squeals of delight.

One day soon, I'll show her how to program using S4A!



Comments

Popular posts from this blog

All about bootloaders

code signing, entitlements, bundles, sandboxes, hardened runtime, notarisation, app store security