Go Down

Topic: Receive Serial, Transmit Serial1 (Read 84 times) previous topic - next topic

ibanman555

Hey Arduinoids.

I'm hoping someone could guide me in the right direction regarding the correct coding to send and receive data between the 'Serial' and 'Serial1' pins.  Actually an example would really help me understand the process. :-/

So, I have my MEGA2560 receiving MIDI messages in via USB, and transmitting another MIDI message out each time it receives that first message (ping). I have this set up using Callbacks and MIDI.sendNoteOn. It is functioning properly.

 I have the Tx of 'Serial1' connected to the Rx of an RS232 converter, and the converters Tx to the Arduinos Rx on 'Serial1'.

OK, so here's what I am having trouble figuring out. I am receiving MIDI messages from my PC into the Arduino, I assume they are coming in on the 'Serial' Rx pin based on the Rx LED activity. I then want to convert that message to another message my RS232 device wants to see to function. However, the RS232 converter is connected to the 'Serial1' pins. So I need to shift the incoming messages from the 'Serial', translate the message, and out to 'Serial1'.

Then, vice versa. Any RS232 messages transmitting from my controller back into the Arduino  via the 'Serial1' pins, those MIDI messages translated back to what my PC program wants to see, transmitting back on 'Serial'.

I hope I am clear enough on what I hope to achieve here, any guidance it greatly appreiated!

HazardsMind

#1
Oct 30, 2014, 08:02 pm Last Edit: Oct 30, 2014, 08:02 pm by HazardsMind
Could you provide an example of what comes in and what needs to go out?
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

ibanman555

Yes sure.

So in my audio recording program, I want to press the Mute button on Track Channel 1. If I click that button, the corresponding LED will light up on my external controller next to the controllers Mute button. And then the opposite, pressing Mute on my controller will activate Mute in the recording program.

So, set up the way I am now, pressing Mute (Track Channel 1) in the program sends the message 'B0 0C 00 B0 2C 02' to the Arduino. Now as soon as I receive that message I need to send message 'B0 46 7F', then 'B0 46 00' immediately following, out 'Serial1' to my external controller, turning on its LED.

The opposite, pressing Mute on my external controller sends 'B0 46 7F' from the controller, to the Arduino via 'Serial1'. Then message 'B0 0F 00 B0 2F 42' back to my recording program via 'Serial'.




HazardsMind

Does everything contain B0?

You could try a look up table of the bytes combined together as a word or just the last two bytes as an int. Then have one part scan the incoming bytes (after converted) and the other send out appropriate response.

I would need to know more to give you a better answer. Some links to these commands would be helpful
.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

ibanman555

#4
Oct 30, 2014, 09:56 pm Last Edit: Oct 30, 2014, 09:57 pm by ibanman555
There is no link to the commands per se. I had to find out what data was being sent from my controllers and convert those to the HUI protocol, custom. I've been using Bome Midi Translator to translate the midi messages, and it all works, I am just now looking for a way to eliminate the need for software running in the background to use these controllers. I will post some images showing the midi messages that need to be sent/received for a better idea. But basically, I've described everything needed to make the conversion happen above, I just don't know the proper code to use to make it happen :/

Nick Gammon

#5
Oct 30, 2014, 11:14 pm Last Edit: Oct 30, 2014, 11:15 pm by Nick Gammon
If it's any help, attached is a sketch I wrote a while back that reads MIDI and decodes it, sending the results to Serial (on a Uno). Therefore it reads MIDI on one serial port, and sends results on another.

Video of it in operation
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

HazardsMind

#6
Oct 30, 2014, 11:21 pm Last Edit: Oct 30, 2014, 11:28 pm by HazardsMind
Well you can still use the lookup table. If you have multiple commands, then you can use 2 lookup tables, one for the receiving side and the other for the transmitting side.

What you need to do is convert the 3 incoming bytes to a unsigned long (4 bytes) variable, then compare that variable to one that is in the lookup table and if it matches, see what that index is and send out the response.

