This is the final project for my pComp I class. The initial idea was to create a light illusion inside of a gate, however in the proposal the gate was only around 2 feet high or lower. After the review in class, I decide to make this an art installation in my locker and make it interactive. The final concept was two use several boards(not limited in 2), and place light strip on all edges. By manipulating the lightness of each edges, the light should create an illusion that the space is shifting with the movement of the audience. During the making process the broads were being limited in 2, but still delivers decent effect. I used two meter NeoPixel from Adafruit, which comes with a library only for Arduino, which left me no choice but not using firmata. The biggest problem when doing this project is communication. Sending values from Arduino to openFrameworks is easy, but the protocol doesn’t support the other way that well(or I haven’t found the best way). It took me a long time to make the Arduino board to no only separate the serial value but also find the head of the string. The face detection was done in with ofxfacetracker. To have the best result, the tracking point was set to the center of nose.
_________arduino code_________
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
#include <Adafruit_NeoPixel.h>
// Which pin on the Arduino is connected to the NeoPixels?
#define PINLEFTBIG 13
#define PINRIGHTBIG 12
#define PINUPBIG 10
#define PINDOWNBIG 11
#define PINLEFTS 9
#define PINRIGHTS 8
#define PINUPS 6
#define PINDOWNS 7
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS1 10
#define NUMPIXELS2 30
#define NUMPIXELS3 5
#define NUMPIXELS4 15
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter–see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixelleft = Adafruit_NeoPixel(NUMPIXELS2, PINLEFTBIG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelright = Adafruit_NeoPixel(NUMPIXELS2, PINRIGHTBIG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelup = Adafruit_NeoPixel(NUMPIXELS1, PINUPBIG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixeldown = Adafruit_NeoPixel(NUMPIXELS1, PINDOWNBIG, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixellefts = Adafruit_NeoPixel(NUMPIXELS4, PINLEFTS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelrights = Adafruit_NeoPixel(NUMPIXELS4, PINRIGHTS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixelups = Adafruit_NeoPixel(NUMPIXELS3, PINUPS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixeldowns = Adafruit_NeoPixel(NUMPIXELS3, PINDOWNS, NEO_GRB + NEO_KHZ800);
int delayval = 0; // delay for half a second
int disX=0;
int disY=0;
int noseX = 0;
int noseY = 0;
int valueX, valueY;
void setup() {
Serial.begin(9600);
pixelleft.begin(); // This initializes the NeoPixel library.
pixelright.begin();
pixelup.begin();
pixeldown.begin();
pixellefts.begin(); // This initializes the NeoPixel library.
pixelrights.begin();
pixelups.begin();
pixeldowns.begin();
}
void loop() {
//led
// noseX = getNoseX();
// noseY = getNoseY();
for(int i=0;i<10;i++){
if (Serial.find(“s”)){
noseX = Serial.parseInt();
noseY = Serial.parseInt();
}
if(noseX != NULL){
if(noseX >= 70 || noseX <= 500 ){
valueX = noseX ;
}
}
Serial.print (valueX);
if(noseX != NULL){
if(noseY >= 70 || noseY <= 400 ){
valueY = noseY ;
}
}
disX= map(valueX, 60, 520, 0, 230);
disY= map(valueY, 80, 400, 0 ,255);
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixelup.setPixelColor(i, pixelup.Color(255-disY,255-disY,255-disY)); // Moderately bright green color.
pixelup.show(); // This sends the updated pixel color to the hardware.
pixeldown.setPixelColor(i, pixeldown.Color(disY,disY,disY)); // Moderately bright green color.
pixeldown.show(); // This sends the updated pixel color to the hardware.
// Delay for a period of time (in milliseconds).
}
for(int i=0;i<30;i++){
disX= map(valueX, 60, 520, 0, 230);
disY= map(valueY, 80, 400, 0 ,255);
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixelleft.setPixelColor(i, pixelleft.Color(disX,disX,disX)); // Moderately bright green color.
pixelleft.show(); // This sends the updated pixel color to the hardware.
pixelright.setPixelColor(i, pixelright.Color(230-disX,230-disX,230-disX)); // Moderately bright green color.
pixelright.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}
for(int i =0;i<5;i++){
disX= map(valueX, 60, 520, 0, 230);
disY= map(valueY, 80, 400, 0 ,255);
pixelups.setPixelColor(i, pixelups.Color(255-disY,255-disY,255-disY)); // Moderately bright green color.
pixelups.show();
pixeldowns.setPixelColor(i, pixeldowns.Color(disY,disY,disY)); // Moderately bright green color.
pixeldowns.show();
delay(delayval);
}
for(int i =0;i<15;i++){
disX= map(valueX, 60, 520, 0, 230);
disY= map(valueY, 80, 400, 0 ,255);
pixellefts.setPixelColor(i, pixellefts.Color(disX,disX,disX)); // Moderately bright green color.
pixellefts.show(); // This sends the updated pixel color to the hardware.
pixelrights.setPixelColor(i, pixelrights.Color(230-disX,230-disX,230-disX)); // Moderately bright green color.
pixelrights.show();
delay(delayval);
}
delay(0);
}
_______openFramworks code___________
#include “testApp.h”
using namespace ofxCv;
using namespace cv;
void testApp::setup() {
ofSetVerticalSync(true);
ofBackground(0);
ofSetLogLevel(OF_LOG_VERBOSE);
serial.listDevices();
vector <ofSerialDeviceInfo> deviceList = serial.getDeviceList();
// this should be set to whatever com port your serial device is connected to.
// (ie, COM4 on a pc, /dev/tty…. on linux, /dev/tty… on a mac)
// arduino users check in arduino app….
int baud = 9600;
serial.setup(0, baud); //open the first device
//serial.setup(“COM4”, baud); // windows example
//serial.setup(“/dev/tty.usbserial-A4001JEC”, baud); // mac osx example
//serial.setup(“/dev/ttyUSB0”, baud); //linux example
cam.listDevices();
cam.setDeviceID(1);
cam.initGrabber(640, 480);
tracker.setup();
tracker.setRescale(.5);
}
void testApp::update() {
bSendSerialMessage = true;
noseBase = tracker.getImageFeature(ofxFaceTracker::NOSE_BASE).getCentroid2D();
int valueX = noseBase.x;
int valueY = noseBase.y;
noseX = ofToString(valueX);
noseY = ofToString(valueY);
//update nose position
// ofLog(OF_LOG_NOTICE) << “nosePosition XY ” << noseBase.x , noseBase.y;
//camera function
cam.update();
if(cam.isFrameNew()) {
if(tracker.update(toCv(cam))) {
classifier.classify(tracker);
}
}
//serial write
if (bSendSerialMessage){
// (1) write the letter “a” to serial:
string a = “s”; // string a
a.append(noseX);
a.append(“,”);
a.append(noseY);
a.append(“\n”);
//string b = “s5,200\n”;
//unsigned char* nextChar = (unsigned char*) b.c_str();
unsigned char* valChar = (unsigned char*) a.c_str(); // cast from string to unsigned char*
// ofLog(OF_LOG_NOTICE) << “warning ” << valChar;
//ofDrawBitmapString(a, 30, 100); // draws a
//ofDrawBitmapString(string((char *)b), 30, 130); // draws b
//unsigned char buf[3] = {‘2’, ‘,’, ‘1’};
//serial.writeBytes(&buf[0], 3);
serial.writeBytes(&valChar[0], 8);
//serial.writeBytes(&nextChar[0], 6);
// (2) read
// now we try to read 3 bytes
// since we might not get them all the time 3 – but sometimes 0, 6, or something else,
// we will try to read three bytes, as much as we can
// otherwise, we may have a “lag” if we don’t read fast enough
// or just read three every time. now, we will be sure to
// read as much as we can in groups of three…
nTimesRead = 0;
nBytesRead = 0;
int nRead = 0; // a temp variable to keep count per read
unsigned char bytesReturned[3];
memset(bytesReadString, 0, 4);
memset(bytesReturned, 0, 3);
while( (nRead = serial.readBytes( bytesReturned, 3)) > 0){
nTimesRead++;
nBytesRead = nRead;
};
memcpy(bytesReadString, bytesReturned, 3);
bSendSerialMessage = false;
readTime = ofGetElapsedTimef();
ofLog(OF_LOG_NOTICE) << “return “ << bytesReadString;
}
}
void testApp::draw() {
ofSetColor(255);
cam.draw(0, 0);
tracker.draw();
int w = 100, h = 12;
ofPushStyle();
ofPushMatrix();
ofTranslate(5, 10);
}