google-site-verification: google3bd66dd162ef54c7.html
fc2ブログ

ACACアダプタとNJM2360を使ってESP32を動かす

◆まえがき
前の記事でESP32を動かすためのAC-ACアダプタとNJM2360を使った電源を作りました。この電源は0.33Aくらい流すとリップルが目立ち始める非力な物です。ESP32はこれをはるかに上回る0.6Aくらいの電流が流れることがあるようなので、これに耐えることが出来るか確認してみました。

◆テストする回路
全体
左側のACACアダプタを電源に使い、右側のESP32の回路を動かすのが目標です。なお、この回路ではWiFi経由でネットに接続しているのですが、その内容は別途紹介予定です。

◆電圧波形
電源投入後の電源電圧(5V出力)を観察したのが次の波形です。

・5V電源電圧
電圧のディップ
5Vの電源が立ち上がった後、0.4秒後に電圧が4.3Vまで下がっています。このあたりのタイミングでWiFiの接続を行っていて、0.6Aくらいの電流が流れるのだと思います。

・電圧低下部拡大
電圧低下の拡大
5ms程度の間に電圧が下がっていて、最低で4.2Vまで電圧が下がっています。なお、この現象は電源電圧の位相のタイミングと関係があるようで、上位機の波形はワーストの場合です。

ESP32のモジュールは3.3Vで動いていて、間にはシリーズレギュレーター(1117)が入っているので、この電圧のドロップがそのままESP32に影響することはありません。念のために3.3Vの電圧変化を見てもその変化はわずかで、問題になるようなものではありませんでした。

ESP32に大きな電流が流れるのは瞬間的なので、電源のデカップリングコンデンサの効果などで、電圧の低下が抑えられているのだと思います。ということで、ESP32の動作には問題無さそうでした。

但しちょっと気になるのは、シリーズレギュレーターの動作電圧が十分確保できていない点です。データーシートによると1117を正常に動作させるためには1.0V以上の電圧差が必要になりますが、現状ではこの電圧が確保できていません。

◆対策
対策としては、トランスのタップを24Vに上げて供給電圧を倍に上げるのが手っ取り早いです。しかし、この場合、整流後の電圧が38VくらいになるのでNJM2360の耐圧の40Vギリギリになってしまいます。それに基板の中に高い電圧の場所があると、間違ってショーとさせた時の被害が大きくなるので、あまり気が進みません。

他の手として、整流用の平滑コンデンサの容量を上げる方法があります。つまり、瞬間的な負荷変動をコンデンサで乗り切ってしまおうという作戦です。

◆対策した回路図
330uFに変更した回路図

基板

C5の容量を100μFから330μF(25V)に増量しました。ちなみに、最初の100μFのコンデンサはトランスのタップを上げた場合を想定して耐圧50Vの物を使っていたので、部品のサイズとしてはほとんど同じです。

◆特性
特性@330uF
負荷電流0.5Aまではほぼ一定の電圧が得られるようになりました。これなら安心して使うことが出来ます。

◆まとめ
電源の整流回路のコンデンサ容量を増やすだけで特性が改善されて、めでたしめでたしでした。元の回路のC5の値は小さすぎで、他の部品の性能を100%引き出すことが出来ていなかったということだと思います。

AC電源を整流して直流を作る場合、どうしてもリップルが残ります。そのリップルの谷間ではコンバーターは出力電圧を維持しようとしてより多くの電流を吸い出します。もし供給力が不足していると支えきれなくなり、出力電圧が低下するという現象が発生していたようです。電源は奥が深いです。

ESP32をブレッドボードで使う

◆まえがき
ESP32 を使ってちょっとやってみたいことがあるのですが、ESP32 DEVKIT V1のように、USB に繋いですぐに使える状態の物の手持ちが無くなってしまいました。AliExpress に発注しているのですが、届くまでのもう少しかかりそうです。

幸いCPU単体である ESP-WROOM-32 のモジュールならあるので、これをブレッドボード上で動かせるように配線してみました。なお、以下の記事ではCPU単体を ESP-WROOM-32、モジュールとして使える状態にした物を ESP32 と呼ぶことにします。

