STM32マイコンでアナログ入力(3)2020/11/26
ADCのDMA転送モードを試してみた
アナログ入力が少ない場合はあまり問題になりませんが、例えば複数のセンサを取り込んでデジタル処理する場合、順番に読み出しを行う方法では効率がよくありません。
このような複数の入力(マルチチャネル)の場合はDMA転送を行うと処理がすっきりします。STM32F334のADCコントローラにはDMA転送のモードがありますので今回はこれを試してみます。
また、単にDMAモードにするだけでは面白くないので、もういっちょう光センサ(CdSセル)をアナログ入力につっこんでみたいと思います。
準備するもの
まずNucleoボードに光センサを接続します。前々回、前回から追加で必要なものを列挙します。
- CdSセル(仕様不明)
- 抵抗(10KΩ)
- クリップ付きジャンパー線
CdSセルはご覧のような形をしており、光の量に応じて抵抗値が変わる素子です。この素子と抵抗で分圧したものをアナログ端子に入力します。回路図としてはこんな感じになります。
PA0は前回使いましたので、今回はPA1を使用します。仕組みとしてはCdSセルに当たる光の量によって抵抗値が変化し、3.3Vが分圧されPA1の電圧が変化します。
各パーツを接続する
CdSセルと抵抗を直接Arduinoのコネクタに差し込みます。結線が必要なところはクリップケーブルで接続しました。
ちょっと写真ではごちゃついて分かりにくいですが、これでちゃんと回路図通りに結線されています。それではソフトウェアの作業に移ります。
再びSTM32CubeIDEでADCを設定する
STM32CubeIDEを起動して、ADCの入力追加とDMAの設定を行います。左のツリーから「adc.ioc」をダブルクリックします。
Device Configuration Toolが開きますので、ADC1をクリックしIN2の設定を「IN2 Single-ended」に変更します。
ここで、IN2の色が黄色になっています。何か警告色のようですが、マウスポインタを持っていくと、画面のようにUSARTとコンフリクトしているようです。
詳しくは分かっていませんが、たぶん同時に使用できないモードなのだと思いますのでUSART2を禁止します。「Connectivity」を開いて「USART2」をクリックし、Modeを「Disable」にします。
再びIN2を見てみますと、まだ黄色のままです。これはどうやら「Differential」に設定したときの警告のようですので無視します。
次はADCの下側のタブにある「DMA Settings」の設定を行います。と言いますのは、ADC側のDMA転送を有効にしようと思ったときに、こちらの設定をまず行わないと変更できなかったためです。「DMA Settings」のタブをクリックして、「Add」ボタンを押します。
DMA Requestを「ADC1」に設定し、DMAの転送先をリングバッファにするため、Modeを「Circular」に設定します。
次は「Parameter Settings」のタブをクリックしてADCの設定を行います。まず、DMA転送を有効するために「DMA Continuous Requests」を「Enable」に設定します。
前回と同様にIN2を有効にすることで「Rank 3」の設定が追加されていますので、変換数を「Number Of Conversion」で3に設定します。次にRank 3の設定では「Channel」と「Sampling Time」をそれぞれ「Channel 2」と「601.5 Cycles」に変更します。
これで一通りの設定は終わりです。保存すればコードジェネレーターで、新たな設定がソースコードに反映されます。
DMAでの値の読み出し
次はADCの読み出し部分を変更します。ソースコードは以下のようになります。
むちゃくちゃシンプルになりました。DMAはバッファを用意しておけば、スタートさせるだけで変換を自動的に繰り返しやってくれます。
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)gu_dma, 3); AD変換を開始し、値を指定バッファに指定個数分DMA転送します。
バッファとして「gu_dma」を配列宣言しています。この変数の要素の0、1、2にそれぞれ、内蔵温度センサ、PA0、PA1の値が格納されます。ですので、値の読み出しは、
gu_temp = gu_dma[0]; gu_ain0 = gu_dma[1]; gu_ain1 = gu_dma[2];
でOKです。それでは、これをビルドしてリアルタイムモニタで確認してみます。
リアルタイムモニタで確認する
前回と同様にPALMiCE4を起動し、リアルタイムモニタのウィンドウから、追加ボタンを押して「gu_ain1」を登録します。設定は前回と同じです。
プログラムを実行してみましょう。下の赤い線が可変抵抗器によるアナログ入力で、真ん中が内蔵温度センサ、上の緑の線が今回追加したCdSセルによるものです。CdSセルの値は何もしなくても若干のばらつきがあるようです。
CdSセルを手で覆い隠すと、抵抗値が上がって電圧変化が起こります。同時に可変抵抗器も変化させてみました。
にぎやかです。グラフが思い通りに反応していますので、ADCのDMA転送はうまく行ったようです。CdSセルは反応が分かりやすいのでやってみるとクセになります。実際に動いている様子を動画にしました。
リアルタイム・モニタ機能でアナログ入力を見える化
DMAは難しそうと思っていましたが、実際やってみるとコーディングがシンプルにできて簡単でした。もっとたくさんのセンサを接続するときも利用できそうです。
今回でSTM32のアナログ入力の記事は終了しますが、今後の予定としてSTM32でFreeRTOSなどの検証もやって行きたいと思っています。