motoh's blog

主に趣味の電子工作やプログラミングについて書いていきます

STM32マイコンで簡易オシロスコープを自作 (3) ハードウェア編

1. はじめに

「STM32マイコンで簡易オシロスコープを自作」シリーズの第3回です。

mzmlab.hatenablog.com

mzmlab.hatenablog.com

前回まででオシロスコープのソフトウェアはそこそこ使えるものになりましたが、ハードウェアはブレッドボードで組んでいる状態のため、実用的ではありません。そこで、ここからは実際に使えるものを目指してハードウェアを製作していきます。 具体的には、

  • 基板上にパーツを配置し、手のひらサイズにする。
  • 前回まではマイコンのADコンバータに信号を直接入力していたため、マイコンの電源電圧3.3Vよりも高い電圧を測定できなかった。今回、入力回路を実装することで電源電圧の10倍程度まで測定できるようにする。
  • 前回まではPCのUSBから電源供給していたため単体で持ち運びができなかった。今回、バッテリー駆動を可能にすることで持ち運びできるようにする。
  • ケースに収めることで、さらに持ち運び易くする。(第4回で実施予定)

ということをしていきます。

2. 基板に配置した様子

写真のようにユニバーサル基板(95mm × 72mm)にSTM32 Nucleoボードと液晶パネルを重ねて配置することで、扱いやすいサイズに収めることができました。オシロスコープ用のプローブを取り付けられるようにBNCコネクタを採用しました。バッテリー(9V電池)もスペースに収まっています。

横から見た様子です。液晶パネルがSTM32 Nucleoボードの高さに合うように、ピンソケットを2段重ねにしています(上側のピンソケットは足の長い連結用ピンソケットです)。9V電池をON/OFFするためのスイッチも付いています。

次の写真は、BNCコネクタにBNC-バナナプラグ変換コネクタを介してみの虫クリップを取り付けた様子です。BNCコネクタなのでオシロスコープ用のプローブも取り付け可能です。

3. 入力回路

電子回路は勉強中なので、ここで紹介する入力回路は、個人的に使うには十分な、最低限の入力回路という扱いでお願いします。

入力回路は、過大電圧からマイコンを保護することと入力インピーダンスを増大させることを目的としたバッファ回路と、マイコンの電源電圧3.3Vよりも高い電圧を測定できるようにするための分圧回路で構成しました。 回路図は次の通りです。

※全体の回路図は作成していませんが、前回記事でSTM32 Nucleoボードと液晶パネルのピンアサインを表にまとめています。

3.1. バッファ回路について

バッファ回路はオペアンプを利用します。オペアンプの出力電圧は、オペアンプの駆動電圧を超えることがないため、駆動電圧にマイコンの電源と同じ3.3Vを使用することで、マイコンを過大電圧から保護します(過大電圧でオペアンプが壊れる可能性はありますが、マイコンが壊れるよりは安価な損失で済みます)。3.3Vは、STM32 Nucleoボードの+3.3V端子から取り出せます。

また、オペアンプを取り付けることで入力インピーダンスが数MΩまで増大します。入力インピーダンスが高いほうが、測定対象の内部抵抗(出力インピーダンス)による電圧降下を抑えられるので、正確な測定ができます。

今回の用途では、単電源でレール・ツー・レールのオペアンプが望ましいため、MCP6022を利用しています。

3.2. 分圧回路について

分圧回路は、2つの抵抗R1(100kΩ)とR2(10kΩ)で構成します。この場合、分圧比は、R2 / (R1 + R2) ≒ 0.09 となります。これにより、電源電圧が3.3Vのマイコンならば、36V程度まで測定することができるようになります。

R1を90kΩにすればぴったり1/10になりますが、今回はそういう必要はなかったので手元にあった適当な抵抗を使用しました。

4. バッテリー駆動

Nucleo Board STM32F401は、Vin端子に外部電源7V~12Vを供給できるので、Vin端子に9V電池をつなげられるようにしました。Vin端子に電源供給する場合のジャンパピンの設定は次の通りです。

  • JP5のピン2と3をジャンパキャップでショートする。
  • JP1のジャンパキャップを外す。