◆回路図
ESP-WROOM-32 を動かすための回路。
ESP-WROOM-32の配線
とりあえず最低限必要な配線だけやった状態の回路図です。あとは必要に応じ追加すれば良いかと。

電源はシリアル接続している USB コネクタの 5Vを使います。自動リセット/書き込み機能は無しで、スイッチ操作で行う方式です。(リセットはENボタン。プログラムの書き込みはPROGボタンを押した状態でENを押して放す)

これでいけるはずだったのですが、PL-2303 を使った USBシリアルアダプタが Windows によって無効化されていたので、いつものおまじないのユーティテイを使ってこれを解除しました。いくら法的に問題があると言っても、ユーザーの持ち物を無断で使えないようにしている訳で、これって自力救済禁止の原則に反する行為だと思うのですがどうなんでしょうね。

◆外観
いろいろ配線出来るようにするためにブレッドボードに組みました。
ESP32(ESP-WROOM-32)をブレッドボードに配線
左側の黒い四角のモジュールが ESP-WROOM-32 です。

ESP-WROOM-32 の端子は基板エッジにはんだ付けするタイプ、更にハーフピッチなので、そのままではブレッドボードに接続出来ません。そこで、下の写真のように、小さな基板に取り付けたピンヘッダを中継に使いました。
ESP-WROOM-32をピンソケットに取り付け

◆ATmega328Pのソケットに挿す
この記事と同じような狙いで、以前にESP32をATmega328のソケットで使うなんてこともやりました。でも電源電圧3.3Vが必要なので、UNO の基板に挿すわけにもいかなかったので、作っただけでほとんど使わないで終わっていました。

◆まとめ
これで無事 ESP32 として使えるようになったので、やりたかった実験が出来るようになりました。この CPU は数年前に秋月で買ったまま放置していた物ですが、こうして使えるようになって良かったです。

ちなみに、まっさらな状態の ESP-WROOM-32 に電源を入れると、起動時には200mAくらい、定常時でも110mAくらいの消費電流だったのですが、Arduino でL-チカを書き込むと消費電流が激減し、11mAくらいで済むようになりました。まっさらな状態では、WiFi を使って何かやりたがっていた感じでしたが、何をやりたかったのでしょうね。

ESP32のタイマー割り込みの精度、応答時間

◆まえがき
前の記事ではESP32のタイマー割り込みのプログラムの書き方について調べました。その記事で使ったプログラムは時計を表示するものだったので、アプリとのインターフェイス方法の確認について良いテストになりました。但し、時計の表示部の処理時間が長いために、割り込みのタイミングなどの性能評価はやりづらかったです。

そんなことで、プログラムを修正し、タイマー割り込みの性能をもっと測定し易くして測定を行ってみました。

・性能測定
ESP32を測定中
ESP32(DEVKIT V1)を使い、ピンの状態をオシロと周波数カウンタを使って測定しました。

◆タイマー割り込みテスト用プログラム
前の記事のプログラムから時計を表示する部分を削除し、代わりにPin2のLEDを点滅させるように修正しました。なお、Pin2のLEDはボードに最初から取り付けられているので、新たに接続しなくても大丈夫です。

// ESP32 タイマー割り込みのテスト by ラジオペンチ

#define LED_PIN 2 // built in LED

hw_timer_t * tm0 = NULL; // 名称tm0でタイマー割り込み定義

volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile boolean flag = false;

void IRAM_ATTR onTimer() { // tm0のタイマー割り込みハンドラ (RAM上に配置)このルーチンは setup以前に書く必要がある
portENTER_CRITICAL_ISR(&timerMux); // 排他制御で下記を実行
flag = true;
digitalWrite(LED_PIN, flag);
portEXIT_CRITICAL_ISR(&timerMux); // 排他制御終了
xSemaphoreGiveFromISR(timerSemaphore, NULL); // セマフォを開放
}

void setup() {
pinMode(LED_PIN, OUTPUT); // blink by sec.
timerSemaphore = xSemaphoreCreateBinary(); // バイナリセマフォを作成
tm0 = timerBegin(0, 80, true); // tm0タイマーをプリスケーラー80に設定
timerAttachInterrupt(tm0, &onTimer, true); // tm0割込み処理ルーチンを onTimeに設定
// timerAlarmWrite(tm0, 1000, true); // tm0を1ms周期に設定
timerAlarmWrite(tm0, 1000040, true); // tm0を1秒周期に設定 (+40は誤差の補正)
timerAlarmEnable(tm0); // tm0開始
}

