ATmega2560でI2Cを用いてDDK0668Tを動かす方法
ダイセンの6chMCB(DDK0668T)をI2C通信を利用してATmega2560で動かす方法
これはATmega2560でI2Cを利用して6chMCBを使おうとしている方々へのまとめ記事です。これまでにこの6chMCBを使うため様々な開拓をされてきた方々の情報も簡単にまとめて載せています。リンクを貼り付けておくので、そのリンク先も是非ご一読下さい。6chMCBはダイセン電子工業さんが発売しているモータードライバーです。品番はDDK0668Tです。このモータードライバーには合計6chあり、そのchに値を送ることでモータードライバーと対応するそのモーターを動かしています。(https://www.daisendenshi.com/download/)
一見すると使えそうなモータードライバーですが、実を言うとこのモータードライバーは癖がありすぎて上手に使うことが非常に困難です。
ですが、E-gadgetで使う分に関しては問題なく動作するので、安心して使えると思います。2022年度全国大会はディフェンス機でE-gadgetにDDK0668Tを積んだ4輪ロボットで出場もしました。
まず癖の一つ目は、時々正転と逆転が入れ替わる可能性があると言うことです。プログラムには特に問題のあることを書いていなかったとしても、何故か正転と逆転が一瞬入れ替わる場合があります。これは自分はまだ対処ができていません。プログラムのせいなのでしょうか?それとも抵抗?ハードの問題?分かった人は教えていただけると幸いです。(ただし、リセットボタンを1度押すと正常に回転する)
二つ目は、スペースを取ると言うことです。このモータードライバーの大きさは横78mm * 縦93mm * 高さ10mmです。この記事を読んでいる人の大体がRCJをしている人なはずなので分かるでしょうが、RCJにおいて空きスペースの問題は非常に重要です。1100gの中に様々な物を積むことは容易ではない上に、その中にモータードライバー単体でスペースを取ってしまうと内部に物を多く置けなくなってしまうので、設計が困難になる要因にもなります。
三つ目は、ダミーデータを入れないとバスフリーズをする問題です。詳しい理由はよく分かりませんが、4chしか使わない場合でも6ch分しっかりとデータをモータードライバーに送信する必要があります。
四つ目は、参考になる記事が少ないと言うことです。私が思うにこのモータードライバーを使われる方々は4輪RCJという競技のまだ比較的初心者なのではないかと考えています(私達も4輪RCJは初心者)。理由としてはダイセン電子工業さんの製品を元々使っていた方々がそのまま4輪RCJに流れてきたという考えが挙げられます。ですが、初心者にしろ初心者でないにしろ、参考になる記事が少ないのは使う人にとってデメリットです。参考になる記事が多い方が信頼性も信憑性も増します。この記事を書く理由も、このモータードライバーに関する記事が少ないなと感じたからです。またネットに転がっている記事も情報が古いものが殆どなので、正しい情報なのか、そうでないのかが分かりにくかったです。
ここまで長々と書いてしまいましたが、正しい使用法でプログラムをしたら実際に動くのは動きます。そのためのプログラム例を書いておきます。私達はこのプログラムで動きました。またこのプログラムを書く上で参考にさせてもらったリンク先です。このリンク先に書いてあるプログラムを現在のバージョンに合うように改変しました。
(引用元:http://scitech.blog130.fc2.com/blog-entry-85.html)
------------------------------------------------------------------------------------------------------------------------------------
#include <Arduino.h>
#include <Wire.h> //I2Cを利用するので必須
void Motor(int, int);
char motor_pow[6] = {0,1,2,3,4,5}; //モーター出力用
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
int Motor_value = 30;
//モーターの番号と大きさ
Motor(0, Motor_value);
delay(5);
Motor(1, Motor_value);
delay(5);
Motor(2, Motor_value);
delay(5);
Motor(3, Motor_value);
delay(5);
//ダミーデータを送らないとフリーズorハングアウト
Motor(4, 0);
delay(5);
Motor(5, 0);
delay(5);
Wire.beginTransmission(0x14>>1); //I2Cの送信開始合図
Wire.write(motor_pow, 6 * sizeof(int));
Wire.endTransmission();
//ディレイをかけないとハングアウト
delay(5);
}
//関数
//ダイセン6chモータードライバー
//モーターnumは0〜5
//入力valは-100〜100 0でストップ 999でブレーキ
void Motor(int num, int val)
{
int mot;
if(val < 0 && val >= -100){
val = abs(val);
motor_pow[num] = val + 128;
}else if(val >= 0 && val <= 100){
motor_pow[num] = val;
}else if(val == 999){
motor_pow[num] = 128;
}else{
return;
}
}
------------------------------------------------------------------------------------------------------------------------------------
(Bloggerでプログラム埋め込む方法分かりませんでした...)
因みに最後のdelayをかけていないとフリーズします。また、このwire.write関数を使う際に配列の要素毎に送ると一回目の送信は成功し、モーターは動き始めます。しかし、二回目からの送信が失敗します。しかし、プログラムのように配列に入っている要素全てを一気に送信してやると二回目からも送信が継続されます(この事に気づくのがとても時間かかった)。
また、Hzの問題があります。以下のことを守れば、バスフリーズする確率が抑えられます。(引用元:https://yukispanicworld.tumblr.com/post/167520323134)
問題とその対策は
・100kHzであれば、ダミーデータを2つ以上入れて送信する(データ型は8バイト以上)ことで動作するが、データ欠損の様なことが起こるので確実にモータードライバーを動かすには2ms以上で連続的に命令を送信する必要がある(delayが2以上で動作する)。
・400kHzであればデータ欠損は起こらない上、ダミー命令の送信も不要だがバスフリーズ問題は避けられない。
です。
これでこの記事は終わりです。この記事を書こうと決めた理由は後世の人々が自分と同じような経験をして欲しくないからです。具体的には、
・参考になる記事が見つからない
・プログラム例が見つからない→見つけても現在のバージョンに対応していない
などです。前述したようにこのモータードライバーを使用する人は初心者の方が比較的多いと考えています。その方々が困らないように記事にして後に伝えるということはとても有意義なことだと考えています。そのため、この記事を読んで下さった方々は記事を書く事をオススメします。考えている事のアウトプットする事で分かってくることもあります。
記事に対するご不明な点や、ここおかしいだろ!という点がありましたら、コメントしていただければ、対応させていただきます。
長くなりましたが、ここまで読んで下さってありがとうございました。機会があればまた次の記事でお会いしましょう。
コメント
コメントを投稿