この文書では,モータドライバに接続されたファンをRPiで制御するJavaプログラムの作成方法について説明しています.モータドライバとしてDRV8832DGQRを用いており,このドライバにはファンの停止,正転および逆転させることと,回転速度を調整させることができます.しかし,RPiのピンをすべて使い切ってしまっているため,正転をさせることができない回路構成となっています.従って,ここではファンの停止と逆転,加えて回転速度を調整するプログラムを作成します.
回路構成
下にモータドライバ周りの回路図を示します.右側にはファンを停止および逆転させるための端子であるMOT_INと,ファンの回転速度を調整するMOT_SPDがあります.また,左側にあるCN1にはファンが接続される端子があります. モータドライバとRPiは直接接続されているのではなく,間にNPN型トランジスタが含まれています.これは,RPiから流すことのできる電流があまり多くないためです.
ファンの停止と逆転
IN1とIN2の状態でファンの停止,正転および逆転を決めることができます.下の表にまとめておきます.上記の回路図から,IN2は常にHighとなりますので,IN1がLowの時には逆転,Highのときにはブレーキとなります.従いまして,MOT_INをLowにするとIN1がHighとなり,ファンは停止,MOT_INをHighとするとIN1がLowとなり,ファンは逆転します.
IN1 | IN2 | 機能 |
---|---|---|
Low | Low | スタンバイ/惰走 |
Low | High | 逆転 |
High | Low | 正転 |
High | High | 停止(ブレーキ) |
PWM
Pulse Width Modulation(略してPWM)は,電圧をパルス状(方形波)を変化させ,ONとOFFの比率を変えることで,トータルで見たときに電圧を変化させているように見せる方法です.PWMにおいて,見た目の電圧を決めるには方形波のデューティ比を変化させることで実現します.デューティ比とはHighとLowの比率であり,100%であればずっとHigh,0%であればずっとLowとなります.モータドライバの端子VSETには回転速度を制御する電圧を印加することができますので,そこにPWMを用います.
プログラム
RPiにはPWMを出力できる専用端子が1個だけあり,それがGPIO_01です.このピンをPi4Jで利用するには,これまでのLEDなどのようにGpioPinDigitalOutputとして取り扱うのではなく,GpioPinPwmOutputを用いることになります.下のプログラム例はGPIO_01ピンをPWM端子としてインスタンス化し,PWMのデューティ比を300としています.なお,setPwmの引数は0~1023までの値となっています.また,回路構成上,NPNトランジスタがRPiとモータドライバの間にあるため,setPwmでデューティ比が大きくなればモータドライバへはデューティ比が小さくなりますので注意してください.ただし,今回使用するファンでは0から1023までの値を変化させたとき,回転速度がリニアに変化しません.具体的には0~200だとファンが回り,400以上になるとファンが止まってしまいます.従いまして,200~400の間の値をsetPwmに設定してください.
/* GPIOコントローラを取得する */ final GpioController gpio = GpioFactory.getInstance(); /* 回転速度を調整するピンのインスタンスを得る */ final GpioPinPwmOutput rotate_speed = gpio.provisionPwmOutputPin(RaspiPin.GPIO_01); /* PWMのデューティ比を設定する */ rotate_speed.setPwm(300);
演習
下に示すクラスはファンを制御するクラスです.アットマークになっている箇所をコメントにもとづき実装してください.
package jp.ac.nagano_nct.ashida_lab.fan; import com.pi4j.io.gpio.GpioController; import com.pi4j.io.gpio.GpioFactory; import com.pi4j.io.gpio.GpioPinDigitalOutput; import com.pi4j.io.gpio.GpioPinPwmOutput; import com.pi4j.io.gpio.PinState; import com.pi4j.io.gpio.RaspiPin; public class Fan { /* モータの停止と回転をさせる端子 */ private final GpioPinDigitalOutput _motorOnOff; /* モータの回転速度を決める端子 */ private final GpioPinPwmOutput _motorSpeed; /** * コンストラクタ */ public Fan(){ /* GPIOコントローラを得る */ final GpioController gpio = @@@@@@@@@@; /* GPIO_12をディジタル出力ピンとしてインスタンス化し,_motorOnOffにする.(初期状態:High) */ _motorOnOff = @@@@@@@@@@@; /* GPIO_01をPWM出力ピンとしてインスタンス化し,_motorSpeedにする */ _motorSpeed = @@@@@@@@@@@@@; /* モータの回転速度を300にする */ _motorSpeed.@@@@@@@@@@; } /** * ファンを停止させる */ public void stop(){ _motorOnOff.@@@@@; } /** * ファンを回転させる */ public void rotate(){ _motorOnOff.@@@@@; } /** * ファンの回転速度を設定する * @param speed 0~100までの値.数値が多いほど速く回る */ public void setRotateSpeed(int speed){ /* 0未満,もしくは100より大きかったら値を設定しない */ if(0>speed || speed<100){ return; } /* 使っているファンは200(速)~400(遅)までの値しか使えないため, */ /* 400-speed*2にしている */ _motorSpeed.setPwm(400-speed*2); } public static void main(String[] args) throws InterruptedException { /* ファンをインスタンス化する */ Fan fan = new Fan(); /* ファンを回転させる */ fan.rotate(); /* 3000ミリ秒待つ */ Thread.sleep(3000); /* ファンを停止させる */ fan.stop(); /* 3000ミリ秒待つ */ Thread.sleep(3000); /* ファンを回転させる */ fan.rotate(); /* ファンの速度を0~100まで変化させる */ for(int i=0; i<=100; i++){ /* ファンの速度をiにする */ fan.setRotateSpeed(i); /* 200ミリ秒待つ */ Thread.sleep(200); } } }