Vin端子に電源供給する場合も、PCのUSBから電源供給する場合と同じように+5V端子と+3.3V端子が機能します。+5V端子は液晶パネルへの電源供給に使用し、+3.3V端子はオペアンプの駆動電源として使用しています。

5. おわりに

前回まではブレッドボードで組んでいた回路を基板上に実装することで、手軽に扱えるオシロスコープになりました。しかし、やはり最終的にはケースに収めたいところです。いつになるかはわかりませんが、次回にご期待ください。

⇒ 2022.9.18追記
ケースも作成しました。次の記事で解説しています。

mzmlab.hatenablog.com

STM32マイコンで簡易オシロスコープを自作 (2) タッチパネル編

1. はじめに

「STM32マイコンで簡易オシロスコープを自作」の続編です。TFT液晶モジュール (MSP2807) のタッチパネルを利用してオシロスコープのいろいろな設定を変更できるようにしました。ソースコード(STM32CubeIDEプロジェクト)は前回のGithubリポジトリにコミットしています。 mzmlab.hatenablog.com

youtu.be

2. Githubリポジトリ

ronron-gh/NUCLEO_F401RE_SIMPLE_OSCILLOSCOPE

3. マイコンのピンアサイ

Nucleo Board STM32F401のピンアサインは以下の通りです。
青文字がタッチパネル用に追加した接続です。

■ Nucleo CN5 (digital)

Pin MCU pin Function 用途
D15 PB8 - MSP2807 T_DO
D14 PB9 - MSP2807 T_IRQ
GND - Ground MSP2807 GND
D13 PA5 SPI1_SCK MSP2807 SCK
D12 PA6 SPI1_MISO MSP2807 SDO(MISO)
D11 PA7 SPI1_MOSI MSP2807 SDI(MOSI)
D10 PB6 - MSP2807 CS
D9 PC7 - MSP2807 DC/RS
D8 PA9 - MSP2807 RESET

■ Nucleo CN6 (power)

Pin MCU pin Function 用途
+3V3 - 3.3V output MSP2807 LED (バックライト)
+5V - 5V output MSP2807 VCC

■ Nucleo CN8 (analog)

Pin MCU pin Function 用途
A0 PA0 ADC1_0 入力チャンネル

■ Nucleo CN9

Pin MCU pin Function 用途
D7 PA8 - MSP2807 T_CLK
D6 PB10 TIM2_CH3 テスト用信号(10kHz矩形波)
D5 PB4 TIM3_CH1 -
D4 PB5 - MSP2807 T_CS
D3 PB3 TIM2_CH2 -
D2 PA10 - MSP2807 T_DIN

4. おわりに

GUI系のプログラムはボタン等が増えていくとどんどんコード量が膨れ上がっていくので、C言語ですがオブジェクト指向的に実装して整理しやすいように工夫しました。液晶表示やタッチパネルのプログラミングは実は初めてでしたが、Githubのプログラムは興味がある方はご自由にご利用ください。

STM32マイコンで簡易オシロスコープを自作

1. 概要

電子工作をしていると、デバッグの際にモータ制御信号や通信線の信号をオシロスコープで確認したくなることがあります。簡易的なオシロスコープであれば数千円で買うこともできますが、簡易的なものであれば自分でも作れるのではないかと思い、自作に挑戦してみました。

簡易オシロスコープということで、仕様は次の通りです。

  • チャンネル数 : 1ch (立ち上がりエッジでトリガ可)
  • 周波数帯域 : 40kHz
  • A/D分解能 : 12bit
  • サンプリング周波数 : 200kS/s (※1)
  • レコード長 : 300サンプル
  • 最高入力電圧 : 3.3V (※2)

STM32マイコンの評価ボード Nucleo Board STM32F401の機能だけで上記仕様を実現しています。まだまだ荒削りですがマイコンのソフトウェアをGithubで公開したいと思います(筆者はオシロスコープの専門知識があるわけではないため、クオリティはあまり期待しないでくださいm(__)m )。
次の写真のように、ブレッドボードでソフトウェアの動作を確認できます。液晶モジュールは、ILI9341搭載タッチパネル付TFT液晶 (MSP2807) を使用しています。

