14. Interface and application programming
Assignment:
Group assignment:
Compare as many tool options as possible
Individual assignment:
Write an application that interfaces a user with an input &/or output device that you made
Planning
For this week, I decided to use a SiSonic SPU0414HR5H-SB microphone, which utilizes MEMS (micro-electromechanical system) technology. To build the electronic board, I based it on a
design presented by Neil in the input devices class. This will allow me to convert an analog sound signal to digital and interact with that signal. For the interface, I decided to use Processing, which uses Java language for programming.
The components of the board are:
- 1 ATtiny45 microcontroller
- 1 Mic MEMS Anolog OMNI -42 db SPU0414HR5H-SB
- 1 1K Ω resistor
- 1 10K Ω resistor
- 3 cap 1uF
- 1 cap 10uF
- 1 FTDI connector
- J1 ISP connector
- IC reg linear 3.3V
This is my finished electronic board:
Programming and Testing
First, I programmed the Attiny45 using Arduino IDE 1.8.18, using an Atmel ICE as a programmer. I loaded a code to print the word "Hello" in the serial monitor. Here is the code and the Hello video:
#include <SoftwareSerial.h>
int rx = 3;
int tx = 2;
SoftwareSerial mySerial(rx, tx); //Setting up the RX/TX pins as a SoftwareSerial
void setup(){
mySerial.begin(9600); //Start the serial communication and select the its speed that deppends of the frequency that it will be program the attiny
}
void loop() {
mySerial.println("hello \n"); //Prints in the screen the actual state
delay(1000);
}
"Next, I used a code that allowed me to visualize the variations in sound captured by the microphone on the serial plotter. This way, I could verify that the microphone works correctly, as soldering it was quite a challenge.
la#include <SoftwareSerial.h>
int rx = 3;
int tx = 2;
int analogPin = A2; // Analog input pin for receiving signal
SoftwareSerial mySerial(rx, tx); // Setting up the RX/TX pins as a SoftwareSerial
void setup(){
mySerial.begin(9600); // Start the serial communication and select the speed
pinMode(analogPin, INPUT); // Set the analog pin as input
}
void loop() {
// Read the analog value from the analog pin
int sensorValue = analogRead(analogPin);
// Print the analog value to the serial monitor
//mySerial.print("Analog Value: ");
mySerial.println(sensorValue);
delay(10);
Finally, I proceeded to download Processing and used a code that allowed me to visualize the variation of sound frequencies in a graph. In all my codes, I used ChatGPT as a basis to generate them, then I modified them according to my interests and preferences.
import processing.serial.*;
Serial myPort; // Create object from Serial class
static String val; // Data received from the serial port
int sensorFreq = 0; // Frequency of the sound
int[] freqHistory; // Array to store frequency history
int historyLength = 500; // Length of history to display
int graphWidth = 800; // Width of the graph
int graphHeight = 400; // Height of the graph
void settings() {
size(graphWidth, graphHeight);
}
void setup() {
background(0);
stroke(255);
noFill();
freqHistory = new int[historyLength];
String portName = "COM11"; // Change the port name to match your setup
myPort = new Serial(this, portName, 9600);
}
void draw() {
if (myPort.available() > 0) { // If data is available from the serial port
val = myPort.readStringUntil('\n');
try {
if (val != null) { // Check if val is not null before using it
sensorFreq = Integer.valueOf(val.trim());
updateHistory(sensorFreq);
drawGraph();
}
} catch(Exception e) {
println("Error reading serial data: " + e);
}
}
}
void updateHistory(int newFreq) {
// Shift the frequency history array to the left
for (int i = 0; i < historyLength - 1; i++) {
freqHistory[i] = freqHistory[i + 1];
}
// Add the new frequency to the end of the history array
freqHistory[historyLength - 1] = newFreq;
}
void drawGraph() {
// Clear the background
background(0);
// Draw the graph lines
for (int i = 0; i < historyLength - 1; i++) {
float x1 = map(i, 0, historyLength - 1, 0, width);
float x2 = map(i + 1, 0, historyLength - 1, 0, width);
float y1 = map(freqHistory[i], 0, 1023, height, 0);
float y2 = map(freqHistory[i + 1], 0, 1023, height, 0);
line(x1, y1, x2, y2);
}
}
To visualize the frequency variation graph, I used the song 'The Great Gig in the Sky' by Pink Floyd.
To make it a bit more interactive, I used a program to add two buttons: one to change the background color and the other to turn sound detection on and off. I used Pink Floyd's "Money" for the music.
import processing.serial.*;
Serial myPort; // Create object from Serial class
static String val; // Data received from the serial port
int sensorFreq = 0; // Frequency of the sound
int[] freqHistory; // Array to store frequency history
int historyLength = 500; // Length of history to display
int graphWidth = 800; // Width of the graph
int graphHeight = 400; // Height of the graph
boolean soundDetectionOn = true; // Flag to control sound detection
boolean isBlackBackground = true; // Flag to control background color
Button soundButton, backgroundButton; // Buttons for sound detection and background color
void settings() {
size(graphWidth, graphHeight);
}
void setup() {
background(0);
stroke(255);
noFill();
freqHistory = new int[historyLength];
String portName = "COM11"; // Change the port name to match your setup
myPort = new Serial(this, portName, 9600);
// Initialize buttons
soundButton = new Button(20, 20, 100, 40, "Sound");
backgroundButton = new Button(140, 20, 200, 40, "Background");
}
void draw() {
if (soundDetectionOn && myPort.available() > 0) { // If sound detection is on and data is available from the serial port
val = myPort.readStringUntil('\n');
try {
if (val != null) { // Check if val is not null before using it
sensorFreq = Integer.valueOf(val.trim());
updateHistory(sensorFreq);
}
} catch(Exception e) {
println("Error reading serial data: " + e);
}
}
// Draw graph
drawGraph();
// Draw buttons
drawButtons();
}
void updateHistory(int newFreq) {
// Shift the frequency history array to the left
for (int i = 0; i < historyLength - 1; i++) {
freqHistory[i] = freqHistory[i + 1];
}
// Add the new frequency to the end of the history array
freqHistory[historyLength - 1] = newFreq;
}
void drawGraph() {
// Set background color
if (isBlackBackground) {
background(0);
} else {
background(0, 0, 255); // Blue background
}
// Draw the graph lines
for (int i = 0; i < historyLength - 1; i++) {
float x1 = map(i, 0, historyLength - 1, 0, width);
float x2 = map(i + 1, 0, historyLength - 1, 0, width);
float y1 = map(freqHistory[i], 0, 1023, height, 0);
float y2 = map(freqHistory[i + 1], 0, 1023, height, 0);
line(x1, y1, x2, y2);
}
}
void drawButtons() {
fill(255);
rect(20, 20, 100, 40);
rect(140, 20, 200, 40);
fill(0);
textSize(16);
textAlign(CENTER, CENTER);
text("Sound", 70, 40);
text("Background", 240, 40);
}
void mousePressed() {
// Check if the mouse is over the sound button
if (mouseX >= soundButton.x && mouseX <= soundButton.x + soundButton.w &&
mouseY >= soundButton.y && mouseY <= soundButton.y + soundButton.h) {
soundDetectionOn = !soundDetectionOn; // Toggle sound detection
}
// Check if the mouse is over the background button
if (mouseX >= backgroundButton.x && mouseX <= backgroundButton.x + backgroundButton.w &&
mouseY >= backgroundButton.y && mouseY <= backgroundButton.y + backgroundButton.h) {
isBlackBackground = !isBlackBackground; // Toggle background color
}
}
class Button {
float x, y, w, h;
String label;
Button(float x, float y, float w, float h, String label) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.label = label;
}
}
Downloads