【ESP32】夢のメカナムホイールラジコンを1から自作した

こんにちは。


<追記・忠告>
この作品では、購入したメカナムホイールを使用しており、ホイールを自作しているわけではありません!


前回、オリジナル2輪駆動ロボットをBlynkyで動作させる記事を投稿しましたが、今回はこいつをメカナムホイールにグレードアップした話です。

ume-boshi.hatenablog.jp


機体の向きを変えずに平行移動させられるロボットとして、メカナムホイールやオムニホイールを用いたロボットが挙げられます。
前者の機構については、DJI社の RoboMaster S1 ↓ でかなり知名度が高まった印象があります。

store.dji.com

その機体を私物として手に入れたいと思いつつも、購入するのは悔しいし、でも作り方わからないし、お金は無駄にしたくないしで何も手を付けてきませんでした。
ロボ研に所属していたのに全般的な知識は全く勉強してこなかったことが仇に。。。

そんなところに、国から超大金が届きブルジョアへの一歩を踏み出したので、踏ん切りがついて開発をし始めました次第です。


未だに機械を知らない人間としてどのように立ち回ればよいかわかりませんが、こういう作り方もあるのだと参考程度になればと思います。

機体について

前回の機体に2つのモータを追加し、タイヤをメカナムホイールに変更しました。

そのときに使用した物品達:

f:id:ume-boshi:20200723021625j:plain
特徴的なメカナムホイールの形状。かっこいいです。

基板にはモータを取り付けるようの穴が、各モータにつき最低2つずつ開いています。
ロボサイトモータには、購入時にモータ固定用の取り付けカバーが付属しており、図のオレンジの丸のように、1.5㎝の間隔でφ3.2mmの穴を空けておくだけで簡単に取り付けられます。

f:id:ume-boshi:20200723021845j:plain
4か所の取り付け位置。それぞれ穴を2つ開けただけ。

このモータによって、KiCADで基板作成できる人は、機体を加工することなくロボットを作成できるというわけであります。

モータとメカナムホイールは、金色のジョイント(軸?)の穴の中にモータの回転部を突っ込んで、ネジを締めることで取り付けられます。
もう説明が面倒くさいので、気になった人はコメントで要求してください。 https://www.vstone.co.jp/robotshop/images/nexus18076_01.jpg

基板回路については前回記事を参考にしてください。

制御について

実装機能としては、Blynkyを用いたジョイスティックによる平行移動と、バーによる回転移動を実装しました。

メカナムホイールにおける特徴である平行移動をする際は、対角線上のモータが同じ速度で移動することで実現できます。なので実質的に2つのモータの回転速度を考えるだけよいです。

f:id:ume-boshi:20200723021155p:plain
平行移動の移動速度と角度計算のイメージ図。

平行移動の計算手順としては下記のとおりです。

  1. atan2関数により、ジョイスティックのラジアンΘを -π から π の値で取得
  2. Θ = Θ + π/4 をすることで直感的な向きに補正
  3. ジョイスティックの傾き(中心からの距離)から移動速度speedを導出
  4. 右上と左下のモータ速度を speed * sin(Θ) で導出
  5. 左上と右下のモータ速度を speed * cos(Θ) で導出

1番の際に、xとyの値はBlynkyの仕様上 0 ~ 1023 までの値が取得されるため、2倍して1024を引くことで -1024 ~ 1023 の範囲にしています。前方を 0 (rad)としたかったため、arctan(y/x)の値を採用。



ソースコードも下記に示します。SSIDなどを簡略化しているので、各自のプログラムに合わせて書き加えてください。

#define BLYNK_PRINT Serial
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

/* GPIO definition */
#include <Adafruit_NeoPixel.h>
#include <Wire.h>

//色々な定義 (省略)

char auth[] = "アプリからコピーしてきたやつ";
char ssid[] = "yourSSID";
char pass[] = "yourPassword";


// 平行移動
BLYNK_WRITE(V1) {
  int x = param[0].asInt();
  int y = param[1].asInt();

  // ジョイスティックの角度を求める
  double rad = atan2(-x*2+1023,y*2-1023) +0.7854; 

  // ジョイスティックの傾け方で移動速度を調整。
  // 糞コードにつき、今回はマジックナンバー"600"を最高速度としている
  double speed = 600*sqrt((y*2-1023)*(y*2-1023)+(x*2-1023)*(x*2-1023))/1023;

  // 前後4つのモータを回す
  actMotorFB(FRONT,speed*cos(rad),speed*sin(rad));
  actMotorFB(BACK,speed*sin(rad),speed*cos(rad));
}

// 回転移動
BLYNK_WRITE(V0) {
  int direction = param[0].asInt();
  actMotorFB(FRONT,direction/2,-direction/2);
  actMotorFB(BACK,direction/2,-direction/2);
}

void setup() {
  Serial.begin(115200);

  init(); // オリジナル基板の各種初期化
  Blynk.begin(auth, ssid, pass); // Blynkyの初期化

  ledcWrite(LEDC_CHANNEL_0,0); // 初期状態ではモータを停止
  ledcWrite(LEDC_CHANNEL_1,0);
  ledcWrite(LEDC_CHANNEL_2,0);
  ledcWrite(LEDC_CHANNEL_3,0);

  pixels.clear(); // フルカラーLEDの初期化
  pixels.show();

}

void loop() {
  Blynk.run();
}

void actMotorFB(int ForB,int speedL,int speedR){ // 前後のモータをDRV8835で制御
  int R1,R2,L1,L2;
  if(ForB == FRONT){
    R1=LEDC_CHANNEL_2; R2=LEDC_CHANNEL_3;  
    L1=LEDC_CHANNEL_0; L2=LEDC_CHANNEL_1;  
  }else{
    R1=LEDC_CHANNEL_6; R2=LEDC_CHANNEL_7;  
    L1=LEDC_CHANNEL_4; L2=LEDC_CHANNEL_5;  
  }

  if(speedL >= 0){
    ledcWrite(L1,1023-speedL);
    ledcWrite(L2,1023);
  }else{
    ledcWrite(L1,1023);
    ledcWrite(L2,1023+speedL);  
  }

  if(speedR >= 0){
    ledcWrite(R1,1023-speedR);
    ledcWrite(R2,1023);
  }else{
    ledcWrite(R1,1023);
    ledcWrite(R2,1023+speedR);    
  }
}

動作例

結構いい感じで動きます。Blynkyの遅延や回転用のバーの特性を無視するとかなり良い機体になったなぁと。
ホイール部にある金色がアクセントになり、イケメンに仕上がりました。

youtu.be

スマホと機体の両方が映るように画角を調整しながら、ロボットを制御するの滅茶苦茶難しかった。。。(全然できていない)

おわりに

夢のメカナムホイールのロボットを手に入れました。手に入れたら手に入れたで、やりたかったことを忘れてしまうものですね。

使うアクチュエータと配置の仕方はわかるけど、それをどう固定していいか・どう取り付けていくかがわからないため、未だに機体作製には高いハードルを感じます。いい本はないかと、この2冊の本を軽く目を通してみたのですが、欲しい情報は見当たりませんでした。

今後はMake move thingsを読んでみて、実際にロボットを設計してみたいなと考えています(Haptics系ので作りたいものがある)。



本記事の机上の空論:こいつを玉乗りロボットにしたり、MRペットにしたいなと考えています。いつ取り掛かれるかなぁ。