Please help me save my project! Adafruit music maker shield bug

Hello everyone, I have just about lost hope in my ability to figure out what is causing Arduino Uno connected to Adafruit music maker shield to freeze up after about 12 - 24 hours. I have an awesome project that is going to be installed in my school but unfortunately after some time the MIDI note player stops working and the note plays endlessly when struck. Very frustrating!

Check out the project here: https://drewbeathard.github.io/capacitive.html

Basically the project involves 6 attiny-85 mcs that are connected to copper plates using CapacitiveTouch library. When the plates sense your hand, they write digital pin to high to trigger the arduino to play a sound through the MIDI machine on the adafruit shield (among other lights and things). The program has functions to change instruments and octaves but i have stripped it down to the bare minimum in order to eliminate potential code issues. My code is below:

Some things you should know:

  • When the arduino freezes, the main loop is STILL running (i know from monitoring the serial monitor) therefore it is actually the Shield that is breaking, not the UNO.

  • Broken behavior: I play a note and then it never stops playing (per the code, a note needs to be played and then turned off)

Things I have tried:

  • Turning off all Serial communication (not included software serial used to send info to the shield. I read the string class can cause this kind of problem. Did not fix the problem.

  • Monitored the free memory in the UNO in case it was somehow a memory leak, that did not solve the problem, memory was constant.

  • Stripping the program to the minimum in order to just get 2 drums to play, still breaks consistently after 1 night.

I'm kinda a noob so therefore hoping that anyone can look at this and have an idea of what might be going wrong. I would be so pumped if I could get this issue fixed and therefore any help would be so appreciated. Look forward to hearing your feedback, Please ask me questions if I left things unclear.

// This code has been simplified to demonstrate the base functionality of my program, 
//usually there are 6 drums and other inputs for changing instruments and octaves.

//#include <MemoryFree.h>

int drum1 = 12;
int drum2 = 11;
int drum3 = 10;
int drum4 = 13;
int drum5 = 8;
int drum6 = 7;
//



bool is1on = false;
bool is2on = false;



// define the pins used
#define VS1053_RX  2 // This is the pin that connects to the RX pin on VS1053

//#define VS1053_RESET 9 // This is the pin that connects to the RESET pin on VS1053
// If you have the Music Maker shield, you don't need to connect the RESET pin!

// If you're using the VS1053 breakout:
// Don't forget to connect the GPIO #0 to GROUND and GPIO #1 pin to 3.3V
// If you're using the Music Maker shield:
// Don't forget to connect the GPIO #1 pin to 3.3V and the RX pin to digital #2

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 31
#define VS1053_BANK_DEFAULT 0x00
#define VS1053_BANK_DRUMS1 0x78
#define VS1053_BANK_DRUMS2 0x7F
#define VS1053_BANK_MELODY 0x79

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 32 for more!
#define VS1053_GM1_OCARINA 80

#define MIDI_NOTE_ON  0x90
#define MIDI_NOTE_OFF 0x80
#define MIDI_CHAN_MSG 0xB0
#define MIDI_CHAN_BANK 0x00
#define MIDI_CHAN_VOLUME 0x07
#define MIDI_CHAN_PROGRAM 0xC0

#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
  #include <SoftwareSerial.h>
  SoftwareSerial VS1053_MIDI(0, 2); // TX only, do not use the 'rx' side
#else
  // on a Mega/Leonardo you may have to change the pin to one that 
  // software serial support uses OR use a hardware serial port!
  #define VS1053_MIDI Serial1
#endif


void setup() 
{
  //Serial.begin(9600);
  
  VS1053_MIDI.begin(31250); // MIDI uses a 'strange baud rate'

  
  ///pinMode(VS1053_RESET, OUTPUT);
 // digitalWrite(VS1053_RESET, LOW);
  //delay(10);
  //digitalWrite(VS1053_RESET, HIGH);
  //delay(10);

  // disable the card (we won't be using it)
  //pinMode(CARDCS, OUTPUT);
  //digitalWrite(CARDCS, HIGH);  


  
  midiSetChannelBank(0, VS1053_BANK_MELODY);
  midiSetInstrument(0, 41); // FUNCTION TO CHANGE INSTUMENT
  midiSetChannelVolume(0, 127);

  pinMode(drum1, INPUT);
  pinMode(drum2, INPUT);
  pinMode(drum3, INPUT);
  pinMode(drum4, INPUT);
  pinMode(drum5, INPUT);
  pinMode(drum6, INPUT);



}

void loop() 
{  

  // PLAY THE INSTRUMENTS 

  
  if (digitalRead(drum1) == HIGH)
  { 
   if (is1on == false) // we only want to turn it one one time
    {
      midiNoteOn(0, 66, 127); // WHEN YOU TURN A NOTE ON, YOU HAVE TO TURN IT OFF, otherwise it will just keep playing
      is1on = true;
      Serial.println("1 ON");
      
    }

  }

  else
  {
    if (is1on)
    {
      midiNoteOff(0, 66, 127);
      is1on = false;
      Serial.println("1 OFF");
    }
  }
  
  if (digitalRead(drum2) == HIGH)
  {
    if (is2on == false)
    {
      midiNoteOn(0, 68, 127); // WHEN YOU TURN A NOTE ON, YOU HAVE TO TURN IT OFF, otherwise it will just keep playing
      is2on = true;
      Serial.println("2 ON");
    }
  }

  else
  {
    if (is2on)
    {
      midiNoteOff(0, 68, 127);
      is2on = false;
      Serial.println("2 OFF");
    }
    
  }

  

  delay(20);
  //Serial.print("Free memory: ");
  //Serial.println(freeMemory());
}



void midiSetInstrument(uint8_t chan, uint8_t inst) {
  if (chan > 15) return;
  inst --; // page 32 has instruments starting with 1 not 0 :(
  if (inst > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_PROGRAM | chan);  
  VS1053_MIDI.write(inst);
}


void midiSetChannelVolume(uint8_t chan, uint8_t vol) {
  if (chan > 15) return;
  if (vol > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write(MIDI_CHAN_VOLUME);
  VS1053_MIDI.write(vol);
}

void midiSetChannelBank(uint8_t chan, uint8_t bank) {
  if (chan > 15) return;
  if (bank > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write((uint8_t)MIDI_CHAN_BANK);
  VS1053_MIDI.write(bank);
}

void midiNoteOn(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_ON | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

void midiNoteOff(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_OFF | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

Post the code here using code tags

Why do you have multiple arduinos ?

Make sure you have the same number of note on and note off messages. If you are missing a note off message when you do things like change the instrument then the MIDI generator will fail and produce a hung note just like you are seeing.

It is a good idea to send a CC message telling all the notes on a channel to stop sounding when making a change that could result in a hanging note.

I put the code in the post.

There is a nano that is in charge of changing different lights when different instruments are selected but that does not relate to this issue. In the full code the arduino tells the nano which instrument is being used so the lights indicating that instrument will turn on.

If you are asking why i have multiple attiny's it's so each one can respond fast enough to play all of the notes at once.

Hi @Grumpy_Mike, Please have a look at the code I posted.

There are only 2 note on messages and 2 note off messages, therefore I don't think this is causing the issue. Also I put a print statement for "1 ON" and "1 OFF" etc so that I can monitor the Serial and see that the midiNoteOff() message is being called. This happens even after the program breaks.

may be you can pick a different pin than 0 for this as this is the hardware Serial Rx. Not sure this would have any impact but...

have you joined GNDs?
post a schema of the wiring

Update:
I did an overnight test with only the MIDI test sketch and the same thing happened. The sketch defines no extra input / output pins and doesn't interface with the rest of my system at all. It just plays notes in the main loop. Which leads me to believe that the issue isn't being caused by my code at all and instead there's a problem with the shield / UNO connection or just with the shield.

Any thoughts on what could be going on here? Could the shield be broken?


/*************************************************** 
  This is an example for the Adafruit VS1053 Codec Breakout
  Designed specifically to work with the Adafruit VS1053 Codec Breakout 
  ----> https://www.adafruit.com/products/1381
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// define the pins used
#define VS1053_RX  2 // This is the pin that connects to the RX pin on VS1053

#define VS1053_RESET 9 // This is the pin that connects to the RESET pin on VS1053
// If you have the Music Maker shield, you don't need to connect the RESET pin!

// If you're using the VS1053 breakout:
// Don't forget to connect the GPIO #0 to GROUND and GPIO #1 pin to 3.3V
// If you're using the Music Maker shield:
// Don't forget to connect the GPIO #1 pin to 3.3V and the RX pin to digital #2

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 31
#define VS1053_BANK_DEFAULT 0x00
#define VS1053_BANK_DRUMS1 0x78
#define VS1053_BANK_DRUMS2 0x7F
#define VS1053_BANK_MELODY 0x79

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 32 for more!
#define VS1053_GM1_OCARINA 80

#define MIDI_NOTE_ON  0x90
#define MIDI_NOTE_OFF 0x80
#define MIDI_CHAN_MSG 0xB0
#define MIDI_CHAN_BANK 0x00
#define MIDI_CHAN_VOLUME 0x07
#define MIDI_CHAN_PROGRAM 0xC0

#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
  #include <SoftwareSerial.h>
  SoftwareSerial VS1053_MIDI(0, 2); // TX only, do not use the 'rx' side
#else
  // on a Mega/Leonardo you may have to change the pin to one that 
  // software serial support uses OR use a hardware serial port!
  #define VS1053_MIDI Serial1
#endif



void setup() {
  Serial.begin(9600);
  Serial.println("VS1053 MIDI test");
  
  VS1053_MIDI.begin(31250); // MIDI uses a 'strange baud rate'
  
  pinMode(VS1053_RESET, OUTPUT);
  digitalWrite(VS1053_RESET, LOW);
  delay(10);
  digitalWrite(VS1053_RESET, HIGH);
  delay(10);
  
  midiSetChannelBank(0, VS1053_BANK_MELODY);
  midiSetInstrument(0, VS1053_GM1_OCARINA);
  midiSetChannelVolume(0, 127);
}

void loop() {  
  for (uint8_t i=60; i<69; i++) {
    midiNoteOn(0, i, 127);
    delay(100);
    midiNoteOff(0, i, 127);
  }
  
  delay(1000);
}

void midiSetInstrument(uint8_t chan, uint8_t inst) {
  if (chan > 15) return;
  inst --; // page 32 has instruments starting with 1 not 0 :(
  if (inst > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_PROGRAM | chan);  
  VS1053_MIDI.write(inst);
}


void midiSetChannelVolume(uint8_t chan, uint8_t vol) {
  if (chan > 15) return;
  if (vol > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write(MIDI_CHAN_VOLUME);
  VS1053_MIDI.write(vol);
}

void midiSetChannelBank(uint8_t chan, uint8_t bank) {
  if (chan > 15) return;
  if (bank > 127) return;
  
  VS1053_MIDI.write(MIDI_CHAN_MSG | chan);
  VS1053_MIDI.write((uint8_t)MIDI_CHAN_BANK);
  VS1053_MIDI.write(bank);
}

void midiNoteOn(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_ON | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

void midiNoteOff(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  VS1053_MIDI.write(MIDI_NOTE_OFF | chan);
  VS1053_MIDI.write(n);
  VS1053_MIDI.write(vel);
}

@J-M-L That line is taken from the example MIDI sketch (see update post). I don't think I can change it because that is the shield pin that is configured to receive SoftwareSerial messages and play notes.

I did a project in the MagPi issue 63.
Free PDF download here
That used a Adafruit Music Maker FeatherWing (VS1053) board, wired up to look like a MIDI input box. Like this

I have just started a test on a Uno with this code GMT 14:30. It sticks to your code as far as possible. However note I do not use software serial.

/*************************************************** 
  This is an example for the Adafruit VS1053 Codec Breakout
  Designed specifically to work with the Adafruit VS1053 Codec Breakout 
  ----> https://www.adafruit.com/products/1381
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
  Modified by Grumpy Mike to test the code on a MIDI sound box containing a VS1053
  with a MIDI serial input From a project I wrote for TheMag Pi magazine #63
 ****************************************************/

// define the pins used
// If you have the Music Maker shield, you don't need to connect the RESET pin!

// If you're using the VS1053 breakout:
// Don't forget to connect the GPIO #0 to GROUND and GPIO #1 pin to 3.3V
// If you're using the Music Maker shield:
// Don't forget to connect the GPIO #1 pin to 3.3V and the RX pin to digital #2

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 31
#define VS1053_BANK_DEFAULT 0x00
#define VS1053_BANK_DRUMS1 0x78
#define VS1053_BANK_DRUMS2 0x7F
#define VS1053_BANK_MELODY 0x79

// See http://www.vlsi.fi/fileadmin/datasheets/vs1053.pdf Pg 32 for more!
#define VS1053_GM1_OCARINA 80

#define MIDI_NOTE_ON  0x90
#define MIDI_NOTE_OFF 0x80
#define MIDI_CHAN_MSG 0xB0
#define MIDI_CHAN_BANK 0x00
#define MIDI_CHAN_VOLUME 0x07
#define MIDI_CHAN_PROGRAM 0xC0

void setup() {
  Serial.begin(31250); // MIDI uses a 'strange baud rate');
  // it is not strange, it is derived form the earlest implementation of MIDI
  // UARTS need a clock of 16 times the baud rate, this needs to be a square wave
  // 1MHz crystal oscilators were often used for computer clocks so:-
  // 1MHz divided by two to get it square, fed the UART witch gave divided by 16 baud rate 
  // 1000000 / 2 / 16 = 31250 
    
  midiSetChannelBank(0, VS1053_BANK_MELODY);
  midiSetInstrument(0, VS1053_GM1_OCARINA);
  midiSetChannelVolume(0, 127);
}

void loop() {  
  for (uint8_t i=60; i<69; i++) {
    midiNoteOn(0, i, 127);
    delay(100);
    midiNoteOff(0, i, 127);
  }
  
  delay(1000);
}

void midiSetInstrument(uint8_t chan, uint8_t inst) {
  if (chan > 15) return;
  inst --; // page 32 has instruments starting with 1 not 0 :(
  if (inst > 127) return;
  
  Serial.write(MIDI_CHAN_PROGRAM | chan);  
  Serial.write(inst);
}

void midiSetChannelVolume(uint8_t chan, uint8_t vol) {
  if (chan > 15) return;
  if (vol > 127) return;
  
  Serial.write(MIDI_CHAN_MSG | chan);
  Serial.write(MIDI_CHAN_VOLUME);
  Serial.write(vol);
}

void midiSetChannelBank(uint8_t chan, uint8_t bank) {
  if (chan > 15) return;
  if (bank > 127) return;
  
  Serial.write(MIDI_CHAN_MSG | chan);
  Serial.write((uint8_t)MIDI_CHAN_BANK);
  Serial.write(bank);
}

void midiNoteOn(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  
  Serial.write(MIDI_NOTE_ON | chan);
  Serial.write(n);
  Serial.write(vel);
}

void midiNoteOff(uint8_t chan, uint8_t n, uint8_t vel) {
  if (chan > 15) return;
  if (n > 127) return;
  if (vel > 127) return;
  Serial.write(MIDI_NOTE_OFF | chan);
  Serial.write(n);
  Serial.write(vel);
}

I will let you know how it goes on over night.

Edit - 09:20 GMT the following day and it is still going.

Well the bad news is that my system crashed as well. When I went to look at it at 13:30 GMT is was keeping on a continuous drone on some notes. I could still here some notes changing over the drone so that confirms your observation that the system still providing it with MIDI messages was still working.

When I looked at it at 16:00 GMT it was working again but my wife tells me the lights flickered when I was out so my guess is that it reset then, as we are having storms heavy in the UK at the moment.

So it looks like indeed the VS1053 is misbehaving itself, and it is nothing to do with your software or the use of software serial.

The simple option would be to look for a hardware MIDI sound generator on eBay. You can get quite good modules for not very much money these days. I would recommend a Yamaha MU10 if you can get your hands on one. I have two of these and the sound quality is several notches above what you get with the VS1053, where many instruments are indistinguishable from each other.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.