void loop() {
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE) { // セマフォを取得 (=onTimer割込み発生)
portENTER_CRITICAL(&timerMux); // 排他制御で以下を実行
flag = false;
digitalWrite(LED_PIN, flag);
portEXIT_CRITICAL(&timerMux); // 排他制御おしまい
}
}
タイマー割り込みの部分は前の記事のプログラムと同じで、セマフォを使った排他制御を行っています。タイマーの周期を 25行目でμs単位で指定していますが、この値が100040と半端な数字になっているのは、正確な周期になるように補正したためです。

割込みルーチンの中の 14行目でLEDを点灯し、loopの中の 33行目でLEDを消灯させているので、このピン(LED)の状態を測定することで、タイマー割り込みの状態が判る仕掛けになっています。

◆時間精度の測定結果
Pin2にユニバーサルカウンタを接続して割り込み周期の測定を行いました。以下はその結果です。

・1秒割り込みの周期
ESP32の1秒、補正あり
誤差は0.4ppmとすばらしい精度が出ました、誤差補正はうまくいっているようです。なお、基準はルビジウムオシレータです。
ちなみに、前の記事のプログラムでは時計の描画ルーチン(約9.5msで微妙に変化)の影響を受けるのでここまで精密な測定は出来ませんでした。

誤差を補正していない状態を見ると、

・周期測定結果 (誤差補正無し)
ESP32の1秒、補正無し
0.99996015秒、つまり1秒に対して 0.00003985秒短い値で、誤差は-39.85ppmということになります。このままでも結構良い精度が出ているので、高精度の時計を作りたい場合など以外ならこのままでも使えそうです。なお、ESP32のモジュールをもう一つ持っているのですが、そっちの誤差は-35ppmでした。

このように割込みの時間精度に問題は無いことが判りました。次に割り込みの応答時間について見て行きます。

◆割り込み応答時間
プログラムの説明に書いたように、Pin2は割り込みが入ってからloopのプログラムが応答するまでの間だけHIGHになっているので、この波形を観察すれば割り込み処理の応答時間が判ります。
なお、この応答時間にはばらつきがあったので、オシロで観察し易くするために、割り込み周期を1msに変更しています。

・割り込み応答、4.4~4.8μs
処理時間にジッタあり
よく見ると、4.4~4.8μsのジッタがありました。つまり、処理時間がこれだけ変化していることになります。
(注:この波形の立ち上がりがハード的なタイマー割り込みの発生タイミングでは無いことに注意)

・ジッター部拡大
ジッタ部拡大
この波形はオシロのディレドイトリガ機能を使って観察したものです。ジッタの幅は430ns程度あり、その発生位置は離散化されたタイミングで発生している感じです。

あと、このジッタはいつも同じように発生しているのではなく、リセットを掛けるたびにタイミングが変化していました。以下に例をいくつか示します。

・割り込み応答、最大5.2μs
最大5.2μs
5μs以上かかることがあります。

・割り込み応答、ジッタ無しで4.4μs
ジッタ無し、但し処理時間が5.2μs
4.4μsでジッター無しのこともあります。

この現象は、たぶんOSのジッターを観察していることになるのだと思います。ESP32は背後でfreeRTOSが動いているので、そのタスク制御の影響で処理時間が変わる、ということなんだと思います。

◆セマフォを使わないとどうなる
処理時間にばらつきが出るのはOSの仕様なので仕方がないのでしょうが、なんだかいやなものです。だったらセマフォを使わないで割り込み処理を行ったらどうなるでしょう。昔の事例を見ると、セマフォは使わないで割り込み処理をやらせていたので、この程度の簡単なプログラムなら問題無く動く気がします。

そんなことで、プログラムを修正してやって見ました。

・セマフォを使わないタイマー割り込みのプログラム。
// ESP32 タイマー割込みのテスト セマフォを使わないプログラム by ラジオペンチ

#define LED_PIN 2 // built in LED

