Go Down

Topic: Problem using Arduino Micro and MIDIUSB library (Read 525 times) previous topic - next topic

Edwin1557

Hey guys!

Recently, I bought an arduino micro in order to make a led strip that reacts to midi signal. I bought this board because it has native usb support.

Now that I have read and work with examples that are included in the MIDIUSB library, I don't know what to do. I tried many times to make a code that seemed "ok", but every time, it didn't work. There's not much tutorials online that use an arduino micro and the new MIDIUSB library, so I have no idea of what I'm actually coding.

After many hours of reading forums and testing codes online, I realize that I should've bought a teensy board instead of an arduino one.

Before I spend my money to buy a teensy board, I want to know if it is possible to do my project of controlling an rgb light strip by receiving midi signal with an arduino micro board, or if it's not possible.

Any help would really be appreciated! Thanks!


If anyone reads this message and wants to help me with my code, I've found a code programmed for a teensy board that do everything that I want my light strip to do.


Grumpy_Mike

I can't see anything in that code that you could not convert to the syntax used in the arduino micro.

Quote
I tried many times to make a code that seemed "ok", but every time, it didn't work.
So post a code that didn't work, describe what it did and what you wanted it to do, and also what software on the computer you were trying to interface to.

Edwin1557

Thanks for your reply,

Here's the code that I'm trying to get working...

Code: [Select]
#include "MIDIUSB.h"
#include "PitchToNote.h"

const byte _NLED = 60;
const byte _DPIN = 6;

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel _LED = Adafruit_NeoPixel(_NLED, _DPIN, NEO_GRB + NEO_KHZ800);

const byte _R[128] = {0, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 36, 73, 109, 146, 182, 219, 255};
const byte _G[128] = {0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 36, 73, 109, 146, 182, 219, 255};
const byte _B[128] = {0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 36, 73, 109, 146, 182, 219, 255};



const byte _PStart = 36;  // First note in array
bool update = false;


void setup() {
_LED.begin();
_LED.show();
}


void loop() {
  while (MidiUSB.read());
  if (update) {
    _LED.show();
    update = false;
  }
}

void noteOn(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, _R[velocity], _G[velocity], _B[velocity]);
  update = true;
}

void noteOff(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, 0, 0, 0);
  update = true;
}

void controlChange(byte *data, unsigned int length) {
  if (length == 6) {
    _LED.setPixelColor(*(data+1) - _PStart, *(data+2), *(data+3), *(data+4));
    update = true;
  }
}



The problem with this code is that I'm getting an error because of the void loop, saying that it cannot convert MidiUSB.read from midiEventPacket_t  to bool. I know that it is because of the "while" structure, but I don't know how to replace it. If I don't put it, the code is doing nothing when I output notes from Ableton Live...

I know that my arduino receives output signal from my computer, because there's some light on the arduino that lights on and off when a midi signal is send, but no lights on my led strip are flashing...

Grumpy_Mike

Thanks for the code.

I think something has changed. There seems to be no support for the pro micro any more. There is the "Arduino Micro (MIDI)", but it seems not to be compatible with a lot of things that used to work like the EEPROM, SPI and so on. The messages I get about these are:-
Code: [Select]
WARNING: Category '' in library EEPROM is not valid. Setting to 'Uncategorized'
WARNING: Category '' in library SPI is not valid. Setting to 'Uncategorized'
WARNING: Category '' in library SoftwareSerial is not valid. Setting to 'Uncategorized'
WARNING: Category '' in library Wire is not valid. Setting to 'Uncategorized'
Warning: platform.txt from core 'Leonardo & Micro MIDI-USB (arcore)' contains deprecated recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}", automatically converted to recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}". Consider upgrading this core.


My own stuff that was working and compiling about eight months ago will now no longer compile as well. I have dropped back to the previous two IDE releases and still no joy.

So unfortunately at the moment I have no solution, but as a lot of my stuff is also suffering I will be working on it and get back to you as soon as I have sorted it.

Edwin1557

Well, that's unfortunate ...

Thanks anyway for taking the time to answer me !  :)

Grumpy_Mike

OK fixed it. The trick was to use the "Arduino/Genuino Micro" board in the Tools menu. That just left your code that would not compile. I got it to compile by changing your loop function to:-

Code: [Select]
void loop() {
  while (MidiUSB.read().header == 0); // hold until a MIDI message is received
  if (update) {
    _LED.show();
    update = false;
  }
}

Edwin1557

Thank you so much!

Now the loop and the code compile, but my led strip doesn't lights up...

The arduino receives midi signal, but I don't know why the led strip doesn't work. I guess i'll have to code my code in a different way.

If you have any idea of how to do it or why my led strip doesn't light up, feel free to help me ahah!


Grumpy_Mike

#7
May 18, 2019, 05:36 am Last Edit: May 18, 2019, 05:38 am by Grumpy_Mike
Quote
but my led strip doesn't lights up.
Didn't think they would.  ;)

The mistake you are making is that you are assuming that the noteOn, noteOff and controlChange functions are called automatically. They are not.

What you have to do is to is to look at the value you get from the MIDIUSB.read call which you currently throw away, and depending on the results you need to call those functions. Then you update flag will be set. You should have looked at the MIDIUSB example MIDIUSB_read which is in the examples folder of the libiary. Get to it from the menu Files -> Examples, all libraries should have examples.

So just to start you off with calling the noteOn function from the loop function try:-
Code: [Select]
void loop() {
  midiEventPacket_t rx;
  rx = MidiUSB.read();
    if(rx.header == 0x9) noteOn(rx.byte1, rx.byte2,rx.byte3);
// check for other types of message you may have received - then do your update thing
}


Note the great thing about the MIDIUSB libiary is that you can also do Serial.print to the monitor for debugging.

Edwin1557

Thank you so much!!!

Now my code works perfectly!

Appart from that, I have a last question... Is there anything I can do about the lag of my led strip ? (I use WS2812B and they are powered only via my macbook usb port) Is using an external power supply will reduce the lag or is it all because of the arduino limitation of reading midi signal?

Thanks again for the help, I'm so happy!

Grumpy_Mike

Using an external power supply will do nothing for the lag, although powering 60 LEDs from the USB is a bit over the top. It depends on how many LEDs are on at the same time.

Not sure why you see a lag. What is driving the MIDI? Can you post your final working code.

Edwin1557

Here's my final code :

Also, I didn't know how to include the controlChange void in the loop...

Code: [Select]
#include "MIDIUSB.h"
#include "PitchToNote.h"

const byte _NLED = 100;
const byte _DPIN = 6;

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel _LED = Adafruit_NeoPixel(_NLED, _DPIN, NEO_GRB + NEO_KHZ800);

const byte _R[128] = {0, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 36, 73, 109, 146, 182, 219, 255};
const byte _G[128] = {0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 36, 73, 109, 146, 182, 219, 255};
const byte _B[128] = {0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 36, 73, 109, 146, 182, 219, 255};



const byte _PStart = 36;  // First note in array
bool update = false;


void setup() {
_LED.begin();
_LED.show();
}


void loop() {
  midiEventPacket_t rx;
  do {
    rx = MidiUSB.read();
    if(rx.header == 0x9) noteOn(rx.byte1, rx.byte2,rx.byte3);
    if(rx.header == 0x8) noteOff(rx.byte1, rx.byte2,rx.byte3);
  }
  while (rx.header == 0); // hold until a MIDI message is received
  if (update) {
    _LED.show();
    update = false;
  }
}

void noteOn(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, _R[velocity], _G[velocity], _B[velocity]);
  update = true;
}

void noteOff(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, 0, 0, 0);
  update = true;
}

void controlChange(byte *data, unsigned int length) {
  if (length == 6) {
    _LED.setPixelColor(*(data+1) - _PStart, *(data+2), *(data+3), *(data+4));
    update = true;
  }
}


Sometimes, when there are a lot of notes pressed at the same time, the leds take a much more long time to do the light effect than it is supposed to (the light effects contains +-600 notes to play in two seconds or so)... And I use Ableton live

Grumpy_Mike

Quote
Also, I didn't know how to include the controlChange void in the loop.
Code: [Select]
    if(rx.header == 0xB) controlChange(rx.byte2, rx.byte3);

However I don't quite "get" what your control change function is trying to do. It is expecting a pointer to a byte and a unsigned int. The MIDI message can not give you a unsigned int because it is only seven bits long and how would Ableton know where any of your data is on the Arduino?

The
Code: [Select]
if (update) {
    _LED.show();
    update = false;
  }

Bit can be removed if you have your show function call inside your 'noteOn' and so on functions.

I will have a go at running at your code tomorrow. Is there any chance you could zip up and attach an Ableton file that sends what you want?

Edwin1557

Here are some examples of midi messages I'm running trough Ableton live. Those are some typical light effects that I will run through my arduino.

I also included a "worst scenario test", which contains a lot of midi notes...

Here's my code (I removed the controlChange void, because it wasn't really doing anything as you explained me)

Code: [Select]
#include "MIDIUSB.h"
#include "PitchToNote.h"

const byte _NLED = 100;
const byte _DPIN = 6;

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel _LED = Adafruit_NeoPixel(_NLED, _DPIN, NEO_GRB + NEO_KHZ800);

const byte _R[128] = {0, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 36, 73, 109, 146, 182, 219, 255};
const byte _G[128] = {0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 36, 73, 109, 146, 182, 219, 255};
const byte _B[128] = {0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 0, 0, 0, 125, 0, 12, 28, 45, 158, 61, 28, 61, 93, 190, 125, 45, 93, 142, 223, 190, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 61, 125, 190, 255, 255, 45, 93, 142, 223, 190, 28, 61, 93, 190, 125, 12, 28, 45, 158, 61, 36, 73, 109, 146, 182, 219, 255};



const byte _PStart = 36;  // First note in array
bool update = false;


void setup() {
_LED.begin();
_LED.show();
}


void loop() {
  midiEventPacket_t rx;
  do {
    rx = MidiUSB.read();
    if(rx.header == 0x9) noteOn(rx.byte1, rx.byte2,rx.byte3);
    if(rx.header == 0x8) noteOff(rx.byte1, rx.byte2,rx.byte3);
//    if(rx.header == 0xB) controlChange(rx.byte2, rx.byte3);
  }
  while (rx.header == 0); // hold until a MIDI message is received
}

void noteOn(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, _R[velocity], _G[velocity], _B[velocity]);
  update = true;
  _LED.show();
}

void noteOff(byte channel, byte pitch, byte velocity) {
  _LED.setPixelColor(pitch - _PStart, 0, 0, 0);
  update = true;
  _LED.show();
}

//void controlChange(byte *data, unsigned int length) {
//  if (length == 6) {
//    _LED.setPixelColor(*(data+1) - _PStart, *(data+2), *(data+3), *(data+4));
//    update = true;
//    _LED.show();
//  }
//}

Grumpy_Mike

Thanks. I haven't run it yet but have just worked out why you see a lag.

The problem is the WS2812 needs precise timing on the output signal. To achieve this all libraries disable the interrupts when updating the LEDs. If the MIDI is being received over the serial port then some bytes will be missed and you will loose some messages and corrupt others.

However you are using the USB to make the Arduino look like a MIDI HID device and so are communicating directly with the USB protocol.

The up side of this is that you will not loose any data because the USB protocol requires your Arduino to acknowledge the start of the USB transfer, therefore it will wait until the interrupts are enabled again before it can do this.

The down side is that this causes a delay in getting the next package of data and I am sure that this is the cause of the lag that you see.

I am not sure of a solution to this. One thing that might work is to use the "Dot Star" or APA102 type of LED. These use an SPI data interface that do not require the interrupts to be disabled during data transfer and take less time to send out the data.

Grumpy_Mike

#14
May 19, 2019, 04:50 am Last Edit: May 19, 2019, 04:51 am by Grumpy_Mike
Wow - what a lot of notes.

I calculate that you are sending about 710 MIDI messages per second, is this right? If so visualising them is going to be hard and a bit pointless. Anything faster than about 30 updates per second is not going to be visible. If this is right then the APA102 type of LED is not going to solve your problem.

What are you actually trying to do?

Go Up