Showing posts with label Lorenz in Living Color. Show all posts
Showing posts with label Lorenz in Living Color. Show all posts

Monday, May 19, 2014

Lorenz in Living Color: Part 6 - Testing the Combined Code

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...

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.

Tuesday, August 06, 2013

Lorenz in Living Color: Part 4 - Visualizing the System

As I mentioned previously, an error in my implementation of the Runge-Kutta algorithm on the Arduino left me convinced that I needed something with higher precision to do the necessary calculations.  This set-back would eventually sideline the project for several months but before I set it aside, I took on the chunk of code that would follow the calculations to find the solution to the Lorenz system, that I was having trouble with.  Given the z, y, and z values that would result from that calculation, I needed be able to determine the red, green, and blue values for all 50 of the LEDs I was going to be using.

This gets to a very fundamental question: once I did get to a place where I had a running list of coordinates of the solution points to the Lorenz system, how was I going to present those in an attractive way?  My first thought was just to use a row of LEDs each one representing a state of the system.  As the Arduino would generate the solution to the system for the next step in time, the new color would be shoved onto the string of LEDs, pushing all the previous solutions down one LED.  The result would look a lot like the animations form previous posts but here's what it looks like when all 50 LEDs are used:


My thoughts were to orient the string of LEDs vertically, maybe four or five feet tall and place them behind a piece of frosted glass or plastic, perhaps with some etching somewhat related to the weather.  I held onto this idea for quite some time before I was confronted with the reality that I had no way to etch a five-foot long piece of glass or plastic nor did I have any specific plans for what that art would be.  And if I was going to be the one to make the art, I suspected I would spend a large amount of time on it and the results would not be that fantastic.  The project would turn into one playing to my weaknesses rather than my strengths.

Lorenz, the man, is the one that coined the term "butterfly effect" to describe how chaotic systems can start out in very similar states but over time diverge drastically.  Interestingly, given the right set of parameters to the Lorenz equations, the shape of the solutions ("the attractor") takes on a vaguely butterfly-like shape.


I started of thinking of ways of trying to use this visual similarity. I still liked the idea of having the LEDs behind frosted glass to diffuse the colors; maybe a butterfly shape could be etched into the frosted glass?  Behind this etched glass I could arrange the LEDs in the shape of the attractor and as the solutions to the system were found, I could light up the LED that corresponded to that place on the X-Z plane with the color that corresponded to the X(red), Y(green), Z (blue) coordinates.  By arranging the string of LEDs in a figure-eight the looping path of the solution to the system would be shown by constantly moving LED with a color based on the the latest solution to the system.

But this would once again require me to create some kind of passible image of a butterfly to be etched. Seeking to avoid this complexity, I decided to switch the two images: I would etch the attractor on the frosted glass and arrange the LEDs in the shape of a butterfly.  I could generate the image of the attractor using Matlab and arranging 50 LEDs in the shape of a butterfly profile seemed something I could manage.

Once this decision was made, the next step was to write the code that would take the latest solution to the Lorenz system, an X, Y, Z coordinate, and define the state of each of the LEDs.

Tuesday, July 16, 2013

Lorenz in Living Color: Part 3 - Differential Equations on the Arduino Uno

We left off last last time with my successful efforts to implement a fourth-order Runge-Kutta algorithm to solve the Lorenz system of differential equations in Microsoft Excel.  To make this project all I hoped it to be, though, I needed to do the same thing using an Arduino Uno.

The Arduino platform is great in many, many ways because it is largely able to hide a lot of the details that have made microcontrollers tricky to deal with for decades. But once you start moving beyond simple flashing LEDs, controlling DC motor speed, and reading analog temperature sensors, that messiness and mandatory attention to detail begins to reappear.  Very quickly, trouble with execution time, accuracy, data types, memory management and program space become pressing.  For this project I had a few specific concerns.

