ESP8266 OpenSound Control
2015-07-05 22:29
electronics,
supercollider
Here some example Arduino code for sending and receiving OSC via the cheap ESP8266 serial WiFi module.
Note that the Open Sound Control messages here are very basic - only 4 bytes packed into a single 32bit integer.
- upload the code below to an Arduino.
- connect ESP8266 TX pin to Arduino pin0.
- connect ESP8299 RX to Arduino pin1. It is safest to use a 3V3 lever converter for this line (or at least a voltage divider).
- power the ESP8266 (VCC and GND) from an external 3V source. Do not use the Arduino 3V3 pin as it cannot provide the required current. I used an LF33CV voltage regulator to get 3.3V from the 5V supply that also powers the Arduino.
- connect ESP8288 RESET pin to Arduino pin4.
- and last, connect ESP8266 CH_PD to 3V3
Optional: connect a separate USB-Serial (FTDI) chip to Arduino pins 2 and 3 to use software serial debugging. Start debugging in a terminal with something like screen /dev/tty.usbserial-A4015TKA 115200
The Arduino code sits and waits for an incoming OSC message (/tap). It then replies by sending out a counter-message (/sti).
//f0 150705
//sending and receiving UDP OSC with an ESP8266
//for an Arduino + ESP8266 with firmware 0.9.5.2
#include <SoftwareSerial.h>
#define WLAN_SSID "SSID"
#define WLAN_PASS "PASS"
#define WLAN_ADDR "192.168.1.51" //laptop running sc
#define PORT 1112 //incoming OSC port
String tag = "/tap"; //incoming OSC addy
SoftwareSerial mySerial(2, 3);
uint8_t buf[16];
byte cnt;
byte id, on, hi, lo;
boolean resp;
void setup() {
//--OSC message
buf[0] = 47; // /
buf[1] = 115; // s
buf[2] = 116; // t
buf[3] = 105; // i
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
buf[8] = 44; // ,
buf[9] = 105; // i
buf[10] = 0;
buf[11] = 0;
buf[12] = 4; // a high (id)
buf[13] = 3; // a low (on)
buf[14] = 2; // b high (hi)
buf[15] = 0; // b low (lo)
mySerial.begin(115200);
Serial.begin(115200);
Serial.setTimeout(10000);
mySerial.println("");
mySerial.println("starting");
mySerial.print("hard reset...");
digitalWrite(4, 0);
pinMode(4, OUTPUT);
delay(10);
pinMode(4, INPUT);
resp = Serial.find("ready\r\n");
mySerial.println(resp);
mySerial.print("mode1...");
Serial.println("AT+CWMODE=1");
resp = Serial.find("OK\r\n");
mySerial.println(resp);
mySerial.print("connecting...");
do {
Serial.print("AT+CWJAP=\"");
Serial.print(WLAN_SSID);
Serial.print("\",\"");
Serial.print(WLAN_PASS);
Serial.println("\"");
resp = Serial.find("OK\r\n");
mySerial.println(resp);
} while (!resp);
mySerial.print("mux1...");
Serial.println("AT+CIPMUX=1");
resp = Serial.find("OK\r\n");
mySerial.println(resp);
mySerial.print("udp...");
Serial.print("AT+CIPSTART=4,\"UDP\",\"");
Serial.print(WLAN_ADDR);
Serial.print("\",57120,");
Serial.print(PORT);
Serial.println(",0");
resp = Serial.find("OK\r\n");
mySerial.println(resp);
Serial.setTimeout(1000);
}
void loop() {
while (Serial.available()) {
String abc = Serial.readStringUntil('\n');
if (abc.startsWith("+IPD,4,16:" + tag)) {
id = abc[22];
on = abc[23];
hi = abc[24];
lo = abc[25];
mySerial.print("id:");
mySerial.println(id);
mySerial.print("on:");
mySerial.println(on);
mySerial.print("hi:");
mySerial.println(hi);
mySerial.print("lo:");
mySerial.println(lo);
buf[15] = cnt++;
Serial.println("AT+CIPSEND=4,16");
Serial.find(">");
Serial.write(buf, sizeof(buf));
resp = Serial.find("OK\r\n");
mySerial.print("send...");
mySerial.println(resp);
}
}
}
SuperCollider test code:
(
//--call&response
var last= Main.elapsedTime;
OSCFunc({|msg, time, addr|
[\id, msg[1]>>24, \on, (msg[1]>>16)&255, \hi, (msg[1]>>8)&255, \lo, msg[1]&255, time-last, addr].postln;
last= time;
}, \sti);
n= NetAddr("192.168.1.50", 1112); //ESP8266 ip address
f= {|id, on, hi, lo| (id&255<<24)|(on&255<<16)|(hi&255<<8)|(lo&255)};
r= Routine.run({
inf.do{|i|
n.sendMsg(\tap, f.value(4, 1, i.asInteger>>8&255, i.asInteger%256));
0.5.wait;
};
});
)
Note: my new and better way to do this is described in this post: /f0blog/f0led/