もっと楽しむために

まだ上っ面をなでただけです!まだまだたくさん楽しめるものがあります。

マルチタスク

作ったプログラムは全てシングルタスクで実行しました。OSがなく、スレッドがないシステムでマルチタスクを実現するにはどうするのでしょうか。 2つの主なアプローチがあります。プリエンプティブマルチタスクと協調的マルチタスクです。

プリエンプティブマルチタスクでは、実行されているタスクは、いつでも、他のタスクによってプリエンプション(割込み)されます。 プリエンプションでは、最初のタスクは一時停止され、プロセッサは2つ目のタスクを代わりに実行します。 どこかの時点で最初のタスクが再開されます。 マイクロコントローラは、プリエンプションを割込みという形でハードウェアサポートしています。

協調的マルチタスクでは、実行されているタスクは中断点に到達するまで実行します。 プロセッサが中断点に到達すると、現在のタスクの実行を停止し、代わりに別のタスクを実行します。どこかの時点で最初のタスクが再開されます。 マルチタスクのための2つのアプローチの主な違いは、いかなるタイミングでも強制的にその実行がプリエンプションされる代わりに、 協調的マルチタスクでは既知の中断点で実行制御を譲ることです。

Direct Memory Access (DMA).

このペリフェラルは、非同期memcpyです。これまでのところ、プログラムは、UARTやI2Cのようなペリフェラルに、バイトごとにデータを送信してきました。 DMAペリフェラルは、データの一括転送を行うために使用できます。RAMからRAM、UARTのようなペリフェラルからRAM、RAMからペリフェラルへ転送できます。 DMA転送をスケジュールすることもできます。 例えば256バイトをUSART1からバッファへ読み込む、という処理をバックグランドで実行しながら、転送が完了したかをレジスタをポーリングすることで、 転送を行っている間、他のことができます。

スリープ

作った全てのプログラムは、必要な処理が終わったかどうかを見るために、ペリフェラルを継続的にポーリングしています。 しかし、なにもすることがないことがあります。 そのような場合、マイクロコントローラは「スリープ」しなければなりません。

プロセッサがスリープしている時、命令の実行を停止し、電力を節約します。 これは、電力節約のために、多くの場合、良いことです。マイクロコントローラは可能な限りスリープしなければなりません。 しかし、何か処理を行うためにいつ目覚めるか、をどうやって知ればよいでしょうか? 「割込み」はマイクロコントローラを目覚めさせるイベントの1つですが、他の方法もあります。 wfiwfeはプロセッサを「スリープ」させる命令です。

パルス幅変調(PWM)

手短に言うと、PWMは、周期的に何かをオンにして、その後オフにすることです。 ここで、「オンの時間」と「オフの時間」の間は、ある割合(「デューティ比」)を保ち続けます。 十分周波数の高いLEDを使用すると、PWMは、LEDを薄暗くするために使用できます。 ディーティ比が低いと、つまり10%オンで90%オフだと、LEDは非常に薄暗くなります。反対に、デューティ比が高いと、 つまり90%オンで10%オフだと、LEDはかなり明るくなります(ほとんど完全に電力を供給されたように)。

通常、PWMは電気機器にどの程度電力を供給するか、制御するために使われます。 マイクロコントローラと電気モータとの間に、適切な(電力)電子機器を用いて、PWMでモータにどれだけの電力供給するか制御できます。 そのため、PWMを使用してモータのトルクと速度を制御できます。 それから、角位置センサを追加し、閉ループコントローラを入手できます。 このコントローラは、様々な負荷でモータの位置を制御することができます。

デジタル入力

LEDを駆動するために、マイクロコントローラのピンをデジタル出力として使用してきました。 しかし、これらのピンはデジタル入力として設定することもできます。 デジタル入力として、これらのピンは、スイッチ(オン/オフ)やボタン(押された/押されていない)の二値状態を読むことができます。

ネタバレ スイッチ/ボタンの二値状態を読むことは、思ったほど簡単ではありません ;-))

センサフュージョン

STM32F3DISCOVERYは3つのモーションセンサを搭載しています。加速度計、ジャイロスコープ、磁力計です。 彼らは(proper)加速度、角速度、(地球)磁場を計測できます。 しかし、これらの測定値は、「ロバストな」ボード向きの測定のように、もっと有用なものに「融合」することができます。 ここでロバストが意味するところは、単一のセンサで計測できるものより、計測誤差が少ないことです。

より信頼性の高いデータを、異なるソースから生み出すためのこのアイデアは、センサフュージョンと呼ばれています。

アナログデジタルコンバータ(ADC)

たくさんのデジタルセンサがあります。I2CやSPIのようなプロトコルを使って、センサからデータを読み出せます。 しかし、アナログセンサも存在しています!これらのセンサは、検知している大きさに比例した電圧レベルを出力するだけです。

ADCペリフェラルは、「アナログ」電圧を変換するために使用します。 つまり1.25ボルトを、プロセッサが計算で使える「デジタル」な数値である[0, 65535]の範囲に変換します。

デジタルアナログコンバータ(DAC)

予想の通り、DACはADCの反対のことを行います。 何らかのデジタル値をレジスタに書き込むと、[0, 3.3V]の範囲の電圧を、「アナログ」ピンに出力します(電源が3.3Vと仮定しています)。 このアナログピンが、何らかの適切な電子機器に接続されており、何らかの定数がレジスタに書き込まれると、 正しい値の速いレート(周波数)は、サウンドや音楽さえも生み出すことができます。

リアルタイムクロック(RTC)

このペリフェラルは、「人間の形式」で時間を追跡するために使用できます。 秒、分、時間、日、月、年の形式です。このペリフェラルは、「ティック」から人間が読みやすい時間の単位への変換を取り扱います。 RTCは、うるう年や夏時間でさえも取り扱います!

他の通信プロトコル

SPI, I2S, SMBUS, CAN, IrDA, Ethernet, USB, Bluetooth,など。

アプリケーションごとに違う通信プロトコルを使います。ユーザーが触れるアプリケーションは、通常USBコネクターを持ちます。 なぜなら、USBは、PCやスマートフォンの至るところで使われているプロトコルだからです。 一方、車の内部では、多くのCAN「バス」を見つけられます。デジタルセンサにはSPIを使うものがあり、他のものはI2CやSMBUSを使います。


さて、次はどこでしょう?いくつかの選択肢があります。

  • f3ボードサポートクレートにある例をチェックできます。全ての例は、STM32F3DISCOVERYボードで動きます。
  • Real Time for The Massesをチェックできます。非常に効率的なプリエンプティブマルチタスクフレームワークです。 これは、タスクの優先度と、デッドロックしない実行を提供します。
  • Rustを別の開発ボードで動かしてみることができます。最も簡単な方法は、cortex-m-quickstartのCargoプロジェクトテンプレートを使うことです。
  • このブログをチェックできます。このブログは、Rustの型システムがI/O設定のバグを防ぐ方法を説明しています。
  • 私のブログをチェックできます。Rustを使った組込み開発について、様々なトピックを書いています。
  • embedded-halプロジェクトをチェックできます。このプロジェクトは、 マイクロコントローラで一般的に用いられる組込みI/O機能に対して、抽象化(トレイト)を構築することを目指しています。
  • Weekly driver initiativeに参加して、embedded-halトレイト上で汎用ドライバを書く手伝いができます。 この汎用ドライバは、あらゆる種類のプラットフォーム(ARM Cortex-M、AVR、MSP430、RISCVなど)で動作します。