cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

Arduino Uno R3とCAN-BUS Shieldを使って、DDT M15モータをテストしたときのコード

DDT M15[1]は、Switch Scienceで輸入されている中国製の安いけど比較的よくできたモーターです。
いいところは置いておいて、問題点だけ列挙しておきます。
・マニュアルがなんか変
・電源電圧の範囲が狭い。24Vが規定電圧で、下限が22V以上で、動作する上限の記述がなし。瞬間最大定格は63V。18V-22Vに落ちても即停止とはならないけれど、アラームが付く。つまり、かなり安定した電源を用意しなければならない。
・初代からバージョンが進んでいるのに、速度制御が怪しいらしい。
・タイヤの交換できなさそう。タイヤの向きの変更方法も不明。

Switch Scienceの方がサンプルコードを公開してくださっているのですが、面倒くさいことにGo言語なので、Arduino用にちょっと書き直してみます。
高トルクモーターDDT-M15の使い方 #DirectDriveTech — スイッチサイエンス

使用機材は、Arduino Uno R3とSeed Studio CAN-BUS Shild v2です。
また電源は、OWON SPE6103(60V/10A)です。最大出力電流がモーターの最大負荷時の電流未満なので、最大負荷テストはできません。
テスト用の土台は、ダイソーで買ってきた木材とアルミのは材で製作しました。

DDT M15のテスト環境


www.youtube.com

// demo: CAN-BUS Shield, send data
// loovee@seeed.cc


#include <SPI.h>

#define CAN_2515
// #define CAN_2518FD

// Set SPI CS Pin according to your hardware

#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat:
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN  = BCM8;
const int CAN_INT_PIN = BCM25;
#else

// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif


#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif

#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif

byte canTx(int id, unsigned char stmp[8], int delay_ms = 10 )
{
    // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
    byte ret = CAN.MCP_CAN::sendMsgBuf(id, 0, 8, stmp);
    delay(delay_ms);                       // send data per 10ms
    SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");

    return ret;
}

byte canRx(byte& len,unsigned long &id, unsigned char *buf)
{
    byte ret = 0;
    if (CAN_MSGAVAIL == CAN.checkReceive()) {         // check if data coming
        ret = CAN.readMsgBuf(&len, buf);              // read data,  len: data length, buf: data buf

        unsigned long canId = CAN.getCanId();

        SERIAL_PORT_MONITOR.println("-----------------------------");
        SERIAL_PORT_MONITOR.print("get data from ID: 0x");
        SERIAL_PORT_MONITOR.print(canId, HEX);
        SERIAL_PORT_MONITOR.print("\t");

        for (int i = 0; i < len; i++) { // print the data
            SERIAL_PORT_MONITOR.print(buf[i]);
            SERIAL_PORT_MONITOR.print("\t");
        }
        SERIAL_PORT_MONITOR.println();
    }  
}

void setup() {
    SERIAL_PORT_MONITOR.begin(115200);
    while(!Serial){};

    while (CAN_OK != CAN.begin(CAN_1000KBPS)) {             // init can bus : baudrate = 500k
        SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
        delay(100);
    }
    SERIAL_PORT_MONITOR.println("CAN init ok!");
    
    byte len = 0;
    unsigned long id = 0;
    unsigned char recv_buf[8];

    // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
    unsigned char motor_can_terminal_resistor_switch_setting[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    canTx(0x109, motor_can_terminal_resistor_switch_setting);
    canRx(len, id, recv_buf);

    unsigned char set_status_report[8] = {0x80, 0, 0, 0, 0, 0, 0, 0};
    canTx(0x106, set_status_report);
    canRx(len, id, recv_buf);

    unsigned char setting_mode_and_feedback[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    canTx(0x105, setting_mode_and_feedback);
    canRx(len, id, recv_buf);
}

void loop() {
  byte len;
  unsigned long id;
  unsigned char recv_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};

  unsigned char query_operation[8] = {0x01, 0x01, 0x02, 0x04, 0x55, 0, 0, 0};
  canTx(0x107, query_operation);
  canRx(len, id, recv_buf);

  unsigned char sending_in_openloop[8] = {0x10, 0x01, 0, 0, 0, 0, 0, 0};
  canTx(0x32, sending_in_openloop);
  canRx(len, id, recv_buf);
}

// END FILE

ボリュームで回転速度を調整できるように修正。中央が0なことに注意。

void loop() {
  byte len;
  unsigned long id;
  unsigned char recv_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};

  int i = analogRead( PIN_ANALOG_INPUT );
  float RANGE_MAX = 32767.f;
  float RANGE_MIN = -32767.f;
  float f = (float)i / 1023.f * (RANGE_MAX-RANGE_MIN) + RANGE_MIN;
  Serial.println( f );

  unsigned char query_operation[8] = {0x01, 0x01, 0x02, 0x04, 0x55, 0, 0, 0};
  canTx(0x107, query_operation);
  canRx(len, id, recv_buf);

  unsigned char data0 = ((int)f >> 8) & 0xff;
  unsigned char data1 = ((int)f) & 0xff;
  unsigned char sending_in_openloop[8] = {data0, data1, 0, 0, 0, 0, 0, 0};
  canTx(0x32, sending_in_openloop);
  canRx(len, id, recv_buf);
}

[1] DDT M1502D_233 タイヤ付きダイレクトドライブモーター 24V/9.6Nm/115rpm — スイッチサイエンス