Go Down

Topic: MIDI.sendNoteOn freezes/ crashes Arduino Mega (Read 1 time) previous topic - next topic

liamorourke

Oct 28, 2015, 05:52 am Last Edit: Oct 28, 2015, 07:20 am by liamorourke
HI,
MIDI.sendNoteOn (obviously followed by MIDI.sendNoteOff) works fine until I send the note repeatedly at a fast frequency for about 30 seconds. Then the TX LED freezes (it stays on) and the board stops working. Then after about 20 seconds the LED then swtiches off again but if I attempt to resend the note (even just once) it freezes back on for 20 seconds. To get it working again I have to re-upload the sketch.

I've tried this on two boards (both Megas) one of which is brand new.

Here is my sketch: -
Code: [Select]
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
MIDI_CREATE_DEFAULT_INSTANCE();

const int buttonPin = 2;  // define pin for pushButton/ trigger

int buttonState = 0;      // current state of pushButton
int lastButtonState = 0;  // previous state of pushButton

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);   //initiate pull-up resistor on pushButton as input
 
  MIDI.begin(4);      // begin MIDI communication:
}

void loop() {
  buttonState = digitalRead(buttonPin);   // read buttonPin (pin 2) and store as buttonState
 
  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      MIDI.sendNoteOn(67, 127, 1);
  lastButtonState = buttonState;
    }
  }
    if (buttonState != lastButtonState) {
      if (buttonState == HIGH); {
        MIDI.sendNoteOff(67, 0, 1);
  lastButtonState = buttonState; 
    }
  }
}


Any help here would be greatly appreciated as I'm currently setting up a series of workshops teaching people to build MIDI controllers using Arduino.

BenKissBox

Hi Liamorourke,

it looks like you are overflowing the MIDI transmission buffer. In fact, the Mega is not crashed but probably waiting until all bytes in the queue are being transmitted.

When you say that it starts to act strangely with "fast frequency", do you have an idea of the value of the frequency (10, 20 times per second? more?)

I do not have my Mega near me, but I will try your scripts later today, to check what happens.

For now, I you to implement a debounce function on your button input, because that's also a source for generating unexpected bursts of messages.

Benoit

liamorourke

Hi Ben.
Thanks for the reply.
My understanding of Debounce is that if it isn't used where it should be it could result in false readings but actually what happens here is it completely freezes up and stops working altogether and as I said earlier it doesn't work again until i completely reupload the sketch. My guess is you were closer with..

"it looks like you are overflowing the MIDI transmission buffer".

I must admit I'm pressing the button at a pretty fast frequency possibly about 7 or 8hz or thereabouts (basically as fast as my finger will let me). Do you think this is too fast? and is there anything i can do to sort this out as when a musician plays the controller there is a good chance that at some point they will be playing that fast.

Thanks

liamorourke

got it sorted...

I simply forgot to add a delay(); to the end of the sketch.

Added: delay(20); and it works perfectly :)

Thanks for your time tho Ben

BenKissBox

Good to know that it works.

The delay you added makes me think that you are facing a boucing contact problem.

What happens in your case is simple : when you press the push button, the contact does not close one time, but it bounces (this is normal with mechanical contacts). At human scale, the contact seems to be closed one time, but in fact it opens and closes maybe 6 or 7 times very quickly, in 1 or 2 ms. The microprocessor is fast enough to see all of them. Since your program generates a Note On and a Note Off every time, you are sending let's say 7 times 3 bytes twice (Note On = 3 bytes, Note Off = 3 bytes), so 42 bytes (where you should expect only 6 because, as a human, you have seen the contact close only one time). If you press the button 7 times per second, you can then generate 294 bytes very quickly. It's not enough to saturate MIDI itself, but it's enough to saturate the UART FIFO.

That's probably why you see this strange behaviour with the UART output being "stuck". I have to check the source code of the Serial object to see what happens in this situation (to be honnest, I would be surprized that the code crash, the library is so used that I assume it is protected against such cases... but I prefer to check myself)

Grumpy_Mike

In place of the fixed delay use a Serial.flush to make sure the send buffer is empty before proceeding.

BenKissBox

Mike, in his case, I think he will loose MIDI messages if he does that. It might turn into stuck note or garbled MIDI data by loosing a byte in middle of the stream

Benoit

Grumpy_Mike

Mike, in his case, I think he will loose MIDI messages if he does that. It might turn into stuck note or garbled MIDI data by loosing a byte in middle of the stream

Benoit
No.

Have you any idea what serial flush does? It:-
Quote
Waits for the transmission of outgoing serial data to complete.
https://www.arduino.cc/en/Serial/Flush

That is way better than sticking in an arbitrary delay. No incoming data will be lost.

BenKissBox

I was still with the old "Flush" in mind. Before 1.0, it was removing clearing the queue.

By the way, I do not understand your remark about loosing data with a delay. There is a 64 bytes buffer on the serial input (so waiting in the code is less critical, as long you don't wait for hours of course °-)

And in this case, the code does nothing with input, it just sends data to MIDI. Why should he loose data with a delay ?

Grumpy_Mike

Quote
By the way, I do not understand your remark about loosing data with a delay.
I think you miss read that, it was not what I was saying. The point I was making is that by using flush you only delayed by exactly the amount you needed not an arbitrary delay. The:-
Quote
No incoming data will be lost.
Was to address your concerns about loosing incoming data with flush, I was not implying that any data would be lost with delay.

Go Up