以前
ESP32で2CH WEBオシロスコープ・Pulse generator・Function Generator
を作りましたが、コンパクトなESP32-C3 Super Miniでも使えるようにしました。
ただし現状ではDMAを使ったADCが出来ないのでサンプリング周波数の上限が20kspsに少し届かないくらい
DMAを使ってもサンプリング周波数の上限が83kspsなのであまりお勧めできない仕上がりになっています(2026.08.02 修正)。
シングルコアのESP32-C3でも何とかWEBオシロスコープとして動いていますが若干不安定です。
まだ不完全ですがPCやスマートフォンの大きな画面で波形を確認できますので、サンプリング周波数が遅くてもよいから使ってみたいという方はお試しください。
ソースコードは「ESP32で2CH WEBオシロスコープ」と一本化できたのですが、性能に違いがあり過ぎるのでこの別ページで紹介します。
開発環境は Arduino IDE 2.3.10 + esp32 by Espressif Systems 3.3.12です。 (2026.10.03 update)
この環境ではAnalogRead()が使えるのですがオーバーヘッドが多過ぎるようで遅いので、adc1_get_raw()を使うようにしました。それでもまだ遅いです。 無印ESP32はI2Sを使って500kspsまで出来るようにしましたが、ESP32-C3はI2Sが有るもののADCとの接続が有りません。DMAを使うContinuous Modeが使えるはずなのですが、Arduino環境ではコンパイルが通っても壊れたデータしかが出て来ません。ESP-IDF v4.4+なら動くらしいのでArduino環境が対応するのを待つしかありません。
(2026.08.02 追記)あれこれ試しているうちにDMAを使うContinuous Modeが使えるようになりました。設定の仕方が悪かったのか、esp32 by Espressif Systems 3.3.11になって良くなったのか分かりません。それでもサンプリング周波数の上限は83.333kspsとあまり高くはありません。
最新版はGitHubのESP32OLEDOscilloscopeに置いてあるものが使えます。
https://github.com/siliconvalley4066/ESP32OLEDOscilloscope
ESP32WebOscillo143.zip (2026.10.20 update)
ボードは"Nologo ESP32C3 Super Mini"を選択します。
USB CDC On Bootは何故か"Enabled"が二つあって"Disabled"が無いのですが"Enabled"であればシリアルモニターが使えます。
OLEDは小さくても良いので0.96インチにして、ドライバはSSD1306用です。Adafruit_SSD1306.hがインストールされていない場合はライブラリマネージャーから検索してインストールしてください。写真はAliExpressで購入したOLEDとスイッチ4個が一体になったモジュールを使いました。SH1106用にするには#define DISPLAY_IS_SSD1306の行をコメントにしてAdafruit_SH110Xをライブラリマネージャーから検索してインストールすればOKです。
WebTask.inoの (削除 2026/10/20)
const char* ssid = "XXXX";
const char* pass = "YYYY";
に使用するWiFiアクセスポイントのssidとpasswordをXXXXとYYYYに記入する必要があります。ソースコードを少し変更すればAPモードにすることも可能です。
v1.43からWiFiマネージャーを採用しました。 初期設定を行う際は、「ESP32_XXXXXXXX」(「XXXXXXXX」は固有のチップID)という名称のアクセスポイントに接続し、ブラウザで「192.168.4.1」にアクセスしてください。その後、接続先となるWiFiネットワークのSSIDとパスワードを入力します。一度設定が完了すれば、それ以降の設定は不要です。設定を変更したい場合は、デバイスの起動時に「DOWN」ボタンを長押ししてください。 (追記 2026/10/20)
WebSocketsのライブラリはライブラリマネージャーから検索できるものを使いました。
WebSockets by Markus Sattler version 2.7.2
余計な電波を出したくないとか消費電力を減らしたいとか技適が無いので怖いとかでWEB機能が不要な場合は
//#define NOWEBのコメントを外せば無効に出来ます。
使用ライブラリ: (追記 2026/10/20)
ADC_ATTEN_DB_12にしても2.9V辺りでAD変換の値が4095になるので3.3Vまで観測できるように入力にアッテネータを入れました。抵抗値は現物合わせで調整してください。
DCモードだけにして簡単にすることができます。
LEDCのPWMで発生できるパルスをほぼ全て出せるようにしました。80MHzを1/2から1/16384まで設定できます。分周比は1/1から1/256まで全て使います。発生できる周波数は19.07Hzから40MHzまでになります。周波数自体を設定するのではなく、発生できる上または下の周波数へ設定を変更して、その設定で発生される周波数を計算して表示します。Duty cycleも実現可能な値が限られている。周波数の分解能は1/256になり、ATMEGA版より荒くなります。なお、分周器がRate Multiplierなのでジッターが発生する可能性があります。
v1.41まではLEDCに関しての認識が間違っていたのが分かってv1.42で設定方法を修正しました。
80MHzを1/1から1/1023まで分周することと、Resolutionを1bitから14bitまで使うことで4.773Hzから40MHzまでを発生出来ます。
高い方の周波数はResolution=1bitで1/1, 1/3, 1/4 ... 1/1023と変化させて小数点以下を使わずになるべく細かく周波数を設定できるようにしましたが、dutyは50%固定になります。
低い方の周波数はResolution=14bitで1/512から1/1023まで変化させて最低4.773Hzになります。
このような設定を実現するためにより低レベルのledc_ll_set_duty_resolution()やledc_hal_set_clock_divider()というライブラリを使っています。周波数カウンタでもLEDCを使っていて時々相互干渉してリブートすることがあります。なるべく干渉が無いように対策をしていますが完全には解消できていません。 (2026.10.03 update)
ESP32-C3にはDACが有りません。その代わりにPWMを使っても良いのですがSigma-Delta変換を使いました。
波形の発生原理には Arduino Sinewave Generator を流用させていただきました。波形データはその他色々な所から集めました。周波数の設定と波形の選択だけがオリジナルです。周波数の分解能は取り敢えず0.01Hzにしました。インタラプト処理が入るので速いサンプリング時にオシロスコープの波形が間延びするようなら明示的にOFFにした方が良い。インタラプトのオーバーヘッドが大きいようで、サンプリング周波数が5kHzまでしか上げられませんでした。ATMEGA版の31kHzより遥かに低い周波数です。メモリに余裕があるので用意した23波形すべてを使えます。
ESP32-C3にはCosine Wave Generatorが無いので波形発生はSigma-Delta変換だけで、0.01Hzから999.99Hzまで指定できます。波形テーブルをフルに使うのは19.5Hz以下ですが、実用的な上限は1周期50サンプルで良ければ100Hz程度です。
Sigma-Delta変換の矩形波"rect256"で時々中間レベルが出てしまいますが原因不明です。
DMAを使うContinuous Modeが使えるはずなのですが、Arduino環境ではコンパイルが通っても壊れたデータしかが出て来ません。ESP-IDF v4.4+なら動くらしいのでArduino環境が対応するのを待つしかありません。(2026.08.02 削除)
(2026.08.02 追記)DMAを使うContinuous Modeを使います。それでもサンプリング周波数の上限は83.333kspsとあまり高くはありません。50ksps以上はシングルチャンネル、40kspsから10ksps迄はデュアルチャンネルで動作させます。
ESP32-C3も無印ESP32と同じようにADCの直線性が悪く、特に3.3V近辺がつぶれています。 その曲がり具合も違っていたので2区間の直線近似の補正値を変更しました。
| 機能 | 内容 |
|---|---|
| 入力チャンネル数 | 2 |
| 入力結合 | DC and AC |
| 入力電圧範囲 | 0 to 3.3V |
| 入力インピーダンス | 125kohm |
| 電圧レンジ(volts/div) | 1V, 0.5V, 0.2V, 0.1V, 50mV |
| 時間レンジ(time/div) | 10s, 5s, 2s, 1s, 0.5s, 0.2s, 0.1s, 50ms, 20ms, 10ms, 5ms, 2ms (5ksps),
(DMA) 1ms, 500us, 250us, (samples only 1 channel) 200us, 120us |
| トリガモード | Auto, Normal, Scan |
| トリガ極性 | rise/fall edge |
| トリガソース | CH1 or CH2 |
| トリガレベル調整 | 画面内位置を上下に調整 |
| 外部トリガ | No |
| 波形位置調整 | 上下に調整可能 |
| 波形反転表示 | Yes |
| 電圧測定表示 | Max, Average, Min (AC入力でもDCレベルを表示) |
| 周波数&Duty測定 | Yes |
| 電圧・周波数・Duty表示 | 表示・非表示切り替え |
| 文字表示 | 文字サイズ固定 |
| FFT | Yes |
| A/D変換分解能 | 12bits |
| サンプル数 | 128samples/channel 12bit/sampleを電圧レンジに応じて0から400にスケーリングして表示 |
| 表示解像度 | 128x400 dots, 水平10dots/div 垂直50dots/div |
| 等価時間サンプリング | No |
| 設定状態EEPROM保存 | Yes |
| 操作方法 | タクトスイッチ4個 (Left, Right, Down, Up) または 5方向スイッチ (Left, Right, Down, Up) |
| プリトリガー | No |
| ホールドオフ機能 | No |
| 時間軸拡大表示 | x2, x5, x10 sin(x)/x補間 |
| X-Y表示 | No |
| Pulse Generator | 4.773Hz to 40MHz 約3.3Vpp方形波 Duty ratio可変 |
| Function Generator | 8bit Sigma-Delta DDS 0.01Hz to 999.99Hz(実用は100Hzまで) 約3.3Vpp
23波形 sine, saw, revsaw, triangle, rectangle, 20% pulse, 10% pulse, 5% pulse, 1dot pulse, noise, gaussian noise, ECG, sinc5, sinc10, sinc20, sine 2 harmonic, sine 3 harmonic, chopped sine, sine abs, trapezoid, step2, step4, chainsaw |
| 周波数カウンタ | No |
| PCへのデータ転送 | No |
| SDカードへの波形保存 | No |
Arduinoで電子工作に戻る
Siliconvalley4066番地に戻る