Introduction: Violano-Lilypad Arduino XBee Instrument

This product is an instrument that synchronizes motion with art and music. By controlling the amount of light that falls on the sensor, one can control the splash of colors being made on the screen along with the music note the instrument generates. This was developed by Jooeun and Noora to mark our right of passage to being Makers.

This product is an attempt to recreate the notion of making the invisible visible through detailed design. The product is inspired by the underlying premise of the paper "making the invisible visible in science museums through augmented reality devices (Yoon & Wang, 2014)"; where by attaching dynamic visualization of magnetic field to the manipulation of real bar magnets, they found visitors to be more engaged as it made provision for difficult concepts to be accessible through visualization.

We tried to emulate this by developing a product that provides visualization in the form of splashing of paint, to represent the degree to which the light was being manipulated by the motion detected by the sensor. This has been developed for kids and adults alike to provide them with a "first person encounter"; a on notion on which museums operate. First person encounter is the degree to which a product can catch and maintain an individual's attention. The underlying premise is by providing an effective first person encounter, one can prompt the individual to build and pursue the curiosity that emerges as a result of such encounters. The complexity of the product varies on the makers prior knowledge with programming.

Step 1: Get Materials

In order to develop this product, you will need:

1) Lilypad Board X 1

2) Lilypad XBee X 1

3) Lilypad LED X 4

4) Lilypad Light Sensor X 1

5) Lilypad Buzzer X 1

6) Conductive thread and Needle X 1

7) Batter and Lilypad Power Supply X 1

8) USB Cable X 1

9) Alligator clips wire X many

10) Fabric X as much as you want

To program, you will also need:

1) Arduino (arduion.cc)

2) Processing(processing.org)

3) X-CTU (http://www.digi.com/support/productdetail?pid=3352)

For Windows user, it is suggested to download ver.5.2.8.6 installer

Step 2: Connecting Lillypad With LED and Sensor

a. It is advisable to stop and check at every step of programming before proceeding on to the attaching the LEDs.

b. Start by checking if the sensor works by attaching Led with the Lillypad board using alligator clips.

c. Use the circuit pathway illustrated in the attachment to connect the LEDs to the sensor.

1. Blink LEDs with light sensor-1 (the result has been recorded below)

Program the light sensor to receive the specified amount of light using the below mentioned code.
This will determine when the LED would turn on.

int myLed[] = {A2, A3, A4};

int i = 0;

int sensor = A5;

void setup() {

Serial.begin(9600);

for (i = 0; i < 3; i++) {

pinMode(myLed[i], OUTPUT);

}

}

void loop() {

int sensorValue = analogRead(sensor);

Serial.println(sensorValue);

delay(100);

if (sensorValue > 225) {{

digitalWrite(myLed[i], LOW);

}

}

else {

light();

}

}

void light() {

for (i = 0; i < 3; i++) {

digitalWrite(myLed[i], HIGH);

delay(100);

digitalWrite(myLed[i], LOW);

delay(100);

}

}

2. Control LEDs with light sensor - 2

The objective is to control the LED separately with the light sensor.

As you check the functioning of light sensor through the serial port, make note of the maximum and minimum value. You can use this to program to determine the manipulation of the light sensor. For instance, to what degree should the light sensor be covered from light for the LED to turn on.

int myLed[] = {A2, A3, A4};

int i = 0;

int sensor = A5;

void setup() {

Serial.begin(9600);

for (i = 0; i < 3; i++) {

pinMode(myLed[i], OUTPUT);

}

}

void loop() {

int sensorValue = analogRead(sensor);

Serial.println(sensorValue);

delay(100);

if (sensorValue < 50) { // Tur all the LED off, if the value is higher than 40

digitalWrite(myLed[i], LOW);

}

else if (sensorValue > 60, sensorValue <120){

digitalWrite(myLed[0], HIGH);

delay(100);

digitalWrite(myLed[0], LOW);

delay(100);

}

else if (sensorValue > 120, sensorValue <230){

digitalWrite(myLed[1], HIGH);

delay(100);

digitalWrite(myLed[1], LOW);

delay(100);

}

else if (sensorValue > 230, sensorValue <330){

digitalWrite(myLed[2], HIGH);

delay(100);

digitalWrite(myLed[2], LOW);

delay(100);

}

else

{

light();

}

}

void light() {

for (i = 0; i < 3; i++) {

//digitalWrite(myLed[i], HIGH);

//delay(100);

digitalWrite(myLed[i], LOW);

delay(100);

}

}

Step 3: Add Buzzer

Finally move to the see if the LED and sensor works with the buzzer.Program the buzzer to be controlled by the amount of light that falls on the sensor. Program the buzzer to correspond to the playing of a note when the specified amount of light falls on the sensor.

Refer to the curicut illustrated to add the sensor.

The Arduino code used is attached below:

int myLed[] = {A2, A3, A4};
int sound[] = {523, 539, 587}; // C,D,E

int lightScope[]={360,370,380,400};

int i = 0;

int sensor = A6;

int sPin = 9;

byte val; //save variable

int buzzerPin = 9;

void setup() {

Serial.begin(9600);

for (i = 0; i < 3; i++) {

pinMode(myLed[i], OUTPUT);

}

}

void loop() {

int sensorValue = analogRead(sensor);

Serial.println(sensorValue);

delay(100);

if (sensorValue < 20) { // Tur all the LED off, if the value is higher than 40

digitalWrite(myLed[i], LOW);

}

else if (sensorValue > lightScope[0], sensorValue < lightScope[1] ) {

lightPin(myLed[0], 100);

tone(buzzerPin, 523, 1000);

delay(100);

}

else if (sensorValue > lightScope[1], sensorValue < lightScope[2]) {

lightPin(myLed[1], 100);

tone(buzzerPin, 587, 1000);

delay(100);

}

else if (sensorValue > lightScope[2], sensorValue < lightScope[3]) {

lightPin(myLed[2], 100);

tone(buzzerPin, 659, 1000);

delay(100);

}

else

{

light();

}

}

void light() {

for (i = 0; i < 3; i++) {

digitalWrite(myLed[i], LOW);

delay(100);

}

}

void lightPin(int ledPin, int ledDelay) {

digitalWrite(ledPin, HIGH);

delay(ledDelay);

digitalWrite(ledPin, LOW);

delay(ledDelay);

}

Step 4: Connect Lilypad With Processing

Before moving forward to wireless part, it is necessary to connect Arduino with Processing. The processing code is provided towards the end of this section. Follow the steps below to make Arduino communicate with Processing.

[Testing]

Start with initial testing by sending numbers from Arduino to Processing.

1. [Arduino] send ASCII 0~255 to serial.

void setup() {
Serial.begin(9600);

}

byte i;

void loop() {

Serial.write(i++);

delay(500);

}

2. Open the serial monitor and check if the numbers are appearing on the serial port monitor. Make sure you close the serial monitor. It is very important to close the serial monitor post the number check to ensure that errors don't pop up.

3. [Processing] Receive this number form Processing and display on the console.

import processing.serial.*;
Serial myPort;

int val;

void setup(){

size(200, 200);

String portName = Serial.list()[2];

myPort = new Serial(this, portName, 9600); }

void draw(){

if (myPort.available() > 0) {

val = myPort.read();

println(val);

}}

a. It is important to identify the port number for Processing so start by checking the port number.

b. You'll receive error when the port number is incorrect. Use Processing code bellow to check your port number.

import processing.serial.*;
Serial myPort;

int val;

void setup(){

println(Serial.list());

}

void draw(){}

c. Result example:

/dev/cu.Bluetooth-Incoming-Port/dev/cu.usbmodem1421 /dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem1421

d. Also, make sure you closed serial monitor. It operates one at a time.

When you receive the number from Processing, it's time for you to add code.

Intended result:

The code below is a remixed Processing code which interactively draws a paint varying with the light value Processing receives. In order to control drawing with the light sensor, there should be certain amount of light. If there is too much or too less light it will not work.

Original code: http://www.openprocessing.org/sketch/132225

[Processing code]

import processing.serial.*;

Serial p;

int a;

float x = random(50, 650);

float y = random(50, 650);

float r = random(700);

float b = random(700);

float t = 0;

float xspeed =2;

float yspeed =2;

float xspeed2 = 2;

float yspeed2 = -2;

float xspeed3 = -2;

float yspeed3 = -2;

float xspeed4 = -2;

float yspeed4 = 2;

void setup() {

p=new Serial(this, Serial.list()[1], 9600); // read serial

size(700, 700);

background(255);

frameRate(60);

}

void randomImgDraw(){

t=t+1;

float m1=random(3);

float m2=random(3);

fill(x/random(4),random(255), y/3);

strokeWeight(0.2);

storke(200);

if(t <= 140) {

xspeed = xspeed + m1*random(2); // large rects

yspeed = yspeed + m2*random(2);

rect(x+xspeed, y+yspeed, 10, 10);

xspeed2 = xspeed2 + m1*random(2);

yspeed2 = yspeed2 + m2*random(-2);

rect(x+xspeed2, y+yspeed2, 10, 10);

xspeed3 = xspeed3 + m1*random(-2);

yspeed3 = yspeed3 + m2*random(-2);

rect(x+xspeed3, y+yspeed3, 10, 10);

xspeed4 = xspeed4 + m1*random(-2);

yspeed4 = yspeed4 + m2*random(2);

rect(x+xspeed4, y+yspeed4, 10, 10);

fill(r/random(4), random(255), b/3); // medium rects

xspeed = xspeed2 + m1*random(-4, 4);

yspeed = yspeed2 + m2*random(-4, 4);

rect(x+xspeed2, y+yspeed2, 5, 5);

xspeed2 = xspeed3 + m1*random(-4, 4);

yspeed2 = yspeed3 + m2*random(-4, 4);

rect(x+xspeed3, y+yspeed3, 5, 5);

xspeed3 = xspeed4 + m1*random(-4, 4);

yspeed3 = yspeed4 + m2*random(-4, 4);

rect(x+xspeed4, y+yspeed4, 5, 5);

xspeed4 = xspeed + m1*random(-4, 4);

yspeed4 = yspeed + m2*random(-4, 4);

rect(x+xspeed, y+yspeed, 5, 5);

fill(x/random(4)-100, random(255)-80, y/3-80); // small rects

xspeed = xspeed2 + m1*random(-4, 4);

yspeed = yspeed2 + m2*random(-4, 4);

rect(x+xspeed, y+yspeed, 2, 2);

xspeed2 = xspeed3 + m1*random(-4, 4);

yspeed2 = yspeed3 + m2*random(-4, 4);

rect(x+xspeed2, y+yspeed2, 2, 2);

xspeed3 = xspeed4 + m1*random(-4, 4);

yspeed3 = yspeed4 + m2*random(-4, 4);

rect(x+xspeed3, y+yspeed3, 2, 2);

xspeed4 = xspeed + m1*random(-4, 4);

yspeed4 = yspeed + m2*random(-4, 4);

rect(x+xspeed4, y+yspeed4, 2, 2);

xspeed = xspeed4 + m1*random(-4, 4);

yspeed = yspeed4 + m2*random(-4, 4);

rect(x+xspeed3, y+yspeed3, 2, 2);

xspeed2 = xspeed2 + m1*random(-4, 4);

yspeed2 = yspeed2 + m2*random(-4, 4);

rect(x+xspeed, y+yspeed, 2, 2);

xspeed3 = xspeed + m1*random(-4, 4);

yspeed3 = yspeed + m2*random(-4, 4);

rect(x+xspeed4, y+yspeed4, 2, 2);

xspeed4 = xspeed3 + m1*random(-4, 4);

yspeed4 = yspeed3 + m2*random(-4, 4);

rect(x+xspeed2, y+yspeed2, 2, 2);

fill(r/random(4)-80, random(255)-80, b/3-80 ); // 2nd G small rects

xspeed = xspeed2 + m1*random(-7, 7);

yspeed = yspeed2 + m2*random(-7, 7);

rect(x+xspeed, y+yspeed, 2, 2);

xspeed2 = xspeed3 + m1*random(-7, 7);

yspeed2 = yspeed3 + m2*random(-7, 7);

rect(x+xspeed2, y+yspeed2, 2, 2);

xspeed3 = xspeed4 + m1*random(-7, 7);

yspeed3 = yspeed4 + m2*random(-7, 7);

rect(x+xspeed3, y+yspeed3, 2, 2);

xspeed4 = xspeed + m1*random(-7, 7);

yspeed4 = yspeed + m2*random(-7, 7);

rect(x+xspeed4, y+yspeed4, 2, 2);

xspeed = xspeed4 + m1*random(-7, 7);

yspeed = yspeed4 + m2*random(-7, 7);

rect(x+xspeed3, y+yspeed3, 2, 2);

xspeed2 = xspeed2 + m1*random(-7, 7);

yspeed2 = yspeed2 + m2*random(-7, 7);

rect(x+xspeed, y+yspeed, 2, 2);

xspeed3 = xspeed + m1*random(-7, 7);

yspeed3 = yspeed + m2*random(-7, 7);

rect(x+xspeed4, y+yspeed4, 2, 2);

xspeed4 = xspeed3 + m1*random(-7, 7);

yspeed4 = yspeed3 + m2*random(-7, 7);

rect(x+xspeed2, y+yspeed2, 2, 2);

}

if (t > 140) {

t= 0;

x = random(50, 650);

y = random(50, 650);

xspeed = 0;

yspeed = 0;

xspeed2 = 0;

yspeed2 = 0;

xspeed3 = 0;

yspeed3 = 0;

xspeed4 = 0;

yspeed4 = 0;

}

if ((x > width) || (x<0)) {

t= 0;

}

if ((y > height) || (y<0)) {

t= 0;

}

}

int th1=8+20;

int th2=180-20;

int lightValue;

void draw(){

if(p.available()>0){

lightValue=p.read();

println(lightValue);

}

if(lightValue>th1 && lightValue

if(mousePressed && (mouseButton==LEFT)){

backround(255);

}

}

[Arduino Code]

int myLed[] = {A2, A3, A4};

int sound[] = {523, 539, 587}; // C,D,E

int lightScope[]={30,120,200,280};

int i = 0;

int sensor = A5;

int sPin = 9;

byte val; //save variable

int buzzerPin = 9;

int a = Serial.read();

void setup() {

Serial.begin(9600);

for (i = 0; i < 3; i++) {

pinMode(myLed[i], OUTPUT);

}

}

void loop() {

int sensorValue = analogRead(sensor/4);

Serial.write(sensorValue/4);

delay(100);

if (sensorValue < 20) { // Tur all the LED off, if the value is higher than 40

digitalWrite(myLed[i], LOW);

}

else if (sensorValue > lightScope[0], sensorValue < lightScope[1] ) {

lightPin(myLed[0], 100);

tone(buzzerPin, 523, 1000);

delay(100);

//Serial.println('0');

}

else if (sensorValue > lightScope[1], sensorValue < lightScope[2]) {

lightPin(myLed[1], 100);

tone(buzzerPin, 587, 1000);

delay(100);

//Serial.println('1');

}

else if (sensorValue > lightScope[2], sensorValue < lightScope[3]) {

lightPin(myLed[2], 100);

tone(buzzerPin, 659, 1000);

delay(100);

//Serial.println('2');

}

else

{

light();

}

}

void light() {

for (i = 0; i < 3; i++) {

digitalWrite(myLed[i], LOW);

delay(100);

}

}

void lightPin(int ledPin, int ledDelay) {

digitalWrite(ledPin, HIGH);

delay(ledDelay);

digitalWrite(ledPin, LOW);

delay(ledDelay);

}

Step 5: Connect Lilypad XBee

1. Connect Lilypad XBee to Lilypad main board (Image 1)

* Connect TX to pin 10 and connect RX to pin 11

2. In order to connect the XBee Lilypad to the main board, program Arduino using the following code to send serial number. (It follows the same logic as the process used in step 5)

[Arduino Code]

#include

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {

Serial.begin(9600);

Serial.println("Goodnight Jooeun!");

mySerial.begin(9600);

mySerial.println("Hello, Jooeun?");

}

byte i;

void loop() { // run over and over

mySerial.write(i++);

delay(500

3. Ensure that processing receive data from Arduino, by checking the display on the console.

4. Then, combine all of the Arduino codes together!

[Final Arduino Code]

#include

SoftwareSerial mySerial(11,10);

int myLed[] = {A4, A3, A2};

int sound[] = {523, 539, 587}; // C,D,E

int lightScope[]={40,100,150,200};

int i = 0;

int sensor = A5;

byte val; //save variable

int buzzerPin = 2;

int a = Serial.read();

void setup() {

Serial.begin(9600);

for (i = 0; i < 3; i++) {

pinMode(myLed[i], OUTPUT);

}

mySerial.begin(9600);//test1

}

void loop() {

mySerial.write(i++);

int sensorValue = analogRead(sensor/4);

Serial.write(sensorValue/4);

mySerial.write(sensorValue/4);

delay(100);

if (sensorValue < 20) { // Tur all the LED off, if the value is higher than 40

digitalWrite(myLed[i], LOW);

noTone(buzzerPin);

}

else if (sensorValue > lightScope[0], sensorValue < lightScope[1] ) {

lightPin(myLed[0], 100);

tone(buzzerPin, 523, 1000);

delay(100);

}

else if (sensorValue > lightScope[1], sensorValue < lightScope[2]) {

lightPin(myLed[1], 100);

tone(buzzerPin, 587, 1000);

delay(100);

}

else if (sensorValue > lightScope[2], sensorValue < lightScope[3]) {

lightPin(myLed[2], 100);

tone(buzzerPin, 659, 1000);

delay(100);

}

else

{

light();

}

}

void light() {

for (i = 0; i < 3; i++) {

digitalWrite(myLed[i], LOW);

noTone(buzzerPin);

delay(100);

}

}

void lightPin(int ledPin, int ledDelay) {

digitalWrite(ledPin, HIGH);

delay(ledDelay);

digitalWrite(ledPin, LOW);

delay(ledDelay);

}

5. Remove USB Cable from Lilypad

6. Connect XBee USB Adapter. (Double check the port number)

7. Check the Processing.

TIP: If XBee doesn’t work, try using the following instructions to troubleshoot. (For Mac User)
a. Install driver

FTDI drive: http://www.ftdichip.com/Drivers/VCP.htm

b. connect XBee to USB

c. Open [XCTU]

d. Click [discover radio devices]

e. Add [Select Devices]

f. click (+) and write +++ [send selected packet] ==> You’ll receive OK.

d.Initialize to factory mode. Same process as [ step f ]. (you must add )

ATRE

ATWR

ATCN

(follow with the image)

Step 6: Stitch the Lilypad to Fabric

Before start stitching, it is advisable to draw a sketch. The Maker highly recommends it.

NOW Play