Bluetooth MIDI (BLE) with Teensy

Status
Not open for further replies.

ybr

Member
Hi Guys,
I'm working on a midi controller right now using a Teensy 3.5. Everything works great and I'm currently looking into implementing midi over Bluetooth in my device so I can wirelessly play on my iPhone, iPad or computer. I haven't found any simple ways to specifically implement this with Teensy but found several other microcontrollers that were able to do it.

1.
https://github.com/sieren/blidino
This project uses the RedBearLab NRF51822 shield for Arduino which is quite large for my desired application.

2.
https://punchthrough.com/bean/docs/guides/features/midi/
The Lightblue Bean by Punch Through Design supports sending Midi over BLE

3.
https://learn.adafruit.com/bluetooth-le-midi-controller/overview
In this project the Feather 32u4 Bluefruit LE by Adafruit is used for sending Midi over Bluetooth.

4.
https://www.youtube.com/watch?v=yS4A0PTdxFk
Yamaha has the MD-BT01 adapter that plugs in directly into a DIN midi port.

Connecting other microcontrollers or adapters to the Teensy feels quite cumbersome and expensive to me. Does anyone have a suggestion of a better alternative that lets me send Midi over Bluetooth from the Teensy? I found this which might be interesting but not sure how I could implement Bluetooth over Midi here.
https://learn.adafruit.com/introducing-the-adafruit-bluefruit-spi-breakout/introduction

Best,

Yannick
 
Last edited:
A warning if you go with the Adafruit Bluefruit Feather: I've been having a lot of trouble with it and the Wire library. Specifically trying to get an MCP23017 IO expander working with it. I've had a "ticket" open on their forum for a bit now with not a lot of help.
 
(Had a quick read through your adafruit forum post) .. Have you tried a different breadboard or different position on the same breadboard? I've had some problems where the internal connector was making poor contact and creating spurious errors on my project.
 
Yeah, I have.

I've rebuilt it on another breadboard and went as far as using a multimeter to make sure all of the connections were actually connected (continuity from pin to connected pin).
 
Hi Guys, thanks for all the information. I went with the Bluefruit SPI Friend LE and managed to let it work without to much hassle. Used the Adafruit Bluefruit LE App to update the device, used Hardware SPI (same pins as Arduino Metro in Adafruit guide) and default midi example in the Bluefruit library.

For anyone looking doing the same thing. My slightly adjusted code:

Code:
#include <Arduino.h>
#include <SPI.h>

// You may or may not need to include this depending on your platform
// Include this for the 32u4, exclude it for the M0 for example
//#include <SoftwareSerial.h>

#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"
#include "Adafruit_BLEMIDI.h"

#include "BluefruitConfig.h"

#define FACTORYRESET_ENABLE         1
#define MINIMUM_FIRMWARE_VERSION    "0.7.0"

// This app was tested on iOS with the following apps:
//
// https://itunes.apple.com/us/app/midimittr/id925495245?mt=8
// https://itunes.apple.com/us/app/igrand-piano-free-for-ipad/id562914032?mt=8
//
// To test:
// - Run this sketch and open the Serial Monitor
// - Open the iGrand Piano Free app
// - Open the midimittr app on your phone and under Clients select "Adafruit Bluefruit LE"
// - When you see the 'Connected' label switch to the Routing panel
// - Set the Destination to 'iGrand Piano'
// - Switch to the iGrand Piano Free app and you should see notes playing one by one

// Create the bluefruit object, either software serial...uncomment these lines
/*
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);

Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,
                              BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
*/

/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
// Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN);

/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

/* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */
//Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO,
//                             BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS,
//                             BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

Adafruit_BLEMIDI midi(ble);

bool isConnected = false;
int current_note = 60;
int channel = 0;

// A small helper
void error(const __FlashStringHelper*err) {
  Serial.println(err);
  while (1);
}

// callback
void connected(void)
{
  isConnected = true;

  Serial.println(F(" CONNECTED!"));
  delay(1000);

}

void disconnected(void)
{
  Serial.println("disconnected");
  isConnected = false;
}

void BleMidiRX(uint16_t timestamp, uint8_t status, uint8_t byte1, uint8_t byte2)
{
  Serial.print("[MIDI ");
  Serial.print(timestamp);
  Serial.print(" ] ");

  Serial.print(status, HEX); Serial.print(" ");
  Serial.print(byte1 , HEX); Serial.print(" ");
  Serial.print(byte2 , HEX); Serial.print(" ");

  Serial.println();
}

void setup(void)
{
  while (!Serial);  // required for Flora & Micro
  delay(500);

  Serial.begin(115200);
  Serial.println(F("Adafruit Bluefruit MIDI Example"));
  Serial.println(F("---------------------------------------"));

  /* Initialise the module */
  Serial.print(F("Initialising the Bluefruit LE module: "));

  if ( !ble.begin(VERBOSE_MODE) )
  {
    error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
  }
  Serial.println( F("OK!") );

  if ( FACTORYRESET_ENABLE )
  {
    /* Perform a factory reset to make sure everything is in a known state */
    Serial.println(F("Performing a factory reset: "));
    if ( ! ble.factoryReset() ) {
      error(F("Couldn't factory reset"));
    }
  }

  //ble.sendCommandCheckOK(F("AT+uartflow=off"));
  ble.echo(false);

  Serial.println("Requesting Bluefruit info:");
  /* Print Bluefruit information */
  ble.info();

  /* Set BLE callbacks */
  ble.setConnectCallback(connected);
  ble.setDisconnectCallback(disconnected);

  // Set MIDI RX callback
  midi.setRxCallback(BleMidiRX);

  Serial.println(F("Enable MIDI: "));
  if ( ! midi.begin(true) )
  {
    error(F("Could not enable MIDI"));
  }

  ble.verbose(false);
  Serial.print(F("Waiting for a connection..."));
}

void loop(void)
{
  // interval for each scanning ~ 500ms (non blocking)
  ble.update(500);

  // bail if not connected
  if (! isConnected)
    return;

  Serial.print("Sending pitch ");
  Serial.println(current_note, HEX);

  // send note on
  // play pressed note
  //   blemidi(channel, 0x9, pitch, vel)
       bleMidi(0, 0x9, current_note, 40);
  delay(500);

 
      
  // send note off
  
      // play note off
//      bleMidi(channel, 0x8, pitch, 0x0);
      bleMidi(0, 0x8, current_note, 0x0);


  delay(500);



  
  // increment note pitch
  current_note++;

  // only do one octave
  if(current_note > 72)
    current_note = 60;

}

void bleMidi(byte channel, byte command, byte arg1, byte arg2) {

  // init combined byte
  byte combined = command;

  // shift if necessary and add MIDI channel
  if(combined < 128) {
    combined <<= 4;
    combined |= channel;
  }

  midi.send(combined, arg1, arg2);

}
 
Last edited:
Status
Not open for further replies.
Back
Top