Hotfix release available: 2014-09-29d "Hrun". upgrade now! [46.4] (what's this?)
Hotfix release available: 2014-09-29c "Hrun". upgrade now! [46.3] (what's this?)

Interface and Application Programming

Goal

Write an application that interfaces with an input &/or output device I designed a ballon game that users can interact with a microphone to blow the ballon.


Board and Sensor

I used a board with Attiny45. On the chip I used two analog pins for sensors and two pins for serial communication. I used sound sensor for this assignment. Sound sensor detects the volume of sound. The volume goes really high when you blow the air towards the microphone. It served perfectly for my blowing game.


Embedded Programming

From Input Devices I've already shown how to read the value of sensors. I used Arduino to display the value of sensor output. The value range is 0 to 1023 and the silence value is between 26 and 28. Since 1024 is bigger than 1 byte, the value was explicitly divided by 4 and sent to Arduino Uno, which sent the value to my laptop via USB. In addition, I made the Attiny 45 to run at internal 8 Mhz because it seemed to be most compatible with the library.

Code for Attiny 45 sound sensor board to detect sounds and send the volume out:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(0, 2); // RX, TX
int sensorPin_A = 3;    //Microphone Sensor Pin on analog 3
int sensorValue_A = 0;
byte sensorValueA_scaled = 0;
void setup() {
  mySerial.begin(9600);
}
void loop() {
  // read the value from the sensor:
  sensorValue_A = (int)analogRead(sensorPin_A); // sensorValue_A ranges from 0 to 1023
  sensorValueA_scaled =  (byte)(sensorValue_A /4) ; // divided by 4 to fit in a byte 0 ~ 255
  mySerial.write(sensorValueA_scaled);
  delay(50);
}

Code for Arduino Uno to receive an input from RX and send it to USB:

byte inByte=0;
void setup() {
  // initialize serial:
  Serial.begin(9600);
}
void loop(){
}
void serialEvent() {
  while ( Serial.available() ){
    inByte = (byte)Serial.read();
    Serial.write(inByte); 
  }
}

Processing

I used Processing to create the interface of this game. Processing libraries made it very easy to communicate with devices and to draw on screen.

Serial

It was very easy to create a serial port if you knew where the device was in OS. On Mac, list all devices in /dev and find something like tty.usbxxxxxxx. Another way was to check Arduino IDE and select Tool → Serial port. This was for the second parameter of a Serial object.

Drawing

Drawing in Processing was also very intuitive. I wanted to drew a circle with light red as a balloon, so i called function ellipse in function draw(). It took 4 parameters, its location and its size in X and Y respectively. There were several options to specify its location size with function ellipseMode(): RADIUS, CENTER, CORNER, and CORNERS. This example showed how they worked and here I used RADIUS.

Algorithm

The logic of the program is very simple. The radius of the ballon is small at first. When it receives USB signal that is larger than a threshold, the silence value, it increase the radius proportionally to the value. The radius increments by 1 steadily so that it looks like a real ballon. When the ballon reaches its maximum size, it explodes with a flash in the background.

import processing.serial.*;
final int windowWidth = 600;
final int windowHeight = 600;
byte val = 0; // to store data from serial port
int air = 10; // to store the accumulation of val
Serial port;  // serial port object
void setup() {
  size(windowWidth, windowHeight);
  background(255, 255, 255); 
  // Change the USB device path before running
  port = new Serial(this, "/dev/tty.usbmodem1411", 9600); 
}
void draw() {
 // draw the ballon
 ellipseMode(RADIUS); 
 fill(255, 50, 50);
 stroke(0);
 ellipse(windowWidth/2, windowHeight/2, air, air);
 // draw the needle
 fill(100, 100, 100);
 triangle(windowWidth/2, windowHeight - 30, 
          windowWidth/2 -5, windowHeight,
          windowWidth/2 +5, windowHeight);
}
// Called whenever there is something available to read
void serialEvent(Serial port) {
  // data from the Serial port is read in serialEvent() using the read() function and assigned to the global variable: val
  val = (byte)port.read();
  if(val > 10) { // the silence is about 6 - 8
      // the higher the value is, the more air is blown in the ballon.
      // increase air steadily in the loop
      for (int i=0; i < val/5; i++) {
        air++;
        delay(5);
      }
  }
  if(air > 270) {
    // hide the ballon for a while
    air = 0; 
    // explosion animation
    for (int i=0; i<10; i++) {
        background(255, 0, 0); 
        delay(60);
        background(255, 255, 0);
        delay(60); 
    }
    // reset the ballon and background
    air = 10;
    background(255, 255, 255);
  }
}

Show Time