Go Down

Topic: Wireless Midi ESP8266+AppleRTP, Help please,  (Read 1 time) previous topic - next topic

gruntotx

Hi all,
at first I would like to tanks all people helping other people here and apologies if I forgot somethings or it is not the appropriate forum section.
Many weeks trying to connect a Mac (El Capitan) trough RTP Midi to an ESP8266 brought me at this forum,
I have usefully long searched for an answer but not found yet.
I'm quite a Noob, I can't write code only search and copy, so trying to explain as best I can.
My problem:
on one side I have a Mac with Cubase playing a soundtrack with many Midi impulses triggering 16 relays trough USB and Arduino Nano, like Christmas lights, it works perfectly with USB cable,
connections are: MAC USB cable to USB Serial FTDI232 and here Tx to Arduino Rx (or directly to Arduino USB it works the same) here the code.


Code: [Select]
/*
 * The MIT License (MIT)
 * Copyright (c) 2014 prock

 */

int ledPins[] = { 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };   // PWM pins for the LEDS
int ledPins2[] = { A6, A5, A4, A3};


//MIDI data
char mCommand = 0;
char mChannel = 0;
char mByte1 = 0;
char mByte2 = 0;

//Misc data
int incomingByte = 0;
int dataByte;
int lNibble;
int rNibble;


// Higher C (C4)
byte h_offset = 0x48;

// Middle C (C3)
byte l_offset = 0x38;


                  
boolean validCommand = false;

boolean readMidi()
{

 
 while(Serial.available() > 0) {
    incomingByte = Serial.read();
    dataByte = incomingByte&0xFF; //keep only a byte

    return true;
  }
  return false;
}



void setup() {
  //  Set MIDI baud rate:
  Serial.begin(115200);
 
  
  for (int i = 0; i < 12; i++) {
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], HIGH);
  
      }

      
 for (int c = 0; c < 4; c++) {
    pinMode(ledPins2[c], OUTPUT);
   digitalWrite(ledPins2[c], LOW);
  
     }

                      
  }


void loop() {
  if (readMidi()) {
    // save the left nibble and right nibble of the byte received
     lNibble = dataByte>>4;
       rNibble = dataByte&0x0f;  
  
    // lNibble is the MIDI command.  Check for a valid command.
    if (lNibble == 0x09 || lNibble == 0x08) {
      validCommand = true;
      mCommand = lNibble;
        mChannel = rNibble;
         mByte1 = 0;
          mByte2 = 0;
    }
    else if (mByte1 == 0 && validCommand) {
      mByte1 = dataByte;
    }
    else if (mByte2 == 0 && validCommand && mByte1 != 0) {
      mByte2 = dataByte;
      
      // Full MIDI command was recieved.  Process it now.
      doMidiCommand(mCommand,mChannel,mByte1,mByte2);
    }
  }

}

// Executes the MIDI Command.  I have yet to implement the channel
void doMidiCommand(char cmd, char channel, char data1, char data2) {
  
                                              //if (cmd == 0xC && data2 > 0) {
                                    
      if (data1 >= l_offset && data1 < (l_offset+0x11)) {
      digitalWrite(ledPins[data1-l_offset], LOW);
  
      
 }  

      if (data1 >= h_offset && data1 < (h_offset+0x11)) {
     digitalWrite(ledPins2[data1-h_offset], HIGH);
  
      
 }  
                                                              

       if (cmd == 0x08 || data2 == 0) {
    // LED off
                
    if (data1 >= l_offset && data1 < (l_offset+0x11)) {
      digitalWrite(ledPins[data1-l_offset], HIGH);
             }

     if (data1 >= h_offset && data1 < (h_offset+0x11)) {
      digitalWrite(ledPins2[data1-h_offset], LOW);
            }
  }

   // Reset MIDI data
    mCommand = 0;
   validCommand = false;
       mChannel = 0;
        mByte1 = 0;
         mByte2 = 0;  
}




Second part in the next post.
Artist from Italy, use automation, sound, sculpture and something more.

gruntotx

But now I need Wireless communication so on one side I put  an ESP8266 (NodeMcu)integrate Serial that from Apple RTP receive the Midi (Serial) signal (from Mac) and transmit it to Arduino Nano to trigger the Relays, connections are, RTPMidi (on Mac) to ESP and ESP Tx on D4 (swap Tx) to Arduino Rx here the code:

