現在本拠地を離れているため機材が不足していて MIDI/CV の製作は難航していますが、できるところから作業を進めてきました。しかしいよいよやることがなくなり、数週お休みしなくてはなりません。その間も何か手を動かしていたいということで、アマゾンからおもちゃのモーターを何個か仕入れてきました。以前から、モーターにもっと詳しくなりたいと考えていたのです。

仕入れてきたのは、減速ギアと車輪がついた DC ブラシモータ 4 セットです。送料込みで 1000円前後。安いです。が、データシートも何もついていません。製品名からそのうち探してきたいと思います。とりあえず電源電圧を決めないといけませんが不明瞭。カタログには 3V から 6V までと書いてあったので、それを信じてまずは USB 電源 5V を使えばよかろう、と、至極適当に進めます。モーターを手に入れたらやってみたかった3点の練習をします。
- PWM を使った回転速度制御
- 回転数の計測
- 回転数の能動制御
PWM を使った回転速度制御
プロセッサとして、MIDI/CV の動作確認のために持ってきた PSoC 5 のキットが手元にあります。これを制御に使うとして、PWM 出力をいきなりモーターに繋ぐと過電流でプロセッサが壊れてしまうかもしれない。ということで、あらかじめ秋月電子からモータードライバを仕入れておきました。
https://akizukidenshi.com/catalog/g/g114746
こちらはさすがにデータシートが配られており
https://akizukidenshi.com/goodsaffix/TC78H653FTG_datasheet_ja_20190129.pdf
ドライバのブロック図はこのようになっており

OUT1/2 と OUT3/4 がセットになってモータ制御するようです。大電流のため 2 セットを同時に使う設定もできるようです。こういう回路を H ブリッジと呼ぶらしいです。いやほんとに何も知らなくて恥ずかしい。ちなみに東芝製なんですね。なにかうれしい。コントロール回路を使って PWM から来た信号によりスイッチを入れたり切ったりと制御するわけですが、動いているモータのスイッチを切ると起こる逆起電力からスイッチを保護するためにダイオードが入っています。これにより PWM オフ時に回転にブレーキをかける役割もあるようです。
このドライバーにはいくつかの制御モードがありますが、今回は Phase 入力モードおよびスモールモードを選択しました。スモール・ラージのモードの違いは一回路でモーターを制御するか二回路で制御するかの違いのようです。Phase 入力モードの対に IN 入力モードというものもあります。Phase 入力モードではフェーズ入力ピンでモーターの回転方向を決めつつ ENB 入力ピンに PWM をかければ回転数制御ができ、今回の実験には向いています。

これをもとに、PSoC のハードウェアの設計をします

7セグメント表示器やロータリーエンコーダなど MIDI/CV の設計からそのまま流用してきたので UART のようないらないモジュールがあったり使っていないピンが残っていたりと紛らわしいですが、PWM_Motor がモータの回転数制御に使う PWMです。GlitchFilter_2 と Timer_1 は後で回転数計測のために使います。あとは数本の出力ピンでドライバのモード決めをします。あとはドライバ・モータを接続して、PWM を可変にするためのコードを書いて、回転数制御は以上です。
無事に思惑通りに動きました。PWM の範囲は 0-127 クロック周波数は 24 kHz と設定しました。7セグメント表示器に PWM 値を出しています。見てわかるように、70 程度まで落とすとモーターが止まってしまいます。手で操作した感覚では、PWM と回転数の関係は線形ではないようです。
回転数の計測
回転数が変えられるようになったので、次は回転数の把握です。回転部分にセンサーを付けることになります。いろんな方法が考えられますが、部屋の隅に反射型の赤外線センサーがあったのでこれを使います。電線も固定用の金具もないですがあるものをかき集めてなんとか組み上げてゆきます。ちょっと楽しい。

反射型のセンサーなので回転部分になにか光を反射するものを付ける必要があります。台所にアルミホイルがあったのでこれでいいか、と取り付け

ひどく不格好、工作精度もへったくれもありません。でも組んじゃう

通電してみて、こんなんでもちゃんと感応することを確認。さらにもう少し試行錯誤して、センサまわりの回路はこんな風にしました

R2 はいらないかもしれません。写真のとおり反射板もセンサーも取り付けが雑ですからチャタリングが出るかもしれません。それを考慮してセンサーの出力に Glitch Filter をかけます。あとはセンサーが反応する時間間隔を計測する必要があるので、タイマをつけます。クロックは 1kHz でタイマカウンタは 16 bit です。これで約 60 秒まで計測可能です。センサのトリガは割り込みを使って処理します。最初に書いたコードは
CY_ISR(RpmSensorHandler)
{
uint16_t value = 65535 - Timer_1_ReadCounter();
Timer_1_WriteCounter(0);
Pin_LED_Write(Pin_LED_Read() ^ 0x1);
int32_t rpm = 60000.0 / value / 2;
LED_Driver_1_Write7SegNumberDec(rpm, 0, 3, LED_Driver_1_RIGHT_ALIGN);
}
Cでもこれだとうまく数えられません。センサの取り付けが雑なので「半回転」ごとのインターバルが不均一で計測値がバタバタ暴れるのです。でもよく考えてみると、同じ反射板に戻ってくる一回転の間隔を測れば取り付けの誤差によるばらつきは出にくいはず、ということで二個前のトリガーからの時間間隔を計測するように変えたプログラムがこちら
static uint16_t prev = 0;
CY_ISR(RpmSensorHandler)
{
uint16_t value = 65535 - Timer_1_ReadCounter();
Timer_1_WriteCounter(0);
Pin_LED_Write(Pin_LED_Read() ^ 0x1);
int32_t rpm = 60000.0 / (value + prev);
LED_Driver_1_Write7SegNumberDec(rpm, 0, 3, LED_Driver_1_RIGHT_ALIGN);
prev = value;
}
C結果の動作はこんな具合。平滑化はほぼやっていないですが回転数は急に変わったりできないせいか、大まかに安定しています。
回転数の能動制御
ここまでくると回転数の能動制御は比較的容易です。目標 rpm を決めて計測した回転数が届いていなければ加速、回転数が大きすぎれば減速というコードを足せば OK です。PWM のカウンタ数は 256 に増やしました。
static uint16_t prev = 0;
static int32_t target_rpm = 50;
static uint8_t pwm_cmp = 200;
int main(void) {
// initialization code here
...
while (;;) {
PWM_Motor_WriteCompare1(pwm_cmp);
}
}
CY_ISR(RpmSensorHandler)
{
uint16_t value = 65535 - Timer_1_ReadCounter();
Timer_1_WriteCounter(0);
Pin_LED_Write(Pin_LED_Read() ^ 0x1);
int32_t rpm = 60000.0 / (value + prev);
LED_Driver_1_Write7SegNumberDec(rpm, 0, 3, LED_Driver_1_RIGHT_ALIGN);
prev = value;
if (rpm < target_rpm) {
uint8_t delta = (target_rpm - rpm) / 3 + 1;
pwm_cmp = 255 - status > delta ? status + delta : 255;
} else if (rpm > target_rpm) {
uint8_t delta = (rpm - target_rpm) / 3 + 1;
pwm_cmp -= delta;
}
}
C結果こんな動きになりました。基礎技術の練習なので、今のところこれで十分です。