Skill Level: Intermediate
Table Of Contents
- Introduction
- What Is Needed
- Background Information
- Constructing The Scene And Circuit
- Writing The Sketch
- Running And Testing The Simulation
- Additional Resources
- Summary
Introduction
This tutorial will show you how to use an Arduino to simulate fireflies so you can enjoy them any time of year.
A basic understanding of electronics and programming is expected along with some familiarity with the Arduino platform. If you are new to Arduino, or would just like to refresh your knowledge, please see our Blink: Making An LED Blink On An Arduino Uno tutorial before proceeding with this one.
This tutorial uses a schematic diagram to build a circuit. The All About Circuit’s Understanding Schematics and SparkFun’s How to Read a Schematic are good resources for understanding how to read schematics.
The resources created for this tutorial are available on GitHub for your reference.
What Is Needed
- Linux, macOS, Or Windows Based Computer With A USB Port
- Printer
- Arduino IDE
- Arduino Uno (Rev3 available on Arduino and SparkFun; WiFi Rev2 on Arduino and SparkFun) With Compatible USB Cable
- 9 x Male/Male Jumper Wires (available on Adafruit and Arrow)
- 9 x Alligator Clip Test Leads (available on Adafruit and SparkFun)
- 8 x Standard 5mm or 3mm Yellow LEDs (5mm available on Adafruit and SparkFun, 3mm available on Adafruit and Sparkfun)
- 8 x 330 Ω Resistors (available on SparkFun and Amazon)
- Conductive Copper Tape (available on Adafruit and Amazon)
- Masking Tape And/Or Electrical Tape (preferred for insulating electrical connections)
- Scissors
- Double Sided Tape Or Glue Stick
- Nail Or Tack
- Cardboard
Background Information
One night while watching fireflies in the backyard, my wife and I came up with the idea to create a firefly project that lit up the same way fireflies do in the summertime. She would create the design and I would create the electronics. For this project, we’ll be printing out her scene design and constructing the circuit on the back of the scene. In order to be as realistic as possible, I reviewed several sources on the internet to determine typical firefly flash timings. I did not realize that there were so many species of fireflies or that they were so different in their flash patterns. I started with some initial flash timings based on that research, but ended up fine tuning them in the sketch based on my own observations watching them in the backyard.
Depending on how you want your simulated fireflies scene to look and how permanent you want the project to be, there are a variety of options you can use for your scene and circuit. The scene can be physically propped up on its side with cardboard stabilizers or placed in a frame or shadow box for a more polished look. The electronics (LEDs and resistors) can be connected in the scene using solder, wires, conductive tape, alligator clip test leads, or some combination thereof. I chose a simpler and more temporary approach for my project, and this tutorial, using conductive tape and alligator test leads, but I am placing the scene within an 8″x10″ frame.
In addition, I wrote this tutorial using the standard Arduino Uno form factor to appeal to a wider audience. However, if you are interested in a more permanent display, one of the smaller form factors, e.g. Arduino Nano Every or Arduino Micro , along with a separate power source or battery may be more suitable for your needs. Specifically, I am using the Arduino Uno WiFi Rev2 development board connected to a macOS based computer running the desktop Arduino IDE. If you are using a different Arduino board or computer setup, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.
If you need assistance with your particular setup, post a question in the comments section below and I, or someone else, can try to help you.
Constructing The Scene And Circuit
Download the printable fireflies scene graphic (shown below) from the GitHub repository for this project. There isn’t anything electronically special about this scene, you can design and use your own scene if you prefer.

Print the scene onto a piece of paper and trim the edges to your desired size. I am using a size of 8″x10″ in order to place the scene within a frame of the same size.
Cut out a piece of cardboard (e.g. corrugated cardboard, cereal box, etc.) of the same size as the paper scene and attach the scene with glue or double sided tape to the cardboard. This makes the scene sturdy enough to attach our electronics.
The circuit for the fireflies will be constructed on the back of the scene according to the schematic shown below.

Poke holes in the scene with a nail or a tack where you want your LEDs to shine through. Poke from the front of the scene so that the excess paper and cardboard are pushed to the back. Use larger holes for fireflies in the foreground and smaller holes for fireflies in the background.
Tape the bodies of all the LEDs (on their sides) with masking or electrical tape over the punched holes on the back of the scene so that the light from the LEDs shines through to the front of the scene. All the terminals of the LEDs should be free of tape (available for connections).
Use long strips of conductive copper tape to connect the cathode (shorter lead) terminals of all the LEDs together to form a common ground.
Attach a 330 Ω resistor to the scene next to the anode (unconnected longer lead) side of one of the LEDs using masking tape across the body of the resistor, leaving both of the resistor’s terminals free. Attach the closest terminal of the resistor to the LED’s anode using a short strip of conductive tape. You may need to use additional masking or electrical tape underneath the connection in order to isolate the resistor connection from the ground connection. Do this for all of the other LEDs as well.
Verify all components are securely attached to the back of the scene and that you do not have any unintended circuit connections.
The back of your scene should look similar to the following once it is complete.

Next, we will connect our scene to the Arduino. Before connecting any circuitry to your Arduino board, disconnect it from power and your computer. This avoids accidental damage during wiring.
Attach one side of 9 male-to-male jumper wires to each of the Arduino’s 8 digital GPIO pins (2 through 9) and a ground pin.
Using the alligator clip test leads, connect the open terminal of each resistor in the scene to the Arduino GPIO jumper wires, and then connect the common ground on the scene to the Arduino’s ground (GND) pin.
Once you’re happy with your fireflies scene and circuit, you can add cardboard stabilizers to the back sides of the scene or place the scene in a frame. The completed scene and circuit should look similar to the following once completed.

Once the circuit and scene are built, verify that you do not have any unintended circuit connections. You can use electrical tape around the alligator clips for more protection.
Connect your Arduino to your computer with the USB cable.
Writing The Sketch
Open the Arduino IDE and create a sketch named Fireflies with the code shown below.
#define DEBUG 1 // mode of operation; 0 = normal, 1 = debug struct Firefly { uint8_t pin; // pin controlling the LED bool isLit; // current lit status; true = on, false = off unsigned long triggerTime; // last time the firefly was lit unsigned long triggerDelay; // delay between successive firefly light times }; const uint8_t LEDs[] = {2, 3, 4, 5, 6, 7, 8, 9}; // LED pins representing the fireflies const uint8_t LEDsNum = sizeof(LEDs) / sizeof(LEDs[0]); // number of LEDs (fireflies) const unsigned long LightTime = 500; // time that a firefly is lit in milliseconds const unsigned long MinDarkTime = 5000; // minimum time that a firefly is not lit in milliseconds const unsigned long MaxDarkTime = 10000; // maximum time that a firefly is not lit in milliseconds Firefly fireflies[LEDsNum]; // array of all firefly instances void setup() { if (DEBUG) { // Serial Monitor Serial.begin(9600); // initialize serial bus while (!Serial); // wait for serial connection Serial.println(F("Running in DEBUG mode. Turn off for normal operation.")); } // Configure all fireflies for (uint8_t i = 0; i < LEDsNum; i++) { pinMode(LEDs[i], OUTPUT); digitalWrite(LEDs[i], LOW); fireflies[i].pin = LEDs[i]; fireflies[i].isLit = false; fireflies[i].triggerTime = 0; fireflies[i].triggerDelay = random(MinDarkTime, MaxDarkTime); } } void loop() { // Process all fireflies for (uint8_t i = 0; i < LEDsNum; i++) { processFirefly(fireflies[i]); } } void printFireflyStatus(unsigned long currentTime, Firefly firefly) { Serial.print(F("Firefly: currentTime = ")); Serial.print(currentTime); Serial.print(F(", triggerTime = ")); Serial.print(firefly.triggerTime); Serial.print(F(", triggerDelay = ")); Serial.print(firefly.triggerDelay); Serial.print(F(", pin = ")); Serial.print(firefly.pin); Serial.print(F(", isLit = ")); Serial.println(firefly.isLit); } void processFirefly(Firefly &firefly) { unsigned long currentTime = millis(); // Light firefly at appropriate trigger time if (!firefly.isLit && (currentTime - firefly.triggerTime >= firefly.triggerDelay)) { if (DEBUG) { printFireflyStatus(currentTime, firefly); Serial.println(F(" Turning on firefly.")); } digitalWrite(firefly.pin, HIGH); firefly.isLit = true; firefly.triggerTime = currentTime; // Turn off firefly after appropriate lit time } else if (firefly.isLit && (currentTime - firefly.triggerTime >= LightTime)) { if (DEBUG) { printFireflyStatus(currentTime, firefly); Serial.println(F(" Turning off firefly.")); } digitalWrite(firefly.pin, LOW); firefly.isLit = false; firefly.triggerDelay = LightTime + random(MinDarkTime, MaxDarkTime); } }
The first line defines the debugging mode of the sketch. If enabled (DEBUG
is set to 1
), then a serial connection is established (lines 22-23) and debugging messages are displayed within the Serial Monitor. Set DEBUG
to 0
for normal operation.
The Firefly
structure, defined on lines 3-8, holds the relevant information required for each distinct firefly instance that we want to simulate. The pin
member contains the GPIO pin that will be used to control the LED for that specific firefly instance. isLit
holds the status of whether the firefly is currently lit or not. The triggerTime
member keeps track of the last time (in milliseconds) the firefly was turned on. And finally, triggerDelay
holds the delay (also in milliseconds) between the time the firefly was last lit to the next time that the firefly will be lit.
The LEDs
array, defined on line 10, specifies all of the GPIO pins that will be used to control the connected LEDs representing our fireflies. The sketch was written to take into account a variable number of GPIO pins. So if you want to use fewer or more pins to simulate your fireflies, the sketch can handle that. For instance, the next line automatically determines the number of LEDs used and stores that number in the LEDsNum
constant that is used throughout the sketch. I am using 8 GPIO pins in this sketch, the same number as the background scene, to demonstrate sufficient firefly activity. If you increase the number of LEDs, ensure the board you are using can handle the extra current load.
Lines 13-15 define the firefly flash timings. As mentioned previously these numbers are based on research and observation. LightTime
specifies how long each firefly will remain lit in milliseconds; a fixed half a second in this case. The MinDarkTime
and MaxDarkTime
constants define the minimum and maximum amount of time that each firefly will not be lit; defined here as somewhere between 5 and 10 seconds. These timing constants can be adjusted to suit your own needs or observations.
Line 17 defines the full array of individual Firefly
structures that are then initialized for use within the setup()
routine (lines 28-35). As you can see on line 34, I am randomizing the trigger delay value to be somewhere between MinDarkTime
and MaxDarkTime
.
The loop()
routine simply processes each firefly in turn by calling the processFirefly()
function on each firefly instance.
The processFirefly()
function, defined on lines 58-79, is the heart of the sketch. It compares the current time against the firefly timing constants to determine the appropriate times to turn on or off the firefly instance along with its associated LED. The isLit
, triggerTime
, and triggerDelay
firefly instance members are then updated as needed in preparation for the next time that the firefly will be processed. If the debugging mode is enabled, the printFireflyStatus()
function, defined on lines 45-56, is utilized to print the current time and status of the firefly instance upon each change of status.
If there is something that needs further explanation, please let me know in the comment section and I will try to answer your question.
Verify (Main Menu > Sketch > Verify/Compile) your code and fix any errors that are reported.
Save your program when you are done editing.
Running And Testing The Simulation
Now that our scene and circuit are built and our software is written, it is time to run and test our simulated fireflies.
Open the Serial Monitor (Main Menu > Tools > Serial Monitor) so that we can see the program’s output. Upload (Main Menu > Sketch > Upload) the sketch to the board and you should see all of the fireflies lighting up within the scene along with each firefly’s status change being printed within the Serial Monitor (if the debugging mode is enabled).
The following video shows my simulated scene.
Working Fireflies Simulation
If you are interested, try adjusting some of the firefly timing constants and watching how those changes affect your simulation.
The flash pattern and timings that I used for my simulated fireflies may be different from the firefly species you have in your neck of the woods. If you are feeling particularly ambitious, perhaps you can try to implement some of the more complex firefly flash patterns as described within the Talk Like a Firefly by Science Friday and Firefly Flash Patterns by the United States National Park Service articles.
Before we end, now would be a good time to upload the BareMinimum sketch (Main Menu > File > Examples > 01.Basics > BareMinimum) to reset all GPIO pins back to their default states. This ensures no outputs are being driven when plugging in your board for your next project.
Additional Resources
The following is a list of additional resources you may find helpful.
- Firefly on Wikipedia
- Talk Like a Firefly by Science Friday
- Firefly Flash Patterns by the United States National Park Service
Summary
In this tutorial, we
- built a scene with LEDs to display simulated fireflies,
- connected the scene’s LEDs to an Arduino,
- wrote a sketch to simulate the firefly flash timings of the LEDs, and
- ran and tested the sketch to display our simulated fireflies.
The final source code, schematic, and scene used for this tutorial are available on GitHub. The GitHub version of the code is fully commented to include additional information, such as the program’s description, circuit connections, and other details. The comments are also Doxygen compatible in case you want to generate the code documentation.
Thank you for joining me on this journey and I hope you enjoyed the experience. Please feel free to share your thoughts or questions in the comments section below.
This tutorial is provided as a free service to our valued readers. Please help us continue this endeavor by considering a donation.
Great tutorial thanks. Is there a way to start lights asynchronous and have it change to be synchronous based on proximity (people, objects, etc) ?
Thank you, I’m glad you liked the tutorial.
If you are wanting the fireflies to sync up their timings when a person or object is close by, you could include a distance sensor (Interfacing Ultrasonic Distance Sensors With An Arduino Uno) and process the fireflies manually when an object is in range. Something like the following should work.