ラズパイとNode.jsでサーボモータをPWM制御してみる
以前の記事では、ポテンショメータに応じてモーターコントローラと PWM で DC モーターを回してみました。
ラズパイとNode.jsでDCモーターをPWM制御してみる
以前の記事では、ポテンショメータから値を取得することが出来ました。 今回はその値を使用して、PWM制御してDCモーターの回転速度をコントロール、と行きたいところですが、とりあえずLEDの明るさ制御をしてみたいと思います。 Next.jsのバックグラウンドメインループに実装します…
今回は同じ PWM 信号でサーボモーターを回してみたいと思います。
ハードウェア - SG90
サーボモーターとはざっくりいうと、内部に DC モーターとギアとコントローラとポテンショメータを内蔵し、指定された角度に出力ギアをコントロールしてくれるモーターです。
今回使用するのは安いサーボで一番有名な SG90。
ラズパイとの接続図は簡単なので省略。赤を 5V、茶色を GND、オレンジを PWM 信号(今回は GPIO19)に接続します。
ソフトウェア - pigpio
前回の DC モーターの PWM 制御には node.js の raspi-pwm と言うパッケージを使いました。前回は単純に電圧だけ調整できればよかったので細かい事を考えなかったんですが、サーボモーターの PWM 制御は周波数とか色々仕様があるみたいなので、考えるのが面倒なので pigpio というライブラリを使いました。
npm i -S pigpio
以下のように使用します。以下はメインループ関数です。
import i2c from 'i2c-bus';
import { Gpio } from 'pigpio';
const DEVICE_NUMBER = 1;
const TARGET_IC_ADDR = 0x4b;
const TARGET_IC_PORTS = [0x84, 0xc4, 0x94, 0xd4, 0xa4, 0xe4, 0xb4, 0xf4]; // A0~
export class Main {
meterDevice: i2c.I2CBus;
servoDevice: Gpio;
constructor() {
// デバイスオープン
this.meterDevice = i2c.openSync(DEVICE_NUMBER);
// 出力用にピンをオープン
this.servoDevice = new Gpio(19, { mode: Gpio.OUTPUT });
}
// ポテンショメーターから値を読み取り
readMeter(num: number) {
// 読み取りポート指定
var writeBuf = Buffer.from([TARGET_IC_PORTS[num]]);
this.meterDevice.i2cWriteSync(TARGET_IC_ADDR, writeBuf.length, writeBuf);
// 読み取り実行
var readBuf = Buffer.alloc(0x01);
this.meterDevice.i2cReadSync(TARGET_IC_ADDR, readBuf.length, readBuf);
return readBuf[0];
}
public Frame() {
// ポテンショメーター値の読み取り
const meter = this.readMeter(0);
const value = meter / 255;
// 出力値の計算
const min = 500;
const max = 2500;
const diff = max - min;
const output = Math.floor(value * diff + min);
this.servoDevice.servoWrite(output);
}
}
ざっと説明すると、 new Gpio(19,{mode: Gpio.OUTPUT}) で GPIO19 ピンをオープン。servoWrite 関数で出力値を指定。これだけです。
このサーボモータの仕様で値は 500 ~ 2500 にする必要があるため、ポテンショメータの値をその範囲に調整して servoWrite 関数に渡しています。
テスト
3D プリンターで適当に作った接続パーツを付けてテスト。
思ったより機敏に反応し、手で止めようとするとそれなりに力が必要で、トルクもまあまあありそうです。
次回は複数のサーボをコントロールするマルチチャンネル PWM 制御基板に挑戦してみたいと思います。