I've been experimenting with sampling analogue audio from an electret microphone with MAX4466 op-amp and sending it over the WiFi using UDP to another machine. This works surprisingly well when all of the work is done in the loop {} - I get approx 8500Hz - i.e. about telephone quality.
I want to remove this code from the loop {} and drive the sampling using timer0 intervals. The problem is that when I do that, I can't set the interval any shorter than about 70000 cycles (~500ms) else I get no network traffic at all. Thus the loop{} driven code is about 8 times faster.
Can someone point me in the right direction?
Here is the Timer0-based code with the speed problem:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
unsigned int udppacketcount=0;
unsigned int adcvalue;
const char* ssid = "acentral-office";
const char* password = "xxxxxxxxxxx";
boolean wifiConnected = false;
IPAddress ip(10, 0, 0, 31);
WiFiUDP UDP;
char ADCBuffer[500] = "";
boolean connectWifi() {
boolean state = true;
int i = 0;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("Connecting to WiFi");
// Wait for connection
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (i > 10) {
state = false;
break;
}
i++;
}
if (state) {
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("");
Serial.println("Connection failed.");
}
return state;
}
void inline handler(void) {
adcvalue=analogRead(A0);
ADCBuffer[udppacketcount] = adcvalue;
// Serial.print(ADCBuffer[udppacketcount]);
// Serial.print(" ");
udppacketcount++;
if (udppacketcount == 500) {
// Serial.println();
UDP.beginPacket(ip, 8989);
UDP.write(ADCBuffer, 500);
UDP.endPacket();
udppacketcount = 0;
}
timer0_write(ESP.getCycleCount() + 70000);
}
void setup() {
Serial.begin(115200);
wifiConnected = connectWifi();
noInterrupts();
timer0_isr_init();
timer0_attachInterrupt(handler);
timer0_write(ESP.getCycleCount() + 70000);
interrupts();
}
void loop() {
}
... and here's the working loop{} based code which samples + sends UDP at about 8kHz
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
unsigned int udppacketcount=0;
unsigned int adcvalue;
const char* ssid = "acentral-office";
const char* password = "xxxxxxxxx";
boolean wifiConnected = false;
IPAddress ip(10, 0, 0, 31);
WiFiUDP UDP;
char ADCBuffer[500] = "";
boolean connectWifi() {
boolean state = true;
int i = 0;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("Connecting to WiFi");
// Wait for connection
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (i > 10) {
state = false;
break;
}
i++;
}
if (state) {
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("");
Serial.println("Connection failed.");
}
return state;
}
void setup() {
Serial.begin(115200);
wifiConnected = connectWifi();
}
void loop() {
adcvalue=analogRead(A0);
ADCBuffer[udppacketcount] = adcvalue;
udppacketcount++;
if (udppacketcount == 500) {
UDP.beginPacket(ip, 8989);
UDP.write(ADCBuffer, 500);
Serial.print(UDP.endPacket());
udppacketcount = 0;
delay(10); // XXX - no network traffic unless this is here!
}
yield();
}
With this I get about 16 x 500-byte packet payloads per second. If I take the delay(10) out of the loop{}, then the network traffic is very sporadic. Of course if I try to put a delay() into the Timer0 handler code, the esp8266 will 'wdt reset' immediately.
Any ideas? I'm using Arduino 1.6.8 with ESP8266 2.1.0 installed through the Boards Manager.
Cheers,
Gavin.