This minimal program works with an Arduino Uno:
/*
This code works with the VS1053 Breakout Board and controls the VS1053 in what is called Real Time MIDI mode.
https://www.sparkfun.com/products/10587
5V : VS1053 VCC
GND : VS1053 GND
D3 (SoftSerial TX) : VS1053 RX
D4 : VS1053 RESET
Attach a headphone breakout board to the VS1053:
VS1053 LEFT : TSH
VS1053 RIGHT : RSH
VS1053 GBUF : GND
When in the drum bank (0x78), there are not different instruments, only different notes.
To play the different sounds, select an instrument # like 5, then play notes 27 to 87.
To play "Sticks" (31):
talkMIDI(0xB0, 0, 0x78); //Bank select: drums
talkMIDI(0xC0, 5, 0); //Set instrument number
//Play note on channel 1 (0x90), some note value (note), middle velocity (60):
noteOn(0, 31, 60);
*/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic inidicator
int instrument = 0;
void setup()
{
Serial.begin(57600);
//Setup soft serial for MIDI control
mySerial.begin(31250);
//Reset the VS1053
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
void loop()
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
delay(2000);
}
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
digitalWrite(ledPin, HIGH);
mySerial.write(cmd);
mySerial.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
mySerial.write(data2);
digitalWrite(ledPin, LOW);
}
However, I try to change the pins to an ESP32, and just get a fuzzy sound:
/*
ESP32 code
https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Pinout
ESP SparkFun Shield
GND GND
16 2
17 3
4 4
RX RX
TX TX
5V +5V
3V3 3.3V
*/
#define RXD2 16 // was 2
#define TXD2 17 // was 3
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
void setup()
{
Serial.begin(57600);
//Setup soft serial for MIDI control
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
//Reset
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
void loop()
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
delay(50);
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
delay(3000);
}
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
Serial2.write(cmd);
Serial2.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
Serial2.write(data2);
}