Sunday, April 10, 2011

Mess Up with Arduino! Digital Vibrate Sensor Part 2

After some experiment, here is the final look of my Arduino Vibrate Sensor:



Here is the code for upload into Arduino chip:


// ranges from 0-15
#define drumchan 1

// general midi drum notes
#define note_bassdrum 36

// define the pins we use
#define switchAPin 3
#define piezoAPin 0
#define ledPin 13 // for midi out status

// analog threshold for piezo sensing
#define PIEZOTHRESHOLD 100

int switchAState = LOW;
int currentSwitchState = LOW;
int val,t;

unsigned char state = 0;

void setup() {
pinMode(switchAPin, INPUT);
digitalWrite(switchAPin, HIGH); // turn on internal pullup

pinMode(ledPin, OUTPUT);
Serial.begin(57600); // set MIDI baud rate
}

void loop() {
// deal with switchA
currentSwitchState = digitalRead(switchAPin);
if( currentSwitchState == LOW && switchAState == HIGH ) // push
noteOn(drumchan, note_bassdrum, 100);
if( currentSwitchState == HIGH && switchAState == LOW ) // release
noteOff(drumchan, note_bassdrum, 0);
switchAState = currentSwitchState;

// deal with first piezo, this is kind of a hack
val = analogRead(piezoAPin);
if( val >= PIEZOTHRESHOLD ) {
t=0;
while(analogRead(piezoAPin) >= PIEZOTHRESHOLD/2) {
t++;
}
}
}

// channel ranges from 0-15
void noteOn(byte channel, byte note, byte velocity) {
midiMsg( (0x99 | channel), note, velocity);
}

// Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte velocity) {
midiMsg( (0x89 | channel), note, velocity);
}

// Send a general MIDI message
void midiMsg(byte cmd, byte data1, byte data2) {
digitalWrite(ledPin,HIGH); // indicate we're sending MIDI data
Serial.print(cmd, BYTE);
Serial.print(data1, BYTE);
Serial.print(data2, BYTE);
digitalWrite(ledPin,LOW);
}

void blink()//Interrupts function
{
state++;
}


The problem that the output is piano sound because of the wrong channel of midi sound. This is the piano sound code:


// channel ranges from 0-15
void noteOn(byte channel, byte note, byte velocity) {
midiMsg( (0x90 | channel), note, velocity);
}


The channel for percussion type instrument sound is 9. So I've modify the code like below:


// channel ranges from 0-15
void noteOn(byte channel, byte note, byte velocity) {
midiMsg( (0x99 | channel), note, velocity);
}


And wohoo! Drum sound is finally comes out! Although the sound is not very nice when played, and there are some codes still need to modify further, this is a big step toward my success!

Reference:
1. http://www.pjb.com.au/muscript/gm.html#perc
2. http://todbot.com/blog/2006/10/29/spooky-arduino-projects-4-and-musical-arduino/
3. http://todbot.com/arduino/sketches/midi_drum_kit/midi_drum_kit.pde

Sunday, April 3, 2011

Mess Up with Arduino! Digital Vibrate Sensor

Today I tested Arduino with digital vibrate sensor. I was first planned to use pressure sensor as the device to detect person who standing on the board but I think that knock sensor or vibrate sensor is best to use in my installation. Below is the arrangement of the digital vibrate sensor.



After I put in the code found online, I managed to make the whole thing function. Below is the photo which LED light up when detect vibration on the table surface.



After that, I add in some more code which will send the signal to analog port when detect vibration. I've downloaded Serial Midi Converter which will convert the signal received into various sound like piano, drum etc. I managed to program the board to produce piano sound but not drum sound. Drum is the main sound that will be used in my installation. It is first step to success although it is not drum sound but piano sound. I'll study the code again... to be continue...

Friday, April 1, 2011

Mess Up with Arduino! Knock Sensor

There are few sensors that I've been considering to use in my installation. I'll test on the sensitivity and usability on different sensor. The sensor that I've been tested is knock sensor. I started with the tutorial in Arduino website. This is the basic arrangement of the knock sensor:



This is the code I've used to test on the knock sensor:

================================================================================
// these constants won't change:
const int ledPin = 13; // led connected to digital pin 13
const int knockSensor = A0; // the piezo is connected to analog pin 0
const int threshold = 100; // threshold value to decide when the detected sound is a knock or not


// these variables will change:
int sensorReading = 0; // variable to store the value read from the sensor pin
int ledState = LOW; // variable used to store the last LED status, to toggle the light

void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
Serial.begin(9600); // use the serial port
}

void loop() {
// read the sensor and store it in the variable sensorReading:
sensorReading = analogRead(knockSensor);

// if the sensor reading is greater than the threshold:
if (sensorReading >= threshold) {
// toggle the status of the ledPin:
ledState = !ledState;
// update the LED pin itself:
digitalWrite(ledPin, ledState);
// send the string "Knock!" back to the computer, followed by newline
Serial.println("Knock!");
}
delay(100); // delay to avoid overloading the serial port buffer
}
================================================================================

I've followed all the instruction and arrangement as stated in the tutorial but I failed to make the knock sensor function. I've tested it over and over again but it react nothing. I thought that I might have burnt the knock sensor but it is quite impossible because the circuit is very simple and all installed as the image in tutorial. So I decided to try on the knock sensor which borrowed from my friend, Stefan. The experiment still show no result. I've tried with the different code from internet and there is still no improvement. So I just leave with the knock sensor first and test with other sensor. This experiment: FAILED!

Thursday, March 31, 2011

Mess Up with Arduino! LED

Today I'm going to test the Arduino things with my zero knowledge on electronic part. It is indeed a big challenge for me! Pray hard and hope that the sensors and Arduino board won't burn >.< ! I feel excited, yet Chuak!(means afraid)... Lets getting start!

First, install the Arduino software in my PC. This stage already make me chuak! I saw the troubleshooting in Arduino website saying that driver doesn't install in Windows 7 64-bit!!! I've spent some time in research how to install driver in my PC and luckily, I've found the new update driver that can be installed! Else I'll have to format my PC @@!

This is the software use to write the program and upload to board:


After that, I randomly pick one tutorial to testing the board whether function or not. I've picked the tutorial to make the LED light and fade out. Here is the basic arrangement of the testing:


This is the code to make it work:


First try... Second try... OMG the LED won't light up! I've gone through some forum online and my hard work finally pay off! Readjust the setting and wohoo! It shine!


This is only the first step. I'll test with other sensor in upcoming days.

Drum Sound

Here is the drum sound that will be played while user steps on the board:










Tuesday, March 29, 2011

Randomize Color

I've go through some tutorial online and I've found the random color display code that will be using in my installation effect. Here are the code:

myColor = Math.round( Math.random()*0xFFFFFF );
myColoredObject = new Color (_root.effect);
myColoredObject.setRGB(myColor);

The tutorial effect:



The color splashing sample that will be used in the installation:

Sunday, March 27, 2011

Motion Tracking

I've download a motion tracking tutorial from the link below:
http://blog.soulwire.co.uk/code/actionscript-3/webcam-motion-detection-tracking

Before that I've get a motion tracking tutorial copy also from lecturer. I want to compare 2 version on the sensitivity in tracking body movement. Below are the original code from the tutorial:

================================================================================
/**
*
* MotionTrackerDemo
*
* @version 1.00 | Apr 2, 2008
* @author Justin Windle
*
**/

