analogRead() in loop{} 8x faster than using Timer0
Posted: Tue Mar 29, 2016 4:37 pm
Hi,
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:
... and here's the working loop{} based code which samples + sends UDP at about 8kHz
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.
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:
Code: Select all
#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
Code: Select all
#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.