youtu.be

※1 自分の用途では200kS/sで十分なのでそのように実装しましたが、ADCの性能的には1MS/s以上にすることも可能かもしれません。

※2 マイコンのADCポートに直接信号を入力しているため、マイコンの電源電圧3.3Vを超える信号は入力できません。本来は入力回路も適切に設計する必要がありますが、そこは追々勉強していきたいと思います...

2. 開発環境

  • 開発用PC ・・・ OS: Windows10 64bit
  • 統合開発環境 ・・・ STM32CubeIDE Version:1.8.0

3. Githubリポジトリ

ronron-gh/NUCLEO_F401RE_SIMPLE_OSCILLOSCOPE

4. マイコンのピンアサイ

4.1. TFT液晶モジュールとの接続

■ Nucleo CN5 (digital)

Pin MCU pin Function TFT液晶 (MSP2807)
GND - Ground GND
D13 PA5 SPI1_SCK SCK
D12 PA6 SPI1_MISO SDO(MISO)
D11 PA7 SPI1_MOSI SDI(MOSI)
D10 PB6 - CS
D9 PC7 - DC/RS
D8 PA9 - RESET

■ Nucleo CN6 (power)

Pin MCU pin Function TFT液晶 (MSP2807)
+3V3 - 3.3V output LED (バックライト)
+5V - 5V output VCC

※バックライトはとりあえず3.3Vに接続していますが、GPIOに接続すればソフトウェアでバックライトをON/OFFできます。

4.2. 入力チャンネル

■ Nucleo CN8 (analog)

Pin MCU pin Function 用途
A0 PA0 ADC1_0 入力チャンネル

4.3. テスト用信号

■ Nucleo CN9

Pin MCU pin Function 用途
D6 PB10 TIM2_CH3 テスト用信号(10kHz矩形波)

5. ソフトウェア設計概要

以下、ソフトウェア設計のポイントになる部分(苦労した部分^^;)について記載します。

5.1. サンプリング機能

5μs (200kHz)の正確な周期でAD変換し、ADデータをメモリ(RAM)に時系列に格納するにはどうすればよいかという問題です。5μs周期の処理はタイマ割り込みを使えば容易に実現できますが、割り込みルーチンの中でAD変換、メモリ格納を行っていては、5μsの内に処理が終わらないかもしれません。

そこで、次の図のように、タイマ、ADC、DMAを連携させて、サンプリングの動作をすべてハードウェアにやらせることにします。すなわち、タイマー割り込みをトリガにしてAD変換を起動し、AD変換終了をトリガにしてDMAでADデータをRAMに転送します。また、DMAをサーキュラモードにすることで、図のように、指定した転送数のメモリ転送を無限に繰り返すことができます(繰り返しにより、先頭データから上書きされていく)。

5.2. トリガ機能

トリガ機能とは、入力信号が閾値を超えたらサンプリング(もしくは画面更新)を停止する機能です。次の図のように、ADCのアナログウォッチドッグ機能(AD変換結果が閾値を超えたら割り込みを発生)とタイマを利用して実現しました。

5.3. グラフ表示機能

サンプリングデータをリアルタイムにTFT液晶モジュール (MSP2807)にグラフ表示します。 ドライバIC (ILI9341) のインタフェースはSPIですが、MSP2807のサンプルプログラムをそのまま使うと、ソフトウェアで1ドットずつRGBデータをSPI送信データレジスタに書き込むため、ディスプレイの更新が非常に遅くなります(ディスプレイが上側から下側に更新されていくのが目で見える程遅いです)。そのため、全体(320x240)のRGBデータを一旦RAM上で作成し、DMAでSPI送信データレジスタに転送するようにして高速化しています。

6. 今後の展望

(1) TFT液晶MSP2807はタッチパネル搭載なので、タッチ操作でいろいろな設定を変更できるようにしたい。
⇒ 2022.06.19 追記
タッチパネルに対応しました。次の記事で解説しています。

mzmlab.hatenablog.com

(2) 入力回路をきちんと設計して、ケースに入れて、本当に使えるものにしたい。
⇒ 2022.08.21 追記
基板上に実装し、入力回路も作成することで実用的になりました。次の記事で解説しています。

