Transmit/ Receive message SysEx in USB

Hello everybody, i need send and read SysEx messages in USB.MIDI with a Leonardo. I have only one type if message length is 9 SysExArray contains my data and the last argument is True. So my message is: message (9, SysExarray, true). My question is: How to use the functions MidiUSB.sendMIDI(midiEventPacket_t event) for sending my message and MidiUSB.read() for Reading the same type of message ?

Thanks for help

The problem with that library is that it will only receive SyEx that are four bytes long. So if you want to receive a longer message you will have to do it in chunks of four bytes at a time.

This is something I wrote for receiving longer SyEx messages:-

/*
 * MIDIUSB SysEx tests
 *
 */ 

#include "MIDIUSB.h"

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting test");
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void loop() {
  midiEventPacket_t rx;
  do {
    rx = MidiUSB.read();
    if (rx.header == 4) { recieveSysEx(rx); }
    else if (rx.header != 0){ // just print the message
      Serial.print(MidiUSB.available());
      Serial.print("  Received: ");
      Serial.print(rx.header, HEX);
      Serial.print("-");
      Serial.print(rx.byte1, HEX);
      Serial.print("-");
      Serial.print(rx.byte2, HEX);
      Serial.print("-");
      Serial.println(rx.byte3, HEX);
    }
  } while (rx.header != 0);
}

byte message [128]; // place to store the full message bytes

void recieveSysEx(midiEventPacket_t sx){
  midiEventPacket_t rx;
  int pointer = 0;
  byte buff [4]; // nibble buffer our messages are sent one nibble at a time
  byte buffPoint = 0;
  Serial.print("Receiving SysEx message: ");
  if(sx.byte2 == 0x5 && sx.byte3 == 0x5){ // Put the ID of what is sending you the message here.
    Serial.println(" SysEx message for us ");
    do {
      rx = MidiUSB.read(); // place into buffer
      buff[buffPoint++] = rx.byte1;
      buff[buffPoint++] = rx.byte2;
      buff[buffPoint++] = rx.byte3;
      // move from the buffer into the message
      // two conditions first with only three bytes in the buffer, second with four
      if(buffPoint == 3){
      message[pointer++] = (buff[0]<< 4) | buff[1]; // extract one byte from nibble buffer
      buff[0] = buff[2]; // move the spair byte to the start
      buffPoint = 1; // set the pointer to next place to go.
      }
      if(buffPoint == 4){
      message[pointer++] = (buff[0]<< 4) | buff[1]; // extract two bytes from nibble buffer
      message[pointer++] = (buff[2]<< 4) | buff[3];
      buffPoint = 0; // set the pointer to next place to go.
      }
      //Serial.println(pointer);
    } while (rx.header != 0);
    
    Serial.println("Recieved message is");
    for(int i = 0; i<pointer; i++){
      if(message[i] >= 0x20 && message[i] < 0x80){
        Serial.write(message[i]);
      }
      else {
      Serial.print(message[i],HEX);
      }
      Serial.print(" ");
      if(i % 32 == 0 && i != 0)Serial.println("");
    }
  }
  else if(sx.byte2 == 0x5 && sx.byte3 == 0x4) { // just chord and capo
      rx = MidiUSB.read(); // place into buffer
      buff[buffPoint++] = rx.byte1;
      buff[buffPoint++] = rx.byte2;
      buff[buffPoint++] = rx.byte3;
    Serial.print("Chord ");
    Serial.print(rx.byte1);
    Serial.print("  Capo ");
    Serial.println(rx.byte2);  
  }
}

How good are you at programming? Can you read this and see the bits you have to miss out?

This link might also help:-
https://github.com/arduino-libraries/MIDIUSB/issues/48

Hi thanks for your reply. I do a program with NoteOn NoteOff and SysEx in use with MIDI protocol and the Midi Library. It's working correctly. But unfortunately sometime it's not quick enough that's why i want to do the same with USB. I haven't any trouble with NoteOn NoteOff or ControlChange because i found some examples. I think i understand what you say. I haven't a very high level at programming. But i will reading your programm and I’ll come back to you after

