ESP32とTFTタッチスクリーンLCDで2CH WEBオシロスコープ・Pulse generator・Function Generator

更新日 2026.10.20 登録日 2023.09.14
*

大阪教育大学の光永さんの Arduino でオシロスコープ を基にESP32に移植し、320x240のタッチパネル付き2.8インチLCDで使えるように変更して、WEB表示機能を追加しました。まだ不完全ですがPCやスマートフォンの大きな画面で波形を確認できます。 基本的に ESP32で2CH WEBオシロスコープ・Pulse generator・Function Generator のLCD版です。

まだ基本的に波形が表示できるようにしただけなので、ユーザーインターフェースのためにLCD表示とタクトスイッチは残してあります。出来ればWEB画面に操作コントロールを追加してLCDとタクトスイッチ無しで設定変更できるようにしたいと思っています。

波形データの送信にはWebSocketを使いました。WebSocketの通信は手抜きでEndian処理をしていません。そのためBig EndianのCPUでは正しく波形が表示できません。いまどきそんなCPUは少ないと思いますしPentiumやARM系のAndroidであれば使えますので大丈夫でしょう。波形の描画にはHTML5のCanvasを使っています。オシロスコープ機能はマルチコアのCORE1で処理し、WiFi機能はCORE0で処理するようにしています。

画面が大きくなって振幅方向の分解能が増えたためにADCの非線形性が目立つようになったので、簡単に2区間の直線近似で補正を加えました。ESP32の個体毎に微調整が必要かもしれません。サンプル数は300ポイントです。

開発環境は Arduino IDE 1.8.19 + Arduino core for the ESP32 2.0.3 ESP32 3.3.12です。
ESP32 2.0.3 から 3.0.0になってからtimerAlarmとledcの関数呼び出しが変更になってコンパイルできなくなって放置していました。こういう変更がよくあるのでESP32からはしばらく遠ざかっていましたが、思い立ってVersion1.10からESP32 3.3.5に対応しました。 Version1.09以前のソースをコンパイルする場合にはESP32 2.0.17まで戻す必要があります。 (2026.01.13 update)

この環境ではAnalogRead()が使えるのですがオーバーヘッドが多過ぎるようで遅いので、adc1_get_raw()とadc2_get_raw()を使うようにしました。それでもまだ遅いです。 I2Sを使って500kspsまで出来るようにしてみました。
書き忘れましたが、その後ADCの実力に合わせて250kspsまでに変更しました。(追記 2026.08.09)

時間軸拡大機能を追加しました。10us/divは250kspsの10倍拡大、20us/divは5倍拡大になります。拡大にはsin(x)/xによる補間をしています。(2024.03.13 update)

OLED版でADCのContinuous Modeを使うようにしたので、v1.12からI2Sを使うのはやめてContinuous Modeを使うようにしてI2S使用時よりも安定しました。2チャンネルが使えるサンプリングレートも向上しました。

v1.13から周波数カウンターを組み込みました。(2026.08.26 追記)

ソースコード

最新版はGitHubに置いてあります
https://github.com/siliconvalley4066/ESP32TFTOscilloscope

ESP32TFTGOscillo115.zip 2026.10.20 update for ESP32 3.3.12

ESP32TFTGOscillo109.zip 2024.03.13 update for ESP32 2.0.3

TFT LCDのライブラリはTFT_eSPIを使用します。Arduino IDEのライブラリマネージャーから検索してインストールしてカスタマイズする必要があります。 GitHubのhttps://github.com/siliconvalley4066/ESP32TFTOscilloscopeを参照してください。

WebTask.inoの
const char* ssid = "XXXX";
const char* pass = "YYYY";
に使用するWiFiアクセスポイントのssidとpasswordをXXXXとYYYYに記入する必要があります。ソースコードを少し変更すればAPモードにすることも可能です。
(削除 2026/10/20)

v1.15からWiFiマネージャーを採用しました。 初期設定を行う際は、「ESP32_XXXXXXXX」(「XXXXXXXX」は固有のチップID)という名称のアクセスポイントに接続し、ブラウザで「192.168.4.1」にアクセスしてください。その後、接続先となるWiFiネットワークのSSIDとパスワードを入力します。一度設定が完了すれば、それ以降の設定は不要です。設定を変更したい場合は、デバイスの起動時に「DOWN」ボタンを長押ししてください。 (追記 2026/10/20)

