Pedalboard, MIDI Clock + Start/Stop

Status
Not open for further replies.

nakatano

Member
Dear all,

For a project I'm working on, I try to built a basic MIDI pedalboard prototype to send Start/Stop and Clock (Sync) MIDI messages, using two push buttons (one for the Tap Tempo, one for Start / Stop).
The idea is to sync Ableton Live (in a first "prototyping" time) and later (finally), a grandMA2 lighting console in order to synchronise lights with my full analog (no MIDI) modular synthetiser.
I spend lot of time searching on Teensy projects and forum and tried to "mix" two pieces of code.
This one : https://github.com/little-scale/arduino-sketches/blob/master/MIDI_Clock_Send_3.ino and this one : https://forum.arduino.cc/t/measuring-the-time-between-2-button-presses/584791/5 (Cattledog's answer / piece of code).
Both work great, separately (with Ableton Live).

My troubles begin when I try to have both working together and I can't figure where is the problem (or incompatibilities)...
Is it a "multiple Bounce functions" problem ?
Something in the organisation or timing of the code ?
Something completely else ? ;-)

A huge thanks for any help !

Code:
#include <Bounce2.h>
Bounce rpmSelectorButton = Bounce();
Bounce pushButton = Bounce();

float bpm; // ajout Nika
float delay_time;
int play_flag;
int pushButton_pin = 4;
int debounce_time = 10;
unsigned long startTime;
unsigned long currentTime;
unsigned  long interval;
const byte buttonPin = 2;
boolean timing = false;


void setup()
{
//  Serial.begin(115200);
  pinMode(pushButton_pin, INPUT_PULLUP);
  pushButton.attach(pushButton_pin);
  pushButton.interval(debounce_time);
  delay(3000);
  pinMode(buttonPin, INPUT_PULLUP);
  
//  Serial.println("Interval Timer Demo");

  rpmSelectorButton.attach(buttonPin);
  rpmSelectorButton.interval(debounce_time); // was debounce period in ms (25) // PROBLEM HERE ?

  delay(3000);
}

void loop()
{
  pushButton.update();

  if (pushButton.fell() == true) {
    play_flag = 1 - play_flag;
    
    if (play_flag == 1) {
      usbMIDI.sendRealTime(usbMIDI.Start);
      Serial.println("MyLady_Clock : Start");

    }
    else {
      usbMIDI.sendRealTime(usbMIDI.Stop);
      Serial.println("MyLady_Clock : Stop");
    }
  }
  
    currentTime = millis();
    rpmSelectorButton.update();//debounced digitalRead()
  if(rpmSelectorButton.fell() && ! timing)
  {
    startTime = currentTime;
    timing = true;
 // Serial.println("start interval timing  ");
    rpmSelectorButton.update();//ensures new debounce reading for second press
  }
  
 if (rpmSelectorButton.fell() && timing)
  {
    interval = millis() - startTime;
    timing = false;

    Serial.println("end interval timing");
    Serial.print("Time between button presses ");
    Serial.println(interval); // in milliseconds

    bpm = (60000 / interval); // to calculate musical time / tempo
    Serial.print("Lady BPM : "); 
    Serial.println(bpm);

    delay_time = (60000000 / bpm) / 24; // to calculate Pulse Per Quarter note (MIDI clock)
    Serial.print("delay_Time : "); 
    Serial.println(delay_time);

    usbMIDI.sendRealTime(usbMIDI.Clock);
    delayMicroseconds(delay_time);  

  // MIDI Controllers should discard incoming MIDI messages.
  // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
//  while (usbMIDI.read()) {
    // ignore incoming messages
//  }
}
}
 
