Arduino API比較をしつつ、Mbed OS6の入出力API群を練習中。前回はアナログ入力。順番からして今回はアナログ出力ですが、まずはPWM出力から。Arduino環境でanalogWrite()というとPWM出力だからです。電圧はデジタルだけれども時間方向はアナログ(時間の最小単位はデジタルだけれども。)
※「モダンOSのお砂場」投稿順Indexはこちら
※Arm社のWeb開発環境(無料)、Arm Keil Studio Cloud 上でArm社のRTOS、Arm Mbed OS6 を使って実験してます。ターゲット機はST Microelectronis製STM32F401RE搭載、NUCLEO-F401REボードです。
PWM(パルス幅変調)
各社の「マイコン」に、あまねく、ほぼ間違いなくタイマ、カウンタなどと呼ばれる回路が搭載されております。そして、そのカウンタをよく見るとその横にコンペア・チャネルなどと呼ばれるものが付属している筈です。カウンタを使って基本となる周期を作り出し、カウンタの指定の値でコンペア・チャネルを使って出力信号をON/OFFします。すると所望のデューティサイクルのPWM波形が得られるっと。出力はハイ、ローの2値だけれども時間方向のデューティは「だいたい」アナログ的に可変です。まあローパス・フィルタにかければ実際アナログ波形にできないこともないけれども。まあLPFかけなくてもPWM波形のままで各種の制御などに使うことが多いじゃないかと思います。
DAコンバータ
一方、アナログ的な電圧を直接出力できるD/Aコンバータを搭載している「ゴージャスな」マイコンも増えてはいるものの、手元に実験に使っているボードでも、その対応は分かれてます。
-
- Arduino UNO R3、DA搭載なし
- Arduino UNO R4、DA搭載あり
- NUCLEO-F401RE、DA搭載なし
- NUCLEO-F446RE、DA搭載あり
ということで、今回はどのボードでも使えるPWM出力の方を先に練習したいと思います。
Arduino環境でのPWM出力
Arduino環境ではanalogWrite() を使ってPWM出力が使えます。ただし細かい設定はボード毎に結構凸凹しているので、各自対応してね、という感じでしょうか。当方で比較対象としている Arduino UNO R3とUNO R4をとっても以下のような違いがあります。
-
- UNO R3、PWM周波数は490Hz固定。一部ピンのみ980Hz。レゾリューションは8ビット。
- UNO R4、PWM周波数は全PWMピン490Hz固定。レゾリューションは8ビット/12ビットの切り替え可能。
なお、UNO R3とR4ではPWM可能な端子はピンソケット的には同一番号で互換性がとれています。具体的には3、5、6、9、10、11番です。ただし、UNO R3では5番、6番は周期980Hzです。
また analogWrite() といってもレベル的にはデジタル出力です。事前に該当の端子をpinMode()関数を使ってOUTPUTに設定しておく必要があります。
UNO R4でのレゾリューション切替
デフォルトではUNO R3でもR4でも8ビットレゾリューションなので、デューティONの期間は0-255の数値で指定できます。しかしUNO R4では12ビットレゾリューション(0-4095の数値でON期間を指定)も可能です。念のためArduino UNO R4の実機で波形をとっておきました。
-
- 12ビットレゾリューション設定で128をanalogWrite()した時の波形
490Hzのとき周期は約2.041msとなるので、レゾリューションを変えても周期は同じ490Hzのままでした。128に相当するPosWidthは約64usです。目論見通りね。
-
- 8ビットレゾリューション設定で128をanalogWrite()した時の波形
デフォルトの周期は変らず、128を出力するとほぼ50%デューティの波形となっていることが分かります。
Mbed OS6上でのPWM出力
お作法どおり、特定のピンに対してインスタンスを生成することによってPWM出力が使えるようになります。使用するクラスは以下です。
実機上で動作確認したクラスインスタンスの生成は以下です。
PwmOut pwmD3(ARDUINO_UNO_D3);
これで、以降 D3 ピンを対象にPWM出力を行う pwmD3 という名のインスタンスが使用できます。
例によってMbed OS6では、各社マイコン内部のコマケー話をAPI的には隠しています。周期の設定を行うメソッドは以下の3種で、引数は全て時間です。
-
- period()、秒単位 float
- period_ms()、ms単位 整数
- period_us()、μs単位 整数
デューティまたはパルス幅設定については以下の4種が使えます。
-
- write()、単位%、float
- pulsewidth()、単位秒、float
- pulsewidth_ms()、単位ms、整数
- pulsewidth_us()、単位μs、整数
よって、以下のようにすることでArduino UNO R4で12ビットレゾリューションで128をanalogWrite()出力した時とほぼ同じ波形を生成できるはず。
pwmD3.period_us(2041); pwmD3.pulsewidth_us(64);
実機(NUCLEO-F401RE)上で観察した上記の波形が以下に。予定通りと。
なお、PwmOutには以下のようなメソッドも含まれていました。
-
- suspend()
- resume()
Mbed OS6のAPIの方がモダン?