WebSocketsのライブラリはライブラリマネージャーから検索できるものではなく、以下を使いました。
Links2004/arduinoWebSockets

WebSocketsのライブラリはライブラリマネージャーから検索できるものを使いました。 (2026.01.13 update)
WebSockets by Markus Sattler version 2.7.2

回路図

10:1プローブを使うために入力インピーダンスを1Mohmに近付けたいので次のような入力回路にしました。OLEDは使わないので配線する必要はありません。
*

WEB表示機能だけを簡単に試すならADC入力のIO34とIO35に直列に10kohm程度の抵抗を付けるだけでも動作出来ます。ただしDCモードだけになります。現状ではPulse GeneratorやDDSの周波数を設定出来なくなります。
*

操作方法

先ず起動する前にArduino IDEのシリアルモニターを開いておきます。プログラムが開始してWiFiアクセスポイントに接続成功したらIPアドレスを取得してシリアルモニタに表示します。そのIPアドレスをWebブラウザのアドレスバーに入力すればWEBオシロに接続できるはずです。
例えばシリアルモニタに、
WiFi Connected. IP = 192.168.1.128
と表示されたら、Webブラウザのアドレスバーに192.168.1.128と入力します。

LCDのタッチパネルで操作出来ます。また、タクトスイッチで画面上の項目を選択して操作することもできます。WEB表示では画面右側のコントロールで操作できます。ただし、タッチパネルやタクトスイッチで変更した内容はWEB表示の波形には反映されますが、設定値の表示はリロードするまで反映されません。

