Introduction: Wireless Finger Drum
I came across these Force Sensitive Resistors. I like them a lot and I wanted to do something with them, may be making them more usesable than standing on the breadboard.
Few months ago, I created the pocket-sized RevIO - Arduino Compatible and having fun with it since then.
While playing with these two, I decided to put them together!
To complicate things further, I wanted to use them wirelessly. So I added XBee module to send commands wirelessly from RevIO to play different drum sound snippets on the PC speakers.
Above was not the only reason to make me put these four force sensitive resistors onto the RevIO case permanently. I saw that I could used these force sensitive resistors as the controllers, such as robot controller, or radio control car, or anything that required the maximum of four controllers.
This instructable only shows how to use these FSRs to make drum sounds as they are pressed.
Here is the video when I tested them.
Few months ago, I created the pocket-sized RevIO - Arduino Compatible and having fun with it since then.
While playing with these two, I decided to put them together!
To complicate things further, I wanted to use them wirelessly. So I added XBee module to send commands wirelessly from RevIO to play different drum sound snippets on the PC speakers.
Above was not the only reason to make me put these four force sensitive resistors onto the RevIO case permanently. I saw that I could used these force sensitive resistors as the controllers, such as robot controller, or radio control car, or anything that required the maximum of four controllers.
This instructable only shows how to use these FSRs to make drum sounds as they are pressed.
Here is the video when I tested them.
Step 1: Parts and Tools
Parts
RevIO or any Arduino compatible board
(Note: If you are using any Arduino or compatible. You will need to have some sort of surface to place the force sensitive sensors on)
XBee breakout board or similar (I used my xB-Buddy kit in this project)
4 nos. Force Sensitive Resistors
4 nos. 10K Resistors
30 AWG Wire Wrap
4 nos. Small Bumpers
2 nos. 4-pin Break Away Male Headers Machine Pin
2 nos. 4-pin Break Away Female Headers Machine Pin
Tools
The tools that I used in this project are:
Hand drill
Paperclip
Solder iron and Solder station
Hookup Wire
Diagonal Cutter
Pliers
X-Acto Knife
Wire Stripper
SolderSucker
RevIO or any Arduino compatible board
(Note: If you are using any Arduino or compatible. You will need to have some sort of surface to place the force sensitive sensors on)
XBee breakout board or similar (I used my xB-Buddy kit in this project)
4 nos. Force Sensitive Resistors
4 nos. 10K Resistors
30 AWG Wire Wrap
4 nos. Small Bumpers
2 nos. 4-pin Break Away Male Headers Machine Pin
2 nos. 4-pin Break Away Female Headers Machine Pin
Tools
The tools that I used in this project are:
Hand drill
Paperclip
Solder iron and Solder station
Hookup Wire
Diagonal Cutter
Pliers
X-Acto Knife
Wire Stripper
SolderSucker
Step 2: And the Sensors Go To..
The most suitable places for the sensors is on the back of the case of RevIO.
If you are going to make this project happen. And you are using any Arduino or compatible. You will need to have some sort of surface to place the force sensitive sensors on.
For the placements, I want to place the two FSRs on top row another two on the bottom row.
And each pair, top and bottom pair, should stay on the same horizontal line.
The result is shown in picture 1 below.
Then I transfered the layout on to the surface of the case.
When we are dealing with these sensors:
- Flex Sensor
- Flexiforce Pressure sensor
- Force Sensitive Resistor
- HotPot Membrane Potentiometer
- etc.
The following instructable shows how to solve the problem :
https://www.instructables.com/id/Cheapest-Wire-Wrapping-Tool/
Step 3: Assembles
Next I used the hand-drill to drill the tiny hole big enough for the 30 AWG wire wraps that came out of the FSRs.
And drilled the holes for the speaker that I scraped out of broken MP3 player. And installed the speaker in place.
After that, I temporary installed al four FSRs just to checked if everything fit well together. And installed the speaker in place.
I thought about solder all the wires from FSRs directly to the RevIO PCB. But I changed my mind, I used 4-pin matched male and female machine pins instead. And chose to place those connectors close to the FTDI connector, since there was enough space to put these connectors.
Then, I sorted out the wire wrap from the FSRs. I assigned the wire wraps that came has black heat shrink wrapped go to 5V. (See the schematic in picture 5). I soldered these wires to 4-pin male header.
And those with the blue heat shrink wrapped go to Analog pin 0 to 3 respectively. And soldered them to another 4-pin male header.
Next I soldered the two female headers and four 10K Resistors to PCB according to the schematic in picture 5 below.
And that's it! Done with the connections inside.
And drilled the holes for the speaker that I scraped out of broken MP3 player. And installed the speaker in place.
After that, I temporary installed al four FSRs just to checked if everything fit well together. And installed the speaker in place.
I thought about solder all the wires from FSRs directly to the RevIO PCB. But I changed my mind, I used 4-pin matched male and female machine pins instead. And chose to place those connectors close to the FTDI connector, since there was enough space to put these connectors.
Then, I sorted out the wire wrap from the FSRs. I assigned the wire wraps that came has black heat shrink wrapped go to 5V. (See the schematic in picture 5). I soldered these wires to 4-pin male header.
And those with the blue heat shrink wrapped go to Analog pin 0 to 3 respectively. And soldered them to another 4-pin male header.
Next I soldered the two female headers and four 10K Resistors to PCB according to the schematic in picture 5 below.
And that's it! Done with the connections inside.
Step 4: Finished Up
This step would be finishing up on the outside.
Trace the FSRs shape and transfer to double-sided foam tape, and cut them out to shape.
Remove one side of the protective plastic from the cutout foam tape.
Stick the cutout foam tape to the case, underneath the FSR.
Remove the protective plastic from the foam tape. And press the FSR to the foam tape. (See picture 3)
Repeat the above steps for the rest of the FSR.
Stick the bumpers to the four corners of the case. These bumpers protecting FSRs from touching the surface.
And it's done! Hardware is ready!
Trace the FSRs shape and transfer to double-sided foam tape, and cut them out to shape.
Remove one side of the protective plastic from the cutout foam tape.
Stick the cutout foam tape to the case, underneath the FSR.
Remove the protective plastic from the foam tape. And press the FSR to the foam tape. (See picture 3)
Repeat the above steps for the rest of the FSR.
Stick the bumpers to the four corners of the case. These bumpers protecting FSRs from touching the surface.
And it's done! Hardware is ready!
Step 5: Test
This step, we will test the FSRs and the RevIO just to see if everything work.
Go to this website - http://arduino.cc/en/Tutorial/Tone3 and download the sketch, or used the modified files below (Tone3.zip)
Before upload the sketch to Arduino, make sure that:
All four force-sensing resistors connected from +5V to analog in 0 through 3
All 10K resistors from analog in 0 through 3 to ground
8-ohm speaker connected to digital pin 8
Upload the sketch to the Arduino.
We needed to modify the sketch because the original sketch used only three FSRs, but we needed four.
Here is the modified code, those with BOLD were the modified.
/*
keyboard
Plays a pitch that changes based on a changing analog input
circuit:
* 3 force-sensing resistors from +5V to analog in 0 through 5
* 3 10K resistors from analog in 0 through 5 to ground
* 8-ohm speaker on digital pin 8
created 21 Jan 2010
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
http://arduino.cc/en/Tutorial/Tone3
*/
#include "pitches.h"
#define SPEAKER 8
const int threshold = 10; // minimum reading of the sensors that generates a note
// notes to play, corresponding to the 3 sensors:
int notes[] = {NOTE_A4, NOTE_B4, NOTE_C3, NOTE_E6}; // I added one more note to the array
//int notes[] = {NOTE_A4, NOTE_B4, NOTE_C3}; // original code
void setup() {
}
void loop() {
for (int thisSensor = 0; thisSensor <= 3; thisSensor++) {
//for (int thisSensor = 0; thisSensor < 3; thisSensor++) { // original code
// get a sensor reading:
int sensorReading = analogRead(thisSensor);
// if the sensor is pressed hard enough:
if (sensorReading > threshold) {
// play the note corresponding to this sensor:
//tone(8, notes[thisSensor], 20);
tone(SPEAKER, notes[thisSensor], 20);
}
}
}
Go to this website - http://arduino.cc/en/Tutorial/Tone3 and download the sketch, or used the modified files below (Tone3.zip)
Before upload the sketch to Arduino, make sure that:
All four force-sensing resistors connected from +5V to analog in 0 through 3
All 10K resistors from analog in 0 through 3 to ground
8-ohm speaker connected to digital pin 8
Upload the sketch to the Arduino.
We needed to modify the sketch because the original sketch used only three FSRs, but we needed four.
Here is the modified code, those with BOLD were the modified.
/*
keyboard
Plays a pitch that changes based on a changing analog input
circuit:
* 3 force-sensing resistors from +5V to analog in 0 through 5
* 3 10K resistors from analog in 0 through 5 to ground
* 8-ohm speaker on digital pin 8
created 21 Jan 2010
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
http://arduino.cc/en/Tutorial/Tone3
*/
#include "pitches.h"
#define SPEAKER 8
const int threshold = 10; // minimum reading of the sensors that generates a note
// notes to play, corresponding to the 3 sensors:
int notes[] = {NOTE_A4, NOTE_B4, NOTE_C3, NOTE_E6}; // I added one more note to the array
//int notes[] = {NOTE_A4, NOTE_B4, NOTE_C3}; // original code
void setup() {
}
void loop() {
for (int thisSensor = 0; thisSensor <= 3; thisSensor++) {
//for (int thisSensor = 0; thisSensor < 3; thisSensor++) { // original code
// get a sensor reading:
int sensorReading = analogRead(thisSensor);
// if the sensor is pressed hard enough:
if (sensorReading > threshold) {
// play the note corresponding to this sensor:
//tone(8, notes[thisSensor], 20);
tone(SPEAKER, notes[thisSensor], 20);
}
}
}
Step 6: Make It Wireless!
RevIO was designed to be XBee ready.
See details of RevIO pins at https://www.instructables.com/id/Build-The-RevIO-Arduino-Clone-My-Way/
Just plug the breakout board in, loads the sketch, and plays!
What's the sketch does?
RevIO or Arduino is monitoring the Analog pins connected to FSRs. Whenever the FSR get pressed, it transmits the command wirelessly via XBee transmitter (attached to Arduino) to XBee receiver module connected to the PC.
And the Processing program on the PC will translate the command and play the drum sound accordingly.
Following is an Arduino Sketch, upload the sketch to Arduino. (already included in the zip files in the following step, FSRControl.ina)
Note: The XBee module or XBee Breakout board need to be removed while uploading the sketch to Arduino or RevIO.
Because the TX and RX pins on FTDI adapter for uploading sketch share the same TX and RX pins of XBee module.
/*
FSRControl.ino
*/
// minimum reading of the sensors that generates a note
const int THRESHOLD = 25;
int pinA0 = 0;
int pinA1 = 1;
int pinA2 = 2;
int pinA3 = 3;
static const int avgCount = 4;
int valFSR1, valFSR2, valFSR3, valFSR4 = 0;
int arr1[avgCount];
int arr2[avgCount];
int arr3[avgCount];
int arr4[avgCount];
int i;
int index = 0;
//Average the values in the averaging arrays
void avg()
{
valFSR1 = valFSR2 = valFSR3 = valFSR4 = 0;
for(i = 0; i < avgCount; i++)
{
valFSR1 += arr1[i];
valFSR2 += arr2[i];
valFSR3 += arr3[i];
valFSR4 += arr4[i];
}
valFSR1 /= avgCount;
valFSR2 /= avgCount;
valFSR3 /= avgCount;
valFSR4 /= avgCount;
}
void setup() {
// reset average arrays
for (i = 0; i < avgCount; i++)
{
arr1[i] = 0;
arr2[i] = 0;
arr3[i] = 0;
arr4[i] = 0;
}
index = 0;
// start serial port at 9600 bps:
Serial.begin(9600);
}
void loop() {
// out actual values into the averaging arrays
arr1[index] = analogRead(pinA0);
arr2[index] = analogRead(pinA1);
arr3[index] = analogRead(pinA2);
arr4[index] = analogRead(pinA3);
// increment index,
// if index exceeds array sizes reset to zero
index++;
if (index >= avgCount)
{
index = 0;
}
// calculate average values
avg();
// divided the value by 4 to scale it down to 0 - 255
// FSR 1
if((valFSR1 / 4) > THRESHOLD) {
//Serial.print(valFSR1 / 4, DEC); Serial.print(", ");
Serial.write('1');
}
// FSR 2
else if((valFSR2 / 4) > THRESHOLD) {
//Serial.print(valFSR2 / 4 , DEC); Serial.print(", ");
Serial.write('2');
}
// FSR 3
else if((valFSR3 / 4) > THRESHOLD) {
//Serial.print(valFSR3 / 4, DEC); Serial.print(", ");
Serial.write('3');
}
// FSR 4
else if((valFSR4 / 4) > THRESHOLD) {
//Serial.print(valFSR4 /4 , DEC); Serial.println();
Serial.write('4');
}
else {
Serial.write('0');
}
delay(100);
}
Wireless XBee
In order to wirelessly communicate between PC and Arduino, we need two XBee Modules, and one FTDI cable. One XBee module will be connected to Arduino without FTDI cable.
The second XBee Module will be connected to PC or Laptop via FTDI cable (or xBee Buddy).
It would take up a lot of space and time to explain the installation, configuration, and test the XBee module. Instead I provide you the links that you could use as the starting point on how to work with XBee module(s).
Here are my WIKI XBee tutorials, show how to configure and test XBee module using Hyperterminal, and X-CTU:
Configure XBee using AT Commands.
Configure XBee using X-CTU Software.
My XBee video tutorial.
See details of RevIO pins at https://www.instructables.com/id/Build-The-RevIO-Arduino-Clone-My-Way/
Just plug the breakout board in, loads the sketch, and plays!
What's the sketch does?
RevIO or Arduino is monitoring the Analog pins connected to FSRs. Whenever the FSR get pressed, it transmits the command wirelessly via XBee transmitter (attached to Arduino) to XBee receiver module connected to the PC.
And the Processing program on the PC will translate the command and play the drum sound accordingly.
Following is an Arduino Sketch, upload the sketch to Arduino. (already included in the zip files in the following step, FSRControl.ina)
Note: The XBee module or XBee Breakout board need to be removed while uploading the sketch to Arduino or RevIO.
Because the TX and RX pins on FTDI adapter for uploading sketch share the same TX and RX pins of XBee module.
/*
FSRControl.ino
*/
// minimum reading of the sensors that generates a note
const int THRESHOLD = 25;
int pinA0 = 0;
int pinA1 = 1;
int pinA2 = 2;
int pinA3 = 3;
static const int avgCount = 4;
int valFSR1, valFSR2, valFSR3, valFSR4 = 0;
int arr1[avgCount];
int arr2[avgCount];
int arr3[avgCount];
int arr4[avgCount];
int i;
int index = 0;
//Average the values in the averaging arrays
void avg()
{
valFSR1 = valFSR2 = valFSR3 = valFSR4 = 0;
for(i = 0; i < avgCount; i++)
{
valFSR1 += arr1[i];
valFSR2 += arr2[i];
valFSR3 += arr3[i];
valFSR4 += arr4[i];
}
valFSR1 /= avgCount;
valFSR2 /= avgCount;
valFSR3 /= avgCount;
valFSR4 /= avgCount;
}
void setup() {
// reset average arrays
for (i = 0; i < avgCount; i++)
{
arr1[i] = 0;
arr2[i] = 0;
arr3[i] = 0;
arr4[i] = 0;
}
index = 0;
// start serial port at 9600 bps:
Serial.begin(9600);
}
void loop() {
// out actual values into the averaging arrays
arr1[index] = analogRead(pinA0);
arr2[index] = analogRead(pinA1);
arr3[index] = analogRead(pinA2);
arr4[index] = analogRead(pinA3);
// increment index,
// if index exceeds array sizes reset to zero
index++;
if (index >= avgCount)
{
index = 0;
}
// calculate average values
avg();
// divided the value by 4 to scale it down to 0 - 255
// FSR 1
if((valFSR1 / 4) > THRESHOLD) {
//Serial.print(valFSR1 / 4, DEC); Serial.print(", ");
Serial.write('1');
}
// FSR 2
else if((valFSR2 / 4) > THRESHOLD) {
//Serial.print(valFSR2 / 4 , DEC); Serial.print(", ");
Serial.write('2');
}
// FSR 3
else if((valFSR3 / 4) > THRESHOLD) {
//Serial.print(valFSR3 / 4, DEC); Serial.print(", ");
Serial.write('3');
}
// FSR 4
else if((valFSR4 / 4) > THRESHOLD) {
//Serial.print(valFSR4 /4 , DEC); Serial.println();
Serial.write('4');
}
else {
Serial.write('0');
}
delay(100);
}
Wireless XBee
In order to wirelessly communicate between PC and Arduino, we need two XBee Modules, and one FTDI cable. One XBee module will be connected to Arduino without FTDI cable.
The second XBee Module will be connected to PC or Laptop via FTDI cable (or xBee Buddy).
It would take up a lot of space and time to explain the installation, configuration, and test the XBee module. Instead I provide you the links that you could use as the starting point on how to work with XBee module(s).
Here are my WIKI XBee tutorials, show how to configure and test XBee module using Hyperterminal, and X-CTU:
Configure XBee using AT Commands.
Configure XBee using X-CTU Software.
My XBee video tutorial.
Step 7: Processing and Minim
Processing and Minim.
What is Minim?
Minim is the ready to used Processing library that allow us to do things with sound. We could playback various audio formats, such as, MP3, WAV files.
Following is the Processing Sketch.(FSRProcessing.pde)
You'll need the drum sound files (included in the zip file below). If you'd like to change the sound file you can got to http://Free-Loops.com (all the drum sound files used in this sketch are from Free-Loops.com) or other free downloadable sound files web site.
And all the files are provided, there are in the folder called data.
What the sketch does?
When we run the sketch, a small 200x200 pixels window pop up, displaying four black circles.
It waits for the commands from the Arduino.
When the command arrives it will play the drum sound accordingly, while animating the circle.
For more information on Minim library, visit Processing.org or browse through the Processing Forum discussions on Minim here.
Processing sketch
import processing.serial.*;
import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
Serial XBeePort;
int val;
Minim minim;
AudioSample kick;
AudioSample BigDrum;
AudioSample Cowbell;
AudioSample Cymbals;
AudioSample Snare;
void setup() {
size(200, 200, P2D);
minim = new Minim(this);
// Audio samples
BigDrum = minim.loadSample("BigDrum.wav");
Cowbell = minim.loadSample("Cowbell.wav");
Cymbals = minim.loadSample("Cymbals.wav");
Snare = minim.loadSample("Snare.wav");
// "COM7" need to be changed according to your XBee Serial Comm. number
// XBeePort = new Serial(this, "COM7", 9600);
}
void draw() {
if(XBeePort.available() > 0) {
val = XBeePort.read();
//println((char)val);
delay(1);
}
background(255);
fill(0);
ellipse(50, 50, 40, 40); // 2
ellipse(150, 50, 40, 40); // 1
ellipse(50, 150, 40, 40); // 4
ellipse(150, 150, 40, 40); // 3
int grow;
switch(val) {
case '1':
fill(204);
ellipse(150, 50, 40, 40); // 2
//delay(1);
fill(255,0,0);
for (grow = 40; grow < 90; grow++) {
ellipse(150, 50, grow, grow);
}
drumTrigger(1);
break;
case '2':
fill(204);
ellipse(50, 50, 40, 40); // 1
//delay(1);
fill(0,255, 0);
for (grow = 40; grow < 90; grow += 2) {
ellipse(50, 50, grow, grow);
}
drumTrigger(2);
break;
case '3':
drumTrigger(3);
fill(204);
ellipse(150, 150, 40, 40); // 4
//delay(10);
fill(0, 0, 255);
for (grow = 40; grow < 90; grow += 2) {
ellipse(150, 150, grow, grow);
}
break;
case '4':
fill(204);
ellipse(50, 150, 40, 40); // 3
//delay(10);
fill(255, 255, 0);
for (grow = 40; grow < 90; grow += 2) {
ellipse(50, 150, grow, grow);
}
//Snare.trigger();
drumTrigger(4);
break;
default:
break;
}
}
void drumTrigger(int drum) {
switch(drum) {
case 1:
BigDrum.trigger();
break;
case 2:
Cowbell.trigger();
break;
case 3:
Cymbals.trigger();
break;
case 4:
Snare.trigger();
break;
default:
break;
}
}
void stop()
{
// always close Minim audio classes when you are done with them
kick.close();
BigDrum.close();
Cowbell.close();
Cymbals.close();
Snare.close();
minim.stop();
super.stop();
}
Video:
What is Minim?
Minim is the ready to used Processing library that allow us to do things with sound. We could playback various audio formats, such as, MP3, WAV files.
Following is the Processing Sketch.(FSRProcessing.pde)
You'll need the drum sound files (included in the zip file below). If you'd like to change the sound file you can got to http://Free-Loops.com (all the drum sound files used in this sketch are from Free-Loops.com) or other free downloadable sound files web site.
And all the files are provided, there are in the folder called data.
What the sketch does?
When we run the sketch, a small 200x200 pixels window pop up, displaying four black circles.
It waits for the commands from the Arduino.
When the command arrives it will play the drum sound accordingly, while animating the circle.
For more information on Minim library, visit Processing.org or browse through the Processing Forum discussions on Minim here.
Processing sketch
import processing.serial.*;
import ddf.minim.*;
import ddf.minim.signals.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
Serial XBeePort;
int val;
Minim minim;
AudioSample kick;
AudioSample BigDrum;
AudioSample Cowbell;
AudioSample Cymbals;
AudioSample Snare;
void setup() {
size(200, 200, P2D);
minim = new Minim(this);
// Audio samples
BigDrum = minim.loadSample("BigDrum.wav");
Cowbell = minim.loadSample("Cowbell.wav");
Cymbals = minim.loadSample("Cymbals.wav");
Snare = minim.loadSample("Snare.wav");
// "COM7" need to be changed according to your XBee Serial Comm. number
// XBeePort = new Serial(this, "COM7", 9600);
}
void draw() {
if(XBeePort.available() > 0) {
val = XBeePort.read();
//println((char)val);
delay(1);
}
background(255);
fill(0);
ellipse(50, 50, 40, 40); // 2
ellipse(150, 50, 40, 40); // 1
ellipse(50, 150, 40, 40); // 4
ellipse(150, 150, 40, 40); // 3
int grow;
switch(val) {
case '1':
fill(204);
ellipse(150, 50, 40, 40); // 2
//delay(1);
fill(255,0,0);
for (grow = 40; grow < 90; grow++) {
ellipse(150, 50, grow, grow);
}
drumTrigger(1);
break;
case '2':
fill(204);
ellipse(50, 50, 40, 40); // 1
//delay(1);
fill(0,255, 0);
for (grow = 40; grow < 90; grow += 2) {
ellipse(50, 50, grow, grow);
}
drumTrigger(2);
break;
case '3':
drumTrigger(3);
fill(204);
ellipse(150, 150, 40, 40); // 4
//delay(10);
fill(0, 0, 255);
for (grow = 40; grow < 90; grow += 2) {
ellipse(150, 150, grow, grow);
}
break;
case '4':
fill(204);
ellipse(50, 150, 40, 40); // 3
//delay(10);
fill(255, 255, 0);
for (grow = 40; grow < 90; grow += 2) {
ellipse(50, 150, grow, grow);
}
//Snare.trigger();
drumTrigger(4);
break;
default:
break;
}
}
void drumTrigger(int drum) {
switch(drum) {
case 1:
BigDrum.trigger();
break;
case 2:
Cowbell.trigger();
break;
case 3:
Cymbals.trigger();
break;
case 4:
Snare.trigger();
break;
default:
break;
}
}
void stop()
{
// always close Minim audio classes when you are done with them
kick.close();
BigDrum.close();
Cowbell.close();
Cymbals.close();
Snare.close();
minim.stop();
super.stop();
}
Video: