Bass Pedal MIDI Controller Video

I’ve put together a short video showing the Bass Pedal project in its current state. Enjoy.

The next step will be to add voice control, so that I can shift it form the default piano voice and perhaps an LCD display panel showing the currently selected options. This could display the current octave, transpose setting, voice and volume.

Connecting to the Pedal Board

I need to be able to plug and unplug the Arduino borad from the Pedal board while I am testing and adding features. For this purpose I’m using a 20 way plug and socket to go with the ribbon cable already installed in the pedal board.

I’ve soldered the socket to a piece of strip board then soldered in the cable being careful to match the correct wire with the appropriate pin.

On other other end of the cable I have soldered a piece of single core wire to each strand and protected it with heat shrink tubing. I’ll then be able to plug these flying leads into the I2C chips on the breadboard.

Next step, trial run and perhaps a YouTube video :-) (I’d better set up an appropriately named account.)

MIDI with octave control

I’ve added a couple of extra controls to the MIDI board. There are two buttons, to the bottom of the board, which control the octave. One for up, one for down. I’ve set the range of the board to four octaves with four LEDs to display the currently chosen octave.

There is also a potentiometer used to set the volume (velocity in MIDI parlance)

I’m still using a floating wire to test the board, next step will be to wire it into the pedal. The layout of the board is clearer in the Fritzing picture below.

Code shown below:

// MultiButtonMIDIOctave.ino
// Driving MIDI using a Multiple Buttons
// Added variables for Octave, Transpose and Velocity
// Rob Ives 2012
// This code is released into the Public Domain.
 
#include 
#include 
 
int keyispressed[16]; //Is the key currently pressed?
int noteisplaying[16]; //Is the Note currently playing?
unsigned char data1; //data from chip 1
unsigned char data2; //data from chip 2
int octave = 2; //set currently played octave
int transpose = 0; //transpose notes on the board
int velocity = 127; //set note velocity
//--- Octave LED output pins
int octave1 = 8;
int octave2 = 9;
int octave3 = 10;
int octave4 = 11;
//--- Octave Switches 
int octaveup = 7;
int octavedown = 6;
//--- Pot
int potpin = 2;
 
void  setup() //The Setup Loop
{
  Wire.begin(); // setup the I2C bus
  for (unsigned int i = 0; i < 16; i++) { //Init variables
    keyispressed[i] = 1; //clear the keys array (High is off)
    noteisplaying[i] = 0; //no notes are playing
  }
  //--- Set up pins
  pinMode(octaveup, INPUT);
  pinMode(octavedown, INPUT);
  pinMode(octave1, OUTPUT);
  pinMode(octave2, OUTPUT);
  pinMode(octave3, OUTPUT);
  pinMode(octave4, OUTPUT);
 
  MIDI.begin(); //initialise midi library
  displayoctave(); //display the current octave
 
}
//---------------------------------------------
void loop() //the main loop
{
  readkeys();
  sendMIDI();
  checkoctave();
}  
//-------------------------------------
void readkeys() { //Read the state of the I2C chips. 1 is open, 0 is closed.
  Wire.requestFrom(0x38, 1); // read the data from chip 1 in data1
  if (Wire.available()){
     data1 = Wire.read(); 
 
  }
  Wire.requestFrom(0x39, 1); // read the data freom chip 2 into data2
  if (Wire.available()){
     data2 = Wire.read();    
  }
 
  for (unsigned char i = 0; i < 8; i++) {// puts data bits from chip 1 into keys array        keyispressed[i] = ((data1 >> i) & 1); // set the key variable to the current state. chip 1
       keyispressed[i + 8] = ((data2 >> i) & 1); //chip 2
  }
}  
//-------------------------------------
void sendMIDI() { // Send MIDI instructions via the MIDI out
  int note; //holder for the value of note being played
 
  velocity = analogRead(potpin)/8;// Read velocity from the pot
  for (unsigned char i = 0; i < 16; i++) { //for each note in the array
    if (keyispressed[i] == LOW){ //the key on the board is pressed 
      if(!noteisplaying[i]){ //if the note is not already playing send MIDI instruction to start the note
         note = i + (octave*12) + transpose;
         MIDI.sendNoteOn(note,velocity,1);  // Send a Note ( vel.127  ch. 1)
         noteisplaying[i] = note; // set the note playing flag to TRUE and store the note value
      }
    }
    else{
      if(noteisplaying[i]){ //if the note is currently playing, turn it off
        note = noteisplaying[i]; //retrieve the saved note value incase the octave has changed
        MIDI.sendNoteOff(note,0,1);   // Stop the note
        noteisplaying[i] = 0; // clear the note is playing flag
      }
    }
  }
}
//----------------------------------------
void checkoctave(){
  int up = digitalRead(octaveup);
  int down = digitalRead(octavedown);
 
  if(up == HIGH){ //up button pressed
    if(octave < 4){       octave++;     }     while(up == HIGH){// wait until button is released       up = digitalRead(octaveup);       delay(20);     }     displayoctave();   }   if(down == HIGH){ //down button pressed     if(octave > 1){
      octave--;
    }
    while(down == HIGH){// wait until button is released
      down = digitalRead(octavedown);
      delay(20);
    }
    displayoctave();
  }
}
//-------------------------------------
void displayoctave(){
  // clear all the LEDs
  digitalWrite(octave1, LOW);
  digitalWrite(octave2, LOW);
  digitalWrite(octave3, LOW);
  digitalWrite(octave4, LOW);
  // ...and then display the current octave
  switch(octave){ // display the current actave
  case 1: digitalWrite(octave1, HIGH); 
          break;
  case 2: digitalWrite(octave2, HIGH); 
          break;
  case 3: digitalWrite(octave3, HIGH); 
          break;
  case 4: digitalWrite(octave4, HIGH); 
          break;
  }
}

Multi Button MIDI

I’ve now mixed the single button MIDI code with the I2C code to create a Multi Button MIDI. This is just the starting point but it works perfectly. Using the same board layout as the earlier post, upload this sketch and you’ll have sixteen inputs for your MIDI device, perfect for wiring into your Bass Pedal!

// MultiButtonMIDI.ino
// Driving MIDI using a Multiple Buttons
// Rob Ives 2012
// This code is released into the Public Domain.
 
#include <MIDI.h>
#include <Wire.h>
 
int keyispressed[16]; //Is the key currently pressed?
int noteisplaying[16]; //Is the Note currently playing?
unsigned char data1; //data from chip 1
unsigned char data2; //data from chip 2
 
void  setup() //The Setup Loop
{
  Wire.begin(); // setup the I2C bus
  for (unsigned int i = 0; i < 16; i++) { //Init variables
    keyispressed[i] = 1; //clear the keys array (High is off)
    noteisplaying[i] = 0; //no notes are playing
  }
  MIDI.begin(); //initialise midi library
}
//---------------------------------------------
void loop() //the main loop
{
  readkeys();
  sendMIDI();
}  
//-------------------------------------
void readkeys() { //Read the state of the I2C chips. 1 is open, 0 is closed.
  Wire.requestFrom(0x38, 1); // read the data from chip 1 in data1
  if (Wire.available()){
     data1 = Wire.read(); 
 
  }
  Wire.requestFrom(0x39, 1); // read the data freom chip 2 into data2
  if (Wire.available()){
     data2 = Wire.read();    
  }
 
  for (unsigned char i = 0; i < 8; i++) {// puts data bits from chip 1 into keys array
       keyispressed[i] = ((data1 >> i) & 1); // set the key variable to the current state. chip 1
       keyispressed[i + 8] = ((data2 >> i) & 1); //chip 2
  }
}  
//-------------------------------------
void sendMIDI() { // Send MIDI instructions via the MIDI out
  for (unsigned char i = 0; i < 16; i++) { //for each note in the array
    if (keyispressed[i] == LOW){ //the key on the board is pressed 
      if(!noteisplaying[i]){ //if the note is not already playing send MIDI instruction to start the note
         MIDI.sendNoteOn(36+i,127,1);  // Send a Note ( vel.127  ch. 1)
         noteisplaying[i] = 1; // set the note playing flag to TRUE
      }
    }
    else{
      if(noteisplaying[i]){ //if the note is currently playing, turn it off
        MIDI.sendNoteOff(36+i,0,1);   // Stop the note
        noteisplaying[i] = 0; // clear the note is playing flag
      }
    }
  }
}

This is just the start. My next step will be to add a volume control and an octave switch.
Possible plan for octave switch: Two foot buttons, one for up, one for down, Four LEDs showing which octave is currently selected.

Testing the I2C bus

I’m using the I2C bus to read the keys in from the bass pedal. The breadboard layout is shown in an earlier post. To make sure that everything is working properly with the chips I have set up a piece of code that will read the sixteen pins in I2C chips and display their output via the Arduino serial monitor.
The code is here:

// MultiButtonTest.ino
// Driving MIDI using a Multiple Buttons
// Rob Ives 2012
// This code is released into the Public Domain.
 
#include <MIDI.h>
#include <Wire.h>
 
int keyispressed[16]; //Variable. Is the key currently pressed?
int noteisplaying[16]; //Variable. Is the Note currently playing?
unsigned char data1; //data from chip 1
unsigned char data2; //data from chip 2
 
void  setup() //The Setup Loop
{
  Wire.begin(); // setup the I2C bus
  Serial.begin(9600); // serial set up for debugging
  for (unsigned int i = 0; i < 16; i++) { 
    keyispressed[i] = 1; //clear the keys array (High is off)
    noteisplaying[i] = 0; //no notes are playing
  }
 
  //MIDI.begin(); //initialise midi library
}
//---------------------------------------------
void loop() //the main loop
{
  readkeys();
  displaykeys();
}  
//-------------------------------------
void readkeys() {
  Wire.requestFrom(0x38, 1); // read the data from chip 1 into data1
  if (Wire.available()){
     data1 = Wire.read(); 
 
  }
  Wire.requestFrom(0x39, 1); // read the data freom chip 2 into data2
  if (Wire.available()){
     data2 = Wire.read();    
  }
 
  for (unsigned char i = 0; i < 8; i++) {// puts data bits from chip 1 into keys array
       keyispressed[i] = ((data1 >> i) & 1); // set the key variable to the current state. chip 1
       keyispressed[i + 8] = ((data2 >> i) & 1); //chip 2
  }
}  
//-------------------------------------
void displaykeys() { //Display the keys presssed for debugging purposes
  for (unsigned char i = 0; i < 16; i++) {
    Serial.print(keyispressed[i]); //print out each value from the array on one line.
  } 
  Serial.println("<<"); 
}

Wire up the chip and run the sketch.

In the Arduino environment on your computer go to Tools -> Serial Monitor
where you should see a display spitting out rows of sixteen ones over and over.
Try connecting each of the data pins on the I2C chips to ground and if all is well, the corresponding one will turn to a zero.

Pullup / Pulldown

Next step in the midification process is to add the PCF8574 chips. These chips let me add multiple inputs using only three of the input lines on the Arduino. The chips can be daisy-chained together using the same three input lines so with two chips I can have sixteen inputs and still have loads in inputs/outputs available on the arduino for other interesting stuff.
Checking the data sheet for the chip I noticed that the i/o lines on the chip have a built in pullup resistor. This means that if the input line is not connected it will be at the high voltage. To close a switch the input line it needs to be connected to the ground line.
In my previous, single switch, set up I had used a pulldown resistor meaning that an open input was at zero volts and needed five volts to be a closed input.
The diagram below shows a pullup resistor in place.

With the switch open Vout will be high. When the switch is closed it goes low.
For consistency I have changed the circuit and code on the single switch project to use a pullup resistor.

This has been simply a case of swapping the resistor and the wire.
The code is modified very slightly as well changing the line

