I’ve built some lights to go on my kites and they have all kinds of patterns and colors. I was asked about how they were made, and several people asked if they could buy some. I’m going with the easier route of describing how I made them. Maybe someday I’ll sell completed sets.
This is not a tutorial for YOU to build one, and I’m not posting source code, although I might write one in the future. If you’re looking to build your own similar project, that’s wonderful and I hope this can help.
First, a video of the lights in action:
This is not a finished project. As I described to a few discussions online, for me these are more like LEGO blocks. You pull out the bucket of parts, build something, tinker with it, and throw the parts back in the bucket when you’re done. When you come back later you pull out the parts and build something different.
This version is actually the third version of the light’s hardware. Some of the code has pieces from prior versions that don’t do much of anything, or that could even crash the program if I triggered them.
This project started in part with a Christmas gift — a gift card given to me a little bit early so I could buy a real present for myself. I had known about lights on kites for ages. I’ve seen kite magazines from the 1980s and 1990s with ads for light strips, and I’ve occasionally seen them in videos and shows. They looked fun. I wanted to try it, and to liven it up a bit with motion.
So I bought a programmable addressable light strip. Specifically a WS2812B light strip through Amazon. You can get them through various companies and under various brand names, so shop around. Since the perimeter of the kite is just over 5 meters, I got a 5 meter strip with 60 lights per meter, totaling 300 lights. Shop around if you build something like this, because they’re the most expensive individual part.
One issue with pixels is the space they take. Unfortunately most of the programs don’t use a packed array with 3 bytes per pixel, or allow for more condensed pixel formats like 565 or 444 or anything else. The FastLED library uses 32-bit values for RGBW, and works with both RGB lights and RGBW lights that include a white component. The NeoPixels library from AdaFruit takes the same memory per pixel, plus some additional overhead, and it runs more slowly. The FastLED library also had some cool built-in test patterns and utilities, so I went with that.
I knew I wanted to control the lights with direction, and with a wireless connection, but more on those in a minute.
Next up, an Arduino microcontroller (a small computer chip) to control the lights. The basic Arduino board has very little memory. With 300 lights a huge chunk of memory would be taken, leaving little room for bluetooth communications or sensors. The Arduino Mega has plenty of memory and lots of pins to work with, so I went with one of those for the first iterations. That’s not the board I’m currently using, so don’t jump out and buy one because there are better choices.
For communications I went with a small Bluetooth chip. For the sensor there are a bunch of chips to choose from. The better chips include a range of sensors, typically a gyroscope to detect changes in direction, an accelerometer to detect force (including gravity), and a magnetoscope to work as a compass. Each of these chips works using something called I2C to communicate, so they require two connections for power and two connections for data. That’s four wires soldered on each end.
All of this needs a battery for power. The Adruino board can run from USB power. The lights are able to draw power from the board if there is enough available. So in the early iterations, I used a small USB power battery. I knew the full set of lights could drain a lot of power, so I wanted to build patterns that used only a few lights.
A bit of soldering and attachment later, I had connections from the board to the bluetooth radio, connections to the sensors, and three pins to the light strip. All of that was wrapped in clear packing tape so I could move it around as a single unit.
On to the programming.
At first, I started with the simple FastLED samples. I verified that the lights worked and could display the lights. Then I tried some of the sensor programming samples, and verified that twisting and turning generated suitable data. Finally, I pulled down some bluetooth libraries (ControlXY at the time) to generate a UI on my tablet that could be controlled with the chip. This confirmed that all the wiring and chips were working. Hooray.
Given how the libraries worked, one of my early approaches was to use the lights and the Bluetooth and ignore the sensors for now. So I mixed together the FastLED samples and the ControlXY content.
Arduino programs have two major pieces. First, there is the setup function. In this code I initialized all the modules as needed for the various demos. Then there is the loop function where the computer loops forever. Merging the two programs meant the main loop did two things. One task was to animate the light patterns based on variables. There were six simple functions to choose from, so I had a variable that tracked the current one and drew it. The other task was to update the Bluetooth communications, which talked to the ControlXY program on the tablet and automatically updated the variable.
My first version in early January (sorry no pictures) could switch through every pattern. Setting it to index 0 (the first pattern) displayed a rainbow, setting it to index 1 could display the confetti pattern, and so on, for each pattern.
Expanding on this, I wrote a bit of code to use the various color palettes that were included in the demo, controlled through a second variable. Now I could draw not just confetti lights or a bouncing beat of lights, I could switch it from using reds or blues or whatever colors I choose.
Next step was writing something for the lights I wanted to use.
With 300 lights wrapped around the kite, I needed to figure out where they were. Knowing there would be a small gap, I decided the best place would be in the center middle. So running clockwise from center middle, there was light 0, then on the right wingtip light 60. Moving clockwise (down and left) around the W shape of the kite gave light 100 on the right foot, 150 in the middle, 200 on the left foot, 240 on the left wing, and light number 299 back in the middle.
Given a palette of 16 colors I could turn it into a ring of 30 lights spaced 10 lights apart. Index 0 and 15 (the two end points) would only be used once, index values 1 through 14 would appear twice. Or if you prefer numbering those from 0 to F, a circular pattern of index: 0 1 2 3 4 5 6 7 8 9 A B C D E F E D C B A 9 8 7 6 5 4 3 2 1.
With that in mind I could play with interesting controller patterns. So I made a few functions to manipulate those 30 lights. Spin was the first and easiest, just shift each of the 30 values one space to the right or to the left, and wrap it around in the middle. I figure that having 30 lights lit is enough to be highly visible, but not drain the battery too quickly.
Next a family of functions to “fling” the lights in any direction. Fling right would throw everything toward light #60. Flight left would throw everything toward light #240. It took a little bit of math to handle the ones on the leading edge, wrapping around between light #240 on the left and #60 on the right. Everything on the lower half of the kite (61-239) moved one direction, everything on the upper half (240-299 and 0-60) moved the other direction. They could now move right or left until they were all bunched up on the ends.
Similarly for flinging forward toward the top and down to the bottom. Flinging toward the top would move them toward the leading edge, but visually the W shape on the bottom would complicate things. So anything inside the V segment would need to be handled differently with four segments. On the right side, anything from 0-99 needed toward the leading edge toward position 0, 100-150 move toward the middle of the V in position 150. On the left side, 150-200 moved into the V, 201-299 moved toward 299 on the leading edge. For moving toward the bottom, everything inside the V would move to the correct foot, and everything on the sides or outer edges would move around to the other feet.
I made another pattern to return to the original position, and a pattern I called “airplane lights” to help me quickly find those key positions. And so I didn’t need to keep a kite on the rig, I cut out some cardboard and taped everything down.
I did get some video of this phase. Notice there is no sensor data yet, just controlling the motion. You can see the big bundle down by my computer, it was easier to run a long wire up to the kite rather than mount the bundle up on the kite frame.
Next up was tinkering with the sensor data.
There are several difficulties. The microcontroller probably wouldn’t be installed perfectly square. Even if it were, when the kite flies it isn’t square to the ground, it is always tipped falling forward slightly to create lift, plus there is always a bit of motion as minuscule corrections are made to keep it straight. And even if you get those right, due to error accumulation the directions would slowly drift out of position.
To solve them I computed a bunch of values based on the sensor data, and some numbers I found by playing around. Some values were taken at every sensor read, other values were accumulated over the past 5 readings.
First, I needed to find “down”. I set the code to wait until there was minimal motion. When the acceleometer’s only force was held at approximately the same as gravity ( 9.8 meters per second ) when considered with all three (X,Y,Z) axes, and when the gyroscope rotation was held very close to zero rotation in all three axes, I would call that direction “down”. I figure it is possible for someone to get a false reading by making the kite slide down diagonally at a speed that is exactly 1G and also perfectly stable, but that’s improbable. If the kite were on the ground or hovering midair, being stopped for a moment would reset the orientation of “down”.
So now that I could periodically update “down”, I needed to accumulate what all the other rotation and acceleration could do. This is the part where knowing trigonometry and being a game programmer came in useful.
I knew a vector for “down”. Because I knew approximately how the sensors would be mounted, I knew I was looking for rotation along the Z axis of the kite, and for acceleration toward the front/back or the right/left. I also knew which direction would be the positive Z axis direction (unless the sensors were mounted backwards).
The vector math is not too complex but more than I want in this blog post. A little bit of trigonometry to compute sines, cosines, and arctangents could compute how much motion was on the two directions and how much rotation was along the third. A little more math and knowing those values I could estimate what the new down direction would be. Knowing how the kite had moved with that sensor update meant I could update what direction was down based on the new rotations.
With all that work, I could finally apply those directional patterns. If the kite was rotating fast enough I wanted to spin the lights, so that was the first test. If the kite had rapidly accelerated forward, back, right, or left within the last few updates I wanted to fling the lights in those directions. This was a simple matter of calling the functions I built above for each purpose.
SO I built it, and weighed it, and it was heavy. Very heavy. Too heavy to fly unless winds were strong. I hooked it up to the kite, and tried to fly in on a windy day, but the weights were just too much. The computer and chips were about 70 grams, the battery over 100 grams, plus the lights at 71 grams. The whole thing together were slightly more than the total weight of the kite, which was about 230 grams.
So I moved on to hardware revisions #2 and revision #3, which is where I’m at today.
Today I’m using a much smaller computer board which only weighs about 7 grams. It also includes the Bluetooth chip so I don’t need the weight of the chip nor the connections. I’m currently on a different sensor chip, too, and I haven’t figured out new magic values for how much acceleration should trigger motion. In my first few tests everything was always being flung to the side, the code assumed that gravity was much stronger than before. It’s going to need some tuning, but I’m not up for that quite yet. I was still able to use the compass directions for coloring effects, so I showed that in the videos.
Lights drain power, the more lights are showing and the brighter they are toward white the more quickly it runs out of power. Currently I’m using a 10 gram battery that provides 350 milliamps. That is tremendously lighter than my original USB battery that weighed close to 100 grams. Unfortunately it only powers the system for 20-40 minutes depending on the light patterns.
I’m experimenting with different battery capacities, so the bundle for the computer and the battery weighs anywhere from 17-21 grams. The light strip around the edges still weighs 71 grams because I haven’t wanted to buy a more expensive strip (almost $60) to save those few grams. Once attached to the kite with clear packing tape, the current rig weighs about 100 grams, which is tolerable when attached the kite that is about 230 grams by itself.
Here’s a video showing the current patterns and color sets. It includes the motion-based colors, but doesn’t show the motion-based patterns, because as discussed, the sensitivity still needs to be tuned.
At first I used ControlXY, but it required a lot of program memory and I didn’t want to pay for the professional version to get all the controls I wanted. Some time later I switched to Virtuino for my tablet, but it was clunky. So I built my own simple app using MIT’s App Inventor. It scans for and connects to the Bluetooth BLE device, reads the names of the color patterns, the names of the motion patterns, the active values for both, plus values for the sensor data and a few other items.
And unlike the other programs I can build any new controls for the tablet for any new features I want to create, and I can easily generate both Apple and Android programs if I choose.
I think that’s enough of a writeup to satisfy those who were curious.