package
{
import uk.co.soulwire.cv.MotionTracker;

/**
* I'm using Grant Skinners fantastic ColorMatrix class:
* http://www.gskinner.com/blog/archives/2007/12/colormatrix_upd.html
*
* And Keith Peters Minimal Components:
* http://www.bit-101.com/minimalcomps/
*/

import com.bit101.components.Label;
import com.bit101.components.Slider;
import com.gskinner.geom.ColorMatrix;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.ColorMatrixFilter;
import flash.media.Camera;
import flash.media.Video;

/**
* MotionTrackerDemo
*/

[SWF(width="870", height="420", backgroundColor="#FFFFFF", frameRate="31")]

public class MotionTrackerDemo extends Sprite
{

// ----------------------------------------------------------------
// PRIVAYE MEMBERS
// ----------------------------------------------------------------

private var _motionTracker : MotionTracker;

private var _target : Shape;
private var _bounds : Shape;
private var _output : Bitmap;
private var _source : Bitmap;
private var _video : BitmapData;
private var _matrix : ColorMatrix;

private var _blurLabel : Label = new Label();
private var _brightnessLabel : Label = new Label();
private var _contrastLabel : Label = new Label();
private var _minAreaLabel : Label = new Label();

private var _blurSlider : Slider = new Slider();
private var _brightnessSlider : Slider = new Slider();
private var _contrastSlider : Slider = new Slider();
private var _minAreaSlider : Slider = new Slider();

// ----------------------------------------------------------------
// CONSTRUCTOR
// ----------------------------------------------------------------

public function MotionTrackerDemo()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}

// ----------------------------------------------------------------
// PRIVATE METHODS
// ----------------------------------------------------------------

private function configureUI() : void
{
_blurSlider.minimum = 0;
_blurSlider.maximum = 40;

_brightnessSlider.minimum = -100;
_brightnessSlider.maximum = 100;

_contrastSlider.minimum = -100;
_contrastSlider.maximum = 200;

_minAreaSlider.minimum = 0;
_minAreaSlider.maximum = 50;

_blurSlider.x = _blurLabel.x = 10;
_blurSlider.y = stage.stageHeight - 20;
_blurLabel.y = _blurSlider.y - 20;

_brightnessSlider.x = _brightnessLabel.x = _blurSlider.x + 110;
_brightnessSlider.y = _blurSlider.y;
_brightnessLabel.y = _brightnessSlider.y - 20;

_contrastSlider.x = _contrastLabel.x = _brightnessSlider.x + 110;
_contrastSlider.y = _blurSlider.y;
_contrastLabel.y = _contrastSlider.y - 20;

_minAreaSlider.x = _minAreaLabel.x = _contrastSlider.x + 110;
_minAreaSlider.y = _blurSlider.y;
_minAreaLabel.y = _minAreaSlider.y - 20;

addChild(_blurSlider);
addChild(_blurLabel);

addChild(_brightnessSlider);
addChild(_brightnessLabel);

addChild(_contrastSlider);
addChild(_contrastLabel);

addChild(_minAreaSlider);
addChild(_minAreaLabel);
}

private function initTracking() : void
{
var camW : int = 420;
var camH : int = 320;

// Create the camera
var cam : Camera = Camera.getCamera();
cam.setMode(camW, camH, stage.frameRate);

// Create a video
var vid : Video = new Video(camW, camH);
vid.attachCamera(cam);

// Create the Motion Tracker
_motionTracker = new MotionTracker(vid);

// We flip the input as we want a mirror image
_motionTracker.flipInput = true;

/*** Create a few things to help us visualise what the MotionTracker is doing... ***/

_matrix = new ColorMatrix();
_matrix.brightness = _motionTracker.brightness;
_matrix.contrast = _motionTracker.contrast;

// Display the camera input with the same filters (minus the blur) as the MotionTracker is using
_video = new BitmapData(camW, camH, false, 0);
_source = new Bitmap(_video);
_source.scaleX = -1;
_source.x = 10 + camW;
_source.y = 10;
_source.filters = [new ColorMatrixFilter(_matrix.toArray())];
addChild(_source);

// Show the image the MotionTracker is processing and using to track
_output = new Bitmap(_motionTracker.trackingImage);
_output.x = camW + 20;
_output.y = 10;
addChild(_output);

// A shape to represent the tracking point
_target = new Shape();
_target.graphics.lineStyle(0, 0xFFFFFF);
_target.graphics.drawCircle(0, 0, 10);
addChild(_target);

// A box to represent the activity area
_bounds = new Shape();
_bounds.x = _output.x;
_bounds.y = _output.y;
addChild(_bounds);

// Configure the UI
_blurSlider.addEventListener(Event.CHANGE, onComponentChanged);
_brightnessSlider.addEventListener(Event.CHANGE, onComponentChanged);
_contrastSlider.addEventListener(Event.CHANGE, onComponentChanged);
_minAreaSlider.addEventListener(Event.CHANGE, onComponentChanged);

// Get going!
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}

private function applyFilters() : void
{
_blurLabel.text = "Blur: " + Math.round(_blurSlider.value);
_brightnessLabel.text = "Brightness: " + Math.round(_brightnessSlider.value);
_contrastLabel.text = "Contrast: " + Math.round(_contrastSlider.value);
_minAreaLabel.text = "Min Area: " + Math.round(_minAreaSlider.value);

_matrix.reset();
_matrix.adjustContrast(_contrastSlider.value);
_matrix.adjustBrightness(_brightnessSlider.value);
_source.filters = [new ColorMatrixFilter(_matrix)];
}

// ----------------------------------------------------------------
// EVENT HANDLERS
// ----------------------------------------------------------------

private function onAddedToStage(event : Event) : void
{
configureUI();
initTracking();
applyFilters();
}

private function onEnterFrameHandler(event : Event) : void
{
// Tell the MotionTracker to update itself
_motionTracker.track();

// Move the target with some easing
_target.x += ((_motionTracker.x + _bounds.x) - _target.x) / 10;
_target.y += ((_motionTracker.y + _bounds.y) - _target.y) / 10;

_video.draw(_motionTracker.input);

// If there is enough movement (see the MotionTracker's minArea property) then continue
if ( !_motionTracker.hasMovement ) return;

// Draw the motion bounds so we can see what the MotionTracker is doing
_bounds.graphics.clear();
_bounds.graphics.lineStyle(0, 0xFFFFFF);
_bounds.graphics.drawRect(_motionTracker.motionArea.x, _motionTracker.motionArea.y, _motionTracker.motionArea.width, _motionTracker.motionArea.height);
}

private function onComponentChanged(event : Event) : void
{
switch(event.target)
{
case _blurSlider :

_motionTracker.blur = _blurSlider.value;

break;

case _brightnessSlider :

_motionTracker.brightness = _brightnessSlider.value;

break;

case _contrastSlider :

_motionTracker.contrast = _contrastSlider.value;

break;

case _minAreaSlider :

_motionTracker.minArea = _minAreaSlider.value;

break;
}

applyFilters();
}
}
}