Code: [Select]


// These need to be included when using standard Ethernet
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "AppleMidi.h"

char ssid[] = "**********"; //  your network SSID (name)
char pass[] = "**********";// your network password (use for WPA, or use as key for WEP)

 
//unsigned long t0 = millis();
bool isConnected = false;

APPLEMIDI_CREATE_INSTANCE(WiFiUDP, AppleMIDI); // see definition in AppleMidi_Defs.h

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup()
{
  // Serial communications and wait for port to open:
  Serial.begin(115200);
  Serial.set_tx(2);  //swap tx su D4 pin led non fa stampare su monitor
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(F("."));
  }
  Serial.println(F(""));
  Serial.println(F("WiFi connected"));


  Serial.println();
  Serial.print(F("IP address is "));
  Serial.println(WiFi.localIP());
  Serial.println(F("OK, now make sure you an rtpMIDI session that is Enabled"));
  Serial.print(F("Add device named ArduinoREC with Host/Port "));
  Serial.print(WiFi.localIP());
  Serial.println(F(":5004"));
  Serial.println(F("Then press the Connect button"));
 
// Create a session and wait for a remote host to connect to us
  AppleMIDI.begin("test");

  AppleMIDI.OnConnected(OnAppleMidiConnected);
  AppleMIDI.OnDisconnected(OnAppleMidiDisconnected);

  AppleMIDI.OnReceiveNoteOn(OnAppleMidiNoteOn);
  AppleMIDI.OnReceiveNoteOff(OnAppleMidiNoteOff);

  AppleMIDI.OnReceiveStart(OnAppleMidiStart);
  AppleMIDI.OnReceiveStop(OnAppleMidiStop);

  Serial.println(F("Listening for Clock events"));
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop()
{
 // Listen to incoming notes
  AppleMIDI.run();
  
    byte note;                                                //this can be omitted
    byte velocity;                                            //as well this
    byte channel;                                            //as well

 if (channel >0 && note > 0 && velocity > 0){  //as well
  AppleMIDI.noteOn(note, velocity, channel);
  AppleMIDI.noteOff(note, velocity, channel);
 }
    
}



//=================================================================
// Event handlers for incoming MIDI messages
//=================================================================

// -----------------------------------------------------------------------------
// rtpMIDI session. Device connected
// -----------------------------------------------------------------------------
void OnAppleMidiConnected(uint32_t ssrc, char* name) {
  isConnected = true;
  Serial.print(F("Connected to session "));
  Serial.println(name);
}

// -----------------------------------------------------------------------------
// rtpMIDI session. Device disconnected
// -----------------------------------------------------------------------------
void OnAppleMidiDisconnected(uint32_t ssrc) {
  isConnected = false;
  Serial.println(F("Disconnected"));
}

// -----------------------------------------------------------------------------
 void OnAppleMidiNoteOn(byte channel, byte note, byte velocity) {
 Serial.print(F("Incoming NoteOn from channel:"));
  Serial.print(channel);
  Serial.print(F(" note:"));
  Serial.print(note);
  Serial.print(F(" velocity:"));
  Serial.print(velocity);
  Serial.println();
}

// -----------------------------------------------------------------------------
 void OnAppleMidiNoteOff(byte channel, byte note, byte velocity) {
    Serial.print(F("Incoming NoteOff from channel:"));
    Serial.print(channel);
    Serial.print(F(" note:"));
    Serial.print(note);
    Serial.print(F(" velocity:"));
    Serial.print(velocity);
    Serial.println();
}


// -----------------------------------------------------------------------------
  static void OnAppleMidiStart() {
  Serial.println(F("Start"));
}


// -----------------------------------------------------------------------------
  static void OnAppleMidiStop() {
  Serial.println(F("Stop"));
}

// -----------------------------------------------------------------------------


It "seems" to work because it can seen "some signal" passing trough ESP(D4 led) and Arduino (Rx led) but no trigger at all, also I can see that because when it effectively works (USB cable) the note 56-G#2 make lamp the led Pin 13 on Arduino not so with ESP.
It seems when I connect ESP Tx to  Arduino Rx the signal do not arrive at the processor to enable the sketch or the Midi signal do not flow correctly from ESP..!
Because the different voltage I connected ESP and Arduino signal trough a Mosfet based level converter  
http://www.hobbytronics.co.uk/image/data/tutorial/mosfet_level_converter.jpg
but neither this works.
Have you some usefull suggestion please?
Artist from Italy, use automation, sound, sculpture and something more.