タクトスイッチでの操作方法は、UpボタンとDownボタンでメニュー内の項目を移動します。それぞれの項目の位置でRightボタンかLeftボタンを押すとその項目の値を変更したりOn/Offの切り替えをします。

  • CH1をタップすると上下正転表示->上下反転表示->非表示->上下正転表示と切り替わります。上下反転時はアンダースコア"_"を表示します。AC入力の時は"~"を表示します。
  • CH2をタップすると上下正転表示->上下反転表示->非表示->上下正転表示と切り替わります。上下反転時はアンダースコア"_"を表示します。AC入力の時は"~"を表示します。
  • 電圧レンジをタップすると色がCyanになり、画面の右半分をタップするとレンジが上がり、左半分をタップすると下がります。
  • 時間軸レンジをタップすると色がCyanになり、画面の右半分をタップするとレンジが上がり、左半分をタップすると下がります。
  • 時間軸の拡大は時間軸レンジがハイライトされてCyanになっている状態で時間軸レンジをタップすると、x1 -> x2 -> x5 -> x10 -> x1 と順に変化します。拡大時にはその右側に倍率を表示します。(2026.07.28 update)
  • 時間軸の拡大時には画面下に拡大位置を示すスクロールバーを表示します。拡大位置の変更にはそのスクロールバーではなく、波形表示エリアをタップした水平位置で指定します。タップしたまま水平位置をずらせばスクロールバーをドラッグしている感覚になります。(2026.07.28 update)
  • トリガレベルは画面右端のレベル表示エリアをタップすることで変更できます。
  • VPOSは通常Gray表示ですが、タップするとPOS1->POS2->VPOSと順に変化します。画面の右半分か左半分をタップすることで上下できます。画面の左右中央をタップすると標準の位置にリセットします。DC時は最下端、AC時は中央になります。
  • TG1が表示されている時はCH1をトリガソースにします。タップするとTG2が表示されてCH2をトリガソースにします。
  • "/"かバックスラッシュが表示されているトリガエッジをタップすると、上下の切り替えが出来ます。
  • トリガモードはタップする度にAuto->Norm->Scan->One->Autoと切り替わります。Oneの場合は右上に赤字でHALTと表示します。画面をタップすると1回ずつトリガが掛かります。他のトリガモードでは画面をタップするとトリガを停止し、再度タップすると再開します。
  • "FUNC"をタップすると外面下側のメニューが切り替わり、"FFT", "PWM", "DDS", "DISP", "FCNT"が選択できます。
  • "FFT"はFFT表示に切り替わります。グラフ表示部分をタップすると元に戻ります。
  • "PWM"はPWM設定に切り替わります。"ON"をタップすると"OFF"に、"OFF"をタップすると"ON"になります。周波数またはデューティー比をタップすると変更モードになります。画面右半分をタップすると増加、左半分をタップすると減少します。
  • "DDS"はDDS設定に切り替わります。"ON"をタップすると"OFF"に、"OFF"をタップすると"ON"になります。波形種類または周波数をタップすると変更モードになります。画面右半分をタップすると増加、左半分をタップすると減少します。
  • "DISP"は文字表示設定に切り替わります。"FREQ"または"VOLT"をタップするとそれぞれCH1のみ、CH2のみ、両方、非表示に切り替わります。"LARG"をタップすると大きいフォントで表示、"SMAL"をタップすると小さいフォントで表示します。"OFF"をタップすると文字表示なしになります。
  • "FCNT"をタップすると周波数カウンタを起動して周波数を表示します。もう一度"FCNT"をタップすると元に戻ります。
  • (2026.10.02 update)

    Pulse Generatorについて

    LEDCのPWMで発生できるパルスをほぼ全て出せるようにしました。周波数自体を設定するのではなく、発生できる上または下の周波数へ設定を変更して、その設定で発生される周波数を計算して表示します。Duty cycleも実現可能な値が限られている。

    v1.13まではLEDCに関しての認識が間違っていたのが分かってv1.14で設定方法を修正しました。
    80MHzを1/1から1/1023まで分周することと、Resolutionを1bitから17bitまで使うことで1Hzから40MHzまでを発生出来ます。
    高い方の周波数はResolution=1bitで1/1, 1/3, 1/4 ... 1/1023と変化させて小数点以下を使わずになるべく細かく周波数を設定できるようにしましたが、dutyは50%固定になります。
    低い方の周波数はResolution=17bitで1/512から1/611まで変化させて最低0.9989Hzになります。 もっと低い周波数にも出来ますが、そもそもAruduino用のライブラリは整数でしか周波数を設定できないので無理して想定外の設定をして余計なトラブルに遭遇するのは避けたいと思います。ESP32-C3での最低周波数はResolution=14bitで1/1023になって4.773Hzになります。
    このような設定を実現するためにより低レベルのledc_ll_set_duty_resolution()やledc_hal_set_clock_divider()というライブラリを使っています。周波数カウンタでもLEDCを使っていて時々相互干渉してリブートすることがあります。なるべく干渉が無いように対策をしていますが完全には解消できていません。 (2026.10.02 update)

    DDS Function Generatorについて

    ESP32とOLEDで2CHオシロスコープ・Pulse generator・Function Generatorと同じです。

    【廃止】I2S(Inter-IC Sound) ADCサンプリングについて

    ESP32で2CH WEBオシロスコープ・Pulse generator・Function Generatorと同じです。(変更 2026.08.09)

    Continuous Mode ADCサンプリングについて

    ESP32で2CH WEBオシロスコープ・Pulse generator・Function Generatorと同じです。(追記 2026.08.09)

    周波数カウンターについて

    (追記 2026.08.26)。ESP32で周波数カウンター で作ったものを組み込みました。PCNTをLEDCのパルスでゲートして正確に計測できるものです。ESP32-C3では使えません。ゲート時間は約1秒です。
    LCDメニューのFUNCからFCNTを押すと開始します。再度押すと終了します。
    計測中にさらにFCNTを押すと較正機能が働きます。 基準周波数の30MHz, 25MHz, 24MHz, 20MHz, 16MHz, 12MHz, 10MHz, 8MHz, 6MHz, 5MHz, 4MHz, 3MHz, 2MHz, 1MHz, 100kHz, 32768Hzと50ppm以内の誤差ならば自動的に補正して補正値を保存するようにしています。
    WEB用のGUIは作っていません。

    周波数カウンターは時々起動に失敗して "Guru meditation Error" になってリブートすることが有ります。原因は分かりません。パルスジェネレーターの起動でも不安が有ります。ネット上ではESP32ボード3.3.2になってからLEDC関係で起きやすくなったと言っている人がいます。 暫定的にledcWrite()の前に2秒間delayを入れて発生頻度を抑えています。

    Known Bugs

  • 時々勝手にリブートする。特にI2Sモードとダイレクトサンプリングモードが切り替わるときにウォッチドッグタイマーに引っかかってリブートしやすい。
  • 波形表示が所々途切れることがある。
  • ESP32のADCの直線性が悪く、特に0V近辺と3.3V近辺がつぶれている。
  • 原理的に周波数測定には画面上で2周期以上が必要。
  • 周波数測定と電圧測定はCH1のみ。CH2のみ表示でもCH1の測定値が出る。v1.08からCH2も測定できるようにした。 2023.11.23 update
  • トリガモードのOneがうまく機能しない。
  • トリガが掛からない状態でトリガモードをNormにすると、トリガ検出から抜け出せなくなり操作不能になる。トリガが掛かる入力を入れれば復帰する。
  • 2ch表示で信号源インピーダンスが大きい場合は相互に観測波形に影響が出る。入力インピーダンスが下がるのを許容して入力回路の抵抗値2Mohmを200kohm以下に下げれば軽減できると思う。
  • 2ch間でレベル差が大きい部分には相互干渉が発生することがある。
  • ADC入力の保護抵抗を省略したのでESP32が壊れやすい。直列に1kohmから10kohmの抵抗を入れておいた方が良い。
  • Pulse generatorは周辺クロックをRate Multiplierで分周していて256/256から129/256の周波数を発生する。周波数の高い方でも一見細かく設定できているように見えるがジッターが多い。その後設定方法を変更して整数分の1だけを使うようにしてジッターは減っている。 2026.10.02 update
  • これ単体で2チャンネル入力にPulse generatorとFunction Generatorの出力を入れて波形観測して遊べます。
  • 2ms/divレンジで2ch表示できるが、サンプリングが間に合っていない。片側だけの表示なら間に合う。Continuous Modeに変更して解消した。(追記 2026.08.09)
  • Pulse generatorの周波数が微妙にずれている。設定方法を変更して解消した。 2026.10.02 update
  • Cosine Wave Generatorの周波数が微妙にずれている。
  • HOLD波形の時間軸の拡大は出来ません。(2026.07.28 追記)
  • 条件によっては周波数カウンターは起動に失敗して "Guru meditation Error" になってリブートすることが有ります。(2026.08.26 追記)
  • 改良可能性

  • 取り込みサンプル数を増やして表示位置を移動できるようにしてみたい。
  • 時間軸拡大表示。
  • Hold Off調整機能を入れた方が便利かもしれない。
  • 機能概要

    機能 内容
    入力チャンネル数 2
    入力結合 DC and AC
    入力電圧範囲 0 to 3.3V
    入力インピーダンス 1Mohm
    電圧レンジ(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,
    (DMA) 2ms, 1ms, 500us, 200us, (samples only 1 channel) 100us, 50us, 20us, 10us (250ksps)
    トリガモード Auto, Normal, Scan, Once
    トリガ極性 rise/fall edge
    トリガソース CH1 or CH2
    トリガレベル調整 画面内位置を上下に調整
    外部トリガ No
    波形位置調整 上下に調整可能
    波形反転表示 Yes
    電圧測定表示 Max, Average, Min (AC入力でもDCレベルを表示)
    周波数&Duty測定 Yes
    電圧・周波数・Duty表示 表示・非表示切り替え
    文字表示 文字サイズ固定
    FFT Yes
    A/D変換分解能 12bits
    サンプル数 300samples/channel 12bit/sampleを電圧レンジに応じて0から200又は400にスケーリングして表示
    表示解像度 LCD: 300x200 dots, 水平25dots/div 垂直25dots/div
    WEB: 300x400 dots, 水平25dots/div 垂直50dots/div
    等価時間サンプリング No
    設定状態EEPROM保存 Yes
    操作方法 タッチパネル及びタクトスイッチ4個 (Left, Right, Down, Up) または 5方向スイッチ (Left, Right, Down, Up)
    プリトリガー No
    ホールドオフ機能 No
    時間軸拡大表示 x2 (50us/div), x5 (20us/div), x10 (10us/div) sin(x)/x補間
    X-Y表示 No
    Pulse Generator 1Hz to 40MHz 約3.3Vpp方形波 Duty ratio可変
    Function Generator 8bit DAC DDS 0.01Hz to 518.79Hz(実用は200Hzまで) 約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
    8bit DAC Cosine Wave Generator 129.70Hzから129.70Hzステップで200kHz程度まで。
    周波数カウンタ ゲート方式 1Hz - 32MHz (Max 40MHz)
    PCへのデータ転送 No
    SDカードへの波形保存 No


    <=Arduinoで電子工作に戻る
    <=Siliconvalley4066番地に戻る
    ゲストブックへ
    siliconvalley4066@yahoo.co.jp