I've finally been able to integrate the two halves of my code: (differential equation solver and the LED light updater) and I'm happy to say that it works! Despite my initial testing with Processing to figure out an aesthetically pleasing choice of colors and timing, I needed to adjust some of these values once I was testing on actual hardware. In particular, I messed around with the differential equation solver step-size (how far into the future it tries to predict the next state of the system) and added a delay in the main processing loop so that the lights didn't run along their path at a highly frantic rate. I also ended up adding in a general dimming factor, allowing me to make the whole string less bright. At dimmer levels the saturation of the colors also improve.
I left the system running for 18 hours or so and it never stabilized into a steady-state (running only in the same lobe of the attractor); this is a good thing. I suspect that this is more a feature of the Lorenz system than any indication of the power and accuracy of the Arduino to solve differential equations well. For my purposes, it doesn't matter; as long as the lights keep flashing and moving, I'm happy.
We're getting close to the final system, very close. I've got the bug in how I calculate which lights to turn on that I would like to clean up but all that remains now is final assembly. I've got the front face plate to etch and the drilling on the LED mounting plate than all that remains is putting it back into the shadow box.
So very close...
Monday, May 19, 2014
Saturday, May 17, 2014
Lorenz in Living Color: Part 5 - Calculating the LED States
With the solution of the Lorenz system in place, the next task was to figure out how to define the color state for each of the 50 LEDs I'm using. The first task: how to figure out which LED corresponds to the latest solution.
Assuming I'm projecting the 3-D solution space onto a 2-D plane (the X-Z plane in this case), I decided to divide the dual-lobed solution space radially into octants. Based on the X and Z coordinates of the solution, I should be able to figure out which half of the attractor I'm in. Once I know that, I can pretend each lobe of the attractor is a circle and calculate the angle of the latest solution. Using that angle, I can then determine which LED to light up. I planned on arranging the LEDs in the shape of a butterfly and with a little bit of work came up with this pattern. (The numbers shown are the LED number.)
Each half of the butterfly shape the LEDs will be arranged in will have 23 LEDS (excluding the common center of 4 LEDs) and this angle will define which one of these LEDs corresponds to the latest solution to the Lorenz system.
But those four common LEDs that make up the body of the butterfly, those are a little tricky. They need to be considered in their own special way. Once the solution is in this region, it could be taking a path as a part of either lobe in the attractor. Rather than try to figure out which half it is in, I decided to make a special rectangular region right down the middle. If the solution landed in this area, I didn't decide which half it was in, I just figured out which of the four LEDs best matched the vertical position of the solution.
To keep it all straight I made a diagram. I have referred to this often, especially as the development of this project has spanned multiple years and I've need to remind myself what all this means. What you see below is the 3-D solution projected onto the X-Z plane along with all my annotations to remind me what was going on.
To increase the aesthetics of the project, I wanted to do more than just light up the LED corresponding to the current solution. As I've already said, the LED was going to be colored based on the X, Y, and Z values of the solution. But his solution would not necessarily progress smoothly from one LED to another. To create that smooth transition, I needed to light up all the LEDs between the LED that was going to light up and the LED that was currently lit up, filling in any gaps with a gradual shift in color between the two. Looking at the butterfly pattern above, this works out neatly because most of the time, the path the solution takes is corresponds to an increase in the LED number. If the current solution lights up LED 11 and the next solution lights up LED 15, I know that I need to also light up 12, 13, and 14.
Except for that center body portion. If the solution is running around the left-hand lobe, it regularly needs to progress from LED 26 to LED 0. Similarly, in the right-hand lobe from 50 to 23. I realized the solution to this problem is that if the difference between the current LED and the next LED is negative, I'm dealing with the center section. It took some trial and error but I figured out how to handle this special case.
To test out this portion of the code, since I didn't have the LED strands mounted in the butterfly pattern, I once again used Processing. I had my Arduino program take a set of solutions for the Lorenz system (solved off-line in Excel) and, using the program I had just written, figure out the brightness and color for each of LEDs in the butterfly pattern. Rather driving these LEDs directly, I had them written out and saved to a file. Processing then used this file to create an animation simulating what I could expect the final project to look like.
Here's what that animation showed:
This is more or less what I was hoping for. The animation should proceed smoothly around either half of the butterfly and it is clear there are some glitches how the Arduino calculates all of this but it will work for a prototype.
Assuming I'm projecting the 3-D solution space onto a 2-D plane (the X-Z plane in this case), I decided to divide the dual-lobed solution space radially into octants. Based on the X and Z coordinates of the solution, I should be able to figure out which half of the attractor I'm in. Once I know that, I can pretend each lobe of the attractor is a circle and calculate the angle of the latest solution. Using that angle, I can then determine which LED to light up. I planned on arranging the LEDs in the shape of a butterfly and with a little bit of work came up with this pattern. (The numbers shown are the LED number.)
Each half of the butterfly shape the LEDs will be arranged in will have 23 LEDS (excluding the common center of 4 LEDs) and this angle will define which one of these LEDs corresponds to the latest solution to the Lorenz system.
But those four common LEDs that make up the body of the butterfly, those are a little tricky. They need to be considered in their own special way. Once the solution is in this region, it could be taking a path as a part of either lobe in the attractor. Rather than try to figure out which half it is in, I decided to make a special rectangular region right down the middle. If the solution landed in this area, I didn't decide which half it was in, I just figured out which of the four LEDs best matched the vertical position of the solution.
To keep it all straight I made a diagram. I have referred to this often, especially as the development of this project has spanned multiple years and I've need to remind myself what all this means. What you see below is the 3-D solution projected onto the X-Z plane along with all my annotations to remind me what was going on.
To increase the aesthetics of the project, I wanted to do more than just light up the LED corresponding to the current solution. As I've already said, the LED was going to be colored based on the X, Y, and Z values of the solution. But his solution would not necessarily progress smoothly from one LED to another. To create that smooth transition, I needed to light up all the LEDs between the LED that was going to light up and the LED that was currently lit up, filling in any gaps with a gradual shift in color between the two. Looking at the butterfly pattern above, this works out neatly because most of the time, the path the solution takes is corresponds to an increase in the LED number. If the current solution lights up LED 11 and the next solution lights up LED 15, I know that I need to also light up 12, 13, and 14.
Except for that center body portion. If the solution is running around the left-hand lobe, it regularly needs to progress from LED 26 to LED 0. Similarly, in the right-hand lobe from 50 to 23. I realized the solution to this problem is that if the difference between the current LED and the next LED is negative, I'm dealing with the center section. It took some trial and error but I figured out how to handle this special case.
To test out this portion of the code, since I didn't have the LED strands mounted in the butterfly pattern, I once again used Processing. I had my Arduino program take a set of solutions for the Lorenz system (solved off-line in Excel) and, using the program I had just written, figure out the brightness and color for each of LEDs in the butterfly pattern. Rather driving these LEDs directly, I had them written out and saved to a file. Processing then used this file to create an animation simulating what I could expect the final project to look like.
Here's what that animation showed:
This is more or less what I was hoping for. The animation should proceed smoothly around either half of the butterfly and it is clear there are some glitches how the Arduino calculates all of this but it will work for a prototype.
Tuesday, May 13, 2014
Daylight Alarm Clock - Indefinite Development Hiatus
To put it simply: this isn't working for us. The real-time clock was a nice addition and guaranteed some sense of normal time-keeping but the the truth of the matter was that both my wife and I found the daylight alarm click unhelpful. We tried different locations. I tried different schedules, different total brightnesses, a diffusing enclosure but it simply doesn't work for us. Maybe we've spent too long with a beeping clock but we find that preferable waking up to a lit room.
For now, the project is being cancelled. If we want to try it again, it should be very easy to pick it back up. Until then, no more messing with it.
Wednesday, May 07, 2014
Daylight Alarm Clock - Real-Time Clock
My wife and I are not sure yet whether this whole daylight alarm clock thing is a good idea but I'm pushing ahead for now. The light failed to wake us the one time we've tried it and the the little direct light that came our way (the lamp was pointed at the ceiling) was too intense for early in the morning.
The first change I've made is moving the light from the dresser across the room to my night stand and putting it under "frosted glass" (heavy scratched now translucent plastic bowl). We'll see if this works any better.
The big electronics improvement for this test is the use of a real-time clock module, driven by a DS1307. If you don't do much with embedded systems like this, it may not occur to you that the Arduino doesn't come with a built-in clock; it literally has no idea what time it is. To solve that problem common problem, there are many readily and cheaply available modules that can be purchased and wired into the Arduino. These modules can be queried to determine the time and data and have a battery back-up so that even when they are not being powered by the Arduino, they still keep track of time. Program the module once with the current time and you never had to worry again.
(Never is an approximation. At some point the battery will run out and the modules have a reputation of being not atomic-clock accurate. Time can drift several seconds per day.)
Before the inclusion of the real-time clock, I had to program the Arduino with the specific number of seconds from when I plugged it in at night to when I wanted to light to begin fading up the next morning. Now, with the real-time-clock, I let it take care of worrying about keeping track of time and I just have to program in what time I want to the fade to start. This is progress and a lot more accurate than my previous technique.
We'll give it a few mornings try and see if we like it any better.
The first change I've made is moving the light from the dresser across the room to my night stand and putting it under "frosted glass" (heavy scratched now translucent plastic bowl). We'll see if this works any better.
The big electronics improvement for this test is the use of a real-time clock module, driven by a DS1307. If you don't do much with embedded systems like this, it may not occur to you that the Arduino doesn't come with a built-in clock; it literally has no idea what time it is. To solve that problem common problem, there are many readily and cheaply available modules that can be purchased and wired into the Arduino. These modules can be queried to determine the time and data and have a battery back-up so that even when they are not being powered by the Arduino, they still keep track of time. Program the module once with the current time and you never had to worry again.
(Never is an approximation. At some point the battery will run out and the modules have a reputation of being not atomic-clock accurate. Time can drift several seconds per day.)
Before the inclusion of the real-time clock, I had to program the Arduino with the specific number of seconds from when I plugged it in at night to when I wanted to light to begin fading up the next morning. Now, with the real-time-clock, I let it take care of worrying about keeping track of time and I just have to program in what time I want to the fade to start. This is progress and a lot more accurate than my previous technique.
We'll give it a few mornings try and see if we like it any better.
Sunday, May 04, 2014
Leather Seat Repair
We recently acquired a very used car that had leather seats. All of the leather was in very good condition except the driver's seat; worn and with a large tear on the side:
The price for a full repair (including two other panels that were well worn) was $300. Given the age of the car, we didn't think it was worth spending that kind of money on a cosmetic repair. Our primary interest was in containing the damage, not so much making the seat look new. We talked over several bad ideas (duct tape, glue, switching driver and passenger seats) before we came up a repair idea that would look OK and keep the tear in check.
We decided to buy a piece of leather of the appropriate color (eBay), cut it to fill in the area behind the tear, and glue the tear down onto the backing piece. So that's what we did.
The trimming and fitting of the leather took longer than I expected and the numerous leather flaps from the compound tear did not want to lay neatly down. We got it more or less in place and then used paint tape (low adhesion) to apply a small amount of pressure while the glue dried.
Twenty-four hours later, we pulled the tape off and got a good look.
Far from perfect but more or less what we were looking for. The flap on the far upper right didn't get glued very well so I'm redoing it but everything else seems to be working fine. We'll see how the special leather flue holds up; I already know from a test on a swatch of the backing leather that it is very flexible when cured. We'll probably need to re-glue it and we may eventually decide to have the panels professionally replaced. For now, we're calling it "good".
The price for a full repair (including two other panels that were well worn) was $300. Given the age of the car, we didn't think it was worth spending that kind of money on a cosmetic repair. Our primary interest was in containing the damage, not so much making the seat look new. We talked over several bad ideas (duct tape, glue, switching driver and passenger seats) before we came up a repair idea that would look OK and keep the tear in check.
We decided to buy a piece of leather of the appropriate color (eBay), cut it to fill in the area behind the tear, and glue the tear down onto the backing piece. So that's what we did.
The trimming and fitting of the leather took longer than I expected and the numerous leather flaps from the compound tear did not want to lay neatly down. We got it more or less in place and then used paint tape (low adhesion) to apply a small amount of pressure while the glue dried.
Twenty-four hours later, we pulled the tape off and got a good look.
Far from perfect but more or less what we were looking for. The flap on the far upper right didn't get glued very well so I'm redoing it but everything else seems to be working fine. We'll see how the special leather flue holds up; I already know from a test on a swatch of the backing leather that it is very flexible when cured. We'll probably need to re-glue it and we may eventually decide to have the panels professionally replaced. For now, we're calling it "good".
Subscribe to:
Posts (Atom)