Python and the 555 Blinking Eyes in the Bushes
For Halloween, I had wired the bushes in front of my house with a dozen or so pairs of blinking LED eyes. Each pair of eyes blinked at their own rate–all powered by an Arduino. After building these centrally-wired daemonic bush entities I wanted to be able to deploy a few more in remote bushes and trees without having to wire them up to an Arduino. So I turned to my good friend the 555 timer chip. 555 timers for the uninitiated are a very versatile integrated circuit that can be used in a variety of timer-related circuits.
LED blinky eye units consisting of craft popsicle sticks and pipe cleaner anchors deployed in a bush.
I was looking to achieve a very specific blinking pattern and was having a hard time figuring out the optimal set of components to use. There are tons of calculators out there for figuring out the characteristics of a 555 circuit based on the values of the components you use. If you’ve ever tried using one of these calculators for this sort of project it can be very frustrating. I don’t actually care what the components’ values are; I’m usually not thinking about that side of the equations at all. What I really care about are the timing characteristics of the circuit in terms of how long a signal is high and how long it is low. I want my “on time” to be X seconds and I want my “off time” to be Y seconds. You figure out what components I need to plug in to get that behavior.
Most of the existing 555 calculators I was able to find take the component values (e.g. R1= 100k, R2= 150k) and then compute the frequency, time_high, duty cycle, etc. I would rather think about the behavior I’m after and plug in the time_high and time_low and receive the values of the components I should use to achieve such a circuit.
Hang on. Let’s turn the real world dial up one more notch. It just so happens, I don’t have a resistor measured at 183.45 Ohms to achieve the specific oscillation I desire. Maybe we could constrain the calculator to only consider component values for components I actually have in my possession. Give me the best possible fit for the components that I do have (or can get my hands on).
So, I whipped up a simple Python tool to help me optimize my component selection to best achieve my desired blinking pattern. Here is an example snippet that solves the 555 timing equations using my inventory of components and my desired signal characteristics:
from optimize_555.opt import optimize
target_high = 42 #42 seconds on
target_low = 15 #15 seconds off
R1, R2, C, time_high, time_low = optimize(target_high, target_low) “’
This results in a timing circuit that goes high for 45.7 seconds and then has a 15.2 second low. And the best part of it is it’s accomplished using components that I have in-stock. R1 is 200KOhm, R2 is 100KOhm, and C is 220uF. The system defaults to a set of commonly available components, but you can override and define your own inventory.
In its current form its a very thin wrapper around some basic SciPy functions. You can check it out over at github. If there is some interest, I hope to expose it through a web interface at some point to make it more accessible to non-programming, electronic hobbyists. Hope it helps and happy blinking!