🗿

RaspberryPi 3B+と.NET5で電子工作(ハードウェアPWM)

2021/09/21に公開

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

前回、Raspberry pi3B+と.NET5で電子工作する準備とLEDチカチカをやってみた。

今回は、そのLEDをPWMを使って明るさ調整してみる。

やりかた

ラズパイ3B+ではハードウェアPWMが使用できるらしく、それを行うためのラズパイの設定方法が.NETのgithub上にかなり分かりやすく書かれていた。

https://github.com/dotnet/iot/blob/main/Documentation/raspi-pwm.md

それをなぞる形で実験をおこなう。

ラズパイのハードウェアPWMを有効にする

標準では、ラズパイのハードウェアPWMは無効になっているらしい。
それを使うために、設定ファイルを書き換えてあげてハードウェアPWMを有効にする。

書き換える設定ファイルは 「/boot/config.txt」

下記を一文、ファイルの最後に付け足す。

dtoverlay=pwm,pin=12,func=4 というのは、

  • ハードウェアPWMを1チャンネルだけ有効にして、
  • GPIO12pin(物理pin番号で言うと35番pin)をハードウェアPWM用のpinとして使用する

という意味。もし別のpinをPWMとして使用するなら、下記の選択肢がある様子。

表の一番右のdtovwerlayにある文言を、上でやったように/boot/config.txtの最後に付け足せばOK。
GPIOの12,13,18,19番が、PWMとして使える。(他のGPIOは使えない)

また、もしハードウェアPWMを2チャンネル有効にしたいときは、下記の選択肢がある様子。

GPIOの12,13,18,19番の組み合わせになる。
   ・
   ・
   ・
という感じで、使うハードウェアPWMのpinを決めて設定ファイルを更新したら、一度再起動して、設定ファイルを反映させる。

配線する

こんな感じで配線する。

GPIO 12 から LED の陽極 (長い正のリード) へ
LED の陰極 (短い負のリード) から 330 Ω の抵抗 (どちらかの端) へ
330 Ω の抵抗 (他の端) からグラウンドへ

という感じ。※今回の実験も330Ωはないので100Ωで代用

コードを書く

今回は、/home/pi に「PwmJikken」というコンソールのプロジェクトを作成して、そこにPWMでLEDの明るさを変えるようなプログラムを作ろうと思う。

まず/home/piにいる状態で、下記のコマンドでプロジェクトを作成する。

dotnet new console -o PwmJikken

これでコンソールアプリのプロジェクトができる。
できたプロジェクトのフォルダの中(/home/pi/PwmJikken)に、Program.csができているので、それをエディタ(今回はVSCodeを使用)で開き、下記のように書き換える。

Program.cs
using System;
using System.Device.Gpio;
using System.Threading;
using System.Device.Pwm;

var pwm = PwmChannel.Create(0, 0, 400, 0.1);
pwm.Start();

while (true)
{
    pwm.DutyCycle += 0.01;
    if (pwm.DutyCycle >= 0.99)
    {
        pwm.DutyCycle = 0.0;
    }
    Thread.Sleep(10);
}

コードを書いたら、プロジェクトのフォルダに

cd PwmJikken

で入って、

dotnet add package Iot.Device.Bindings --version 1.1.0-*

で必要なファイブラリを追加してから、

dotnet build

でビルドする。さらに

bin/Debug/net5.0/PwmJikken

で実行すると、LEDが暗→明→暗→明→暗→明→・・・ を繰り返す動きをする。

備考

MSのgithubには書かれているが、もし/boot/config.txtにPWMを有効にする一文を書き忘れると、下記のようなエラーが実行時に発生する。(実際、今回試しているときに発生した。)

Unhandled exception. System.ArgumentException: The chip number 0 is invalid or is not enabled.
   at System.Device.Pwm.Channels.UnixPwmChannel.Validate()
   at System.Device.Pwm.Channels.UnixPwmChannel..ctor(Int32 chip, Int32 channel, Int32 frequency, Double dutyCycle)
   at System.Device.Pwm.PwmChannel.Create(Int32 chip, Int32 channel, Int32 frequency, Double dutyCyclePercentage)
   at TestTest.Program.Main(String[] args) in C:\tmp\TestTest\TestTest\Program.cs:line 12
Aborted

その場合は/boot/config.txtに設定忘れがないか確認する。

また、パーミッションの関係でエラーが発生することもある様子。
こちら参照

その場合は、MSのgithubに記載のあるように対応必要っぽい。
(今回はそのようなエラーにならなかったので未実験)

参照

MSのgithub。とてもわかりやすい。
https://github.com/dotnet/iot/blob/main/Documentation/raspi-pwm.md

コードで使ったクラスのドキュメント。
https://docs.microsoft.com/ja-jp/dotnet/api/system.device.pwm.pwmchannel?view=iot-dotnet-1.1

ラズパイのpinアサイン。A+,B+、B2と書かれてるが、3B+でも一緒っぽい。
https://elinux.org/RPi_Low-level_peripherals#Model_A.2B.2C_B.2B_and_B2

前回のLチカの参考にしたMSページ。
プロジェクトの作り方はこれと同じ。
https://docs.microsoft.com/ja-jp/dotnet/iot/tutorials/blink-led

Discussion