@Grumpy_Mike I think the parser you’re using is incomplete, as it only works if the length of the SysEx is a multiple of 3, and it misses the final 3 bytes. I’ll refer to the MIDI USB spec (p. 16, §4: USB-MIDI Event Packets) for more details, but there are four valid Code Index Numbers for SysEx messages: 0x4 (SysEx starts or continues), 0x5 (SysEx ends with following single byte), 0x6 (SysEx ends with following two bytes), 0x7 (SysEx ends with following three bytes).

This is the code I use:

Parser: Control-Surface/USBMIDI_Parser.cpp at 5a7eaea1b399a29720cbb0b5b2822a541b82e594 · tttapa/Control-Surface · GitHub
Sender: https://github.com/tttapa/Control-Surface/blob/5a7eaea1b399a29720cbb0b5b2822a541b82e594/src/MIDI_Interfaces/USBMIDI_Interface.hpp#L109-L126

Both the parser and the sender are unit-tested for edge cases, and I’ve tested them in real-world applications as well.

The easiest way to use them is by installing the Control Surface library that they’re part of. This library provides (among other things) an abstraction layer on top of different MIDI interfaces (MIDI over USB on Arduino, Teensy, Serial MIDI, MIDI over Bluetooth LE, etc.).
It should be noted that it uses the MIDIUSB library under the hood.

Here’s an example for sending and receiving SysEx messages:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color]

[color=#434f54]// Instantiate the MIDI over USB interface[/color]
[b][color=#d35400]USBMIDI_Interface[/color][/b] [color=#00979c]midi[/color][color=#000000];[/color]

[color=#434f54]// Custom MIDI callback that prints incoming SysEx messages.[/color]
[color=#00979c]struct[/color] [color=#000000]MyMIDI_Callbacks[/color] [color=#434f54]:[/color] [color=#000000]MIDI_Callbacks[/color] [color=#000000]{[/color]
  [color=#00979c]public[/color][color=#434f54]:[/color]
    [color=#00979c]void[/color] [color=#000000]onSysExMessage[/color][color=#000000]([/color][color=#000000]Parsing_MIDI_Interface[/color] [color=#434f54]&[/color][color=#00979c]midi[/color][color=#000000])[/color] [color=#00979c]override[/color] [color=#000000]{[/color]
      [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]F[/color][color=#000000]([/color][color=#005c5f]"Received SysEx message: "[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
      [color=#000000]SysExMessage[/color] [color=#000000]sysex[/color] [color=#434f54]=[/color] [color=#00979c]midi[/color][color=#434f54].[/color][color=#000000]getSysExMessage[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
      [color=#5e6d03]for[/color] [color=#000000]([/color][color=#00979c]uint8_t[/color] [color=#000000]i[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000];[/color] [color=#000000]i[/color] [color=#434f54]<[/color] [color=#000000]sysex[/color][color=#434f54].[/color][color=#d35400]length[/color][color=#000000];[/color] [color=#434f54]++[/color][color=#000000]i[/color][color=#000000])[/color]
        [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]sysex[/color][color=#434f54].[/color][color=#000000]data[/color][color=#000000][[/color][color=#000000]i[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#00979c]' '[/color][color=#000000])[/color][color=#000000];[/color]
      [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#000000]F[/color][color=#000000]([/color][color=#005c5f]"\t on cable "[/color][color=#000000])[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]sysex[/color][color=#434f54].[/color][color=#000000]CN[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#000000]}[/color]
[color=#000000]}[/color] [color=#000000]callback[/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]}[/color][color=#000000];[/color]

[color=#434f54]// Push button connected between pin 2 and ground.[/color]
[color=#434f54]// SysEx message is sent when pressed.[/color]
[b][color=#d35400]Button[/color][/b] [color=#000000]pushbutton[/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]2[/color][color=#000000]}[/color][color=#000000];[/color]  

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]pushbutton[/color][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]  [color=#434f54]// enables internal pull-up[/color]
  [color=#00979c]midi[/color][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
  [color=#00979c]midi[/color][color=#434f54].[/color][color=#000000]setCallbacks[/color][color=#000000]([/color][color=#000000]callback[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#434f54]// Send a SysEx message when the push button is pressed[/color]
  [color=#00979c]uint8_t[/color] [color=#000000]sysex[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0xF0[/color][color=#434f54],[/color] [color=#000000]0x11[/color][color=#434f54],[/color] [color=#000000]0x22[/color][color=#434f54],[/color] [color=#000000]0x33[/color][color=#434f54],[/color] [color=#000000]0xF7[/color][color=#000000]}[/color][color=#000000];[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]pushbutton[/color][color=#434f54].[/color][color=#d35400]getState[/color][color=#000000]([/color][color=#000000])[/color] [color=#434f54]==[/color] [b][color=#d35400]Button[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]Falling[/color][color=#000000])[/color]
    [color=#00979c]midi[/color][color=#434f54].[/color][color=#d35400]send[/color][color=#000000]([/color][color=#000000]sysex[/color][color=#000000])[/color][color=#000000];[/color]
    
  [color=#434f54]// Read incoming MIDI data and call the callback if a new [/color]
  [color=#434f54]// SysEx message has been received.[/color]
  [color=#00979c]midi[/color][color=#434f54].[/color][color=#d35400]update[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

Pieter

Thank's Pieter

I’ll look into it.

I think the parser you're using is incomplete, as it only works if the length of the SysEx is a multiple of 3, and it misses the final 3 bytes.

It was not written as a universal routine but for a specific project I did. What it does show is how using the SysEx message has to be broken up into small packets.

Hello,

Mike: I tried your sketch. It's working well. I understand better what i must to do. I must try to adapt it to my

Pieter:

I tried too. It seems simpler. Again, I have to try to adapt it.

To explain, I need to be able to read tempo messages from a keyboard. And also by referring to this keyboard by making a variation from a pedal.

Thank's a lot for your help. I’ll be back to let you know what happens next.

Eric

Hello everybody,

i know this is an old topic but i use the same code PieterP quoted before (the control Surface library) to send SySex messages over USB from a Leonardo to a Zoom G1xon guitar pedal to cycle through patches.

I am new, both to arduino and to MIDI so please forgive the mess in my head!

I have a Raspberry Pi 4 with latest Arduino IDE.

The code so far is this:

#include <Control_Surface.h>

// Instantiate the MIDI over USB interface
USBMIDI_Interface midi;

// SysEx message is sent when pressed.
Button pushbutton1 = {2};
Button pushbutton2 = {3};
byte patchNum=0;
uint8_t sysexmsg[] = {0xc0, patchNum};

void setup() {
//  Serial.begin(115200);
//  while(!Serial);
  
  pushbutton1.begin(); // enables internal pull-up
  pushbutton2.begin(); // enables internal pull-up

  midi.begin();
}

void loop() {
  // Send a SysEx message when the push button is pressed

    if (pushbutton1.update() == Button::Falling && patchNum != 0) {
      patchNum--; 
 //     Serial.println(patchNum);
      sysexmsg[1]=patchNum;   
      midi.send(sysexmsg); 
      delay(10);         
    }
    if (pushbutton2.update() == Button::Falling && patchNum < 99) {
      patchNum++; 
//      Serial.println(patchNum);
      sysexmsg[1]=patchNum;
      midi.send(sysexmsg); 
      delay(10);         
   }

}

Simple circuit with 2 buttons to pins 2 and 3 with which you cycle through patches using SySex commands.
The SySex command for the ZOOM G1xon to select a specific patch is “0xC0 0xYY” with YY ranging from 00 to 99.

So far i have managed the following:

Conncect the ZOOM G1xon to the Raspberry using USB and by

$ amidi --port=“hw:1,0,0” --send-hex=“C0 YY”
with YY=01 to 99
i can select the specific patch.
Other G1xon specific sysex codes also work ok.

By plugging the Leonardo in a Raspberry USB port it is also recognized as MIDI and with:

$ amidi --port=“hw:2,0,0” --dump

when i press buttons on pins 2 or 3 on the Leonardo i receive
C0 01
C0 YY and so on.
(Also i get the patchNum variable on serial.println…)

But when i plug the G1xon on the Leonardo, both with ther own power supply, nothing happens. Is there a setting for the Leonardo USB that must be set?

What am i missing? Any suggestions? I also tried some other libraries but i messed up so i ended with Peter’s Control Surface library.

“C0 01” is not a SysEx message, it’s a Program Change message.

You’ll have to use the sendPC method, not the methods for sending SysEx messages.
If you send the message “C0 01” as a SysEx message, this won’t work, because it’s not a valid SysEx message (it doesn’t start with 0xF0 and doesn’t end with 0xF7). It seems like ALSA doesn’t care and displays the message nonetheless, but it’s still a protocol violation, and it won’t work on the Zoom or other devices that listen for program change messages specifically.

Also note that amidi --send-hex sends any MIDI data, not just SysEx.

You can use the Selectors module of the library so you don’t have to implement the button input yourself:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color] [color=#434f54]// Include the Control Surface library[/color]
 
[color=#434f54]// Instantiate a MIDI over USB interface[/color]
[b][color=#d35400]USBMIDI_Interface[/color][/b] [color=#00979c]midi[/color][color=#000000];[/color]

[color=#434f54]// Class that selects a patch by sending MIDI program change events[/color]
[color=#434f54]// when the patch selection changes.[/color]
[color=#434f54]// @tparam  N[/color]
[color=#434f54]//          The number of programs.[/color]
[color=#5e6d03]template[/color] [color=#434f54]<[/color][color=#000000]setting_t[/color] [color=#000000]N[/color][color=#434f54]>[/color]
[color=#00979c]class[/color] [b][color=#d35400]ProgramChangeRange[/color][/b] [color=#434f54]:[/color] [color=#00979c]public[/color] [color=#000000]Selectable[/color][color=#434f54]<[/color][color=#000000]N[/color][color=#434f54]>[/color] [color=#000000]{[/color]
  [color=#00979c]public[/color][color=#434f54]:[/color]
    [color=#434f54]// Constructor[/color]
    [color=#434f54]// @param channel[/color]
    [color=#434f54]//        The MIDI channel (and optional cable number)[/color]
    [color=#434f54]//        to send the program change messages to.[/color]
    [color=#434f54]// @param rangeStart[/color]
    [color=#434f54]//        The first program number in the range of N programs.[/color]
    [color=#434f54]//        Should be less than or equal to 128 - N.[/color]
    [b][color=#d35400]ProgramChangeRange[/color][/b][color=#000000]([/color][b][color=#d35400]MIDIChannelCN[/color][/b] [color=#000000]channel[/color] [color=#434f54]=[/color] [color=#00979c]CHANNEL_1[/color][color=#434f54],[/color] 
                       [color=#000000]setting_t[/color] [color=#000000]rangeStart[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000])[/color]
      [color=#434f54]:[/color] [color=#000000]channel[/color][color=#000000]([/color][color=#000000]channel[/color][color=#000000])[/color][color=#434f54],[/color] [color=#000000]rangeStart[/color][color=#000000]([/color][color=#000000]rangeStart[/color][color=#000000])[/color] [color=#000000]{[/color][color=#000000]}[/color]

    [color=#434f54]// This function is called by the selector.[/color]
    [color=#00979c]void[/color] [color=#d35400]select[/color][color=#000000]([/color][color=#000000]setting_t[/color] [color=#000000]setting[/color][color=#000000])[/color] [color=#5e6d03]override[/color] [color=#000000]{[/color]
      [color=#000000]setting[/color] [color=#434f54]=[/color] [color=#5e6d03]this[/color][color=#434f54]-[/color][color=#434f54]>[/color][color=#000000]validateSetting[/color][color=#000000]([/color][color=#000000]setting[/color][color=#000000])[/color][color=#000000];[/color]
      [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#d35400]sendPC[/color][color=#000000]([/color][color=#000000]channel[/color][color=#434f54],[/color] [color=#000000]rangeStart[/color] [color=#434f54]+[/color] [color=#000000]setting[/color][color=#000000])[/color][color=#000000];[/color]
    [color=#000000]}[/color]

  [color=#00979c]private[/color][color=#434f54]:[/color]
    [b][color=#d35400]MIDIChannelCN[/color][/b] [color=#000000]channel[/color][color=#000000];[/color]
    [color=#000000]setting_t[/color] [color=#000000]rangeStart[/color][color=#000000];[/color]
[color=#000000]}[/color][color=#000000];[/color]

[color=#434f54]// Instantiate a program changer with 100 programs (0-99)[/color]
[b][color=#d35400]ProgramChangeRange[/color][/b][color=#434f54]<[/color][color=#000000]100[/color][color=#434f54]>[/color] [color=#000000]programChanger[/color] [color=#000000]{[/color]
  [color=#00979c]CHANNEL_1[/color][color=#434f54],[/color] [color=#434f54]// MIDI channel to use[/color]
  [color=#000000]0[/color][color=#434f54],[/color]         [color=#434f54]// first program in the range[/color]
[color=#000000]}[/color][color=#000000];[/color]
 
[color=#434f54]// Instantiate a selector that reads two buttons and controls the [/color]
[color=#434f54]// program changer[/color]
[b][color=#d35400]IncrementDecrementSelector[/color][/b][color=#434f54]<[/color][color=#000000]100[/color][color=#434f54]>[/color] [color=#000000]programSelector[/color] [color=#434f54]=[/color] [color=#000000]{[/color]
  [color=#000000]programChanger[/color][color=#434f54],[/color] [color=#434f54]// what to select[/color]
  [color=#000000]{[/color][color=#000000]2[/color][color=#434f54],[/color] [color=#000000]3[/color][color=#000000]}[/color][color=#434f54],[/color]         [color=#434f54]// pins (increment, decrement)[/color]
[color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Initialize Control Surface[/color]
[color=#000000]}[/color]
 
[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Update the Control Surface[/color]
[color=#000000]}[/color]

Thanks for the quick reply Pieter!! It seems i have messed up all the midi info i got! I 'll try your code and report

I get the following error (sorry but my c++ knowledge is way too limited):

Arduino: 1.8.12 (Linux), Board: “Arduino Leonardo”

pieter:20:38: error: expected ‘)’ before ‘channel’
ProgramChangeRange(MIDIChannelCN channel = CHANNEL_1,
^~~~~~~
pieter:31:5: error: ‘MIDIChannelCN’ does not name a type
MIDIChannelCN channel;
^~~~~~~~~~~~~
/home/pi/Arduino/pieter/pieter.ino: In member function ‘void ProgramChangeRange::select(CS::setting_t)’:
pieter:27:23: error: ‘class CS::Control_Surface_’ has no member named ‘sendPC’
Control_Surface.sendPC(channel, rangeStart + setting);
^~~~~~
pieter:27:30: error: ‘channel’ was not declared in this scope
Control_Surface.sendPC(channel, rangeStart + setting);
^~~~~~~
/home/pi/Arduino/pieter/pieter.ino: At global scope:
pieter:39:1: error: no matching function for call to ‘ProgramChangeRange<100>::ProgramChangeRange()’
};
^
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate: ProgramChangeRange<100>::ProgramChangeRange()
class ProgramChangeRange : public Selectable {
^~~~~~~~~~~~~~~~~~
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate expects 0 arguments, 2 provided
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate: constexpr ProgramChangeRange<100>::ProgramChangeRange(const ProgramChangeRange<100>&)
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate expects 1 argument, 2 provided
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate: constexpr ProgramChangeRange<100>::ProgramChangeRange(ProgramChangeRange<100>&&)
/home/pi/Arduino/pieter/pieter.ino:11:7: note: candidate expects 1 argument, 2 provided
exit status 1
expected ‘)’ before ‘channel’

Please upgrade to the latest master version. I should probably make an "official" release, but I don't have time for that right now.

I did it compiled ok. But it doesn't seem to work. The pedal doesn't change patches. Also using amidi i always get C0 00 when i press either button.

How did you wire the buttons? They should be wired between ground and the input pin.

i removed all the extra stuff and now with amidi i do get changed program changes but the pedal still does not respond.

How are you routing the MIDI data from the Arduino to the pedal?

Through the pedal's USB port

If i connect it to raspberry i can send th C0 YY command with amidi

ard2000: Through the pedal's USB port

If i connect it to raspberry i can send th C0 YY command with amidi

That won't work. Both the Arduino and the pedal are USB devices. You need one of the two to be a USB host.

Ok. i am confused. Can i tell the Leonardo to act as a usb host?

ard2000: Can i tell the Leonardo to act as a usb host?

No, that is not possible, the Leonardo is device only. Some Teensies support host mode, and you get a USB host shield, but finding/writing USB drivers is often a problem.

How are you connection them anyway? What cable connects the two?

You can use the Raspberry as a USB host, and route the MIDI messages between the Leonardo and the Zoom in software.