gdsports

I suggest using Serial1 to send MIDI to the nano. I think the existing code sends debug output to D4/GPIO2 which is connected to the nano.

Try this instead

Code: [Select]
  Serial.begin(115200);
  Serial1.begin(115200);


You should see ESP8266 debug output as usual.

Remove all the code in function loop() except for the call to function AppleMIDI.run.

In the OnAppleMidiNoteOn and OnAppleMidiNotOff functions add code that builds a 3 byte MIDI message then calls Serial1.write(midi_msg, 3) to send it to the nano.

gruntotx

Remove all the code in function loop() except for the call to function AppleMIDI.run.

In the OnAppleMidiNoteOn and OnAppleMidiNotOff functions add code that builds a 3 byte MIDI message then calls Serial1.write(midi_msg, 3) to send it to the nano.

Thanks,
what's about 3 byte Midi message?
Are note, velocity and channel?
I changed code in this way,
Code: [Select]
// These need to be included when using standard Ethernet
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "AppleMidi.h"

char ssid[] = "************"; //  your network SSID (name)
char pass[] = "************";    // your network password (use for WPA, or use as key for WEP)
 
//unsigned long t0 = millis();
bool isConnected = false;

APPLEMIDI_CREATE_INSTANCE(WiFiUDP, AppleMIDI); // see definition in AppleMidi_Defs.h

// ---------------------------------------------------------------------------
void setup()
{
  // Serial communications and wait for port to open:
  Serial.begin(115200);
  Serial1.begin(115200);
  //Serial.set_tx(2);  //swap tx su D4 pin led non fa stampare su monitor
  // Get current baud rate
  int br = Serial.baudRate();
  Serial.printf("Serial is %d bps", br);
  Serial.print(F("Getting IP address..."));
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(F("."));
  }
  Serial.println(F(""));
  Serial.println(F("WiFi connected"));


  Serial.println();
  Serial.print(F("IP address is "));
  Serial.println(WiFi.localIP());
  Serial.println(F("OK, now make sure you an rtpMIDI session that is Enabled"));
  Serial.print(F("Add device named ArduinoREC with Host/Port "));
  Serial.print(WiFi.localIP());
  Serial.println(F(":5004"));
  Serial.println(F("Then press the Connect button"));
 
// Create a session and wait for a remote host to connect to us
  AppleMIDI.begin("test");

 
  AppleMIDI.OnReceiveNoteOn(OnAppleMidiNoteOn);
  AppleMIDI.OnReceiveNoteOff(OnAppleMidiNoteOff);

  Serial.println(F("Listening for Clock events"));
}



void loop()
{
 // Listen to incoming notes
  AppleMIDI.run();

    byte note;
    byte velocity;
    byte channel;

}



//=================================================
 Event handlers for incoming MIDI messages
//=================================================


 void OnAppleMidiNoteOn(byte channel, byte note, byte velocity) {
Serial1.write( note);
Serial1.write(velocity);
Serial1.write( channel);
 
  Serial.print(F("Incoming NoteOn from channel:"));
  Serial.print(channel);
  Serial.print(F(" note:"));
  Serial.print(note);
  Serial.print(F(" velocity:"));
  Serial.print(velocity);
  Serial.println();
}
//---------------------------------------------------------------------------
 void OnAppleMidiNoteOff(byte channel, byte note, byte velocity){
 Serial1.write( note);
 Serial1.write(velocity);
 Serial1.write( channel);
 
    Serial.print(F("Incoming NoteOff from channel:"));
    Serial.print(channel);
    Serial.print(F(" note:"));
    Serial.print(note);
    Serial.print(F(" velocity:"));
    Serial.print(velocity);
    Serial.println();
}


Added Serial1.write() to OnAppleMidiNoteOff, OnAppleMidiNoteOn

now I can see on monitor notes flow on, the led transmission light is changed a bit, before was too bright,
Code: [Select]
Incoming NoteOff from channel:12 note:56 velocity:127
Incoming NoteOn from channel:12 note:56 velocity:127
Incoming NoteOff from channel:12 note:56 velocity:127


but no trigger on nano yet.

