Skip to content

Instantly share code, notes, and snippets.

@frederickk
Created February 3, 2012 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frederickk/1729700 to your computer and use it in GitHub Desktop.
Save frederickk/1729700 to your computer and use it in GitHub Desktop.
A collection of classes used for my lightBrush http://kenfrederick.blogspot.com/2009/08/lightbrush.html
/**
* LightBrushColorduino receiver 1.0
*
* Ken Frederick
* ken.frederick@gmx.de
*
* http://cargocollective.com/kenfrederick/
* http://kenfrederick.blogspot.com/
*
* Arduino code for receiving Serial messages from SerialPixelSender.pde
*
*/
//-----------------------------------------------------------------------------
// includes
//-----------------------------------------------------------------------------
#include <Colorduino.h>
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
/**
* these must match what is being sent
* from the host app
*/
#define ARDUINO_BAUD_RATE 115200 // must be exactly the same in the arduino sketch
// data packet constants
#define BUFFER_SIZE 64 // 8*8
#define START_BYTE 42 // 42 = *
#define DELIMITER 44 // 44 = ,
#define END_BYTE 35 // 35 = #
#define MODE_BYTE 63 // 32 = ?
#define DRAW_BYTE 124 // 124 = |
#define SEND_BYTE 95 // 95 = _
//-----------------------------------------------------------------------------
// properties
//-----------------------------------------------------------------------------
//int bufferPacket[BUFFER_SIZE][5];
int bufferPacket[BUFFER_SIZE][3];
unsigned char red, green, blue;
int pos, index;
bool bDraw = false;
bool bMode = true;
//-----------------------------------------------------------------------------
// methods
//-----------------------------------------------------------------------------
void setup() {
// serial
Serial.begin(ARDUINO_BAUD_RATE);
red = green = blue = 0;
pos = 0;
index = 0;
// colorduino
Colorduino.Init();
/**
* compensate for relative intensity differences in R/G/B brightness
* array of 6-bit base values for RGB (0~63)
* whiteBalVal[0] = red
* whiteBalVal[1] = green
* whiteBalVal[2] = blue
*/
unsigned char whiteBalVal[3] = { 10,25,25 };
Colorduino.SetWhiteBal(whiteBalVal);
}
//-----------------------------------------------------------------------------
void update() {
while (Serial.available()) {
byte serialBuffer = Serial.read();
switch(serialBuffer) {
case START_BYTE:
pos = 0;
//Serial.flush();
continue;
break;
case DELIMITER:
pos++;
break;
case DRAW_BYTE:
bDraw = !bDraw;
//continue;
break;
case MODE_BYTE:
bMode = !bMode;
//continue;
break;
case END_BYTE:
//Serial.print(SEND_BYTE);
Serial.flush();
//continue;
break;
} // end switch serialBuffer
/**
* how many values are we sending at once?
* switch between to load the proper variables
*/
switch(pos) {
case 0:
red = serialBuffer;
break;
case 1:
green = serialBuffer;
break;
case 2:
blue = serialBuffer;
break;
case 3:
index = serialBuffer;
// push to bufferPacker
bufferPacket[index][0] = red;
bufferPacket[index][1] = green;
bufferPacket[index][2] = blue;
/*
unsigned int x = index / ColorduinoScreenWidth;
unsigned int y = index % ColorduinoScreenHeight;
bufferPacket[index][3] = x;
bufferPacket[index][4] = y;
*/
break;
}
} // end while
}
//-----------------------------------------------------------------------------
void loop() {
update();
/**
* process color
*/
if(bDraw) {
if(bMode) {
ColorFill(bufferPacket[0][0], bufferPacket[0][1], bufferPacket[0][2]);
} else if(!bMode) {
ColorFrame(bufferPacket);
/*
for(int i=0; i<BUFFER_SIZE; i++) {
ColorPoint(bufferPacket[i][0], bufferPacket[i][1], bufferPacket[i][2], i);
}
*/
}
}
Colorduino.FlipPage();
}
//-----------------------------------------------------------------------------
void ColorFrame(int buffer[BUFFER_SIZE][3]) {
ColorRGB *p = Colorduino.curWriteFrame;
int pindex = 0;
for(unsigned char y=0; y<ColorduinoScreenWidth; y++) {
for(unsigned char x=0; x<ColorduinoScreenHeight; x++) {
// p->r = bufferPacket[pindex][0];
// p->g = bufferPacket[pindex][1];
// p->b = bufferPacket[pindex][2];
p->r = buffer[pindex][0];
p->g = buffer[pindex][1];
p->b = buffer[pindex][2];
pindex++;
p++;
}
}
}
//-----------------------------------------------------------------------------
void ColorPoint(unsigned char R,unsigned char G,unsigned char B, unsigned int _index) {
ColorRGB *p = Colorduino.curWriteFrame;
p[index].r = R;
p[index].g = G;
p[index].b = B;
//Colorduino.FlipPage();
}
void ColorPoint(unsigned int x, unsigned int y, unsigned char R,unsigned char G,unsigned char B) {
ColorRGB *p = Colorduino.GetPixel(x,y);
p->r = R;
p->g = G;
p->b = B;
//Colorduino.SetPixel(x,y, R,G,B);
//Colorduino.FlipPage();
}
//-----------------------------------------------------------------------------
void ColorFill(unsigned char R,unsigned char G,unsigned char B) {
ColorRGB *p = Colorduino.GetPixel(0,0);
for(unsigned char y=0; y<ColorduinoScreenWidth; y++) {
for(unsigned char x=0; x<ColorduinoScreenHeight; x++) {
p->r = R;
p->g = G;
p->b = B;
p++;
}
}
//Colorduino.FlipPage();
}
/*
* OpenCVTracker.pde
*
* Ken Frederick
* ken.frederick@gmx.de
*
* http://cargocollective.com/kenfrederick/
* http://kenfrederick.blogspot.com/
*
*/
//-----------------------------------------------------------------------------
// libraries
//-----------------------------------------------------------------------------
import codeanticode.gsvideo.*;
import hypermedia.video.*;
public class OpenCVTracker extends Thread {
//-----------------------------------------------------------------------------
// properties
//-----------------------------------------------------------------------------
private PApplet papplet;
private PGraphics imageBuff;
boolean bRunning = false;
// video
private GSCapture video;
// openCV
private OpenCV opencv;
private Blob[] blobs;
private int cvBrightness;
private int cvContrast;
private int cvThresh;
// points
float avgWeight = 0.5;
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
public OpenCVTracker(PApplet _papplet, int _width, int _height) {
papplet = _papplet;
imageBuff = createGraphics(_width,_height, P2D);
// setup video
video = new GSCapture(_papplet, _width, _height);
video.play();
// setup openCV
opencv = new OpenCV(_papplet);
opencv.allocate(_width, _height);
setBrightness(0);
setContrast(0);
setThreshold(0);
}
//-----------------------------------------------------------------------------
// methods
//-----------------------------------------------------------------------------
public void start() {
bRunning = true;
super.start();
}
//-----------------------------------------------------------------------------
public void run() {
while(bRunning) {
update();
try {
} catch (Exception e) {
}
}
}
//-----------------------------------------------------------------------------
public void update() {
// open cv
opencv.copy(video);
opencv.convert(GRAY);
opencv.brightness(cvBrightness);
opencv.contrast(cvContrast);
opencv.threshold(cvThresh);
blobs = opencv.blobs(10, video.width*video.height/2, 4, false, 1); //OpenCV.MAX_VERTICES*4 );
// video
if (video.available()) {
video.read();
//video.loadPixels();
}
}
//-----------------------------------------------------------------------------
public void draw(int _x, int _y, boolean bVideo) {
draw(_x,_y, video.width,video.height, bVideo);
}
public void draw(int _x, int _y, int _width, int _height, boolean bVideo) {
pushMatrix();
translate(_x,_y);
PVector videoSize = new PVector(video.width, video.height, 0);
PVector avg = getAvg().get();
avg.mult(videoSize);
imageBuff.beginDraw();
imageBuff.background(0);
imageBuff.noFill();
if(bVideo) {
imageBuff.image(video, 0,0, video.width,video.height);
} else {
imageBuff.image(opencv.image(), 0,0, video.width,video.height);
//imageBuff.image(opencv.image(), 0,0+video.height, video.width,video.height);
//imageBuff.image(opencv.image(), 0+video.width,0, video.width,video.height);
}
// draw blobs
imageBuff.stroke(255,0,255, 255*0.6);
imageBuff.beginShape();
for(int i=0; i<blobs.length; i++) {
for(int j=0; j<blobs[i].points.length; j++ ) {
//imageBuff.ellipse(blobs[i].points[j].x, blobs[i].points[j].y, 9,9);
imageBuff.line(blobs[i].points[j].x-4.5,blobs[i].points[j].y, blobs[i].points[j].x+4.5,blobs[i].points[j].y);
imageBuff.line(blobs[i].points[j].x,blobs[i].points[j].y-4.5, blobs[i].points[j].x,blobs[i].points[j].y+4.5);
imageBuff.vertex(blobs[i].points[j].x, blobs[i].points[j].y);
}
imageBuff.vertex(avg.x,avg.y);
}
imageBuff.endShape();
// averaged blob point
//imageBuff.fill(0,255,255, 255*0.6);
//imageBuff.ellipse(getAvg().x,getAvg().y, 9,9);
imageBuff.strokeWeight(3);
imageBuff.stroke(0,255,255, 255*0.7);
imageBuff.line(avg.x-4.5,avg.y, avg.x+4.5,avg.y);
imageBuff.line(avg.x,avg.y-4.5, avg.x,avg.y+4.5);
imageBuff.ellipse(avg.x,avg.y, 12,12);
imageBuff.endDraw();
image(imageBuff, 0,0, _width,_height);
popMatrix();
}
//-----------------------------------------------------------------------------
/**
* filter the current result using a weighted average filter:
* http://web.archive.org/web/20070224180400/http://www.tigoe.net/pcomp/code/archives/arduino/000710.shtml
*/
private float filter(float rawValue, float weight, float lastValue) {
float fValue = 0.0f;
float x = weight; // is a value between 0 and 1
//int x = 0;
//x = weight/102; // convert the weight number to a value between 0 and 1:
fValue = (x * rawValue + (10-x)*lastValue)/10; // run the filter:
return fValue;
}
//-----------------------------------------------------------------------------
public void quit() {
bRunning = false;
opencv.stop();
papplet.stop();
interrupt();
}
//-----------------------------------------------------------------------------
// public void stop() {
// quit();
// opencv.stop();
// papplet.stop();
// }
//-----------------------------------------------------------------------------
// sets
//-----------------------------------------------------------------------------
public void setBrightness(int val) {
cvBrightness = val;
}
public void setContrast(int val) {
cvContrast = val;
}
public void setThreshold(int val) {
cvThresh = val;
}
//-----------------------------------------------------------------------------
public void setAvgWeight(float val) {
avgWeight = val;
}
//-----------------------------------------------------------------------------
// gets
//-----------------------------------------------------------------------------
public boolean getRunning() {
return bRunning;
}
//-----------------------------------------------------------------------------
public PVector getCoord(int num) {
PVector v = new PVector();
if( blobs.length != 0) {
int c = constrain(num, 0,blobs.length);
v.set( norm(blobs[c].points[0].x, 0,video.width), norm(blobs[c].points[0].y, 0,video.height), 0);
}
return v;
}
//-----------------------------------------------------------------------------
PVector pv = new PVector();
public PVector getAvg() {
PVector v = new PVector();
int count = 0;
for(int i=0; i<blobs.length; i++) {
v.x += getCoord(i).x;
v.y += getCoord(i).y;
v.z += getCoord(i).z;
count++;
}
v.x /= count;
v.y /= count;
v.z /= count;
v.x = filter(v.x, avgWeight, pv.x);
v.y = filter(v.y, avgWeight, pv.y);
v.z = filter(v.z, avgWeight, pv.z);
pv = v.get();
return v;
}
}
/**
* SerialPixelSender.pde
*
* Ken Frederick
* ken.frederick@gmx.de
*
* http://cargocollective.com/kenfrederick/
* http://kenfrederick.blogspot.com/
*
* threaded code for sending data from processing to arduino
*
*/
//-----------------------------------------------------------------------------
// libraries
//-----------------------------------------------------------------------------
import processing.serial.*;
public class SerialPixelSender extends Thread {
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
private int ARDUINO_BAUD_RATE = 115200; // must be exactly the same in the arduino sketch
private final int ARDUINO_TIMEOUT = 0; // milliseconds
private final char START_BYTE = 42; // 42 = *
private final char DELIMITER = 44; // 44 = ,
private final char END_BYTE = 35; // 35 = #
private final char MODE_BYTE = 63; // 32 = ?
private final char DRAW_BYTE = 124; // 124 = |
private final char SEND_BYTE = 95; // 95 = _
//-----------------------------------------------------------------------------
// properties
//-----------------------------------------------------------------------------
// application
private PApplet papplet;
private boolean bMode = false;
private boolean bRunning = false;
private boolean bSendMessage = false;
// serial
private Serial arduino;
private boolean bConnected = false;
// image
private PImage src;
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
public SerialPixelSender() {
}
public SerialPixelSender(PApplet _papplet) {
// application
papplet = _papplet;
// serial
println( Serial.list() );
String portName = Serial.list()[0];
arduino = new Serial(papplet, portName, ARDUINO_BAUD_RATE);
arduino.bufferUntil( END_BYTE ); // lf == line feed, ASCII 10; the line ending from arduino
// image
//PImage src = new PImage(8,8, RGB);
}
public SerialPixelSender(PApplet _papplet, int _ARDUINO_BAUD_RATE) {
// application
papplet = _papplet;
// serial
println( Serial.list() );
String portName = Serial.list()[0];
ARDUINO_BAUD_RATE = _ARDUINO_BAUD_RATE;
arduino = new Serial(papplet, portName, ARDUINO_BAUD_RATE);
arduino.bufferUntil( END_BYTE ); // lf == line feed, ASCII 10; the line ending from arduino
// image
//PImage src = new PImage(8,8, RGB);
}
//-----------------------------------------------------------------------------
// methods
//-----------------------------------------------------------------------------
public void start() {
bRunning = true;
super.start();
}
//-----------------------------------------------------------------------------
public void run() {
while(bRunning) {
update();
try {
//sleep( (long)(ARDUINO_TIMEOUT) );
} catch (Exception e) {
}
}
}
//-----------------------------------------------------------------------------
public void update() {
if(bSendMessage) {
sendImage(src);
}
}
//-----------------------------------------------------------------------------
private void sendImage(PImage _src) {
toggleDraw();
try {
//img.resize(8,8);
PImage img = new PImage(8,8, RGB);
if(_src.width > 7 || _src.height > 7) {
img = setImage(_src);
/*
img.copy(_src, 0,0,_src.width,_src.height, 0,0,8,8);
img.loadPixels();
*/
} else {
img = _src;
}
for(int index=0; index<img.pixels.length; index++) {
int col = img.pixels[index];
int r = (int) ((col >> 16) & 0xFF);
int g = (int) ((col >> 8) & 0xFF);
int b = (int) (col & 0xFF);
sendRGB(r,g,b, index);
}
} catch(Exception e) {
}
toggleDraw();
}
//-----------------------------------------------------------------------------
private void sendRGB(int R, int G, int B, int index) {
arduino.write( START_BYTE );
//R
arduino.write(R);
arduino.write( DELIMITER );
//G
arduino.write(G);
arduino.write( DELIMITER );
//B
arduino.write(B);
arduino.write( DELIMITER );
//INDEX
arduino.write( index );
arduino.write( END_BYTE );
arduino.clear(); // dumps buffer before asking for next data point
}
//-----------------------------------------------------------------------------
private void toggleDraw() {
arduino.write( START_BYTE );
arduino.write( DRAW_BYTE );
arduino.write( END_BYTE );
arduino.clear(); // dumps buffer before asking for next data point
}
//-----------------------------------------------------------------------------
private void toggleMode() {
arduino.write( START_BYTE );
arduino.write( MODE_BYTE );
arduino.write( END_BYTE );
arduino.clear(); // dumps buffer before asking for next data point
}
//-----------------------------------------------------------------------------
public void quit() {
bRunning = false;
interrupt();
arduino.clear();
arduino.stop();
}
//-----------------------------------------------------------------------------
// sets
//-----------------------------------------------------------------------------
public void send() {
bSendMessage = true;
}
//-----------------------------------------------------------------------------
public void set(int[] colors, int colorsNum) {
PImage img = new PImage(8,8, RGB);
//img.loadPixels();
for(int i=0; i<colors.length; i++) {
img.pixels[i] = colors[i];
}
setImage(img);
}
//-----------------------------------------------------------------------------
public PImage setImage(PImage _src) {
src = _src;
PImage temp = new PImage(8,8, RGB);
temp.copy(src, 0,0,src.width,src.height, 0,0,8,8);
temp.loadPixels();
return src;
}
//-----------------------------------------------------------------------------
// gets
//-----------------------------------------------------------------------------
public boolean getRunning() {
return bRunning;
}
//-----------------------------------------------------------------------------
PImage getImage() {
return src;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment