COI - Beat Keeper
The end product is a beat training machine, which the user can program with a custom beat with two different sensory inputs (a touch sensor and a sound sensor (tapping, snapping)). The user can adjust the training tempo using the rotation sensor, and their score is displayed on the lcd screen. The yellow LED flashes in time with the beat, the green and red LED's indicate when the user should trigger the touch sensor and the sound sensor respectively.
The touch and sound sensors can also be put into custom enclosures or traded out for other sensors in order to make the game more interesting.
Hardware
- Intel Edison
- Static Mat
- Computer
- 2 Mini USB Cables
- 4 Jumper Cables
- Bread Board
- 3 LED Lights (Yellow, Green, Red)
- 4 Pin Cables
- 3 1000 OHM resistors
- Seeed RGB Backlight LCD
- Seeed Rotary Angle Sensor
- Seeed Sound Sensor
- Seeed Touch Sensor
Setup
- Plug your Grove base shield into your Edison (doesn’t have to be an Intel Edison - can be an Arduino board).
- Plug jumper cable into port I2C (doesn’t matter which one). Connect other end to RGB Backlight LCD.
- Plug jumper cable into port D8. Connect other end to Touch Sensor.
- Plug jumper cable into port A0. Connect other end to Rotary Angle Sensor.
- Plug jumper cable into port A3. Connect other end to Sound Sensor.
- Plug pin cable into 5V port (located by the I2C ports).
- Plug pin cables into ~3, ~5, and ~6 ports. We will connect these to the yellow, green, and red lights respectively.
- Check bread board diagram and set up accordingly.
- Download code at the end of the page.
- Upload the code into Arduino IDE.
- Upload the code into Edison.
- Practice keeping beat.
- Start making beats.
- Get record deal.
- Become world famous.
- Go to music awards show.
- Jump on stage while awards are being handed out.
- Grab mic.
- “Imma let you finish, but Beyonce had one of the best videos. OF ALL TIME.”
Programming/Code
Download the file at the end of the instructable, or copy the following code into your Arduino-Intel IDE (Integrated Development Environment). Upload the code to the Edison Board. Note that there are several customizable parameters appearing in the code, most significantly a String called beat with letters that represent the sensors to be triggered on beat, and a unitsPerBeat which tells how many characters go into a single beat.
#include<br>
#include
#include
rgb_lcd lcd;
#define S_SENS A3
#define T_SENS 8
#define ROT_SENS A0
int yellowPinNum = 3;
int greenPinNum = 5;
int redPinNum = 6;
int thresholdSound = 400; //Out of 1024
//minTime and maxTime can be customized.
int minTime = 250;//Corresponds to 240 bpm
int maxTime = 1000;//Corresponds to 60 bpm
int beatTime = maxTime;
long long lastMillis = 0;
double score = 1.0; //This is a value kept between 0 and 1 which is affected by your most recent performance.
double memoryPersistance = .8; //This value is customizable and should be between 0 and 1;
char touchCode = 'T';
char soundCode = 'S';
char bothCode = 'B';
char silentCode = '-';
String beat = "S-T-T-T-"; //This is customizable to produce a new beat. Beats can be of arbitrary length.
int unitsPerBeat = 2; //Customizable, is the number of characters in beat per "beat"
int beatIndex = 0;
boolean touchedLastTime = false;
boolean soundLastTime = false;
boolean scoreIntegrated = false;
void setup() {
// Make Sure to Initialize the Pins for Output:
pinMode(yellowPinNum, OUTPUT);
pinMode(greenPinNum, OUTPUT);
pinMode(redPinNum, OUTPUT);
//Set up LCD screen
lcd.begin(16,2);
lcd.setRGB(255,255,255);
// Set the pinMode of the inputs
pinMode(S_SENS, INPUT);
pinMode(T_SENS, INPUT);
pinMode(ROT_SENS, INPUT);
//Safety:
unitsPerBeat = max(unitsPerBeat, 1);
}
void loop() {
//Check for a beat rollover
boolean rollOver = false;
if(millis()-lastMillis > beatTime){
lastMillis = lastMillis + beatTime;
rollOver = true;
beatIndex = (beatIndex + 1)%beat.length();
}
if(millis() < lastMillis){
lastMillis = millis();
rollOver = true;
beatIndex = (beatIndex + 1)%beat.length();
}
//Read speed preference and display on LCD.
if(rollOver){
beatTime = minTime+(int)(analogRead(ROT_SENS)/1024.0 * (maxTime-minTime));
double bpm = 60.0*1000.0/beatTime;
lcd.setCursor(0,0);
lcd.print(" ");//Clear Screen
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("BPM: ");
lcd.print(bpm);
beatTime = beatTime/unitsPerBeat;
}
//Check to see if in first quarter. If so, turn on appropriate LED's, and check for touches.
if(millis()-lastMillis < beatTime/3){
scoreIntegrated = false; //Means soundLastTime, touchedLastTime have potentially new values;
if(beatIndex == 0){
analogWrite(yellowPinNum, 0); //Full brightness on first beat.
}
else if (beatIndex%unitsPerBeat==0){
analogWrite(yellowPinNum, 200); //Lower Brightness.
}//End if is first beat
if(beat[beatIndex]==touchCode || beat[beatIndex] == bothCode){
analogWrite(greenPinNum, 0);
}
if(beat[beatIndex]==soundCode || beat[beatIndex]==bothCode){
analogWrite(redPinNum, 0);
}
if(digitalRead(T_SENS)==1){
touchedLastTime=true;
}
if(analogRead(S_SENS)>thresholdSound){
soundLastTime=true;
}
}
else if(millis()-lastMillis > (beatTime * 2)/3){
scoreIntegrated = false; //Means soundLastTime, touchedLastTime have potentially new values;
if(digitalRead(T_SENS)==1){
touchedLastTime=true;
}
if(analogRead(S_SENS)>thresholdSound){
soundLastTime=true;
}
}
else{
analogWrite(yellowPinNum, 255);//Inverted for some reason.
analogWrite(greenPinNum, 255);
analogWrite(redPinNum, 255);
if(scoreIntegrated == false){
double correctness = 0;
if(beat[beatIndex]==bothCode && touchedLastTime && soundLastTime){
correctness=1;
}
else if(beat[beatIndex]==touchCode && touchedLastTime && !soundLastTime){
correctness=1;
}
else if(beat[beatIndex]==soundCode && !touchedLastTime && soundLastTime){
correctness=1;
}
else if(beat[beatIndex]==silentCode && !touchedLastTime && !soundLastTime){
correctness=score;
}
score = score * memoryPersistance + correctness*(1-memoryPersistance);
lcd.setRGB((int)(255*(1-score)),(int)(255 * score),0);
lcd.setCursor(0,1);
lcd.print((int)(score*100));
lcd.print("%");
scoreIntegrated = true;
touchedLastTime=false;
soundLastTime=false;
}
}
}
Downloads
Lessons Learned
- Use a delay in the loop if you are debugging, as this allows you to see everything that happens.
- Leave extra time for a project to account for the time you will spend adjusting and fine-tuning your design.
- Test your designs frequently for usability.