13. Interface and Application Programming¶
Assignment:¶
- individual assignment:
- write an application that interfaces a user with an input &/or output device that you made
- group assignment:
- compare as many tool options as possible
Laser Harp¶
This week I worked with using Arduino to communicate with Processing to make a laser harp. Arduino as the hardware and Processing as the interface.
Refference¶
Prototype¶
I used Arduino UNO with breadboard to make a prototype:
Bom:¶
Qty | Name | Description | Image |
---|---|---|---|
1 | Arduino UNO | Controller | |
4 | Photoresistor | Input | |
4 | Laser generator | Output |
Code:¶
const int NUM_NOTES=4;
const int notePin[] = {A0,A1,A2,A3};
void setup() {
for (int i=0; i<NUM_NOTES; i++) {
pinMode(notePin[i], INPUT);
}
Serial.begin(38400);
}
void loop() {
for (int i=0; i<NUM_NOTES; i++) {
int value = analogRead(notePin[i]);
Serial.print(i);
Serial.print(",");
Serial.println(value);
delay(500);
}
}
Interface and Tone function design¶
Because Arduino IDE’s serial monitor is very simple, and I hadn’t use speaker or buzzer to creat sound, So I used Processing3 to design the Inerface and creat tone.
First, using library manager to instal the ddf.minim. It will allow me to use the library function to creat tone.
Second, downloading 12 Audio files and drag into Porcessing and it will creat a “data” folder. Then I got the tone files.
Code(Processing)¶
import ddf.minim.*;
import processing.serial.*;
Serial port;
Minim minim;
AudioSample k0;
float k = 50;
void setup()
{
size(1900,1000);
noStroke();
minim = new Minim(this);
port = new Serial(this,"COM5",9600);
k0 = minim.loadSample("1.mp3", 512); // library load music
}
void draw()
{
while(port.available()>0)
{
char input = port.readChar();
switch(input)
{
case 'a': k = 300; k0.trigger(); break; // k0-k11 music file k[0]-k[11] length of rect
}
}
background(255);
if(k>50) k=k-k*0.02;
for(int j=0; j<k; j=j+1)
{
fill(255,0,0,255-j);
rect((j-50)*10,i*80+10,10,80);
}
}
Tip
The “data” folder should be in the same folder of the Processing program. Otherwise the program won’t run successfully.
Some description of the command I have used:
fill(255,0,0,255-j)
RGB color setting, in proper order stands for Red, Green, Blue and brightness.
rect((j-50)*10,i*80+10,10,80)
Draw a rectangle from left to right through chaning ordinate little by little.
Back to Arduino(My PCino). To tragger Processing‘s function Draw, which means Processing will give me a visual feedback, I have to give a specific signal through the serial. So I used one photoresistance to make a test.
Once the sensor is traggered, PCino will give an “a” to Processing. Then Processing will receive it and work its corresponding function.
Code(Arduino)¶
int pin = 0;
int lastValue = 0;
void setup() {
pinMode(pin, INPUT);
Serial.begin(9600);
}
void loop() {
int value = digitalRead(pin);
if (value != lastValue) {
Serial.println(value);
lastValue = value;
if(value == 1){
Serial.write("a");
}
}
}
Prototype outcome¶
Here is the test outcome. I just used one photoresistance for test. If this test passed, then 12 inputs would also work.
3D Design and Assemble:¶
Because this time I want to make a larger laser harp with 12 photoresistors and 12 laser generators, which allows me to play with more tones, so I need 24 pins for my project. My PCino has not enough pins for those, so I decided to use Arduino Mega as cotroller.
Tip
Because each photoresitor and laser generator has one VCC and one GND, you can connect all the VCC into one cable and the same as GND cables. So that at the end of all the VCC and GND there will be onle 1 cable for each, not 12.
Tip
There is a litte knob on the photoresistor module to adjust the sensitivity. Use the tool to rotate the knob until the LED turns off. Which means the threshold is just right.
Code(on Arduino):¶
const int NUM_NOTES=12;
const int notePin[] = {22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44};
int lastState[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
void setup() {
for (int i=0; i<NUM_NOTES; i++) {
pinMode(notePin[i], INPUT_PULLUP);
}
Serial.begin(9600);
}
void loop() {
for (int i=0; i<NUM_NOTES; i++) {
int value = digitalRead(notePin[i]);
if (lastState[i] != value) {
lastState[i] = value;
if(value == 1)
{
switch(i)
{
case 0: Serial.write("a"); break;
case 1: Serial.write("s"); break;
case 2: Serial.write("d"); break;
case 3: Serial.write("f"); break;
case 4: Serial.write("g"); break;
case 5: Serial.write("h"); break;
case 6: Serial.write("q"); break;
case 7: Serial.write("w"); break;
case 8: Serial.write("e"); break;
case 9: Serial.write("r"); break;
case 10: Serial.write("t"); break;
case 11: Serial.write("y"); break;
}
}
}
}
}
Code(on Processing):¶
import ddf.minim.*; // library for tone
import processing.serial.*; // library for communication
Serial port;
Minim minim;
AudioSample k0;
AudioSample k1;
AudioSample k2;
AudioSample k3;
AudioSample k4;
AudioSample k5;
AudioSample k6;
AudioSample k7;
AudioSample k8;
AudioSample k9;
AudioSample k10;
AudioSample k11;
float []k = {50,50,50,50,50,50,50,50,50,50,50,50};
void setup()
{
size(1900,1000);
noStroke();
minim = new Minim(this);
port = new Serial(this,"COM5",9600);
k0 = minim.loadSample("1.mp3", 512); // library load music
k1 = minim.loadSample("2.mp3", 512);
k2 = minim.loadSample("3.mp3", 512);
k3 = minim.loadSample("4.mp3", 512);
k4 = minim.loadSample("5.mp3", 512);
k5 = minim.loadSample("6.mp3", 512);
k6 = minim.loadSample("7.mp3", 512);
k7 = minim.loadSample("8.mp3", 512);
k8 = minim.loadSample("9.mp3", 512);
k9 = minim.loadSample("10.mp3", 512);
k10 = minim.loadSample("11.mp3", 512);
k11 = minim.loadSample("12.mp3", 512);
}
void draw()
{
while(port.available()>0)
{
char input = port.readChar();
switch(input)
{
case 'a': k[0] = 300; k0.trigger(); break; // k0-k11 music file k[0]-k[11] length of rect
case 's': k[1] = 300; k1.trigger(); break;
case 'd': k[2] = 300; k2.trigger(); break;
case 'f': k[3] = 300; k3.trigger(); break;
case 'g': k[4] = 300; k4.trigger(); break;
case 'h': k[5] = 300; k5.trigger(); break;
case 'q': k[6] = 300; k6.trigger(); break;
case 'w': k[7] = 300; k7.trigger(); break;
case 'e': k[8] = 300; k8.trigger(); break;
case 'r': k[9] = 300; k9.trigger(); break;
case 't': k[10] = 300; k10.trigger(); break;
case 'y': k[11] = 300; k11.trigger(); break;
}
}
background(255);
for(int i=0;i<12;i++)
{
if(k[i]>50) k[i]=k[i]-k[i]*0.02;
for(int j=0; j<k[i];j=j+1)
{
fill(255,255,0,255-j);
rect((j-50)*10,i*80+10,10,80);
}
}
}