Here is an example. (Added comments)
Code: [Select]
unsigned long Receiver[4] = {0x414141, 0x424242, 0x434343, 0x444444};
unsigned long Transmiter[4] = {0x616161, 0x626262, 0x636363, 0x646464};
unsigned long temp = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop()
{
  // put your main code here, to run repeatedly:
  static byte j = 0;
  temp = 0;

  if (Serial.available() > 2) // or (... == 3) for exactly 3 bytes
  {
    for (byte i = 0; i < 3; i++) // 3, for the 3 bytes you are looking for
    {
      char myData = Serial.read();// collect the incoming byte
      //Serial.println(myData, HEX);
      temp = (temp << 8) | myData; // store them into a 4 byte variable + bit shifting
    }

    for (j = 0; j < 4; j++) // 4 = the number of commands in your array
    {
      if (temp == Receiver[j]) // if your bitShifted bytes are equal to one of the commands, then this condition is true
      {
        Serial.print("We have a match at index: ");
        Serial.println(j);
        delay(1000); // just for effect
        Serial.print("Sending response: ");
        Serial.println(Transmiter[j], HEX); // Send out on Serial1
        break;
      }
    }
    if (j == 4) // self explanatory
      Serial.println("No match found");
  }
}
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

ibanman555

Ok... for being a novice just trying to get my bearings, I still find the code a bit confusing, even though you comment well. I'll get there. I hoped there would be more straight forward coding using decimal or hex, without having too many variables. I forgot to mention that my Arduino is flashed with HIDUINO, and I am programming the 2560 via ISP.

Here are some screen shots showing the exact MIDI messages that are being sent and received between my audio recording program and my external controllers:

Here, the "incoming" messages are in HEX, these are the messages being sent from my audio recording program. Bome's MIDI translates that message and shows the "outgoing" code to the external controller, which is what it wants to see to function properly.


This image shows "incoming" messages from the controller, and Bome's MIDI translates that message and shows the "outgoing" code to the audio recording program, which is what it wants to see to function properly.


Here is the code I've started for that PING I mentioned earlier, which is "pinging" properly, but also my attempt at sending this data the way I thought it needed to be sent. Comments are welcome:

Code: [Select]
#include <MIDI.h>
#include <stdlib.h>
#include "Arduino.h"
#include "HardwareSerial.h"
#define LED 13

MIDI_CREATE_DEFAULT_INSTANCE();

// -----------------------------------------------------------------------------
//This sketch programs the MEGA2560 to receive a HUI ping and return that ping
//back to HUI to allow external controller conversion to occur. Arduino is bootloaded
//with HIDUINO firmware on the Atmel8u2 as a class-compliant driverless MIDI device,
//passing MIDI messages through it. Programmed via ISP as the HIDUINO firmware does not
//allow for USB<>Arduino sketch programming.

void Ping(byte channel, byte pitch, byte velocity)//channel 1, pitch 0, velocity 0
{
     if (velocity==0);
     digitalWrite(LED, LOW);
     delay(400);                //LED flash for 1/2 second to confirm Ping Return
     digitalWrite(LED, HIGH);   
     MIDI.sendNoteOn(0, 127, 1);//note, velocity, channel
     delay(5);
     MIDI.sendNoteOff(0, 127, 1);
  // Notice that NoteOn messages with 0 velocity are interpreted as NoteOffs.
}
void Channel_1(byte channel, byte pitch, byte velocity){
     
  //Mute Press On Track Channel 1 from Pro Tools to Controller
      if(channel==176, pitch==12, velocity==0, channel==176, pitch==44, velocity==2);
      byte Mute_1[] = {176,70,127,176,70,0};
      Serial1.write(Mute_1,6);
      delay(50);
      if(channel==176, pitch==12, velocity==0, channel==176, pitch==44, velocity==66);
      byte Mute_1_1[] = {176,70,127};
      Serial1.write(Mute_1_1,3);
}


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

void setup()
{
    Serial1.begin(38400);//Serial 1 pin 19(Rx) pin 18(Tx)
    MIDI.setHandleNoteOff(Ping);
    MIDI.setHandleNoteOn(Channel_1);

    // Initiate MIDI communications, listen to all channels
    MIDI.begin(MIDI_CHANNEL_OMNI);
   

}

void loop()
{
    // Call MIDI.read the fastest you can for real-time performance.
    MIDI.read();


}

Nick Gammon

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

ibanman555

#9
Today at 04:04 am Last Edit: Today at 04:07 am by ibanman555
My audio recording program sends a Ping (90 00 00), so the velocity of that is 0. Once receiving that "message" with a zero velocity, it needs to send back (90 00 7F);

     MIDI.sendNoteOn(0, 127, 1);//note, velocity, channel
     delay(5);
     MIDI.sendNoteOff(0, 127, 1);

Im sure there's a better way to do it...

HazardsMind

He was reffering to the semicolon at the end of that If statement.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories


Go Up