Electronics Software Development

Simulating Fireflies With An Arduino

Arduino Fireflies Graphic
Written by John Woolsey

Skill Level: Intermediate

Table Of Contents

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.

Fireflies Scene
Fireflies Scene

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.

Schematic Diagram Of The Firefly LEDs Connected To An Arduino Uno
Schematic Diagram Of The Firefly LEDs Connected To An Arduino Uno

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.

Components Attached To Back Of Fireflies Scene
Components Attached To Back Of Fireflies Scene

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.

Completed Fireflies Circuit Connected To An Arduino Uno
Completed Fireflies Circuit Connected To An Arduino Uno

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.

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.

About the author

John Woolsey

John is an electrical engineer who loves science, math, and technology and teaching it to others even more.
 
He knew he wanted to work with electronics from an early age, building his first robot when he was in 8th grade. His first computer was a Timex/Sinclair 2068 followed by the Tandy 1000 TL (aka really old stuff).
 
He put himself through college (The University of Texas at Austin) by working at Motorola where he worked for many years afterward in the Semiconductor Products Sector in Research and Development.
 
John started developing mobile app software in 2010 for himself and for other companies. He has also taught programming to kids for summer school and enjoyed years of judging kids science projects at the Austin Energy Regional Science Festival.
 
Electronics, software, and teaching all culminate in his new venture to learn, make, and teach others via the Woolsey Workshop website.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.