2022年8月28日日曜日

メカナムホイールのラジコンをRoverC化してみた

 前回ついにアナログスティックで操作が可能になったメカナムホイールラジコン。メカナムで充電式で2000円ぐらいのラジコンに文句は言えないが、最初からアナログスティックのほうが楽しいと思う…
でも改造楽しいしむしろコントローラなしの開発キットより断然安いのでこれもおもちゃのなせる技。

それはさておきMX1616の調査をするのにPWMの周波数変えたりDuty変えたりいろいろ試してみたけど、データシートをよく読んでみるとPWMモードAとPWMモードBの注意書きが。前回のESP32でのサンプルはPWMモードAで動かしていたんだけど、PWM周波数を高くしたいならPWMモードBのほうが良さそうな。結局データシートで言うモードAがFast DecayでモードBがSlow Decayっぽい。MX1508のライブラリを見てもFast DecayとSlow Decayが切り替えられるようになってたし…

テスト用にESP32にシリアル通信で周波数とDecayモードとDutyを変えられるようなプログラムを作ってみた。これで色々テストしてみたけど20kHzぐらいでもSlow Decayだといい感じにDuty10%ぐらいでも動く。PWM周波数も十分高いのでうるさくないし。とりあえずPWM周波数は14kHzぐらいで行こうと思う。

これでモータの回転数のリニアリティーが高まったので、今度はRaspberry Pi Picoを積んで見ることに。というのもせっかくメカナムのいい感じの車体なのでRaspberry Pi 3Bとかを乗っけてもいいかなと思ったので、ただしPWMを8ch分生成するのはマイコンのほうがいいし。
ということでRaspberry Pi Picoを乗っけて、i2c接続のモータドライバとして動かしてみようかなと。これはM5StackのRoverCも同じ様になっていたので、レジスタやアドレスもRoverC互換にしてみた。GroveコネクタにしてしまえばM5も乗るし…

i2cデバイスをArduinoで作るのは以前作ったものをベースにして、Raspberry Pi PicoからPWMを出力するだけ。Arduino公式のArduino Mbed OS RP2040 Boardsだとレジスタへの書き込みは問題ないから普通に動くんだけど、i2cdumpとか読み出しをするとフリーズしてしまうのでサードパティー製のArduino-Picoを使用した。Mbedとはi2cのポート選択方法が違うのと、pwmのヘッダファイルを手動でインクルードしないといけなかったけど、こっちのほうが快適に動く気がする。動作クロックを125Mhz以外で動かしたいときはclkdiv変更しないとPWM周波数も変わってしまうので注意。

//Raspberry Pi Pico
//Arduino-Pico(C++ SDK)
//CPU Speed 125Mhz

#include <Wire.h>
#include "hardware/pwm.h"

#define SLAVE_ADDRESS 0x38
//MbedI2C i2c_slave(p16, p17); // I2C SDA:GP16, SCL:GP17

#define DEBUG

#define M1p 2
#define M1n 3
#define M2p 4
#define M2n 5
#define M3p 6
#define M3n 7
#define M4p 8
#define M4n 9
#define PWMmax 255
uint SLICE[4];

//使用するレジスタ範囲指定
#define I2C_REG_ROW 1
#define I2C_REG_COL 4
uint8_t I2C_REG[I2C_REG_ROW][I2C_REG_COL];


//読み書きするレジスタアドレス
uint8_t REG_SELECTED;

boolean DATA_RECIEVED = false;

//i2c受信イベント
void receiveEvent(int _length) {
  //1byte目を読み込む(レジスタアドレス指定)
  REG_SELECTED = Wire.read();
  uint8_t startRow = REG_SELECTED >> 4;
  uint8_t startCol = (REG_SELECTED & 0x0F);

#ifdef DEBUG
  Serial.print("REG:");
  Serial.println(REG_SELECTED, HEX);
#endif

  while (Wire.available() > 0) {
    if (startRow < I2C_REG_ROW && startCol < I2C_REG_COL) {
      DATA_RECIEVED = true;
      I2C_REG[startRow][startCol] = Wire.read();
#ifdef DEBUG
      Serial.print("Write:");
      Serial.println(I2C_REG[startRow][startCol], HEX);
#endif
    } else {
      Wire.read();
    }
    ++startCol;
  }
}