Artist from Italy, use automation, sound, sculpture and something more.

gdsports

In the OnAppleMidiNoteOn() function add code like this. My MIDI muscle is out of shape so take this with a grain of salt.

 
Code: [Select]
uint8_t midi_msg[3];
 midi_msg[0] = 0x90 | channel;
 midi_msg[1] = note;
 midi_msg[2] = velocity;
 Serial1.write(midi_msg, 3);


Do something similar for the NoteOff function but use the Note Off command.

gruntotx

#5
Dec 08, 2017, 10:02 am Last Edit: Dec 08, 2017, 10:12 am by Coding Badly
Great muscle anyway I can see.
It seems working, now I need some more time to test it on a field.
So with "uint8_t midi_msg[3];" I store in the memory a MIDI message that I call with "Serial1.write(midi_msg, 3);"isn't it? Correct me if I am wrong please?
I gave a look at "https://www.badprog.com/c-type-what-are-uint8-t-uint16-t-uint32-t-and-uint64-t"
just to understand about "uintN_t".
But where do came from "midi_msg"? From what library?
I dig a bit in a Arduino MIDI library but without success.
Anyway this could be the new code
Code: [Select]
// These need to be included when using standard Ethernet
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "AppleMidi.h"

char ssid[] = "************"; //  your network SSID (name)
char pass[] = "************";    // your network password (use for WPA, or use as key for WEP)
 
bool isConnected = false;

APPLEMIDI_CREATE_INSTANCE(WiFiUDP, AppleMIDI); // see definition in AppleMidi_Defs.h

void setup()
{
  // Serial communications and wait for port to open:
  Serial.begin(115200);
  Serial1.begin(115200);
  Serial.print(F("Getting IP address..."));
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(F("."));
  Serial.println(F("WiFi connected"));
  Serial.println();
  Serial.print(F("IP address is "));
  Serial.println(WiFi.localIP());
  }
 
// Create a session and wait for a remote host to connect to us
  AppleMIDI.begin("test");

  AppleMIDI.OnReceiveNoteOn(OnAppleMidiNoteOn);
  AppleMIDI.OnReceiveNoteOff(OnAppleMidiNoteOff);

}

void loop(){
 // Listen to incoming notes
  AppleMIDI.run();
}
 
 void OnAppleMidiNoteOn(byte channel, byte note, byte velocity) {
 uint8_t midi_msg[3];
  midi_msg[0] = 0x90 | channel;
  midi_msg[1] = note;
  midi_msg[2] = velocity;
  Serial1.write(midi_msg, 3);
 
}

 void OnAppleMidiNoteOff(byte channel, byte note, byte velocity){
 uint8_t midi_msg[3];
  midi_msg[0] = 0x80 | channel;
  midi_msg[1] = note;
  midi_msg[2] = velocity;
  Serial1.write(midi_msg, 3);

}

Artist from Italy, use automation, sound, sculpture and something more.

gruntotx

It definitely works!! All afternoon running without faults, really very good.
Many many thanks!
Artist from Italy, use automation, sound, sculpture and something more.

gdsports

So with "uint8_t midi_msg[3];" I store in the memory a MIDI message that I call with "Serial1.write(midi_msg, 3);"isn't it? Correct me if I am wrong please?
You are correct. The message is built in the midi_msg array then sent out the Serial1 port to the nano. See the following for details on other MIDI messages.

https://www.midi.org/specifications/item/table-1-summary-of-midi-message

Quote
But where do came from "midi_msg"? From what library?
midi_msg is an array to hold 3 unsigned 8 bit integers. It does not come from a library. There are Arduino MIDI libraries that where you call a function named, for example, NoteOn(channel,note, velocity). But the function builds the same 3 byte MIDI message then it sends it. For this simple program, a MIDI library is not helpful.

Your code looks good.

gdsports

Looks like our messages crossed. Glad to hear it is working!

gruntotx

I start to understand, I wondering about midi_msg syntax, but I see that it is the array [3]
the significative part of the code, I mean I can write "midi_cool", "midi_sun", "midi_byke" etc..
it will work the same, I know it can look like a stupid things but I have to build in my mind yet
arrays like function, variables, pointers and so on.
In my artist mind they tend to become like clouds, rain, fire etc..!
  thanks again.
Artist from Italy, use automation, sound, sculpture and something more.

Go Up