Modify Huey the Chameleon
Note, that this script is pretty complicated due to the need to read accurate values from the color sensor. This is embedded in the read_color() function. This is almost certainly the hardest of the available lab projects, so if you're intimidated, you may want to try a different one.
Huey contains:
- a switch on pin 5
- a color sensor module using pins 8-12, no library for this
an 8 LED strip, NOT NeoPixels, on pins 2 and 3
- note that 2 of the leds are supposed to be positioned behind the eyes, but I think one has slipped out of place...
To use this, you will need to download and install the LPD8806 library to drive the LED strip.
Here is Huey's current sketch:
#include "LPD8806.h" #include "SPI.h" // Number of RGB LEDs in strand: int nLEDs = 8; int dataPin = 2; int clockPin = 3; // First parameter is the number of LEDs in the strand. The LED strips // are 32 LEDs per meter but you can extend or cut the strip. Next two // parameters are SPI data and clock pins: LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin); void setup() { // Start up the LED strip strip.begin(); // Update the strip, to start they are all 'off' strip.show(); pinMode(5,OUTPUT); // Using 5/6 combined for the pushbutton switch pinMode(6,INPUT_PULLUP); // output is just to avoid another solder connection pinMode(8,OUTPUT); // 8 & 9 define color (RBCG) pinMode(9,OUTPUT); pinMode(10,OUTPUT); // 10 & 11 define amplification (off, .02, .2, 1.0) pinMode(11,OUTPUT); pinMode(12,INPUT); // color out, frequency encoded, ~16khz max digitalWrite(5,LOW); digitalWrite(10,HIGH); digitalWrite(11,HIGH); } int lp=1; unsigned long cm[4] = {0,0,0,0}; // color max values //unsigned long cmi[4] = {500,500,500,500}; // color min values unsigned long cmi[4] = {0,0,0,0}; // color min values const uint32_t read_color(float gamma) { int c,i; unsigned long cs[4]; // This block reads the color values from the hardware sensor and keeps track of min/max for (c=0; c<4; c++) { digitalWrite(9,(c&1)?HIGH:LOW); digitalWrite(8,(c&2)?HIGH:LOW); for (i=0; i<4; i++) pulseIn(12,LOW,100000); //wait in case it takes time to adjust unsigned long av=0; for (i=0; i<10; i++) { av+=pulseIn(12,HIGH,100000); } av++; // just in case it's zero cs[c]=200000/av; // 320 should be the max value we get here if (cs[c]>cm[c]) cm[c]=cs[c]; // keep track of the maximum for each color if (cs[c]<cmi[c]) cmi[c]=cs[c]; // and the minimum } float r2,g2,b2,c2; int s; r2=(cs[0]-cmi[0])/(float)(cm[0]-cmi[0]); g2=(cs[3]-cmi[3])/(float)(cm[3]-cmi[3]); b2=(cs[1]-cmi[1])/(float)(cm[1]-cmi[1]); c2=(cs[2]-cmi[2])/(float)(cm[2]-cmi[2]); r2=pow(r2,gamma); g2=pow(g2,gamma); b2=pow(b2,gamma); s=(int)(127*c2); float l=r2+g2+b2; r2/=l; g2/=l; b2/=l; return strip.Color((int)(r2*s),(int)(g2*s),(int)(b2*s)); } uint32_t cary[7] = { 0,0,0,0,0,0,0 }; int cycle = 0; uint32_t red(uint32_t color) { return (color>>8)&127; } uint32_t blue(uint32_t color) { return color&127; } uint32_t green(uint32_t color) { return (color>>16)&127; } int ldr=1,on=1; void loop() { uint32_t c; int i; // Draw the back if in "on" mode if (on) { // every 10 cycles we shift back if (cycle==0) { for (i=0; i<6; i++) cary[i]=cary[i+1]; cary[6]=read_color(3.0); } // draw the interpolated colors for (i=0; i<6; i++) strip.setPixelColor(i,(red(cary[i])*(9-cycle)+red(cary[i+1])*cycle)/9,(green(cary[i])*(9-cycle)+green(cary[i+1])*cycle)/9,(blue(cary[i])*(9-cycle)+blue(cary[i+1])*cycle)/9 ); } int dr=digitalRead(6); if (dr==0 && ldr==1) on^=1; // draw the eyes in the currently seen color c=read_color(3.0); if (dr) { strip.setPixelColor(6,c); strip.setPixelColor(7,c); } else { strip.setPixelColor(6,strip.Color(0,0,0)); strip.setPixelColor(7,strip.Color(0,0,0)); } strip.show(); delay(30); ldr=dr; cycle=(cycle+1)%10; }
- You might want to try compiling the stock sketch first and make sure you can get it to work.
- Make Huey do something interesting
That's it. You're done. Nothing to turn in (though if you made Huey do something particularly interesting, you could send me a copy of the sketch).