//i2c読み込みイベント
void requestEvent() {
  uint8_t startRow = REG_SELECTED >> 4;
  uint8_t startCol = (REG_SELECTED & 0x0F);

  if (startRow < I2C_REG_ROW && startCol < I2C_REG_COL) {
    Wire.write(I2C_REG[startRow][startCol]);
  } else {
    Wire.write(0xff);
  }
}

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
pinMode(LED_BUILTIN,OUTPUT);
toggle_led();

  //SlaveでWireライブラリを初期化
  Wire.setSDA(16);
  Wire.setSCL(17);
  Wire.begin(SLAVE_ADDRESS);
  //イベント設定
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);

  gpio_set_function(M1p, GPIO_FUNC_PWM);
  gpio_set_function(M1n, GPIO_FUNC_PWM);
  gpio_set_function(M2p, GPIO_FUNC_PWM);
  gpio_set_function(M2n, GPIO_FUNC_PWM);
  gpio_set_function(M3p, GPIO_FUNC_PWM);
  gpio_set_function(M3n, GPIO_FUNC_PWM);
  gpio_set_function(M4p, GPIO_FUNC_PWM);
  gpio_set_function(M4n, GPIO_FUNC_PWM);

  SLICE[0] = pwm_gpio_to_slice_num(M1p);
  SLICE[1] = pwm_gpio_to_slice_num(M2p);
  SLICE[2] = pwm_gpio_to_slice_num(M3p);
  SLICE[3] = pwm_gpio_to_slice_num(M4p);

  // PWM周期を設定
  for (int i = 0; i <= 3; i++) {
    pwm_set_clkdiv(SLICE[i], 35);  // 125,000Khz/(255*14Khz)
    pwm_set_wrap(SLICE[i], PWMmax);
    pwm_set_chan_level(SLICE[i], PWM_CHAN_A, 0);
    pwm_set_chan_level(SLICE[i], PWM_CHAN_B, 0);
    pwm_set_enabled(SLICE[i], true);
  }
}

void loop() {
  if (DATA_RECIEVED == true) {
    setspeed();
    DATA_RECIEVED = false;
  }

}

void setspeed() {
  int8_t pwm[4];
  for (int i = 0; i <= 3; i++) {
    pwm[i] = (int8_t)I2C_REG[0][i];
#ifdef DEBUG
    Serial.print("PWM:");
    Serial.println(pwm[i]);
#endif
    if (pwm[i] >= 0) {
      pwm_set_chan_level(SLICE[i], PWM_CHAN_A, (PWMmax - (pwm[i] * 2)));
      pwm_set_chan_level(SLICE[i], PWM_CHAN_B, PWMmax);
    } else {
      pwm_set_chan_level(SLICE[i], PWM_CHAN_A, PWMmax);
      pwm_set_chan_level(SLICE[i], PWM_CHAN_B, (PWMmax - abs(pwm[i] * 2)));
    }
  }
  toggle_led();
}

void toggle_led() {
  static boolean led_state = false;
  led_state = !led_state;
  digitalWrite(LED_BUILTIN, led_state);
}

とりあえずこれでi2cからモータ制御できるようになった。watchdogとかつけるべきかも…
1秒通信しなかったらタイムアウト的なやつ。
とりあえずRaspberry Pi 3Bからのコマンドではモータが動いてるけど回転のリニアリティー確認用にRoverC用のソフトをESP32に乗せてテストしてみるか…
i2cでホストが色々すげ替えられる様になったのでESP32乗っけてラジコンとして遊んでもいいしラズパイ乗っけてDonkey Carみたいなのを乗っけても面白そう。

次回は車体の上を平らにして色々乗っけられるようにしたい。

2022年8月27日土曜日

メカナムホイールのラジコンを改造してESP32で動かす

 前回分解してみたメカナムホイールのラジコン、制御基板の様子もわかったことだし改造してみた。