Last edited:
I will try to explain the weird behavior of each button (since everything seems to work in Arduino's serial monitor...) :

The button 1 (pushButton_pin = 4) seems to work but only to "engage" the Start message to Ableton Live (as if Live was in a "Pause mode"). It's normal behavior would be to Start / Stop Ableton Live.

The button 2 (buttonPin = 2), when double pushed, "activates" Live's Start but doesn't transmit the MIDI CLock / Tempo / PPQ (which looks ok in Arduino's serial monitor...).

Any help or advice ?
Best,
Nicolas.
 
I tried your code on a T3.2 and used MIDI-OX on the PC to monitor its output.
When pushed Button 1 toggles between sending a MIDI Start and a MIDI Stop.
The first push of Button 2 starts a timer. The second push measures the time between button pushes, send one MIDI Clock message and prints some info. In particular, this only sends one Clock message. Were you expecting it to send more?

Code:
> First push of button 2
end interval timing
> Second push of button 2
Time between button presses 2397
Lady BPM : 25.00
delay_Time : 100000.00

"activates" Live's Start but doesn't transmit the MIDI CLock / Tempo / PPQ (which looks ok in Arduino's serial monitor.
It does transmit the clock but only once. I'm not clear what you mean here. What "looks ok in Arduino's serial monitor"?

Pete
 
Thanks el_supremo for your answer !

"looks ok in Arduino's serial monitor" means that the calculation step was functionnal when printed in Arduino's IDE serial monitor.
I fixed the issue : the timer was sending its value at the wrong moment : it had to be calculated and sent before the start / stop function.
Below, the corrected code, if it can help someone !
(There's probably a much more elegant and efficient way to write this piece of code but this one seems to work great, since yesterday...)
Now, I have to "filter" aberrant values and add two buttons with "next" and "previous" functions (via MIDI notes) in order to navigate from scene to scene in Ableton before I can test the networked definitive system (with the help of 2 BomeBox) on the GrandMA !
Can't wait !!

Nicolas.

Code:
#include <Bounce2.h>

float bpm = 125;
float delay_time = 20000;
int play_flag;
int pushButton_pin = 4;
int debounce_time = 10;
unsigned long startTime;
unsigned long currentTime;
unsigned  long interval;
int buttonPin = 2;
boolean timing = false;
int led = 13;


// #################################
// #################################

  Bounce rpmSelectorButton = Bounce();
  Bounce pushButton = Bounce();

// #################################
// #################################

void setup() {
  
  pinMode(pushButton_pin, INPUT_PULLUP);
  pushButton.attach(pushButton_pin);
  pushButton.interval(debounce_time);
  pinMode(buttonPin, INPUT_PULLUP);
  rpmSelectorButton.attach(buttonPin);
  rpmSelectorButton.interval(debounce_time); // was debounce period in ms (25) // PROBLEM HERE ?
  pinMode(led, OUTPUT);
  delay(1000);

}

// #################################
// #################################

void loop() {

    currentTime = millis();
    rpmSelectorButton.update();  //debounced digitalRead()

if(rpmSelectorButton.fell() && ! timing)

  {
    startTime = currentTime;
    timing = true;
    Serial.println("start interval timing  ");
    rpmSelectorButton.update();  //ensures new debounce reading for second press
}
  
 if (rpmSelectorButton.fell() && timing)

  {

    interval = millis() - startTime;
    timing = false;
    Serial.println("end interval timing");
    Serial.print("Time between button presses ");
    Serial.println(interval); // in milliseconds

    bpm = (60000 / interval); // to calculate musical time / tempo
    Serial.print("Lady BPM : "); 
    Serial.println(bpm);

    delay_time = (60000000 / bpm) / 24; // to calculate Pulse Per Quarter note (MIDI clock)
    Serial.print("delay_Time : "); 
    Serial.println(delay_time);
}
     
  pushButton.update();

if (pushButton.fell() == true) 

{
  
    play_flag = 1 - play_flag;
    
if (play_flag == 1) 

{
  
      usbMIDI.sendRealTime(usbMIDI.Start);
      Serial.println("Lady_Clock : Start");
      digitalWrite(led, HIGH); 
}
    
else 

{
      usbMIDI.sendRealTime(usbMIDI.Stop);
      Serial.println("Lady_Clock : Stop");
      digitalWrite(led, LOW);
}
}

if (play_flag == 1) 

{

      delay_time = (60000000 / bpm) / 24;
      usbMIDI.sendRealTime(usbMIDI.Clock);
      delayMicroseconds(delay_time);

}
}

// #################################
// #################################
 
Status
Not open for further replies.
Back
Top