Arduino APIとの比較をしながら、Mbed OS6の入出力API群を練習してます。前回は基本のキの字のデジタル入出力でした。今回はアナログ入力です。ADコンバータを使ってアナログ電圧を読み取るもの。コマケー話はいろいろあるケド、まずは読み取るところから。アナログ出力の方は2系統やらないとならないのでまた今度ね。
※「モダンOSのお砂場」投稿順Indexはこちら
※Arm社のWeb開発環境(無料)、Arm Keil Studio Cloud 上でArm社のRTOS、Arm Mbed OS6 を使って実験してます。ターゲット機はST Microelectronis製STM32F401RE搭載、NUCLEO-F401REボードです。
Arduino環境でのアナログ入力
以下の3つのAPIがアナログ入力のために使われますが、ぶちゃけデフォルト設定のままであれば、analogRead()一つで即座にアナログ入力可能です。
-
- analogRead()
- analogReadResolution()
- analogReference()
analogRead()関数に渡すのはADコンバータに接続可能なピン名のみです。Arduino UnoであればA0からA5までの6本がアナログ入力向けのピンであるのでA0からA5のどれか、ということになります。
Arduino UNO R3の場合、10ビットのADコンバータを搭載しているのでレゾリューションは固定。しかしUNO R4の場合は14ビットのADC搭載だけれども、UNO R3との互換性を考えて初期状態10ビットだそうな。変更したい場合は以下のようにanalogReadResolution()を呼び出せとあります。
analogReadResolution(14);
また、ADコンバータには必ず参照電圧というものがあり、これを基準にAD変換するわけであります。この電圧、UNO R4では2系統使用可能です。この切替に使うのがanalogReference()です。
-
- AR_DEFAULT、デフォルト5V(電源電圧に同じ)
- AR_INTERNAL、内蔵リファレンス電源 1.5V
Mbed OS6上でのアナログ入力
Mbed OS6上では、入出力するピンを対象に「インスタンス」を生成することから始めるという統一的なお作法です。アナログ入力で使うクラスは以下です。
上記からURLをたどっていただいてAPIのリファレンスを見ると分かりますが、ピン名だけでも初期化可能なコンストラクタですが、参照電圧を追加で与えることも可能だと。
ADコンバータのスペックは各社のマイコンでいろいろある筈なので、Mbed OS6上のAPIは「汎用的」なインタフェースになってます。
-
- read()メソッドは、正規化されたfloat値を返す [0.0, 1.0]
- read_u16()メソッドは、符号無整数値16ビットを返す。今回実験につかったSTM32F401REの場合、ADコンバータは12ビットなので、12ビットの値に下4ビット0のゲタを履かせて16ビット化している
- read_voltage()メソッドは、float型のV単位の値を返す。
今回は、なるべく生の値に近くということで read_u16()メソッドを使ってみました。
実機動作確認
毎度お馴染みの被テストデバイスが以下に。今回はArduino式名称「A5」端子の先に50KΩの多回転ポテンショメータを取り付けてアナログ入力信号としています。
実験に使ったソース main.cpp が以下に(LCD制御部分などは変更ないので以前のまま。)
#include "mbed.h" #include "AQM0802.h" #include "MYSTAT.h" #define BLINKING_RATE 500ms #define AIN_RATE 1000ms I2C i2c(I2C_SDA, I2C_SCL); AQM0802 lcd(i2c); DigitalOut ledRED(ARDUINO_UNO_D2); Thread threadLED; AnalogIn ain5(ARDUINO_UNO_A5); Thread threadAIN5; void blink_thread() { while (true) { ledRED = !ledRED; ThisThread::sleep_for(BLINKING_RATE); } } void ain_thread() { char dstr[8]; while (true) { sprintf(dstr, "%u", ain5.read_u16()); lcd.displaySTR(LCD_LLINE, dstr); ThisThread::sleep_for(AIN_RATE); } } int main() { lcd.init(); lcd.displaySTR(LCD_HLINE, "Voltage"); threadLED.start(blink_thread); threadAIN5.start(ain_thread); while (true) { ThisThread::sleep_for(10s); } }
折角RTOSを使っているのに、前回まではThread使ってなかったので、今回は、
-
- LEDを点滅させるLチカスレッド
- アナログ入力値を読んでLCD画面に値を表示するスレッド
を独立させてみましたぞ。ポテンショメータのねじを回すと表示の値が変化しますな。これでアナログ入力の練習はできたっと。随分手抜きな。
次回はアナログ出力だな。