モータドライブICのMX1616Hはそのまま使えそうなので、基板はそのままに改造してみることに。電源スイッチや充電ポートもそのまま使えるし。
その前に改造のときに基板を動かしているとケーブルが切れそうだったのでホットボンドでケーブルを補強。
モーターにつながっているケーブルのところにホットボンドを流し込む。多分これをしておかないと振動でも切れそうなんだけど…
そしたらそしたらレシーバのIC(XC2455B)を剥がす。はんだですべての足をショートさせてはんだごて2本で外した。無理をするとパターンが持っていかれそうな基板。
そんでもってMX1616Hの入力に直接線をハンダ。ICのピンに直結したのはパターンにケーブルハンダしたら剥がれそうだったので。
そして先程と同様にホットボンドでケーブルを固定。あとGNDも引き出した。電源はとりあえず別電源で試してみようと思っているので今回は信号線のみ。
基板をもとに戻したらとりあえず準備は完了。
この上にユニバーサルプレートをマウントしたいなぁ。平面がないのでブレッドボードとか置きにくい。

とりあえず動作確認としてESP32で適当なプログラムを作ってみた。ESP32ならPWMも16ch出せるし、Bluetoothでコントローラ直結できるし。
本当はMX1616Hのロジック電圧を切り離したかったけど、基板改造が面倒だったので直結。ESP32からは出力しかないしMX1616HのHighのしきい値まで出てれば認識できるだろうし。

PWMの周波数は高すぎるとDutyが低いところで全く動かないのでとりあえず2kHzで動かしてみている。コントローラはBLEでXboxのコントローラと接続している。(Nimbleライブラリ使用)ESP32の電源は1300mAの小さなモバイルバッテリを積んでる。

とりあえずアナログのジョイスティックになるだけで断然コントロール性が上がった。オンオフしかない純正のプロポには戻れないぞ。このぐらい改造が簡単ならメカナムロボットのベースとしてもいいかも。ロボットキット買ったり、自作するよりも安いかも…
まずはPWMで動くことがわかったのでもうちょっとソフトを煮詰めよう。

しかしPWMにしてもDutyが40%以上じゃないとモータが回らなかったりしているので、もう少しPWMの設定を煮詰める必要はあるかも。
次回はモータドライバのPWM制御を改善してみる。


2022年8月26日金曜日

メカナムホイールのラジコンを分解してみた

 前回購入したメカナムホイールのラジコンを早速分解してみた。やっぱりオンオフ入力だけじゃ全然うまくコントロールできなくてすぐ飽きた…
改造してアナログ入力対応にしたいのでまずは調査。

裏側(スイッチがある方が裏)のプラスネジを6本取るとカバーが外れる。
作りは悪くない。というか思ったより良い作りをしていると思う。(改造ベースとして)
蓋を開けてもギアボックスが取れてきたりしないのでこの状態でも走れそう。
モーターは130モータが4つ。ギアボックスは前後で同じ設計のデュアルタイプのものが2つついてる。
バッテリは14500タイプのリチウムイオンバッテリだった。容量は500mAh。コネクタはPHコネクタっぽい。
JD-00742BBR-2213RX

制御基板の方は結構簡単な構造。モータドライバはMX1616Hが2つ。XC2455BってなってるICにはアンテナ出力がついていたり、モータドライバに直結されていたりしているので、2.4Ghzの無線内蔵のマイコンかな?SOT-23のICはXC2455B用の3.3Vレギュレータ。
分解する前は改造の際にモータドライバとしてDRV8833あたりを載せてもいいかなと思っていたんだけど、データシート見る限りはもともと乗っているMX1616Hがそのまま使えそうだ。
MX1616HはMX1508とピンコンパチ。スペック的にも電子工作用に出回ってるMX1508やDRV8833に近いし、MX1508の情報がそのまま参考にできそう。MX1616とMX1616Lもあるようだけど何が違うんだろう…

電源スイッチはオフにすると充電端子に切り替わるように接続されていた。オンにすると充電器からは切り離される。充電回路はUSB端子の根本側についていた。

ちなみにモータの接続はM1が右後、M2が左後、M3が右前、M4が左前になってた。

モータドライバそのまま使えそうなので改造としてはXC2455Bを剥がして、各MX1616Hからケーブルを4本ずつ出せばいいのか。8本+GNDでモータ4個制御できそう。
ケーブルたくさん出すのが面倒なのでRoverCみたいにI2C経由でコントロールできるようにしたいなぁ。PWM8ch出せるお手軽なマイコンとかで…
まぁ8本出してきて全部ESP32に突っ込んでも良さそうだけど。

次回はついに基板を改造してみる。


2022年8月24日水曜日