mzmlab.hatenablog.com

⇒ 2022.09.18 追記
ケースも作成しました。次の記事で解説しています。 mzmlab.hatenablog.com

micro:bitの各種BLEサービスを試せるAndroidアプリを作ってみた

最近、興味本位でmicro:bitを購入しました。micro:bitは、小さな基板上に温度、加速度、磁力といったセンサを搭載しており、それらセンサ情報をBluetooth Low Energy (BLE)のサービスで他のデバイスに提供することができます。また、UARTサービスを利用すれば、BLE経由でmicro:bitとシリアル通信することができます。今回は、Androidスマートフォンからmicro:bitの各種BLEサービスを試すために作成したアプリを紹介したいと思います。

AndroidアプリのソースはこちらGithubで公開します。本記事の中でソースの解説はしませんが、ソースにはある程度コメントは入れてあります。また、アプリを作成するにあたって参考にさせていただいたサイトを最後に紹介します。

尚、micro:bitのBLEサービスをただ試すだけなら、Google Playで公開されているnRF Connect等のアプリを使った方が簡単です。今回は、自作アプリでmicro:bitと通信できれば、今後おもしろいものが作れるかもしれないと思い、あえて自作にチャレンジしました。BLEの基本的な仕組みについての良い勉強にもなり、micro:bit以外にも応用ができそうです。

動作環境

Android Studio 3.1.4
実機: S7-SH(Android 11)

micro:bit側のプログラム

micro:bitでBLEを使うためには、まずMake Codeのプロジェクトの設定を変更する必要があります。
こちらのサイトでとてもわかりやすく解説されています。
monomonotech.jp

プログラムはお好みで構いませんが、私は次のように作りました。

”最初だけ”のイベントで、利用したいBLEサービスを立ち上げます。

Bluetoothデータを受信したとき”のイベントで、受信したデータをそのまま送り返します(エコーバック)。
受信したことがわかるように、LEDにも受信データを表示します。

接続/切断したことがわかるように、接続/切断それぞれのイベントでLEDにアイコンを表示します。

アプリ仕様

f:id:mzmlab:20220120232740p:plain

f:id:mzmlab:20220120232755p:plain

f:id:mzmlab:20220120232810p:plain

f:id:mzmlab:20220120232821p:plain

f:id:mzmlab:20220120232833p:plain

f:id:mzmlab:20220120232844p:plain

参考にさせていただいたサイト

BLEを使ってAndroidとマイクロビットをつなげるまで(1) | ECF Tech
周辺のBLEデバイスをスキャンしてmicro:bitを見つけるところから、センサの値を取得するところまで丁寧に解説されており、とても参考になりました。

04.BLEデバイスから値を読み込む処理を作る
先にご紹介したサイトは、Notificationモード(micro:bitから一定周期でセンサデータを通知するモード)を利用していますが、Androidアプリから要求したとき(ボタンを押したとき)だけmicro:bitからセンサデータが返信されるようにする場合の処理はこちらを参考にしています。

06.BLEデバイスへ値を書き込む処理を作る
micro:bitのUARTサービスに文字列を送信する処理は、こちらを参考にしています。

ハマりかけたこと

初めの頃、デバイススキャンでmicro:bitを発見しサービスを取得したときに、温度計サービスや加速度計サービスが取得できない事象が発生しました(その他のデフォルトで立ち上がるサービス(Generic Access 等)は取得できる)。既成アプリのnRF Connectを使っても同じ事象だったので、私のスマホ固有の事象かもしれないと諦めかけましたが、ダメ元でスマホmicro:bitのペアリング(A、Bボタンとリセットボタンを同時に押すやつ)を実行してから再トライすると、無事に温度計サービスや加速度計サービスを取得できました。その後は、ペアリングしなくても問題なくサービスを取得できています。ペアリングはその時が初めてではなかったので、本当にそのおかげで解決したのかは不明です・・・

マイコン&距離センサでプラレールの自動ブレーキ制御

2歳の子どもが遊ぶプラレールが、しばしば前方車両や壁に衝突するのをみて(そもそも対象年齢じゃないのですが^^;)、自動で減速するように改造できないかと思っていたところに以下の記事を発見。電子工作は経験が浅いのですが、自分でもトライしてみました。

