ESP32のADC速度、RAW系の命令使って読み出せば、
無駄な処理せず速く行えると思い込んでいたんだけど、
こないだ見つけたサイト、
http://pikacchu.blog.fc2.com/blog-entry-3.html
ここを改めて見てみると、Arduino由来のADC入力関数
「analogRead」使って、1サンプル9u秒とか書いてある
ことに気づく。
ん?なんで?Arduinoのお気楽関数の方が速いって…
どういうことなの?
と思って、こないだ作ったテストスケッチを改造して、
サンプル時間を計測しなおしてみる。
…なんと!9u秒台が出てるよ。大体9.5u秒くらい。
こないだの37u秒から比べると、1/4くらいの時間で
サンプリングが完了している。なんだ、元々こんなに
速いのか。
普通、Arduinoのお気楽機能使うと、ピン番号変換とか
のせいで、色々時間掛かるものだと思い込んでいた
けど、RAW系の機能使うよりanalogReadの方が速いとは!
でも、まてよと。
ESP32のアッテネータって、デフォルトで1/1では?
analogReadと組みあわせて使うアッテネータの設定
の関数について調べなおしてみると、
https://trac.switch-science.com/wiki/esp32_tips
スイッチサイエンスでtipsが公開されていたんだけど、
「analogSetAttenuation」関数で指定するのは一緒
みたい。そうなの?なんか効いてないみたいなんだけど
なぁ、と思いつつ、時間がないので、外付けの部品とか
抜きに調べられる範囲でささっといくつか実験。
「analogSetAttenuation」に「ADC_11db」と「ADC_0db」
を指定したときの値を見比べてみると、やっぱレンジが
ちゃんと変わっているみたいだな。
そもそも、analogReadで読み込んだときって、デフォルト
でアッテネータは-11dBに設定されるみたい。RAW系の
関数で読み出すときは0dBなんだけど、そこはやっぱ
他のArduino環境と合わせてある感じなのかな。
スケッチはこんな。
#include <driver/adc.h>
/* global variables */
#define LED 2
#define SAMPLES 32768
//int val[SAMPLES];
uint16_t val[SAMPLES];
/* sub routine */
void prt_hex(int n, char c) {
for (int i = 1; i < 4; i++) {
if ( (n >> (4*i)) == 0) {
Serial.print(c);
}
}
Serial.print(n, HEX);
}
/* main process */
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
Serial.println();
Serial.println("----- adc width = 12 bits -----");
Serial.println("----- attenuator = -11dB -----");
analogReadResolution(12); //12 bits
analogSetAttenuation(ADC_11db); //For all pins
// analogSetPinAttenuation(A18, ADC_0db); //0db attenuation on pin A18
// analogSetPinAttenuation(A19, ADC_2_5db); //2.5db attenuation on pin A19
// analogSetPinAttenuation(A6, ADC_6db); //6db attenuation on pin A6
// analogSetPinAttenuation(A7, ADC_11db); //11db attenuation on pin A7}
}
void loop() {
/* display heap size */
Serial.print("Heap size : ");
Serial.println(ESP.getFreeHeap());
Serial.println();
Serial.println("start sampling.");
Serial.println();
digitalWrite(LED, HIGH);
/* input 1024 samples with simple loop */
unsigned long starttime = millis();
for (int i=0; i<SAMPLES; i++) {
val[i] = analogRead(38); // 38 = analog4
}
unsigned long endtime = millis();
digitalWrite(LED, LOW);
Serial.println("complete sampling.");
Serial.println();
Serial.print("start time = ");
Serial.print(starttime);
Serial.println("ms");
Serial.print("end time = ");
Serial.print(endtime);
Serial.println("ms");
Serial.print("total time = ");
Serial.print(endtime - starttime);
Serial.println("ms");
Serial.print("unit time = ");
Serial.print((endtime - starttime) * 1000 / SAMPLES);
Serial.println("us / sample");
Serial.print("sampling speed = ");
Serial.print(1000 * SAMPLES / (endtime - starttime));
Serial.println("sps");
for (int i=0; i<SAMPLES; i++) {
if ((i % 16) == 0 ) {
Serial.println();
prt_hex(i, '0');
Serial.print(" : ");
}
prt_hex(val[i], ' ');
Serial.print(", ");
}
Serial.println();
/* display heap size */
Serial.print("Heap size : ");
Serial.println(ESP.getFreeHeap());
Serial.println();
for (;;);
}
先頭のinclude文は要らないはずだな。多分。
なんだ。それなら、あまり悩むことなくアナログ入力
を使いつつ、あとは40k~50kspsくらいでタイマ割り込み
使ってサンプリングして、取りこぼしが発生しないかを
確認したいところだな。
そのくらいでokなら、音声の可聴域は全然使えそう
だよな。
もっと問題は、Wi-Fiとか通信機能使いながらでも、
(通信負荷が十分小さい間なら)サンプリング速度が
確保できるかが問題かな。
https://twitter.com/count_nmani/status/1022336035500388353
カンニングペーパー1枚のみ持込可。これ頭良いよな。
自分でカンニングペーパー作ることを前提におく
なら、確かに頭に入っちゃうもんな。
https://twitter.com/t_okada/status/1022892656727273473
これホントそう思う。思いつきでわざわざ混乱を
増大させるようなことしてくれるなよと。
せめて、思いついてから3秒くらい考えてから口を
開いてくれよ。
https://twitter.com/Har7201/status/952910164826484740
エストニア!! エストニア!!
https://www.youtube.com/watch?v=h1o47b9umn0
しょっぱながクレイジークライマーなところがとても良い。
こないだ頼んでた、PAM8403が届いてた。
https://ja.aliexpress.com/item/15949-Free-shipping-PAM8403-module-Super-board-2-3W-Class-D-digital-amplifier-board-efficient-2/32357176265.html
なんだかんだで、10個入りを買ったのだった。いろいろ
使いまわし効くしねぇ。