小型ドローンSky Fight Xを買ってみた。

 昔やっていたクアッドコプター、登録するまでもないので最近解体したんだけど、おもちゃのドローンを買ってみようと思い立って買ってみた。
最初はHolyStoneのHS210あたりを狙っていたんだけど、同じサイズでSky Fight Xっていうのがヤフオクやメルカリに安く出ていたので、仲間内で募って複数台購入してみた。複数台割引で一人あたり920円だった。とても安い。

箱にぎっしり6台ほど詰まってきたが、ちゃんと交換用羽や日本語の説明書とかも人数分付属していた。バッテリは702025サイズの220mAhでコネクタはPHコネクタ。
中身はHS210やe010に似ている、モータがコネクタ式になっていたり、赤外線トランスポンダがついていた。事業用ドローンということもあって詳細は不明だけどドローンレースのタイム測定用とかに使うものかもしれない。DipスイッチでID変更できる感じだったし。
とりあえずトランスポンダは使わないので取り外した。重量は1gぐらいなんだけど、高輝度な赤外線LEDを積んでいるだろうからこれを外すだけでバッテリ消費が抑えられると思う。受信機がないと使い物にならないし。
気圧センサで高度を自動で保持してくれるんだけど、これも前にフライトコントローラーに対策していたようにスポンジを付けておいた。これで風が直接あたって値がふらつくのを防止できる気がする。
ちなみにレシーバはRF2500っていうICだった。e010と同じチップだと思う。プロポの方はRF2518なのでこれもe010と同じチップかも。もしかしてマルチプロトコルプロポとか使えたりしないかなぁ?プロポはブザーが少しうるさかったのでブザーの穴にテープを張っておいた。

飛ばした感じはめちゃめちゃ安定して飛ばすことができる。これは楽しい。一緒に購入した仲間もみんな結構ハマっているので良かった。みんな追加のバッテリが欲しくなっている。
使えそうなバッテリ探すか




2022年8月21日日曜日

メカナムホイールのラジコンを買ってみた

 メカナムホイールで遊びたくなったのでメカナムホイールを探していたんだけど、部品点数が多いからか地味にお高い。というわけでメカナムホイールを装着しているラジコンを探していたんだけど、2000円以下で売っているものを発見。メカナムホイール買うより安いのでポチってみた。

SQ2335-058SQ2335-058
DRIFT CAR EXTREME。メカナムホイールとは言っていない。
確かにメカナムホイールだとドリフトしてるような動きできるけど。まぁおもちゃだし。
SQ2335-058
説明書にはスタント用ドリフトリモコンカーってなってる。ちゃんと日本語の説明書だった。しかも変な日本語っぽくもなかったぞ…さすが定価は4000円以上するだけある。
そして本体は思ったより質感が良い。プロポはめっちゃしょぼい。

ラジコン本体はUSB充電できるバッテリー式。付属の充電器で充電中はUSBコネクタ部が赤く光る。充電完了で消える。
プロポは今どきの2.4Ghzタイプで乾電池が2本だった。自動ペアリングっぽい。
プロポは左のパッドは上下、右のパッドは左右にしか動かない。あとはLとRボタンにスタントボタン。全部タクトスイッチのデジタル入力。上下左右ぐらいはアナログが欲しかったなー。さすがおもちゃ。対象年齢が低いのもあって、電池蓋はネジ式である。

メカナムホイールは65mmタイプだった。60mmのやつがよく売っているけど、4個で3500円のことを考えるとホイール取り用にしてはいい買い物をした気がする。
電源を入れると青く光る。このラジコン、裏表どっちでも操作できるんだけどセンサーとかはついてないので裏になると操作が前後逆転する。
そしてやっぱりアナログ入力ほしいし、旋回がLとRボタンはとってもやりにくい。家の中で遊ぶのにいきなり全速全開は危ない。

まぁ少し遊んだら分解してみよう。多分これアナログスティックで操作できたらすごく楽しいと思う。ドリフトの定常円旋回みたいな動きは流石にデジタル入力だときつい。
Amazonで売っているOSOYOOのメカナムホイールキットは知り合いが購入したのを借りて、これまたコントローラアプリが微妙だったのでゲームパッドで遊べるようにソフトを変更してみたけどなかなか面白かった。

とりあえずこいつをゲームパッドで動くようにはしてみたいな。
次回は分解