tandh.work

製作物紹介(使用部品、回路図)

先の記事の例に倣って先頭車両の単2電池の代わりに単4電池2本と電子回路を収めました。マイコンは手元にあったATtiny2313、赤外線距離センサは最大10cmまで計測可能なVL6180Xを搭載したセンサモジュールを選びました。マイコンと距離センサはI2Cで接続します。電源はDC-DCコンバータで電池の3V(充電式なら2.4V)を3.3Vに昇圧してマイコンとセンサに供給し、モータードライバICには電池から直接供給します。

 

f:id:mzmlab:20210718084102j:plain

少しわかりづらいですが、フロントのセンサ部分をくり抜いています。

 

f:id:mzmlab:20210718084156j:plain

基板1枚には収まらなかったため、マイコンの上側にモータドライバICをスタックしています。

ATtiny2313はプログラム書き込み用のポートとI2Cポートが共用になっているため、距離センサはコネクタで取り外しできるようにしました。

 

回路図です。 

f:id:mzmlab:20210718084308p:plain

動画

youtu.be

動いている様子です。前方車両との接近を検出して減速しています(動画の後半は制御が間に合わず衝突してしまっているので、ソフトは改善の余地がありそうです)。なお、PWM制御により、モータにかかる電圧は1.5Vに制限しています。制限を外せばMAX 3Vまで上げられるので、カーブで脱線するくらい高速で走ることもできます(※モータの定格を超えるので壊れるかもしれません)。

 

以下のような応用も楽しそうですね。

・せっかくHブリッジなので、壁を検出するなどしたら後進させてみる。

・距離センサVL6180Xは環境光も測れるので、部屋が暗くなったらLEDを点灯する。

Bluetoothモジュールを搭載してスマホアプリから遠隔操縦できるようにする。

 

苦労したこと

・単2電池のスペースはそこそこ広く見えますが、実際やってみると電池ボックスと回路を収めるのにとても苦労しました。高さがぎりぎりで、部品を出来る限り低く付けたり電池ボックスの底を削ったりしてなんとか収めました。

 

・単4電池2本(3V)ですべての電源を賄うのも、初めてだったので少し迷走しました。最初に選定したモータドライバICTB67H450FNG)が4.5V以上でないと動作しないことに後で気付き、低電圧動作するNJU7386を選びなおしました。

 

・ATtiny2313フラッシュメモリ2Kバイト、RAM 128バイトという制限が、これまた思いの外厳しいです。デバッグ用のコードをいろいろ入れたせいでもありますが、すでにフラッシュメモリのプログラム領域は97%を使用しています。RAMも小さいため、スタックのサイズに気を付けないと、関数を入れ子にしたり割り込みをかけたりしたときにプログラムが暴走しました。もし同じことをしてみたいという方がいらっしゃれば、もう少し高スペックなマイコンを選んでもよいかもしれません。

 

このように思いの外苦労したので、2歳の怪獣に壊されるのが惜しくなってきました()。見せてあげるのはもう少し対象年齢に近づいてからにしたいと思います…

 

参考情報

ATtiny2313の開発環境構築

こちらで一通り解説してくださっており、迷わずプログラム書き込みまでできました。

なお、開発環境Microchip Studioは新しくなっているのでこちらを参考にダウンロード、インストールしました。

なお、今回はFuseは出荷時のままで問題ありません。間違って書き換えると動作しなくなったりするのでご注意ください。

 

ATtiny2313I2C Masterの実装

ATtiny2313SCLSDAのポートがありますが、ハードウェアは最低限の機能しかなく、ソフトウェアでI2Cを実装する必要があります(自分も作りながら気付きました...)。ネットでいろいろ調べてみると、本家のサンプルコードがあったのでこちらを利用しました。

アプリケーションノート

サンプルコード

サンプルコードはサイト内で”I2C”で検索して出てくる”AVR310 USI as I2C master”をダウンロードし、その中のUSI_TWI_Master.cUSI_TWI_Master.hを自分のプロジェクトに追加すると使えました。