Last weekend me and 3 other Altoms participated at Somes Delivery, a local event in Cluj that wants to present different ways of integrating the local river(Somes) into the lives of the city’s inhabitants. We applied with a project that proposes to bring digital fireflies on the banks of the river. They would be lights that react to noise and light.
The “fireflies” placed in two trees above a resting place by the river would light up only when the noise was under a set threshold. We wanted to encourage people to sit quietly and contemplate the river in the evening.
To reach this goal, we chose some technical elements that would constitute the installation: 400 addressable leds, 2 arduinos, 2 sound sensors, 2 light sensors, a raspberry pi, and a wifi router.
Here’s a schema of what the installation looked like:
The arduino boards would contain the code to animate the lights and model input from the sensors. The raspberry pi was used to communicate with both arduino boards and connect to wifi. This way we planned to be able to remotely control the sound and light thresholds, in case the environment conditions were not what we anticipated. We could also monitor the installation and get reports remotely, to understand if the leds are working or not. And to spice things up, we used the wifi connection to automatically set a special kind of lights animation for when people would post on social media using the #licuricilarau hashtag(which translates to #firefliesbytheriver :D).
We shared the project repo on github, in case you want to check it out.
We had several animations to simulate fireflies behavior. One of them was simulating a pulsating group. Each led is addressable and builds the color with Red, Green, and Blue. We could control the values of each of these colors, which affected their intensity. So the RGB values would vary in a certain time interval by a uniform rate, with a random parameter to avoid an artificial feel to how the lights were behaving (we used the sound sensor for the random seed). Another was simulating a firefly that was moving in between 2 fireflies clusters. For that we would sequentially light up the leds in the string.
In terms of technologies and languages, we used C for the Arduino code, and on the Raspberry pi we had a slack bot built with NodeJs that was running as a service.
This was a challenging project because of several aspects:
- We were working with scarce resources – limited memory – on Arduino, so the C code needed to be well optimized, which sometimes meant making it less readable, so bugs could lurk more easily.
- The installation was going to be placed in trees by the river, so the environment would be pretty much beyond our control.
- We were doing this after work, so we mostly spent evenings and weekends on it and hadn’t allocated much time for it.
- None of us had ever worked with this combination of technologies, so it was a process of discovery in terms of how to connect the lights, what type of current we need for the entire installation, and so on.
- We had a hard deadline: the starting date of the event
- We were in charge of everything related to figuring out how to build the installation, ordering the parts, actually building it, figuring out how to mount it and mounting it in the trees, and removing it after the event.
Although we thought of many of these aspects in advance and the associated risks they carry, some we discovered as we navigated through the project, and some we thought of during or after the actual event.
Before we began ordering parts and implementing the algorithm, all 4 of us gathered and discussed our goal and broke down the work into some starting tasks. We built a Trello board where we took ownership on these tasks and had an overview of what was left to do: someone was in charge of the logistical aspects, discussing with the organizers whatever details we might need, someone was in charge of testing the audio sensor to understand how/if we could use it in our context, someone else would implement the animation algorithms, and so on. We sometimes worked together on tasks, based on availability and skills.
We obviously didn’t anticipate everything that came along, and I don’t think we expected to. We knew where we wanted to get and with that common goal in mind we collaborated to get the results we wanted. This meant sometimes adapting, taking on new tasks, or leaving some tasks to other team members.
I think the teams I liked working with most on my projects had this in common: team members understood the project mission, testers, in particular, understood the testing mission, and they actively collaborated to achieve that. Instead of waiting for someone to assign tasks, the team self-organized to reach a goal each member shared and understood. Everyone contributed to the discussions about how to achieve that goal and the intention was to help the team. New ideas were encouraged.
Here are some of the risks we thought of:
- it might rain (which it did, a lot) and be windy up in the trees
- it might be noisier during the event than we anticipated, which meant there was a risk that the sound thresholds we set initially would not trigger the lighting at all
- it might be very hot were the arduinos and raspberry pi are placed
- we might not have access for debugging during the event, since people were around and the lights and devices were placed remotely up in the trees, well fastened so we would address the risk of theft
- the electrical supply was going to be provided by the organizers somehow (we didn’t know exactly how until 1 day prior of the event), and it might not integrate well with our installation
- the shape of the trees on which we would mount the installation might make the fastening more difficult and we would risk falling or breaking some part of the installation.
When we proposed the starting tasks, a lot of them stemmed from risks we considered. Similarly, often when I test a product, I start from a list of risks that I think are relevant and that I want to address. The risks shape both the building and the testing of products. They are part of the woven fabric of context.
This was both a hardware and software project, and I found it encompassed some of the challenges and risks I encounter in software projects I contribute to. It comes to show that small pet projects can be great learning opportunities, as although they might not embody the contexts in which we work with big teams, over a large interval of time, they do exemplify some aspects which are common to larger, more “serious” projects, like the dynamics between team members, the process of making decisions when we have limited resources, and of addressing important risks we identify.
As the project unfolded, we each took on different activities to help with reaching our goal. It was quite a wide array of activities, now that I look back:
- Researching fireflies colors and lighting behavior
- Searching for and ordering the needed parts
- Building custom sockets for the lights (on which another colleague, Ionut, helped us a lot)
- Figuring out how to access each led in a string
- Writing and testing the code for arduino and the Slack bot
- Understanding and testing the behavior of the sensors and how to set the thresholds
- Building a strategy for powering up the devices and leds
- Searching for a big ladder
- Clarifying the location with the organizers
- Searching for boxes to insulate the devices from dampness
- Mounting the wires, devices and sensors in the boxes
- Climbing in the trees and on the ladder to mount the installation and to remove it
- Verifying the system after we mounted it
- Monitoring the system while it was running
- Designing and implementing a website to present more information about the project
- Making stickers with the QR code and url of the website
Testing and surprising [hardware] findings
Since we didn’t have a power supply at the location until the evening before the event, we decided to test the system at the office. As soon as we had a version of the code which created animations for the lights and we could connect some leds to the arduino, we placed the installation in the office kitchen and kept it plugged in all day with 50 leds at first.
When we got the sound sensor, we integrated that as well. It helped us see how the system would behave when people were chatting around it. It allowed us to set a realistic threshold to detect voices in an otherwise quiet environment, and to see how the system reacts to prolonged usage.
It also helped us polish the animation and further model the behaviour of the fireflies. If initially we thought we would light off all leds when the sound was above a threshold, we realized we might as well light off only a percentage of them, based on how much the threshold is exceeded. And it revealed some interesting bugs too.
For example, when the pulsate animation was used, we would sometimes see isolated red flickering leds. We had a few theories for why this could happen: an overflow for the color values, or a wrong calculation. Having randomness in play made it more difficult to debug this issue. A good option could have been to animate all leds in the same way, instead of having a random variety, but we didn’t think of that then. The intermittent nature of this event also suggested it might be related to the electrical current. This issue seemed paired with another issue in which the first led of the series would be lit red always. The idea which seemed to solve both problems was to connect the ground wire of the data section of the light string to ground. Before we had connected only the ground of the power connection section. Although we thought of software causes for this issue, it seems the cause was related to the hardware.
As when testing software on projects, we noticed a behavior we considered out of place, developed theories to isolate the cause, and tested those theories.
We started with theories which were based on familiar oracles and previous experience, and as we eliminated them, we came up with ideas from different sources and looked at the problem from different perspectives.
We also looked at another weird behavior and asked ourselves if there might be a connection between that behavior and the one we are analyzing now. Might they have the same cause?
As soon as the DC power supply we needed arrived, we could connect more lights to the Arduino. We connected 200, the number we would have in “production” per Arduino, and continued to test them in the office kitchen. Here’s how messy it looked:
Again, we thought this was a relevant test in terms of how the system reacts to longer term usage. We knew it would need to function for 48 hours continuously, so we wanted to test it in similar conditions.
New problems were visible now. We used 4 strings of 50 leds each that we connected together. When we powered up all of them, the leds in the string at the end would flicker inconsistently. After some debugging and measuring the voltage across the line, the conclusion was we needed to add power input not only at the beginning of the long thread of lights, but also along the thread, to intermediary segments of leds. Once we added wires directly from the power supply to intermediary strings of leds, the problem seemed fixed.
The context in which the product will be used is an important aspect that guides my test design. This was very visible in this case, because we would place the installation in a very concrete physical environment in which users would interact with it. Like in the case of this project, I try to simulate this environment when testing, thinking of different dimensions, like:
- Where will the software product logic be placed physically? (Where are the servers?)
- From where are the users accessing it? (Platform, device, etc.)
- For how long will it be used? (What happens after x years worth of data is added into the system?)
- Who can interact with the system? (What types of users are there and how do they overlap/interact in the system?)
- What other input sources, apart from direct user input, does the system handle? (Is data gathered from various sources?)
- The information gathered when asking these questions can be an important source of risks, and of flows through the product.
We did try to simulate the production environment really well, however we fell short of one detail. We knew we needed an internet connection, but the details of that were not clear to us. The organizers mentioned the area should have a wifi network during the event, but we didn’t know if we could make the set-up we needed on it, or if the signal would be strong enough for our raspberry pi. We also talked to some people which had a guesthouse near the trees we would use, and they offered to share their internet connection. But again, we didn’t know if the signal would be powerful enough or if the set-up would be appropriate. It proved out that it would be most reliable to use our own access point, to place it and power it together with the rest of our devices. What was different now was that the power supply for the router was common with the raspberry pi and with the lights. Before we had used the wi-fi connection at our office, which was independently plugged in.
What happened during the event was that the power supply from which we plugged in all our devices would drop sometimes. And this resulted in an issue we had not seen before. This was an integration issue that only occurred if the raspberry pi and the router would boot at the same time. Somehow, the router would initialize later, and this resulted in the slack bot going crazy and posting every minute on slack redundant information. What seemed to happen was that the slack bot would start, call the “initialize the instagram connection” method, barely start executing the method, then crash and restart, and do that again, and again. What would “solve” this would be to restart the raspberry pi while the wifi router was plugged in. However, we could not do this remotely, so we had to got there whenever there was a power shortage and the whole system would restart. And, although we did not anticipate that, we had several power shortages during the event.
Although we tested at the office how the raspberry pi integrates with the arduinos and with an existing wifi network, we did not try booting the router and raspberry pi at the same time.
Since we did not have much control over the electric current connection at the venue, we studied the logs, but couldn’t do there a lot of follow-up tests. Some ideas we have now for further isolating this issue are: start the raspberry pi and only after plug in the router; or
try to reproduce the issue consistently by restarting the whole system.
This was, I think, a good illustration of the importance of integration testing and the value it can provide. Modelling the system as a set of elements that interact and communicate, then explore risks at the interfaces between them.
To my mind, this case was missing from our system analysis, because we did not model the wifi connection as part of the system, instead we took it for granted, as an exterior element.
Here’s a schema we built to model our system:
The wifi connection is missing from there. So although we did systematically address every combination of elements from that model, we left out the wifi router. We were blind to what was not explicitly part of our model.
An important part of doing integration testing well is modelling the system so as to include the relevant elements that are part of it. Some may not be very obvious, but lurk around in the background, taken for granted.
We can ask questions like “What else are we relying on?”, “What kind of services interact with our system?”. Another technique to identify missing elements could be to create the model, then put together the system from scratch based on it.
These are some of the lessons, reflections and reminders that emerged from this pet project. I hope this encouraged you to take on small projects involving contexts and technologies that are less familiar to you. The initial feeling of discomfort and uncertainty may turn into an exciting learning adventure!