if (keyispressed == HIGH){ //the key on the board is pressed

to

if (keyispressed == LOW){ //the key on the board is pressed

//Driving MIDI using a single button
// Rob Ives 2012
// This code is released into the Public Domain.
 
#include 
 
#define KEY 8
#define LED 13
 
int keyispressed = 0; //Variable. Is the key currently pressed?
int noteisplaying = 0; //Variable. Is the Note currently playing?
 
void  setup() //The Setup Loop
{
  pinMode(LED, OUTPUT);  //Set pin 13 , the led, to output
  pinMode(KEY, INPUT);  //Set pin 8 to input to detect the key press
  MIDI.begin(); //initialise midi library
}
//---------------------------------------------
void loop() //the main loop
{
  keyispressed = digitalRead(KEY); //read pin 8
 
  if (keyispressed == LOW){ //the key on the board is pressed
    digitalWrite(LED, HIGH); //set the LED to on. 
    if(!noteisplaying){ //if the note is not already playing send MIDI instruction to start
       MIDI.sendNoteOn(36,127,1);  // Send a Note (pitch 36 (C2), vel.127  ch. 1)
       noteisplaying = 1; // set the note playing flag to TRUE
    }
  }
  else{
    digitalWrite(LED,LOW); // the key is not pressed. Turn off the LED
    if(noteisplaying){ //if the note is currently playing, turn it off
      MIDI.sendNoteOff(36,0,1);   // Stop the note
      noteisplaying = 0; // clear the note is playing flag
    }
  }
}

The good news is that it still works. Time for more inputs

Single Button MIDI

Stage two of my further adventures in MIDI land. Using a single button to play a single note via MIDI. A MIDI.sendnoteon turns on a note which keeps playing unless otherwise instructed. To stop the note a second instruction is sent. MIDI.sendnoteoff

To do this you need to send a MIDI message whenever the state of the key changes. This is known as edge detection.

The switch in the centre of the breadboard acts as the key.

A 10k pull down resistor ensures that pin 8 on the Arduino board is kept low until the key is pressed.

// SingleButtonMIDI.ino
// Driving MIDI using a single button
// Rob Ives 2012
// This code is released into the Public Domain.
 
#include <MIDI.h>
 
#define KEY 8
#define LED 13
 
int keyispressed = 0; //Variable. Is the key currently pressed?
int noteisplaying = 0; //Variable. Is the Note currently playing?
 
void  setup() //The Setup Loop
{
  pinMode(LED, OUTPUT);  //Set pin 13 , the led, to output
  pinMode(KEY, INPUT);  //Set pin 8 to input to detect the key press
  MIDI.begin(); //initialise midi library
}
//---------------------------------------------
void loop() //the main loop
{
  keyispressed = digitalRead(KEY); //read pin 8
 
  if (keyispressed == HIGH){ //the key on the board is pressed
    digitalWrite(LED, HIGH); //set the LED to on. 
    if(!noteisplaying){ //if the note is not already playing send MIDI instruction to start
       MIDI.sendNoteOn(36,127,1);  // Send a Note (pitch 36 (C2), vel.127  ch. 1)
       noteisplaying = 1; // set the note playing flag to TRUE
    }
  }
  else{
    digitalWrite(LED,LOW); // the key is not pressed. Turn off the LED
    if(noteisplaying){ //if the note is currently playing, turn it off
      MIDI.sendNoteOff(36,0,1);   // Stop the note
      noteisplaying = 0; // clear the note is playing flag
    }
  }
}

Wire up the Arduino as shown and upload the Sketch. The unit will play a low C whenever the key is pressed. Works a treat for me even without switch de-bounce.

Back to Basics

I’ve been experimenting with the Arduino MIDI library. The code is available to download here. WIth the library installed using MIDI is simpler and your code is clearer. The MIDI library is initialises in the void setup(); function by inserting the line

MIDI.begin();

Then the code to start a note playing is

MIDI.sendNoteOn(36,127,1);

and to stop the same note is

MIDI.sendNoteOff(36,0,1);

In both these functions the first variable is the note value, in this case C2, the second variable is the velocity and the final variable is the channel.

In the meantime I have got my hands on a Yamaha MU10 tone generator from eBay.

This simplifies things considerably as I’m not having to use the computer as both editing station for the Arduino and MIDI playback device.

And so, back to basics. I’ve rigged up an Arduino with a MIDI port , connected it to the MU10 and have been experimenting with the MIDI library.

The first batch of code is a simple test. It turns on one note, turns on a second note then turns them both off one after the other.

 

// Experimenting with Arduino MIDI library. 
// Rob Ives 2012
// This code is realeased into the Public Domain.
 
#include <MIDI.h>
#define LED 13   		// LED pin on Arduino board
 
void setup() {
  pinMode(LED, OUTPUT);  //Set pin 13 , the led, to output
  MIDI.begin();          // initialise MIDI 
}
 
void loop() {
   MIDI.sendNoteOn(36,127,1);  // Send a Note (pitch 36 (C2), vel.127  ch. 1)
   digitalWrite(LED,HIGH);     // turn on the LED
   delay(1000);		// Wait for a second
   MIDI.sendNoteOn(42,127,1);  // Send a second Note (pitch 42, vel.127  ch. 1)
   delay(1000);		// Wait for a second
   MIDI.sendNoteOff(42,0,1);  // Send a Note (pitch 42, vel.127  ch. 1)
   delay(1000);		// Wait for a second
   MIDI.sendNoteOff(36,0,1);   // Stop the note
   digitalWrite(LED,LOW);      //turn off the LED
   delay(1000);		// Wait for a second	
}

Latest Circuit Layout

Circuit Board

I’ve re-layed the circuit for the midi-pedal project onto this useful board from Ooomlout¬†which handily holds an Arduino board and a breadboard. The circuit is basically the same but tidied up and with the addition of a volume pot. I’m just debugging the code at the moment and will post that when its done.

The flying white lead at the top is the test contact lead instead of having to wire in the whole of the pedal board.

First Draft of Code

First draft of the code to convert keyboard input to midi. There is a bug somewhere, the midi sounds continuously with new notes added but not switched off.

// Convert thirteen input wires from bass pedal into midi output
// Rob Ives 2012
// This code is realeased into the Public Domain.
 
#include <wire.h>
unsigned char data1; //data from chip 1
unsigned char data2; //data from chip 2
unsigned char keys[16]; //storage array for key states.
byte notevalue = 0; //lowest note on the bass board
 
void setup() // the setup loop
 
{
  Wire.begin(); // setup the I2C bus
  Serial.begin(9600); // serial set up for midi
  for (unsigned int i = 0; i < 16; i++) { //clear the keys array
    keys[i] = 1;
  }
}
// ----------------------------------------------------------------
void loop() // the main loop
{
  byte velocity; //note velocity
  velocity = 90; //initially set at 90 - add volume control later
  Wire.requestFrom(0x38, 1); // read the data from chip 1 into data1
  if (Wire.available()){
     data1 = Wire.read(); 
 
  }
  Wire.requestFrom(0x39, 1); // read the data freom chip 2 into data2
  if (Wire.available()){
     data2 = Wire.read();
  }
 
  for (unsigned char i = 0; i &lt; 8; i++) {// puts data bits from chip 1 into keys array     if (keys[i] != ((data1 &gt;&gt; i) &amp; 1)){ // edge detect. If the key state has changed.
      if (keys[i] == 1){// if the key was on send an Start Note midi command
        playnote(0x90, notevalue + i, velocity); // channel 1 midi on
      }
      else{ // send a end note midi command
        playnote(128, notevalue + i, 0); // channel 1 midi off
      }
    }
    keys[i] = ((data1 &gt;&gt; i) &amp; 1); // set the key variable to the current state.
  }
 
 /* for (unsigned char i = 0; i &lt; 8; i++) {// puts data bits from chip 2 into keys array     if (keys[i+8] != ((data2 &gt;&gt; i) &amp; 1)){ // edge detect. If the key state has changed.
      if (keys[i+8] == 1){// if the key was on send an start Note midi command
          //Serial.print(i+8);
          //Serial.println(" Midi On");
          Serial.print(0x80); // channel 1 midi on
          Serial.print(notevalue+i+8); //note value
          Serial.println(velocity); // note velocity
      }
      else{ // send a end note midi command
        //Serial.print(i+8);
        //Serial.println(" Midi Off");
        Serial.write(0x90); // channel 1 midi off
        Serial.write(notevalue+i+8); //note value
        Serial.write(velocity); // note velocity
      }
    }
    keys[i + 8] = ((data2 &gt;&gt; i) &amp; 1);
  } */
 
  /* for (unsigned char i = 0; i &lt; 16; i++) {
      Serial.print(keys[i]);
  }
  Serial.println("-"); */
}
 
//-------------------------------------
//play note
void playnote(byte cmd, byte data1, byte data2) {
   //--------------- debug
   Serial.print(cmd);
   Serial.print(" | ");
   Serial.print(data1);
   Serial.print(" | ");
   Serial.println(data2);
   //-----------------
   Serial.write(cmd);
   Serial.write(data1);
   Serial.write(data2);
 }