Here are the steps to build a small wireless midi controller
with ESP8266, in this example we use module version ESP-03.
The first thing to do is programming with a new firmware the for ESP-03
As soon as we are ready, we load our firmware using Arduino IDE
(to configure Arduino IDE with code esp8266, see here in section "configuration IDE Arduino")
This firmware reads INPUT of all the pin provided by ESP-03 and he takes care to convert push button in MIDI notes.
/*
***************************************
ESP-03:
vcc wifi_ant
14 ch_pd (vcc)
12 18
13 rx
(gnd) 15 tx
2 nc
(gnd) 0 gnd
***************************************
ESP-07:
rst tx
adc rx
(vcc) ch_pd 5
16 4
14 0 (gnd)
12 2
13 15 (gnd)
vcc gnd
***************************************
*/
#include "ESP8266WiFi.h"
const char *ssid = "********";
const char *password = "********";
const char *host = "192.168.1.2"; // change this ip with address of your midi servers
String ip = "";
#define NUM 6
int pin [NUM] = { 14, 12, 13, 2, 18 };
int note [NUM] = { 65, 66, 67, 68,69 };
int state[NUM] = { 0, 0, 0, 0, 0 };
int tmp [NUM] = { 1, 1, 1, 1, 1 };
void setup() {
for (int i = 0; i < NUM; i++)
{
pinMode(pin[i], INPUT);
}
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
ip = WiFi.localIP().toString();
}
void loop() {
for (int i = 0; i < NUM; i++)
{
state[i] = digitalRead(pin[i]);
if (state[i] != tmp[i])
{
WiFiClient client;
const int port = 9055;
if (!client.connect(host, port))
{
Serial.println("connection failed");
return;
}
Serial.print(ip);
Serial.print(":");
Serial.print(note[i]);
Serial.print(":");
Serial.println(state[i]?"0":"100");
client.print(ip);
client.print(":");
client.print(note[i]);
client.print(":");
client.println(state[i]?"0":"100");
client.stop();
}
tmp[i] = state[i];
}
delay(1);
}
For testing i connected only two buttons, but you can connect up to five buttons.
Now we prepare the TCP Midi server with openFrameworks ofxMidi and ofxNetwork addons, the server creates a virtual MIDI device, and waits for a connection from an ESP-03 client sending the notes to it when you press and release the button to simulate the ON and OFF of the midi protocol.
The server provide more client connection, so you can connect more ESP-03 to midi server
#include "ofMain.h"
#include "ofxMidi.h"
#include "ofxNetwork.h"
#include "ofAppNoWindow.h"
class ofApp : public ofBaseApp
{
public:
ofxTCPServer TCP;
ofxMidiOut midi;
int channel, port, mport;
ofApp(vector conf)
{
port = ofToInt(conf[0]);
mport = ofToInt(conf[1]);
channel = ofToInt(conf[2]);
}
void setup()
{
TCP.setup(port);
TCP.setMessageDelimiter("\n");
midi.listPorts();
midi.openPort(mport);
}
void update()
{
for(unsigned int i = 0; i < (unsigned int)TCP.getLastID(); i++)
{
if( !TCP.isClientConnected(i) )
{
continue;
}
else
{
string str = TCP.receive(i);
if(str!="")
{
vector pars = ofSplitString(str,":");
string ip = pars[0];
int note = ofToInt(pars[1]);
int velocity = ofToInt(pars[2]);
if(velocity > 0)
{
midi.sendNoteOn(channel, note, velocity);
}
else
{
midi.sendNoteOff(channel, note, velocity);
}
if(TCP.disconnectClient(i))
{
ofLog()<<"disconnect: "+ip;
}
}
}
}
ofSleepMillis(5);
}
void exit()
{
TCP.close();
midi.closePort();
}
};
int main(int argc, char *argv[])
{
if(argc > 3)
{
ofAppNoWindow w;
ofSetupOpenGL(&w, 1024,768, OF_WINDOW);
vector conf;
conf.push_back(argv[1]);
conf.push_back(argv[2]);
conf.push_back(argv[3]);
ofRunApp( new ofApp(conf));
}
else
{
cout << "Error: parameter[ tcp-port, midi-port, midi-channel ]\n\t./bin/tcpmidiserver 9055 0 1\n";
}
}
The server is a batch, which includes as input the TCP port, the port for the MIDI device and channel
./bin/tcpmidiserver 9055 0 1