らずらいと姫の挑戦日記(第16回)~モーターを動かしてみよう①~
2016-07-19
コントローラの仕組みと値を送信するプログラムは完成しました。今回からORIZURU本体側の作成にとりかかりたいと思います!
まずは、モーターについてです。ORIZURUを飛ばすための必需品ですね♪ 今回はDCモータについて勉強してみたいと思います。
この図は、ORIZURUの構成です。DCモーターで羽を動かして、サーボモーターで上下・左右の制御を行っています。
ORIZURUに搭載されている小型版Lazurite(Lazurite Fly)から、2種類のモーターを動かしています。
1.DCモーター・・・羽をバタバタと羽ばたかせています。エンジンの働きをするモーターです。
2.サーボモーター・・・尾翼を左右上下させて方向を決めるモーター
DCモーターってどんなもの?
直流モータ(direct-current motor)とも呼ばれていて、内部にエナメル線を何重にも巻いたコイルと磁石が入っていて、コイルに電気が流れて磁性を持つことで、磁石と反発しながら回転するモーター、との事です。
模型やミニ四駆、ラジコンなどを走らせたり、扇風機の羽を回すことが出来るモーターです。
+から-へ電気を流すとモーターが回ります。-から+だと逆回転します。車のタイヤなら正回転させて前進、逆回転でバックする感じです。また、+から-、-から+の正負両方があるものをHブリッジとも呼ぶそうです。
ORIZURUの場合、コントローラーのスライドボリュームを操作してDCモーターを動かしています。DCモーターの値は0~1023の間で、レバーの位置によって力の強さが変わってきます。0の位置なら0/1023の力を出している、真ん中辺りなら510/1023、MAXで1023/1023でフルパワーでモーターが動いています。
※μs(マイクロセック)=1/1,000,000秒 ms(ミリセック)=1/1,000秒
DCモーターの力は『分数』で考えます。まず、分母にあたる周期を決めて、その周期のうちの何%の力を出すかを決めています。例えば、下の図の場合、
- 「周期が100でAが50」を分数にすると→50/100(50%の力)
- 「周期が-100でBが-40」を分数にすると→-40/-100(40%の力)
となります。
DCモーターを動すプログラム
ORIZURUのコントローラーから無線で送信された値を受信して、DCモーターを動かすプログラムです↓↓↓
[c]
#define DEBUG
#define SUBGHZ_CH 36
#define SUBGHZ_PANID 0xABCD
uint8_t rx_data[256];
uint32_t last_recv_time = 0;
SUBGHZ_STATUS rx;
#define MOTOR_PS 17
#define MOTOR_PWM 2
void setup(void)
{
SUBGHZ_MSG msg;
long myAddress;
#ifdef DEBUG
Serial.begin(115200);
#endif
msg = SubGHz.init();
if(msg != SUBGHZ_OK)
{
SubGHz.msgOut(msg);
while(1){ }
}
#ifdef DEBUG
myAddress = SubGHz.getMyAddress();
Serial.print("myAddress1 = ");
Serial.println_long(myAddress,HEX);
#endif
msg = SubGHz.begin(SUBGHZ_CH, SUBGHZ_PANID, SUBGHZ_100KBPS, SUBGHZ_PWR_1MW);
if(msg != SUBGHZ_OK)
{
SubGHz.msgOut(msg);
while(1){ }
}
msg = SubGHz.rxEnable(NULL);
if(msg != SUBGHZ_OK)
{
SubGHz.msgOut(msg);
while(1){ }
}
pinMode(25,OUTPUT);
digitalWrite(25,HIGH);
// initializing motor
digitalWrite(MOTOR_PWM, LOW);
digitalWrite(MOTOR_PS, HIGH);
pinMode(MOTOR_PWM,OUTPUT);
pinMode(MOTOR_PS,OUTPUT);
hhb.init(3,1023);
hhb.attach(3,4,5);
hhb.attach(3,6,7);
hhb.write(3,0);
hhb.start(3);
return;
}
void loop(void)
{
uint32_t get_time;
uint32_t delta_time;
short len;
short motor[3];
do
{
len = SubGHz.readData(rx_data,sizeof(rx_data));
} while (len <= 0);
memcpy(motor,&rx_data[7],6);
#ifdef DEBUG
// Serial Output
get_time = millis();
SubGHz.getStatus(NULL,&rx);
delta_time = get_time – last_recv_time;
last_recv_time = get_time;
Serial.print_long(delta_time,DEC);
Serial.print(" ");
Serial.print_long((long)rx.rssi,DEC);
Serial.print(" ");
Serial.print_long((long)rx.status,DEC);
Serial.print(" ");
Serial.print_long((long)motor[2],DEC);
Serial.println("");
#endif
hhb.write(3,(unsigned short)motor[2]);
hhb.update();
return;
}
[/c]
54~58行目、95~96行目の『hhb』がDCモーター用のLazurite専用関数です。内容はこちらに記載されています。開発者いわく、全てハードウエアで制御しているので、モーターを制御するタイミングがずれずに、動作が安定しているそうです。
→https://www.appliot.co.jp/lazurite-jp/contents/reference/motor.html
Hardware H-Bridgeライブラリ: hhb
モーターライブラリの初期化:
まずは初期化する部分を見てみたいと思います。
54行目:hhb.init(3,1023);
これはモーターを制御する3番回路をDCモーターで使う、その時の周期(間隔)は1023μs(1.023ms)という宣言になります。
55行目:hhb.attach(3,4,5);
56行目:hhb.attach(3,6,7);
3番回路の出力を正側4pin、負側5pinにする;3番回路の出力を正側6pin、負側7pinにする
57行目:hhb.write(3,0);
3番回路の出力を0にする
58行目:hhb.start(3);
モーター用の回路を動かして信号を出力する
コントローラから送られたモーターの値を反映する
72~74行目: ここで受信したデータをmotorという変数にコピーしています。
95行目: hhb.write(3,(unsigned short)motor[2]);
コントローラから受信したDCモータの値はmotor[2]に格納されています。それを、3番のモータ回路にそのまま書きこんでいます。コントローラから送信されてくる値が0~1023で、DCモータの周期も1.023ms(1023us)にしているので、そのまま書きこむことが出来るんですね。
96行目: hhb.update();
hhbライブラリではwriteするだけではDCモーターの値が反映されません。updateをして初めてその値が有効になります。
3番回路とは??
突然登場した、3番回路とは何でしょうか?
Lazuriteのマイコンには4個のモーターを動かす回路が入っていて、それをDCモーターやサーボに割り当てて使用しているようです。今回のORIZURUは、サーボ 2個、DCモータ1個なのですが、色々と訳があって次のように使用しているそうです。
ORIZURUでの使用方法:
サーボ 1 = FTM0の0を使用
サーボ2=FTM1の2を使用
DCモータ=FTM3とFTM4を使用
(今回のサンプルプログラムではFTM3しか使用していません)
色々な事情があるようなのですが、とりあえずFTM3を使用してDCモータを動かしているという事は解りました。だからhhb.init(3,1023)のように、3番の回路を用いていたのですね。
今週はここまでです。実際に動いたところは最後にお見せしたいと思います。