ESP8266のアナログリードで嵌る
久しぶりの更新です。実は、以前に、ESP8266のアナログポートの挙動がおかしい、という記事を書いたのですが、この問題を何とか解決出来ないかいろいろ試していたのですが、どうしてもうまくいかなくて時間だけ経ってしまいました。
このまま続けても解決出来そうに無い感じなので、ここまでにやってみたことを書いておこうと思います。まあ、頭の整理をしつつ自分へのメモ代わりを兼ねています。
問題になっている環境は、ESP-WROOM-02 (ESP8266) を Arduino の IDE(1.6.5)で実行した場合で、現象としてはsystem_adc_read(); を高速で繰り返し呼ぶと実行時間が短くなることがあるというものです。ちゃんとAD変換やった結果ならそれでもいいのですが、どうもAD変換を実際にやらないで、単に以前の値を返してきている疑いがあります。
詳しい現象は以前の記事を見ていただくとして、おっと今回試したのは以前の記事の最後に書いた for ループで回数を指定してAD変換を実行させた場合の話です。
以下のようなプログラムでテストしました。AD変換がうまくいかない現象の対策として、割り込みを禁止したり、タイミングを調整したりいろいろやったのですが、全部ダメでした。コメントに 対策・・・・ と書いてあるのが試した内容の痕跡です。
◆テストプログラム
どうやってもリセット後ある程度の時間経過後、具体的には数秒以上経つとAD変換の実行時間が短い場合が発生します。裏にデーモンのようなプロセスが走っていてそいつが悪さをしている気がします。
この現象の対策につきいろいろ検索しているのですが、うまい情報がヒットしません。system_adc_read() の中で何をやっているのか調べた方が早いのかも知れません。
あるいは、いつまでもやっていてもダメそうなので、外付けのADCを使った方が早道なのかも知れません。んと、これは7月頃に考えていた話で、ちっとも進歩してません。トホ、
このまま続けても解決出来そうに無い感じなので、ここまでにやってみたことを書いておこうと思います。まあ、頭の整理をしつつ自分へのメモ代わりを兼ねています。
問題になっている環境は、ESP-WROOM-02 (ESP8266) を Arduino の IDE(1.6.5)で実行した場合で、現象としてはsystem_adc_read(); を高速で繰り返し呼ぶと実行時間が短くなることがあるというものです。ちゃんとAD変換やった結果ならそれでもいいのですが、どうもAD変換を実際にやらないで、単に以前の値を返してきている疑いがあります。
詳しい現象は以前の記事を見ていただくとして、おっと今回試したのは以前の記事の最後に書いた for ループで回数を指定してAD変換を実行させた場合の話です。
以下のようなプログラムでテストしました。AD変換がうまくいかない現象の対策として、割り込みを禁止したり、タイミングを調整したりいろいろやったのですが、全部ダメでした。コメントに 対策・・・・ と書いてあるのが試した内容の痕跡です。
◆テストプログラム
/* ESP8622-WROOM-02
* アナログデーターを高速で連続読み取りするテスト
* 2016/10/30 ラジオペンチ
* 最初は良いが、15から35回くらい繰り返すとAD変換しないで
* 値を返してくる場合がある。(実行時間が短い)
*
*/
int dataNN = 0;
int dataN, AdcData;
long SumAdc, SumAdc2;
unsigned long TimeStart, TimeElapsed;
//ESP-WROOM-02でアナログ入力をするための設定
extern "C" { // ADCを使うためのおまじない
#include "user_interface.h"
}
void setup() {
// noInterrupts(); // 対策テスト、割り込み禁止
Serial.begin(115200);
pinMode(13, OUTPUT); // 観察用ポート
loops(); // 自前のloopで実行
}
void loops() { // loop()では無い場所でループ
for (;;) {
dataN = 0; SumAdc = 0; SumAdc2 = 0; // 変数初期化
dataNN++;
digitalWrite(13, HIGH);
//system_timer_reinit(); // ダメ対策 タイマー初期化
wdt_disable(); // ダメ対策 WDT禁止
TimeStart = micros();
for (int i = 0; i < 1058; i++) { // 約100msのループを実行
// __asm__ __volatile__ ("nop"); // 対策 nopでタイミング調整
// __asm__ __volatile__ ("nop");
noInterrupts(); // 対策 割り込み禁止
delayMicroseconds(100); // 対策 delayMicrosecondsでタイミング調整
AdcData = system_adc_read(); // アナログ電圧読み出し
// AdcData = 700; // 固定値代入テスト
// Interrupts(); // 対策 でもこんな関数無かった
// __asm__ __volatile__ ("nop");
// __asm__ __volatile__ ("nop");
SumAdc = SumAdc + AdcData; // ΣXi
SumAdc2 = SumAdc2 + AdcData * AdcData; // ΣXi^2
dataN++; //
}
TimeElapsed = micros() - TimeStart; // ループ通過時間を求める
delay(10); // 対策 シリアル出力前にちょっと待つ
digitalWrite(13, LOW);
Serial.print(dataNN); Serial.print(", "); // 平均値
Serial.print(SumAdc / dataN); Serial.print(", "); // 平均値
Serial.print(sqrt(SumAdc2 / dataN)); Serial.print(", "); // 実効値
Serial.print(TimeElapsed); Serial.print(", "); // 測定時間
Serial.println(dataN); // ループ回数
delay(400); // 適当に待つ
}
}
void loop() {
delay(1); // 対策 意味の無いdelay
}
どうやってもリセット後ある程度の時間経過後、具体的には数秒以上経つとAD変換の実行時間が短い場合が発生します。裏にデーモンのようなプロセスが走っていてそいつが悪さをしている気がします。
この現象の対策につきいろいろ検索しているのですが、うまい情報がヒットしません。system_adc_read() の中で何をやっているのか調べた方が早いのかも知れません。
あるいは、いつまでもやっていてもダメそうなので、外付けのADCを使った方が早道なのかも知れません。んと、これは7月頃に考えていた話で、ちっとも進歩してません。トホ、