================================================================================

The original tutorial doesn't have any effect displayed on the right side. Below is the original testing:



I've refer to the tutorial that have been given by lecturer and add in a circle and extra code the original code:

================================================================================
_target = new Shape();
_target.graphics.lineStyle(0, 0xFFFFFF);
_target.graphics.drawCircle(0, 0, 10);
addChild(_target);
addChild(round);

_bounds.graphics.clear();
_bounds.graphics.lineStyle(0, 0xFFFFFF);
_bounds.graphics.drawRect(_motionTracker.motionArea.x, _motionTracker.motionArea.y, _motionTracker.motionArea.width, _motionTracker.motionArea.height);
round.x = _motionTracker.motionArea.x+(_motionTracker.motionArea.width/2);
round.y = _motionTracker.motionArea.y+(_motionTracker.motionArea.height/2);;
trace(round.x);
}

================================================================================

The problem now is the circle will move upward and downward according to movement. I've remove the y-axis detection in the code and become like this:

_bounds.graphics.clear();
_bounds.graphics.lineStyle(0, 0xFFFFFF);
_bounds.graphics.drawRect(_motionTracker.motionArea.x, _motionTracker.motionArea.y, _motionTracker.motionArea.width, _motionTracker.motionArea.height);
round.x = _motionTracker.motionArea.x+(_motionTracker.motionArea.width/2);
trace(round.x);
}

================================================================================

The circle is now move according to the movement of my hand and it only move in the x-axis and fixed y-axis. Below is the testing:



The circle will be replaced with the color splashing effect which will project on the user's body.