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);
}