(note: the firefly behavior in this video has been greatly sped up in order to be easier to represent in a short film. The default behavior has significantly more variance in its brightness and delay between plays.)
Step 1: About This Project
The inspiration for this project comes from having never lived in an area where fireflies were common and being deeply fascinated whenever I encounter them in my travels.
The flash patterns have been digitized from firefly behavioral research data found online and were modeled in Mathematica so that variations of speed and intensity could be generated. The final output was transformed by a lightness function and written into header files as 8-bit PWM data.
The software is written in avr-gcc C and source code is provided along with a pre-compiled .hex for convenience. The code has been significantly optimized for efficiency and to minimize power consumption. Crude runtime estimates predict a 600mAh 3V CR2450 battery should last between 4 to 10 months, depending on the song pattern used. RIght now the source comes with two patterns, song1 and song2, with song2 as default. Song2's estimated runtime is 2 months, song1's is 5 months.
This project involves a fair amount of surface-mount level soldering. However the circuit design is trivial and the fact that we're able to use an off-the-shelf SMD prototyping board rather than having a custom PCB made greatly saves on cost. It would be very simple to create a non-surface mount version using the PDIP version of the ATTiny45 and through-hole LED's.
The cost of the electronic components comes in at around $10-$15 (after shipping) or so and assembly time is on the order of 2 hours.
Step 2: Parts
In this section I list the parts I used in the construction of this project. In many cases, the exact part is not required and a substitute will suffice. For instance, it isn't required that you use a CR2450 battery to power the circuit, any 3V power supply will suffice and CR2450's just happened to be the cheapest battery that I found which fit the size and capacity requirements I was looking for.
- 1 AVR ATTiny45V microcontroller, 8-pin SOIC package (DigiKey part# ATTINY45V-10SU-ND) (see note 1)
- 1 Surfboard 9081 SMD prototyping board (DigiKey part# 9081CA-ND)
- 6 Green LED's (DigiKey Part# 160-1446-1-ND) (see note 2)
- 1 22.0K Ohm 1206 resistor (see note 3)
- 2 100 Ohm 1206 resistors (see note 2)
- 1 CR2450 battery holder (DigiKey Part# BH2430T-C-ND)
- 1 CR2450 battery (any 3V power supply will do)
- 1 spool of #38 Magnet wire (Ngineering.com Part# N5038)
- 6 inches or so of bare thin wire, I used stripped wirewrapping wire but about anything will do
#1 - The difference between an ATTiny45V and an ATTiny45 is that the ATTiny45V is spec'd to run on voltages between 1.8V - 5.5V while the ATTiny45 wants 2.7V - 5.5V. For this project, the only implication is that the ATTiny45V can possibly run for just a little bit longer as the battery dies. In reality this probably isn't the case and the ATTiny45 can be considered interchangable with the ATTiny45V (guess which one I happened to have on-hand when I started?). Use whatever one you can get your hands on. Also, the ATTiny85 will work just fine too for a little bit more money.
#2 - Substituting a different model of LED with different current-draw characteristics will have implications on what resistor you use. See the Circuit Schematic section for more information and check the spec sheet for your LED's.
#3 - This is only a pull-up resistor, the specific value is not important. It just needs to be 'big enough' without being 'too big'. See the Circuit Schematic section for more information.
Step 3: Tools
These are the tools I used:
Radio Shack #270-373 1-1/8" Micro Smooth Clips
"clip-on-a-stick" - One of the Micro Smooth Clips mounted on a nail or other sort of stick.
Temperature-Regulated Soldering Iron with a fine tip (I use the Weller WD1001 digital soldering station with 65 watt iron and 0.010" x 0.291"L micro tip). On a budget however, a 15-watt Radio Shack style soldering iron should be fine.
Multimeter (for circuit testing)
Flux (I like the Kester Water-Soluble Flux-Pen, available at HMC Electronics (part# 2331ZXFP))
Solder (the thinner the better)
Exacto Knife / Razor blade
Step 4: Circuit Board Assembly - Part 1 of 3
Preparing the circuitboard and attaching the resistors -
Flux the pads -
I tend to flux everything, even when using solder that already contains flux. This is especially true when I'm using the water-soluable flux-pen since cleanup is so easy and the pen makes it easy to not get flux everywhere.
Solder jumper wire across pads as illustrated -
The consequence of not having our own PCB made for this project is that we have to add our own bus wires. Also note the bus wires on PIN_C, PIN_D, and PIN_E. These are not strictly necessary but it looks cleaner this way and also gives us some elbowroom when attaching a clip to the microprocessor for programming.
Solder resistors to the board -
There are a number of good guides on the internet with examples of how to solder surface mount components. In general, you want to start by puting a little bit of solder on one pad. Holding the component in a pair of tweezers, heat the solder and hold one side of the component in the solder until it flows onto the pin. You want to keep the component flush with the board while you're doing this. Then, solder the other side. See the pic.
Step 5: Circuit Board Assembly - Part 2 of 3
Soldering the microcontroller to the board -
Bend pins on the microcontroller -
Another consequence of not having our own PCB made is that we have to deal with the unusual width of the ATTiny45 chip which happens to be slightly wider than will comfortably fit on the Surfboard. The simple solution is to bend the pins inwards so that the chip stands on the pads instead of sitting on them.
Solder microcontroller to board -
Again, there are many SMD soldering guides out there but the executive summary is this:
- Flux the pins of the chip (I find this makes it *much* easier to get a good solder joint, especially with the weird surface topology of these bent pins)
- Hold the chip to the pad and draw solder down from the square pad and onto the first pin of the chip (add more solder if there isn't enough on the square pad but you'll typically have enough already).
- Make sure that the solder actually flows up and *onto* the pin. The soldering motion is sort of like "pushing" the solder onto the pin.
- Once the first pin is soldered, go to the pin on the opposite corner of the chip and solder that down as well. Once those two corners are tacked down, the chip should remain firmly in place and the remaining pins become simple to complete.
Also, be very careful that you solder the chip to the board in the correct orientation! If you look closely on the chip you'll see a little round indentation on the top in one of the corners. That indentation marks pin #1 which I've otherwise marked as the "reset' pin on the chip (see diagram). If you solder it down in the wrong orientation, I promise you that it won't work ;)
Step 6: Circuit Board Assembly - Part 3 of 3
Test all connections -
Since everything is fairly small here, it's quite easy to make a bad solder joint that looks fine to the eye. That's why it's important to test everything. Use a multimeter and test all of the pathways on the board for connectivity. Make sure to test everything, for instance don't touch the probe to the pad that the pin of the chip looks soldered onto, touch the pin itself. Also test the resistance values of your resistors and make sure they match with their expected values.
A small problem now is easy to correct but becomes a big headache if discovered after all the LED strings have been attached.
Step 7: Making a Firefly LED String - Part 1 of 4
Prepare the wires -
Ngineering.com has a good writeup of how to work with this magnet wire and covers tinning as well as twisting it which are two steps of making a firefly LED string. However I've never been satisfied with the results of burning away the insulation as they describe in the guide and have instead settled on gently scraping the insulation away with a razor. It's quite possible that I simply wasn't doing the tinning steps right (despite many attempts) and your own mileage may vary.
Cut red and green wires to desired length of string. I prefer to use different lengths of wire for each firefly string so that once assembled they don't all hang at the same "altitude". Generally I calculated the lengths that I was going to use by figuring out the shortest string (based on measuring the jar I was going to use), the longest string, and dividing the interval between them equally into 6 measurements. The values I ended up with for a standard widemouth jelly jar are: 2 5/8", 3", 3 3/8", 3 3/4", 4 1/8", 4 5/8".
Strip one end of each wire exposing a millimeter or less. Using the razor method, gently scrape the insulation away by softly dragging the blade over the wire. Turn the wire and repeat until the insultation has been removed. Using this method I find it hard to only strip a millimeter of wire so I simply cut off the excess.
Step 8: Making a Firefly LED String - Part 2 of 4
Preparing the LED -
Using a microclip, pick up an LED so that the bottom side is facing out, exposing the pads.
Mount microclip + LED in the helping-hands and apply flux to the pads on the LED.
Step 9: Making a Firefly LED String - Part 3 of 4
Soldering the LED -
Using another microclip, pick up the green wire first and mount it in the helping-hands.
Now comes the hardest part of the project, soldering the LED. Manipulate the helping hands so that the exposed part of the green wire is resting gently on the cathode pad of the LED. This is the time-consuming part that requires patience and cannot be rushed. Plan your moves in advance and act slowly and with deliberation. This is basically ship-in-a-bottle type delicate work and shouldn't be underestimated. However you don't have to be the favorite son of a watchmaker in order to pull this off either, it *is* within the realm of mortals. I find it considerably easier to manipulate the arms of the helping hands rather than the wire itself or the microclip.
Rest the exposed part of the wire on the cathode pad and arrange your mangifying gear and lighting to make sure you can perfectly see what you're doing in preperation for soldering.
Using a soldering iron set to around 260 degrees C, pick up a very small blob of molten solder onto the tip of the iron and, very gently, touch the tip of the iron to the cathode pad on the LED. A small amount of solder should instantly run off of the tip and onto the pad (thanks to the flux), securing the wire to the pad in the process. Be careful not to burn the LED by holding the iron to the pad too long (3 seconds max, when done right you need less than 0.10 seconds of tip contact, it's very fast).
Unfortunately what tends to happen here is that you knock the wire off the pad with the tip of the iron, forcing you to go through setting it all up again. For that reason you have to be *very* slow and gentle with the iron. I tend to place my elbows on the workbench on either side of the helping-hands and hold the iron with both hands in a seppuku type grip, gently bringing the iron down towards the pad. This grip is sometimes the only way I can get enough control. Another tip: don't drink a pot of coffee before attempting this.
This does get easier with practice.
(Very gently) tug on the green wire to test that it's firmly secured. Release the wire from the microclip and, without changing the orientation of the LED, repeat the process with the red wire, only this time soldering it to the anode pad of the LED. Since the red wire will be flying over the cathode (green) pad, it's important to not have too much exposed red wire, lest it come down in contact with the cathode pad and create a short.
Step 10: Making a Firefly LED String - Part 4 of 4
Twist the wires and test -
Once both wires have been attached to the LED it's time to twist the wires. Twisting the wires results in a cleaner look, greatly adds durability to the LED string, and also reduces the number of delicate free-flying wires you have to deal with when working with the board later.
To twist the wires, begin by mounting a microclip in your helping-hands and clip it to the two wires right beneath the LED. Now, using another microclip (I have it mounted on a nail to make this process easier), grab the other end of the string about 1.5 inches from the end. Gently twist the microclip while applying just enough tension to keep the wires straight until the wires are sufficiently twisted together. I tend to prefer a somewhat tight twist as this results in a string that's easier to keep straight.
Once the string has been twisted, strip about 2-3mm from the free end of the wires and test by putting 3 volts through a 100 Ohm resistor and into the ends of the wires. I've found it very difficult to make a good connection by pressing probes into the bare ends of the magnet wire so I clip microclips onto the ends and touch those with the probes instead. You don't have to get a good solid "ON" from the LED for the string to pass the test, since even with the clips its hard to get a good connection. Even a few flickers are enough to pass. When soldered, the connection will be much better.
Set the LED string aside in a safe place.
Repeat this process for each of the 6 strings.
Step 11: Attaching LED Strings to the Board - Part 1 of 2
Bundle the red string wires into 3-wire groups and solder to the board -
Once you've completed all six of the LED strings and the circuit board, it's time to attach the strings to the board.
Sort the LED strings into two groups of three. For each group, we will twist and solder the three red wires together into one and then solder that to the board.
Grab three of the red wires between your thumb and forefinger. After taking special care to ensure that the stripped ends of the three wires all line up, microclip the three wires close together and mount the microclip in the helping-hands.
Twist the exposed parts of the wires together. This is to prevent them from coming apart while you solder them to the board.
Tin the twisted ends of the wires with solder. Use flux to ensure a good contact between the wire tips (the last thing you want to do is have to untwist these three wires to get at one that's not making good contact).
Carefully solder the red-wire bundle to the far side pad of PIN_A, so that the resistor seperates the bundle and the microcontroller.
Repeat the process with the other three LED strings, soldering the bundle to the far side of the resistor on PIN_B.
You should now have both 3-string bundles soldered to the board with the green wires flying free.
Step 12: Attaching LED Strings to the Board - Part 2 of 2
Bundle the green wires into 2-wire bundles and solder to the board, test -
Using a similar process to how you made the red 3-wire bundles, join the green wires together into 2-wire bundles and solder them to PIN_C, PIN_D, and PIN_E. By not soldering the bundles to the pad closest to the microcontroller, we give ourselves more elbow room should we need to do any touchup soldering work on the microcontroller or attach a programming clip to the board.
Once all the LED strings have been soldered to the board, it's a good idea to test them. With a 3V power source, test the strings by placing a positive voltage on either PIN_A or PIN_B, being careful to place it *behind* the resistor since 3V will damage these LED's without it, and moving the negative voltage between PIN_C, PIN_D, and PIN_E. Each combination of pins should result in a LED lighting up when probed.
(if your chip happens to be already programmed at this point then simply applying power to the board (VCC and GND) should be enough to test all six LED's in one go. The provided program cycles through all the LED's on boot.)
Step 13: Preparing and Attaching the Battery Holder
Take the wires that you're going to use to attach the battery holder with and cut them to length. I tend to use the following lengths:
Red Wire: 2"
Green Wire: 2 3/8"
Strip a little bit off both ends of the wires and solder one end of the wire to the battery holder and the other end to the circuit board, being careful to get the polarities correct. Check the illustrations for details.
Also, once you have soldered the wires to the battery holder, you may want to snip the pins on it short so its not quite as awkward to attach to the lid of the jar.
Step 14: Final Assembly
By this point you've completely assembled the circuit board and attached the LED strings and battery holder.
All that's left is to program the chip and affix the board assembly to the lid of your jar.
As to how to program the chip, I'm afraid that's a bit beyond the scope of this document and is heavily dependent on what platform of computer you're using and what development environment you're working with. I've provided the source code (written for GCC) as well as compiled binaries but figuring out what to do with them is up to you.
Thankfully, there are loads of good resources out there for getting started with AVR, here are a couple:
http://www.avrfreaks.net/ - This is the penultimate site for AVR. The active forums are indispensable.
http://www.avrwiki.com/ - I found this site quite helpful when I got started.
If there's sufficient interest I may put together a kit so that people don't have to get their hands dirty with the chip programming aspect.
As for attaching the board and battery to the lid, there are probably a million ways to do this but I'm not confident that I've found the best one yet. The methods that I've tried have been to use either epoxy or hot glue. I've already had a few instances of epoxied boards pop off so I wouldn't recommend using that. Hot glue seems to work ok but I have little faith that after a few hot/cold cycles it'll fair much better than the epoxy.
So, I leave figuring out how to attach the board and battery holder to the lid up to you as well. However I will offer a few tips:
-- Be careful that when you attach the battery holder that the two pins don't short out due to the metalic lid. Some lids are insulated, others aren't.
-- http://www.thistothat.com/ -- This is a website that offers glue recommendations based on what you're trying to glue. For glass to metal (the closest approximation I can think of for silicon circuitboard) they recommend "Locktite Impruv" or "J-B Weld". I haven't ever used either.
Step 15: [Appendix] Circuit Schematic
This section describes the design of the Jar o'Fireflies circuit and is meant to shed light on some of the design decisions made. It is not neccessary to read or understand this section in order to build your own fireflies. However it will hopefully be of use to anyone wanting to modify or improve the circuit.
The following schematic describes the Jar of Fireflies circuit. In particular, there are a few notes to make about its design:
VCC - the positive terminal of your 3V power supply (i.e. battery), for those unfamiliar with electronic schematic naming conventions.
GND - likewise, this goes to the negative terminal on your battery.
R1 - 22.0K Ohm resistor - This is used as a pull-up resistor to drive the voltage at the reset pin high during operation thus preventing the chip from being reset. The circuit would actually work just fine if this resistor was simply replaced by a wire. However there would be one critical difference: you wouldn't be able to reprogram the chip once it was soldered to the board. The reason for this is because the chip programmer wouldn't be able to drive the reset pin low without shorting to VCC at the same time. That's the sole purpose of R1, to allow a chip programmer to toggle the reset pin without shorting to VCC. As such, the value of R1 isn't actually important, so long as it's 'large enough' (without so large as to block the reset pin from seeing VCC at all). Any value between 5k-100k is probably just fine.
R2,R3 - 100 Ohm resistors - The value of these resistors dependent on the characteristics of the model of LED's you happen to be using. Different LED's, even of the same size and color, have widely different characteristics, particularly when it comes to how much current they draw and how much light they produce. For instance, the model of LED's that I wound up using are spec'd to draw around 20mA at 2.0V and 10mA at 3V through a 100 Ohm resistor.
Now had I this circuit to do all over again, I probably would have chosen a slightly larger value for R2,R3. The reason for this being that, were I to see a firefly in nature glow as brightly as one of these LED's do at 10mA, I would expect it to explode in a wet green mist a millisecond later. That is to say, at 10mA these LED's glow too brightly to be realistic fireflies. This is an issue that I addressed in software by limiting the maximum brightness that the LED's are ever driven at. If you use the same part # LED's that I used, you'll find the firefly software to already be tuned to an appropriate brightness. Otherwise, unless you intend to change the brightness scaling in the source code, you may find yourself going back and fiddling with the value of R2,R3 to find a value more appropriate to whatever LED's you end up using. Fortunately, this shouldn't take much effort as SMD resistors are easy to rework.
PIN_A,B,C,D,E - These are names that I arbitrarily gave to the pins in order to tell them apart and I refer to the pins by these names in the source code. Pins A and B I refer to as "master" pins. If you don't plan on reading the source code, then this distinction won't make any difference. If you do plan on reading the source code, hopefully the comments I've placed in it will sufficiently describe the role of the master pins and how the LED's are driven.
Irregardless, here is the executive summary of how the LED's are driven:
Before a firefly 'song' is played, a random decision is made as to what LED is to be driven. This decision starts with the selection of the 'master' pin, either PIN_A or PIN_B. This selection narrows down the choice of what actual LED's can be driven. If PIN_A is chosen, then we have a choice between LED1, LED2, or LED3. Likewise for PIN_B and the other LED's. Once the master pin is chosen, then we randomly choose the specific LED to drive from the reduced list of candidates.
For example, lets say that we've chosen PIN_A and LED2.
To turn LED2 on, we drive PIN_A high and drive PIN_D (the pin that the other side of LED2 is connected to) low. To turn LED2 off again while playing the song, we leave PIN_A high and drive PIN_D high as well, thus removing the potential difference between the two sides of LED2 and stopping the current through it, turning it off. Since we leave PIN_A driven high all the time, we can also choose to play either of the other two LED's, LED1 or LED3, completely independently. In practice, the code is written to play a maximum of two songs at the same time (two firelies glowing at the same time).
Step 16: [Appendix] Source Code
The file firefly.tgz contains the source code and compiled .hex file for this project.
This project was built using avr-gcc 4.1.1 (from the FreeBSD ports tree) along with avr-binutils 2.17 and avr-libc-1.4.5.
Step 17: [Appendix] Production Notes
The photos in this Instructable were all taken using a Canon SD200 compact digital camera and processed (read: salvaged) in Photoshop.
(Trying to take pictures of small objects floating in space wth complex depths of field without any form of manual focus could be an Instructable itself. yerg.)
Step 18: [Appendix] Areas for Improvement
It's somewhat of a personal problem of mine that I have a tendency to start projects but never finish them. I tend to get overfocused on little twiddly details that, while interesting and neat, aren't terribly relevant when zoomed out to the big picture, and this tends to go on until finally my interest in the project as a whole evaporates and I move onto something else. I've determined that this tendency makes me ultimately unhappy and that's why, three months ago when I started work on this project, I resolved to put this behavior to an end and that this project was going to be the first step -- I was going to finish something (dammit).
Sure enough, while working on this project all sorts of neat ideas and whizbang features popped into my head. However, due to time constraints and my resolution to finish the project, some of them had to be abandoned on the drawing board. In this section I record some of my thoughts for improvement on the project, in case someone else wants to take it upon themselves to make it better. A number of these have already been brought up by other users in the comments, and I wanted to comment on those a little.
Probably more than any other feature, this is the one I regret having to have dropped the most, as it would have been quite cool (at least how I was intending on doing it).
The basic idea I was going to use was to take advantage of a little-known property of LED's, namely that if you shine light on them, they will generate a tiny voltage. I.e. they work as little photocells. In fact I've seen someone build an extremely inexpensive solar tracker (used to keep solar panels facing the sun all day) using this effect (brilliant, I thought). Anyways, it was my intention to use this effect as well, along with the analog to digital (ADC) feature of the ATTiny45 to detect the ambient light level in a room and automatically turn off if it got too bright.
I prototyped this out, using ADC1 (PIN_D), and setting up the ADC to compare the voltage on this pin to the internal reference voltage of 1.1, and it *worked*. I was able to get results that went up as high as about 30 in quite bright light (next to a 100watt bulb). So I was reading a range of 0-30 or so, which should at least be enough to make some sort of decision as to how bright the room was. So I indeed believe it's possible to do this entirely in software without making a hardware change. How cool is that?
I did run into some caveats however. For instance, without any extra components, the values I was reading back tended to be extremely noisy, almost to the point of being useless. I'd see huge swings in the values I was reading off and, while indeed I'd see the average bias of those swings change with the amount of light, the signal to noise ratio was just too extreme. I found that by adding a small capacitor between PIN_D and GND tended to clean this up and it was when I was using the capacitor that I got the most reliable values. I think a 4.7uF cap gave me pretty good results. However, I didn't get so far as to investigating whether or not having the capacitor installed would significantly interfere with playback or make it impossible to program the chip on the board. That investigation I leave up to you.
The biggest issue that prevented me from going through with this was that of calibration. I was planning to give these out as christmas gifts to my family and friends and I had no idea how bright the room they were going to place them in would be. So how do I, as the fireflies, determine when to turn on and when to turn off without risking being "always off" or "always on" simply due to the choice of where I was placed? This was the technical obstacle, that of calibration, that ultimately forced me to abandon the idea.
I considered putting a little solar cell on the lid of the jar and using that to charge a rechargable battery instead of using the lithium coin cell. Also, this could be used as a means of detecting the ambient light level in the room and turning off it its too bright.
I think I stopped looking into the idea when I saw how much it would cost to buy solar cells that were small enough and yet could put out greater than 3 volts. Also, I'm not so solid in the raw electronics that working out the battery charging part of the circuit is something I can do easily (i'm still mostly a software guy).
It's certainly doable, I'm sure.
For the reference of anybody looking into this, here are the estimated average current values for the firefly circuit, depending on whether you're using the song1 pattern or song2 (song2 is default)
song1 = 0.159mA
song2 = 0.405mA
This is average.
Also, I considered possibly using a solar cell coupled with a supercap instead of a battery, but calculated you'd need a freakishly large one (2F or greater) to get any reasonable sort of runtime out of it. It still may be possible however and I wouldn't discourage someone from looking into it.
The idea is to make the fireflies move somehow to increase the realism. I didn't consider this one long since adding any kind of motor is going to have a disasterous impact on the battery life and also I couldn't figure out how I'd get the motor to move the fireflies in any way that looked remotely realistic. Just having a motor agitate the strings would result in fireflies that quickly swung back and forth like tiny little pendulums, and I couldn't imagine firefiles moving like that even after a half-dozen vodka martinis.
More LED strings (10 strings)
My original design was to have 10 LED strings charlieplexed in such a way that I could still play two songs at the same time. I worked out the logical connections, however I don't remember if I fully checked out that they would work 100%. Anyways, I've provided the last drawing I made of that idea before I abandoned it for the 6 strings idea (chiefly because I found that making the strings was a pain in the ass). It's up to you to figure out if it's workable or not.