The first was accuracy.  Like all chaotic systems, the Lorenz system is sensitive to small deviations which, over time, cause a divergence between states that started out very near each other.  Approximations at any step of the process can lead to widely differing results in short order.  This is particularly a problem when using a numerical solver because numerical solutions always involve some degree of estimation; you always only get approximate solutions.

For the purposes of this project, I was not highly concerned with the accuracy of the specific solution, only that the system continues to behave in the characteristically chaotic fashion.  As long as the colors kept oscillating back and forth I was OK; if the system ever leveled out and settled into a single color or small spectrum of colors I had problems.  Not knowing enough about the system, I was not sure what degree of accuracy was needed to make this work.  As the programmer reference states, floating point variables (values with a decimal place) only have six or seven digits of accuracy.  It was not obvious to me if this would be enough accuracy for my needs.

My second concern was speed. The Arduino Uno runs at 16MHz by default and the Runge-Kutta algorithm uses floating point values every step of the way.  Floating point operations are the slow on the Uno because it has no dedicated floating point processor so I knew calculating the solutions could be time consuming.  I was also concerned with the time it would take to send out the new color state to all of the LEDs I was using.  As I could tell from the tutorial from the distributor, each LED would need 24 bits sent and I was planning on using 50 LEDs.  For the system to work as I wanted, both the calculations and the updates would have to be fast enough that I could update the system in real time.

There was only one way to address these concerns: try and see how it works. My first pass at implementing the Runge-Kutta code was a failure and unfortunately for me, I didn't realize I had made a critical mistake in translating my work in Excel to Arduino code.  When I ran this faulty code the system quickly settled out into a constant value, leading me to believe that the Uno lacked the precision for this application. These results lead me to desperation and I decided to take an entirely different tack: I was going to cheat.

Rather than calculating the solution to the Lorenz system I decided to take the red, green, and blue values I had already found when implementing the Runge-Kutta algorithm in Excel and store them in the Uno.  There wasn't a ton of room in the flash memory available for me to use but it was enough and I was able to demonstrate that this could work.  The Uno would just play back the pre-calculated solution and then and use it to drive the LEDs.  It worked but I wasn't happy that I would only ever be able to display a fairly limited set of values, those stored in flash memory.  This small setback and the normal busy-ness of life led me to sideline the project for several months.

A month or two ago I  picked the project up again with inspiration from an artist friend of mine and did the hard work of remembering where I left off and developing new strategies to solve the problem before me.  I ordered a dedicated floating point processor with hopes it would provide me the precision I thought I needed.  I ordered a 32-bit Arduino Due which has this precision built in the microprocessor architecture (and it runs much faster).  I even ordered extra off-chip flash memory to store an impossibly large amount of pre-calculated values (worst-case scenario). And while I waited for those to arrive in the mail, I relearned how to implement the Runge-Kutta algorithm and looked over the code I had written.  With a more systematic approach to checking my work I discovered errors in both my Excel and Arduino code and after correcting both was greeted with surprising results.

The Uno had enough calculating precision and speed to do what was needed. The solution to the Lorenz system that it finds appears to be accurate enough though I won't be sure until I get the system entirely assembled and can let it run for hours or days.  This result greatly encouraged me.  I was getting close but there was still more to do.


Monday, July 08, 2013

Lorezn in Living Color - Part 2: Solving the System

So where did we leave off....?  Oh yeah, the Lorenz system.

The Lorenz system is a three dimensional system that has this intriguing property in that as the system evolves over time, the solution never repeats yet tends to follow a semi-regular pattern.  My goal is to map the three co-ordinates of the solution onto a red, green, blue (RGB) color space so that I can see the system in another way.

The first challenge to overcome: since I was planning on implementing this project on an Arduino, I needed to solve the system of differential equations numerically.  I knew that solving differential equations this way was common (almost every computing device solves in this manner) but having never done it myself, I was a bit intimidated.  I knew from one of my recent math classes that the most common way of doing this was using an algorithm called Runge-Kutta, the fourth order variant being the most common:

(From Wikipedia)

(In the world of math and science, the most fame you can reasonably hope for is getting something you've done named after you.  This carries very little value outside the math and science circles, though.  Can you name more than ten famous mathematicians or scientists?  Come to think of it, if you're reading this blog you probably can. But I bet your next-door neighbor can't.)

Even though I working on my PhD in electrical engineering, I am not used to looking at numerical algorithms described in equations and  implementing them for, say, the Lorenz system.  I decided rather than start by writing code directly on the Arduino, I was going to use tool of every of every rookie to the field of numerical analysis: Microsoft Excel.  When you're just starting, Excel makes things easier by explicitly showing the  intermediate values for every step of the process.  Each intermediate value in the process has its own column with each step in time (n from the equations above) getting its own row.

After messing around in Excel for a while I had figured out how to interpret the equations for the algorithm and seemed to have produced results that were consistent with what I understood about the system.  I could see the x, y, and z values oscillating over time, never running away to infinite or getting stuck at any particular value and always circling back and forth.  Always moving, never repeating.

But these were just numbers and its hard to get a feel for how they would look if represented as RGB values. Engineering/Artistic epiphany: I could use Processing (a close cousin of the Arduino development system) to visualize the changing state of the system.  Processing was designed for real-time animation and visualization and I was sure there would be a way to take the values from my Excel spreadsheet and use it to draw a string of circles filled with the colors produced by the calculations.

And it was.


(The full animation has 50 circles; you're just seeing a portion of it here.)

I noticed that the colors that were being produced by these solutions were not that, uhmm, colorful.  I was already scaling the values from the Lorenz solutions to make them fit the way the RGB color definition used by processing (0-255 for each color channel); a little bit more tweaking probably wouldn't hurt anything. It took a few guess-and-check attempts but I eventually found a simple equation that changed numerical solutions from the Lorenz system into color values I liked.  





Using Processing to check my work was a great idea and it gave me confidence I was on the right track.I could see the results of the Runge-Kutta algorithm, see the progression of the colors, and verify that, for my purposes, the system was producing useful results.

Next up: moving all of this work I had done in Excel onto the Arduino.



Friday, May 17, 2013

Lorenz in Living Color - Part 1: The Lorenz System

I've been working on a technology art project (not as cool as this one) for over a decade now and by "working" I mean "mostly not working".

The project got a started during the jolting transition from no-free-time college days to evenings-and-weekends-free life as a working engineer.  In the meager discretionary time during my college years I had read "Chaos: Making a New Science" by James Gleick and was captivated by chaotic systems.  The seed had been planted in middle school by the book and movie "Jurassic Park" and was nurtured by my physics professor into something that I could begin to understand.

And the quintessential chaos-exhibiting system was the Lorenz system, boring when expressed as a system of seemingly simple differential equations...

but compelling when plotted in space...

Each one of those green dots is a unique value of x, y, and z that satisfies those three equations.  And given any set of x, y, and z coordinates, those equations will determine where the next dot will be in a second or minute or year.  All these dots, this collection that defines the solution that appears over time, the math people decided to call the shape of these types of solutions "attractors".  The solutions to these equations swirl and combine yet never settle down into regular, predictable patterns.  Looking at the attractor from another angle makes this clearer..


There are two foci to the attractor, two black holes that the solutions swirl around but this view of the attractor shows the solutions move back and forth between the two lobes. Sometimes the solutions loop repeatedly on one side and sometimes they will switch and start swirling around the other.  We never know when a switch is going to happen and the paths never cross or intersect.  Looking at an animation of the solutions over time shows this best...


I found this all very intriguing in many ways.  Here was a simple system that acted infinitely, a set of equations that produced values that never repeated themselves yet clearly had structure and was much more than just random noise. The regular-but-not-repeatable pulled me in and I began to think of ways that I could try to express this, to show others just how interesting I found it.

x, y, z.

red, green, blue.

Each point in space on the Lorenz attractor could be represented by a unique color, a combination of varying amounts of red, green, and blue.

This was the kernel of the idea that started the project all those years ago.