この文書では,モータドライバに接続されたファンをRPiで制御するJavaプログラムの作成方法について説明しています.モータドライバとしてDRV8832DGQRを用いており,このドライバにはファンの停止,正転および逆転させることと,回転速度を調整させることができます.しかし,RPiのピンをすべて使い切ってしまっているため,正転をさせることができない回路構成となっています.従って,ここではファンの停止と逆転,加えて回転速度を調整するプログラムを作成します.


回路構成

下にモータドライバ周りの回路図を示します.右側にはファンを停止および逆転させるための端子であるMOT_INと,ファンの回転速度を調整するMOT_SPDがあります.また,左側にあるCN1にはファンが接続される端子があります. モータドライバとRPiは直接接続されているのではなく,間にNPN型トランジスタが含まれています.これは,RPiから流すことのできる電流があまり多くないためです.

MotorDriver

 


ファンの停止と逆転

IN1とIN2の状態でファンの停止,正転および逆転を決めることができます.下の表にまとめておきます.上記の回路図から,IN2は常にHighとなりますので,IN1がLowの時には逆転,Highのときにはブレーキとなります.従いまして,MOT_INをLowにするとIN1がHighとなり,ファンは停止,MOT_INをHighとするとIN1がLowとなり,ファンは逆転します.

IN1IN2機能
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);
		}
	}
}