Saturday, August 22, 2009

Generating Permutations and Combinations

One of the things I did when playing around with the HL1606 is write a routine that ran through ALL the colors. I mean all 64 possible permutations both my way and Synoptic Labs way to compare. Did I write these out by hand. Um, no. This is what computers are for.

 First of all, how do we know there are 64? If you look at the command byte for the HL1606 there are 6 bits involved in determining color, each of which can be one of two options (0 or 1). Doing the probability math: 2*2*2*2*2*2, 2 to the 6th... or 64. The other way to think about it is that we have 4 options to chose from: 01, 11, 10, 00 or (right to left) ON, DOWN, UP, OFF. We pick any one of these options 3 separate times (R, G and B). 4*4*4, 4 to the 3rd or again 64. Whether you think of it as 2 options 6 times or 4 options 3 times we can still simply count up in binary to generate the needed command bytes.

 Since I needed to create a predefined array for my purposes I wrote a function that would spit out something serially I could copy and paste:

  void loop() {  delay(2000); // time to switch over to serial mode  if (i < 1) { // do it only once  for (b=0; b<64; b ++) {   commandByte = b + B10000000; // add the latch command   Serial.print("colorArray[");   Serial.print(b, DEC);   Serial.print("] = B");   Serial.print(commandByte, BIN);   Serial.println(";");  }  }  i++; }

 Just a heads up, this works because you add the 1 onto the left edge of the command byte by adding the actual value of the variable not by trying to tack it on with Serial.print before it. What I mean is that 63 prints out as 111111, 6 characters, but 23 is 10111, 5 characters. You can't just paste numbers to left edge with text and expect the value to be correct when you copy the printout.

 This writing your own program is way more time consuming for a non-numeric situation like writing out UP OFF DOWN and ON for the Synoptic Lab style code - In case you don't remember those lines look like:

   docolor(DOWN, DOWN, UP,128/(2*SPULSE),1);

 You'd start with something like the below, but I haven't tested it.

  void permutate(int n_options, int r_times) {  int n;  int r;    for (r=0; r<r_times; r ++) { for (n=0; n><n_options; n ++) { Serial.print(r, DEC); Serial.print(" : "); Serial.print(n, DEC); Serial.print(" | "); } Serial.println(); } Serial.println(); } I just borrowed Math is Fun >'s permutations and combinations calculator. They generate the list and then a bit of find and replace magic in BBEdit got me the code I needed.

 Oh, and for those of you who are curious and don't care about having a pre-written array the following function does work, and is what the attached video is of.

  void playAll() {  int b; for (b=0; b<64; b ++) {   nextColor = colorArray[b];   nextCommand = nextColor + B10000000; // latch it   doColor2(nextCommand);  } }

Download now or watch on posterous
MVI_4528.AVI (14411 KB)

Posted via email from what2day's posterous

Combinations and Permutations Calculator

Posted via web from what2day's posterous

Friday, August 21, 2009

Last significant HL1606 update before the burn...

I can now get my LED lightstrip to play through a button-calibrated gradient.

 In the video you can see I'm using an FSR in lieu of a piezo mic for testing. When the strip flashes green after the button press, the chip is taking a reading off the FSR to be the new gradientMax. When it goes red it means all of a sudden the values are higher than the system thinks is okay. You can set the last value of the gradient to be the same as the second to last if you don't care. Same with the "off" state, easily side stepped. Again the whole code is a little long to post here, but here some of the new stuff.

  // ----- some stuff from the setup  colorArray[0] = B10000000; // Dark  colorArray[1] = B10100001; // Pink Red colorArray[2] = B10000001; // Red Red  colorArray[3] = B10000101; // Yellow  colorArray[4] = B10000100; // Green  colorArray[5] = B10010000; // Blue  colorArray[6] = B10010100; // Turquoise  colorArray[7] = B10010001; // Purple  colorArray[8] = B10010101; // White    //gradient  gradientArray[0] = 0; // what gradient does if sensor is out of bounds too low   // set this to the same as the one after it if you don't care  gradientArray[1] = 8;  gradientArray[2] = 6;  gradientArray[3] = 5;  gradientArray[4] = 2; //what gradient does if sensor is out of bounds too high   //set this to the same color as the one before it if you   //don't care. // ---- end in setup   //---- partial main loop  gradientLineLevel = analogRead(sensorPin); // get a reading from the fsr  gradientNum = getGradientLevel(gradientLineLevel); // get what gradient segment you are  //in the future could run case statements that have light patterns  doColor(gradientArray[gradientNum], 20); // low duration, more responsive system.  //my version of doColor looks a lot like the doNote function is some previous code  //but without the "white space" at the end of it. //---- end of some of the stuff in mail loop   byte getGradientLevel(int myLineLevel) {  int s;    if (myLineLevel > gradientMax) {   return (gradientArrayLength-1);  }  if (myLineLevel < gradientMin) {   return 0;  }      for (s = 1; s <= (gradientArrayLength-2); s++) {   int myMin = gradientMin + (s-1)*gradientSteps;   int myMax = gradientMin + (s)*gradientSteps;     // covers the extra little slop so I don't have to deal with   // making gradientSteps a float   if (s == (gradientArrayLength)) {   myMax = gradientMax;   }     // range hit   if (myLineLevel >= myMin && myLineLevel <= myMax) {   return s;   } }    // if it made it through the for loop with no hits, out of bounds exception  // should really never get here b/c of if statements at top of function  return 0;   }   void setGradientRange() {  gradientMax = analogRead(sensorPin);  gradientRange = gradientMax - gradientMin;  // gradient steps uses gradientArrayLength-1 as the divisor  //because gA[0] is the out of bounds exception  //gA[last] is the upper out of bounds exception  gradientSteps = gradientRange/(gradientArrayLength-2); }

Download now or watch on posterous
MVI_4523.AVI (10341 KB)

Posted via email from what2day's posterous

Thursday, August 20, 2009

HL1606: Separated timing and rate, rate based on potentiometer

See, better code.

 Posting the whole thing is a bit of a bear, I'm not loving the ePaper option, I will come up with something else but for now the important changes to the subroutines, rateModulo is the variable set by the analog sensor in the main loop.
void twoBits() {  int l;  for (l=0; l< 8; l++) {   //add a check kill switch   doNote(twoBitNoteArray[l], twoBitTimeArray[l], millis());  }  // just a little extra white space at the end in case it isn't followed  // by a clearStrip();  doNote(0,300, millis()); }   void doNote (byte colorNum, int duration, long startTime) {  int d;  int r;  int mCheck = 0;    byte color = colorArray[colorNum];  long endTime = startTime + (long) duration;  // release whitespace eats into the previous note!!!!!!!!  while (millis() < (endTime-release)) { //add a check_kill_switch   mCheck = micros() % rateModulo;   if (mCheck==0) {   //Serial.println(mCheck);   mystrip.pushCmd(color);   mystrip.latch();   }  }    while (millis() < endTime) { //add a check_kill_switch   mCheck = micros() % rateModulo;   if (mCheck==0) { mystrip.pushCmd(colorArray[0]);   mystrip.latch();   }  } }  

Download now or watch on posterous
MVI_4515.AVI (7187 KB)

Posted via email from what2day's posterous

Wednesday, August 19, 2009

Shave and a hair cut... Color and Time on HL1606 (tags: electronics, physcomp, HL1606, Arduino)

So I guess I did a cheesey musical Hello World.  I mapped a note array and a color array and a time array together and got my light strip to blink. I'm not posting the code because it has some fatal flaws, like no separate control of the rate of latching speed and the "human time" it looks like it is coming out of the end.  It is also dependent on the clock speed  for  (t = 0, t < duration, t ++) style in a way that is easily broken.

If you desperately need it, ask for it. But better will happen.


Download now or watch on posterous
MVI_4514.AVI (2203 KB)

Posted via email from what2day's posterous

Tuesday, August 18, 2009

HL1606 Digital Manual Control

So because I like to go simple and low level first I wrote code with Xanders library that would step through an array of colors every time you press a button.

 The main loop is some single button debounce code (Limor's from Arduino.cc) and this:

    if (pressFlag) { nextColor = colorArray[i];   mystrip.pushCmd(nextColor); mystrip.latch();   i++; }   if (i >= 9) {   i = 0;  }

 Which basically means every time the button gets pushed get the next item in the 10 item array and send it as a command byte to the LED strip. Because the latch is only thrown when the button is pressed it requires a button press for the colored lights to march on up the strip. I wrote this code to make sure I knew how the the bytes were flowing out and what they were doing to the LEDs because I was having some trouble with the original "doColor" function.

 The byte array I wrote looks like this:

   colorArray[0] = B10000001;  colorArray[1] = B10000101;  colorArray[2] = B10000100;  colorArray[3] = B10010100;  colorArray[4] = B10010000;  colorArray[5] = B10010101;  colorArray[6] = B10010001;  colorArray[7] = B10000000;  colorArray[8] = B10001010;  colorArray[9] = B10100010;

 It looks a lot some colors we saw in John Cohn's Pixaxe code... The important thing to remember when looking at these numbers is that the bit furthest to the right is the one that gets send first, so when it is 1 the red LED is on. The command byte is explained in the Synoptic Labs library, but keep in mind it is explained as LEFT -> RIGHT, so the INVERSE of what you might think you're seeing here. I've added a couple of graphics to show the current set up and how it works. I'll make another video when the results are more exciting.

 I'm attaching the code as a compressed file so it won't get displayed in its entirety.

See and download the full gallery on posterous

Download now or preview on posterous
buttonMarch.txt (4 KB)

Posted via email from what2day's posterous

Arduino Board Switch

So, hoping to be on the same platform as the other folks working on the lights to make sure troubleshooting would be seemless I updated my board to the Duemilanove and my software to v 16. I did this through my favorite US Vendor: SparkFun

 One of the nice things about buying an Arduino board from Arduino is that they have joined Zero Impact . Zero Impact is a carbon offset company. Even though CO2 emissions are really not the biggest environmental problem with electronics, it is a nice touch. Arduino seems to have picked building forests in Costa Rica, so, since I've been there, I get to think of my trip every time I use the board.

 To make the software transition:

   * I close the old version (Arduino 12),
  * Open the new (Arduio 16)
  * Switch the type of board I was using (there are A LOT of new ones)
  * and then QUIT ARDUINO 16 AND REOPEN IT. I do this because then
  Arduino writes a preferences file when it quits. I've found that
  having the new version writes its own is just a nice just-in-case
  that smooths over some troubles occasionally.

 And the good news... When I attached the wires to the new board and uploaded the code it just worked!

 Yay!

See and download the full gallery on posterous

Posted via email from what2day's posterous