hw_timer_t * tm0 = NULL; // 名称tm0でタイマー割り込み定義

// 【削除】volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile boolean flag = false;

void IRAM_ATTR onTimer() { // tm0のタイマー割り込みハンドラ (RAM上に配置)このルーチンは setup以前に書く必要がある
portENTER_CRITICAL_ISR(&timerMux); // 排他制御で下記を実行
flag = true;
digitalWrite(LED_PIN, flag);
portEXIT_CRITICAL_ISR(&timerMux); // 排他制御終了
// 【削除】 xSemaphoreGiveFromISR(timerSemaphore, NULL); // セマフォを開放
}

void setup() {
pinMode(LED_PIN, OUTPUT); // blink by sec.
// 【削除】 timerSemaphore = xSemaphoreCreateBinary(); // バイナリセマフォを作成
tm0 = timerBegin(0, 80, true); // tm0タイマーをプリスケーラー80に設定
timerAttachInterrupt(tm0, &onTimer, true); // tm0割込み処理ルーチンを onTimeに設定
timerAlarmWrite(tm0, 1000, true); // tm0を1ms周期に設定
// timerAlarmWrite(tm0, 1000040, true); // tm0を1秒周期に設定 (+40は誤差の補正)
timerAlarmEnable(tm0); // tm0開始
}

void loop() {
// 【削除】 if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE) { // セマフォを取得 (=onTimer割込み発生)
if (flag == true) { // 【代替】フラグが立っていたら
portENTER_CRITICAL(&timerMux); // 排他制御で以下を実行
flag = false;
digitalWrite(LED_PIN, flag);
portEXIT_CRITICAL(&timerMux); // 排他制御おしまい
}
}
元のプログラムに対する変更点が判るように、変更前のコードもコメントアウトの形で残しています。loopの中での割り込み有無の判定は、31行目のように flag をポーリングする方式に変更しています。

この状態で走らせてみると、特に問題無く動きました。まあそうでしょうね、昔というか2-3年前はこういう書き方が普通だったみたいなのですから。

で、割り込みの応答時間がどうなったのか、オシロで見ると、

・セマフォを使わない場合の応答波形
セマフォ無し
応答時間は1.7~2.1μsに短縮されていました。(横軸が500ns/Div.に変わっています)。
処理が必要な手続きが減ったので当然でしょう。しかし残念ながらジッタは無くなりませんでした。まあ、これもしょうがないでしょうね。

この例では調査のためにセマフォを使わないで動かしています。特に事情の無い限り、普段はセマフォを使った排他処理を行った方が安全だと思います。

◆まとめ
いろんなことを一つの記事に書いたので判り難くなってしまいました。私が良く判っていないからこうなっちゃうんでしょうね。

この記事の測定結果で重要と思える点は、ESP32でタイマー割り込みを行う場合、処理時間のジッターが0.5μs程度発生するということだと思います。ギリギリのタイミングで動くようにしていると、えらい目に合うかも知れません。

そうなると、このジッターがワーストでどれくらい大きくなるのかが気になります。たぶんRTOSの最大応答時間に関係があるはずなので、どこかに書いてあるはずですが、残念ながら発見できませんでした。

ATmega328のようなCPUでは、回路とコードの実行時間とクロックのタイミングだけ考えていれば良かったのに対し、ESP32ではOSも関係してくるので話はややこしくなるようです。I/Oピンの状態変化に対し、マイクロ秒の単位で正確に応答するシステムは、ESP32だけでは作れない可能性がありそうです。だったら、以前ESP32を使ってオシロを作ろうと考えていて断念したのですが、これは無謀な試みだったのかも知れません。

【追記】
この記事を書いた後で気付いたのですが、ESP32のRTOSについては、Lang-shipさんが「ESP32のFreeRTOS入門」というタイトルで連載の解説記事を書かれていました。
タイマー割り込みについては、下記の記事が参考になります。
ESP32のFreeRTOS入門 その7 タイマー
この記事はその1からその9まであるので時間のある時に読んでみようと思います。というか難しくて付いていけないかも知れません。
カレンダー
05 | 2023/06 | 07
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。
記事の内容のご利用は読者の自己責任でお願いします。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード