#■物語の始まり、想定外のエラーに遭遇
obniz Boadって1つの端子で電流1Aまでとれるので、DC Motorも直接ドライブできてとても便利ですよね。ライブラリも用意されていて、正転も逆転もスピードも簡単にコントロールできるんですよね。
ということで、DC Motor4台をobnizに直接接続してライブラリを使ってメカナムホイール車を走らせるべく、次のようなコードを書きました。
ところが、下記のエラーで拒否られてしまいました。
#■ライブラリで制御できるDC Motorは3台まで!!
obnizのDC MotorライブラリはPWMで動いていて、1台のDC Motorで正転と逆転でそれぞれ1つづつ計2つのPWMを占有するようです。obnizのPWMの総数は6個というH/W制約があるため、ライブラリで制御できるDC Motorは3台までということになります。よって、4台目を宣言すると上記のエラーになるわけです。
#■4台の直刺しDC Motorを制御する代替Tips
#正転と逆転で動的に+/-のピンアサインを変更することで、1台のDC Motorを1つのPWMで制御します。
具体的には、+側にしたいピンにPWMを割り当て、-側にしたいピンをoutputでfalseにします。PWMのduty比を変える事でスピードを指定します。これにより4台のDC Motorを接続した場合でも、使用するPWMは4つで済みPWM最大6っまでという制約内で動作させることがてきます。
(原理的には、この方式で最大6台までのDC Motorを直刺しで制御できます。)
##以下0番ピンにDC Motorの-を、1番ピンに+を接続し、スピード50%で制御する場合のコード例です。pwm番号は、DC Motor毎に変えます。
##正転
await obniz.io0.output(false);
await obniz.pwm0.start({io:1});await obniz.pwm0.duty(50);
##逆転
await obniz.io1.output(false);
await obniz.pwm0.start({io:0});await obniz.pwm0.duty(50);
##停止
await obniz.pwm0.end();
#■(参考)4WDメカナムホイール車への応用例
##動画
とある制約で意外とできそうでできない #obniz にDC Motor 4台直刺しての制御、TipsとしてQiita投稿準備中。メカナムホイール 4WD Carに応用してみた。 pic.twitter.com/hL8ZowalK4
— Google Homer (@google_homer_) November 7, 2019
##コード
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<script src="https://unpkg.com/obniz@2.4.0/obniz.js" crossorigin="anonymous"></script>
</head>
<body>
<br>
<font size="5" color="#000000">
メカナムカー 4WD Direct
</font>
<br><br>
<button id="FORWARD_LEFT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↖</button>
<button id="FORWARD" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↑</button>
<button id="FORWARD_RIGHT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↗</button>
<br><br>
<button id="LEFT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">←</button>
<button id="STOP" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">停止</button>
<button id="RIGHT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">→</button>
<br><br>
<button id="BACK_LEFT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↙</button>
<button id="BACK" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↓</button>
<button id="BACK_RIGHT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↘</button>
<br><br>
<button id="TURN_LEFT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↰</button>
<button id="NULL2" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;"></button>
<button id="TURN_RIGHT" class="btn btn-warning" style="width:30%;height:50px;font-size:30px;">↱</button>
<script>
const SP =50; //走行スピード、上げ過ぎるとLow batteryになるので注意
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
/**************/
/* BUTTON操作 */
/**************/
//前進
$("#FORWARD").on('touchstart mousedown', async ()=> { await FORWARD(SP); })
$("#FORWARD").on('touchend mouseup', async ()=> { await STOP(); })
//左前
$("#FORWARD_LEFT").on('touchstart mousedown', async ()=> { await FORWARD_LEFT(SP); })
$("#FORWARD_LEFT").on('touchend mouseup', async ()=> { await STOP(); })
//右前
$("#FORWARD_RIGHT").on('touchstart mousedown',async ()=> { await FORWARD_RIGHT(SP); })
$("#FORWARD_RIGHT").on('touchend mouseup', async ()=> { await STOP(); })
//左横
$("#LEFT").on('touchstart mousedown', async ()=> { await LEFT(SP); })
$("#LEFT").on('touchend mouseup', async ()=> { await STOP(); })
//右横
$("#RIGHT").on('touchstart mousedown', async ()=> { await RIGHT(SP); })
$("#RIGHT").on('touchend mouseup', async ()=> { await STOP(); })
//左回転
$("#TURN_LEFT").on('touchstart mousedown', async ()=> { await TURN_LEFT(SP); })
$("#TURN_LEFT").on('touchend mouseup', async ()=> { await STOP(); })
//右回転
$("#TURN_RIGHT").on('touchstart mousedown', async ()=> { await TURN_RIGHT(SP); })
$("#TURN_RIGHT").on('touchend mouseup', async ()=> { await STOP(); })
//左後
$("#BACK_LEFT").on('touchstart mousedown', async ()=> { await BACK_LEFT(SP); })
$("#BACK_LEFT").on('touchend mouseup', async ()=> { await STOP(); })
//右後
$("#BACK_RIGHT").on('touchstart mousedown', async ()=> { await BACK_RIGHT(SP); })
$("#BACK_RIGHT").on('touchend mouseup', async ()=> { await STOP(); })
//後進
$("#BACK").on('touchstart mousedown', async ()=> { await BACK(SP); })
$("#BACK").on('touchend mouseup', async ()=> { await STOP(); })
//停止
$("#STOP").on('touchend mouseup', async ()=> { await STOP(); })
/*******************/
/* Motion Controll */
/*******************/
async function STOP(){
await MOVE( " " , " " ,
" " , " " );
}
async function FORWARD(speed){
await MOVE( "↑" , "↑" ,
"↑" , "↑" , speed );
}
async function BACK(speed){
await MOVE( "↓" , "↓" ,
"↓" , "↓" , speed );
}
async function LEFT(speed){
await MOVE( "↓" , "↑" ,
"↑" , "↓" , speed );
}
async function RIGHT(speed){
await MOVE( "↑" , "↓" ,
"↓" , "↑" , speed );
}
async function TURN_LEFT(speed){
await MOVE( "↓" , "↑" ,
"↓" , "↑" , speed );
}
async function TURN_RIGHT(speed){
await MOVE( "↑" , "↓" ,
"↑" , "↓" , speed );
}
async function FORWARD_LEFT(speed){
await MOVE( " " , "↑" ,
"↑" , " " , speed );
}
async function FORWARD_RIGHT(speed){
await MOVE( "↑" , " " ,
" " , "↑" , speed );
}
async function BACK_LEFT(speed){
await MOVE( "↓" , " " ,
" " , "↓" , speed );
}
async function BACK_RIGHT(speed){
await MOVE( " " , "↓" ,
"↓" , " " , speed );
}
async function MOVE( FL,FR,
BL,BR,speed ){
if ( BR == "↑" ) { await obniz.io0.output(false);await obniz.pwm0.start({io:1});await obniz.pwm0.duty(speed); }
if ( BR == "↓" ) { await obniz.io1.output(false);await obniz.pwm0.start({io:0});await obniz.pwm0.duty(speed); }
if ( BR == " " ) { await obniz.pwm0.end(); }
if ( BL == "↑" ) { await obniz.io2.output(false);await obniz.pwm1.start({io:3});await obniz.pwm1.duty(speed); }
if ( BL == "↓" ) { await obniz.io3.output(false);await obniz.pwm1.start({io:2});await obniz.pwm1.duty(speed); }
if ( BL == " " ) { await obniz.pwm1.end(); }
if ( FR == "↑" ) { await obniz.io4.output(false);await obniz.pwm2.start({io:5});await obniz.pwm2.duty(speed); }
if ( FR == "↓" ) { await obniz.io5.output(false);await obniz.pwm2.start({io:4});await obniz.pwm2.duty(speed); }
if ( FR == " " ) { await obniz.pwm2.end(); }
if ( FL == "↑" ) { await obniz.io6.output(false);await obniz.pwm3.start({io:7});await obniz.pwm3.duty(speed); }
if ( FL == "↓" ) { await obniz.io7.output(false);await obniz.pwm3.start({io:6});await obniz.pwm3.duty(speed); }
if ( FL == " " ) { await obniz.pwm3.end(); }
}
}
</script>
</body>
</html>
#■まとめ
DC Motorを直刺しできるのはobniz Boardの大きなアドバンテージなので、これを最大限生かす意味で、PWM制約のMAX6台まで直刺しで制御できるようDC Motorライブラリー自体を更新してくれたらうれしいですね。(電源が耐えられないような気もするが。。。)