概要
ESP8266 (以下、WROOM02) を使って、ステッピングモータを制御する。
はじめに
年末に購入した Arduinoをはじめよう 互換キット UNO R3対応互換ボード 初心者専用実験キット 基本部品セット20 in 1 。電子工作初心者の私は、ごく普通の回路設計をし、ごく普通にブレボーにジャンパー線を刺しました。でも、ただひとつ違っていたのは、UNO は未開封で… いきなり、WROOM02 だったのです。
今回は懐かしい「奥さまは魔女」風のオープニングにしてみましたが、実はこのキット、けっこう、モリモリに部品が盛り込まれていて、買ってすぐに脱落してました。そんな折、WROOM02 と出会い、「こ、こいつで、部品を一通り使ってみよう」と一大決心したわけです。
その長い旅路の、そろそろゴールが見えてきました。
あと残すところ、赤外線関連とLCDディスプレイ、そして、ステッピングモータです。
部品調達
ステッピングモータは「28BYJ-48」
仕様は以下になります
- 4相
- 1 / 64 に回転数を落としているモデルのようです。
- 1回転は 360 / 5.625 x 64 = 4,096 ステップ (1-2相励磁)
- 無負荷では 1,000Hz で脱調
Key | Value |
---|---|
Rated voltage | 5VDC |
Number of Phase | 4 |
Speed Variation Ratio | 1/64 |
Stride Angle | 5.625° / 64 |
Frequency | 100Hz |
DC resistance | 50Ω±7%(25℃) |
Idle In-traction Frequency | > 600Hz |
Idle Out-traction Frequency | > 1000Hz |
In-traction Torque | >34.3mN.m(120Hz) |
Self-positioning Torque | >34.3mN.m |
Friction torque | 600-1200 gf.cm |
Pull in torque | 300 gf.cm |
Insulated resistance | >10MΩ(500V) |
Insulated electricity power | 600VAC/1mA/1s |
Insulation grade | A |
Rise in Temperature | <40K(120Hz) |
Noise | <35dB(120Hz,No load,10cm) |
Model | 28BYJ-48 – 5V |
参考 Youtube
もう一方の、基板のICには「ULN2003APG」と書かれています。
こ、これは、ESP8266 (ESP-WROOM-02) で7セグメントLEDを制御するで使った、反転型トランジスタアレイ(シンクドライバ)の7ch版ではないですか。フムフム。(データシートには「製造中止: メーカーにてモデル廃止予定のため、製造中止となります」と書かれてます。そういうこともあるのですね。)
折角なので、この基板は使わないで、手持ちのトランジスタアレイ TD62083APG を使いましょう。
他には、8bitシフトレジスタ SN74HC595N と、温度センサー を使います。用途は後ほど。
回路
- 4相それぞれに1ピンを直接割り当てるのではなく、シストレジスタを使って割り当ててます。
- シフトレジスタ操作には4ピン必要なので、シフトレジスタ使わずに直接割り当てても同数のピンを消費しますねwww
- A/D変換ピン(tout端子)に温度センサーをつないでいます。
- tout端子の入力は 0V〜1,000mV なので、温度センサーの出力を1/3に降圧します。
- ステッピングモータは、5V で駆動しています。
回路図
Eagle
スケッチ
- そのものズバリの「Stepper」ライブラリがありますが、挙動を理解したいので、今回は自前で作成してみます。
- A/D変換ピン(tout)の値(0-1024)を、-RANGE〜+RANGE ステップにマッピング。
- その位置になるように、ステッピングモータを回転させます。
- つまり、ステッピングモータによる「アナログ温度計」的な動作になります。
extern "C" {
#include <user_interface.h> // A/D (system_adc_read) 用
}
#include <Ticker.h>
Ticker ticker;
Ticker moter;
#define SCK 14 // CLK クロック信号出力ピン
#define RCK 12 // LOAD ラッチ動作出力ピン
#define SI 13 // MOSI - DI データ信号出力ピン
#define CLR 15 // クリア
// 2相励磁 (4096ステップで2回転)
const int S = 4;
const int steps[S] = {
// HGFEDCBA
0b00001100,
0b00000110,
0b00000011,
0b00001001
};
// 初期化
void setup() {
Serial.begin(115200);
Serial.println("");
pinMode(SCK, OUTPUT) ;
pinMode(RCK, OUTPUT) ;
pinMode(SI, OUTPUT) ;
pinMode(CLR, OUTPUT) ;
// 温度センサー
// 1,000 msec 毎に取得
ticker.attach_ms(1000, timer);
// 回転速度調整
// 回転速度遅すぎる(1/64)のでもっと高速に回転させたいが
// 2 msec だと脱調することがある
// 3 msec が限界だった
moter.attach_ms(3, drive);
}
// ループ
void loop() {
// Do nothing.
}
// シリアル出力
void out(int x) {
digitalWrite(CLR, LOW); // クリア信号
digitalWrite(CLR, HIGH);
digitalWrite(RCK, LOW);
shiftOut(SI, SCK, MSBFIRST, x);
digitalWrite(RCK, HIGH); // ラッチ信号
}
const int RANGE = 1024;
volatile int P_ref = 0; // 目標位置
volatile int P_now = 0; // 現在位置
// A/Dセンサー値取得
void timer() {
// A/Dセンサー値取得
int tout = system_adc_read();
Serial.println(tout);
// A/Dセンサーの値(tout)を、-RANGE〜RANGE にマップする
P_ref = map(tout, 0, 1024, -RANGE, RANGE);
}
// モータードライブ
void drive() {
// 目標位置 と 現在位置 との 差
int d = P_ref - P_now;
if (d != 0) {
// P_ref に近づくように ±1 する
P_now += d / abs(d);
Serial.print(" P_ref:");
Serial.print(P_ref);
Serial.print(" P_now:");
Serial.print(P_now);
// P_now にするには、どの方向に回せばよいか
int i = (P_now + RANGE) % S;
Serial.print( " i:");
Serial.print(i);
Serial.println("");
// 1ステップ移動する
out(steps[i]);
} else {
// 0を出力すれば電流が流れない
out(0);
}
}
動作確認
- このモータで、2相励磁 で駆動する場合、4,096 ステップで 2回転 になります。
- 無負荷での、脱調しない最高速は 1ステップ 3msec でした。360度回転するには 6.144秒 かかります。
センサー等なしで、周回テストしたい場合は、drive関数を適当に修正して下さい。
<例>
void drive() {
static int n = 0;
n++;
if (n < 4096) {
// 2回転 (2相励磁)
out(steps[n % S]);
} else {
out(0);
}
}
カスタマイズ
1相励磁 にしたい場合は、以下。
- 4,096 ステップで 2回転
- 消費電力は下がりますが、その分、トルクも下がります。
const int S = 4;
const int steps[S] = {
// HGFEDCBA
0b00001000,
0b00000100,
0b00000010,
0b00000001
};
1-2相励磁 にしたい場合は、以下。
- 4,096 ステップで 1回転 (2倍のステップが必要)
- 回転が滑らかになりますが、そもそも、1 / 64 なので必要ないです。
const int S = 8;
const int steps[S] = {
// HGFEDCBA
0b00001000,
0b00001100,
0b00000100,
0b00000110,
0b00000010,
0b00000011,
0b00000001,
0b00001001
};
まとめ
- このモータは 1 / 64 に回転が落ちている(その分トルクは大きい)ので、とてもゆっくり回転します。
- 静止時は(0を指定して)電流を切断しておけば、発熱もなく、理想的に静止します。
- ステッピングモータは角度を正確に指定できますが、初期状態で自分自身の角度を知る手段が無い部分が悩みどころです。
- サーボモータと比較して、使う場面が難しい気がします。
ESP8266 (ESP-WROOM-02) でサーボを制御する - 静止時に電流を流さなくても良いので、スリープモードと相性が良さそうです。
- 目覚めた時に記憶が戻るよう、『掟上今日子の備忘録』的に、眠る直前の状態(角度)を保存しておく必要がありますが。
- ESP8266 (ESP-WROOM-02) でWi-Fi使用時のSSID/パスワードをブラウザで設定できるようにで使った、SPIFFS に保存しておけばよいでしょう。