Introduction: COI - Beat Keeper

About: ABOUT FCFI FCFI is a community oriented public workshop where people can meet and work on their projects. We provide a facility that is open 10 AM to 10 PM, 6 days a week (with plans to eventually be open 24/7…

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.

Step 1: 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

Step 2: Setup

  1. Plug your Grove base shield into your Edison (doesn’t have to be an Intel Edison - can be an Arduino board).
  2. Plug jumper cable into port I2C (doesn’t matter which one). Connect other end to RGB Backlight LCD.
  3. Plug jumper cable into port D8. Connect other end to Touch Sensor.
  4. Plug jumper cable into port A0. Connect other end to Rotary Angle Sensor.
  5. Plug jumper cable into port A3. Connect other end to Sound Sensor.
  6. Plug pin cable into 5V port (located by the I2C ports).
  7. Plug pin cables into ~3, ~5, and ~6 ports. We will connect these to the yellow, green, and red lights respectively.
  8. Check bread board diagram and set up accordingly.
  9. Download code at the end of the page.
  10. Upload the code into Arduino IDE.
  11. Upload the code into Edison.
  12. Practice keeping beat.
  13. Start making beats.
  14. Get record deal.
  15. Become world famous.
  16. Go to music awards show.
  17. Jump on stage while awards are being handed out.
  18. Grab mic.
  19. “Imma let you finish, but Beyonce had one of the best videos. OF ALL TIME.”

Step 3: 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;
    }
  }
}

Step 4: Lessons Learned

  1. Use a delay in the loop if you are debugging, as this allows you to see everything that happens.
  2. Leave extra time for a project to account for the time you will spend adjusting and fine-tuning your design.
  3. Test your designs frequently for usability.