高トルクDDTモーター https://www.switch-science.com/catalog/8248/ のコントロール方法をまとめてみます。
必要なもの
- 任意のSPI機能が使えるマイコン(今回はRaspberryPi Pico https://www.switch-science.com/products/6900 )
- CANトランシーバー
- 24V10~20A電源
電源は22V以上必要でしたトルクが減ってもいいからと18Vで動かすといったことはできません。また、電流容量の少ない電源での運用はよほど負荷が少なく安定していないと安定動作が難しいので、しっかりと容量を確保するのがおすすめです(移動体として動作させたとき、段差にぶつかるだけでも瞬間的に大電流を要求されます)。
ケーブルについて
付属のケーブル長は約0.5m。
番号
|
役割 |
色 |
1 |
VCC(24V) |
赤 |
2 |
GND |
黒 |
3 |
CAN High |
黄 |
4 |
CAN Low |
白 |
CANアダプタについて
[Amazonの例](https://amzn.asia/d/b9DWvV3)
MCP2515は任意のVCC(2V~5V)で動くSPI接続のCANアダプタです。
Picoとの接続
Pico名称
|
ピン番 |
MCP側名称 |
unuse |
- |
INT |
SCK |
GP2 |
SCK |
SDO |
GP3 |
MOSI |
SDI |
GP4 |
MISO |
|
GP28 |
CS |
GND |
- |
GND |
3.3V |
- |
VCC |
M15の資料
https://doc.switch-science.com/media/files/bb32803a-dbdb-45a6-8cc5-0558f81eb66b.pdf
主に使う指令コマンド
0x106: ステータスレポート頻度の指定コマンド
モーターから自発的に出力するのを止めるために0x80を指定。
0x105: モーター制御モードの指定コマンド
0x00: Open Loopモード(0x00)を指定。
0x01: 電流制御モード
0x02: 速度制御モード
0x03: 角度制御モード
0x09: モーター無効化
0x0a: モーター有効化(電源ON時、有効)
0x107: ステータスレポートの発行要求コマンド
ループ処理中にこれを送信してレポートを吐かせる。
出力させる項目をいくらか指定できる。
0x32: 制御目標値の設定
TinyGoで制御サンプル
あらかじめ必要
準備
go mod init sample
go get tinygo.org/x/drivers
サンプルコード
package main
import (
"fmt"
"machine"
"runtime"
"time"
"tinygo.org/x/drivers/mcp2515"
)
var (
spi = machine.SPI0
csPin = machine.GP28
)
func ReadFrame(can *mcp2515.Device) (*mcp2515.CANMsg, error) {
for !can.Received() {
runtime.Gosched()
}
return can.Rx()
}
func main() {
for !machine.Serial.DTR() {
time.Sleep(100 * time.Millisecond)
}
led := machine.LED
led.Configure(machine.PinConfig{
Mode: machine.PinOutput,
})
if err := spi.Configure(
machine.SPIConfig{
Frequency: 500000,
SCK: machine.GP2,
SDO: machine.GP3,
SDI: machine.GP4,
Mode: 0,
},
); err != nil {
println(err.Error())
}
can := mcp2515.New(spi, csPin)
can.Configure()
if err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz); err != nil {
println(err.Error())
}
if err := can.Tx(0x109, 8, []byte{0, 0, 0, 0, 0, 0, 0, 0}); err != nil {
println(err.Error())
}
msg, err := ReadFrame(can)
if err != nil {
println(err.Error())
}
fmt.Printf("%#v\n", msg)
if err := can.Tx(0x106, 8, []byte{0x80, 0, 0, 0, 0, 0, 0, 0}); err != nil {
println(err.Error())
}
msg, err = ReadFrame(can)
if err != nil {
println(err.Error())
}
fmt.Printf("%#v\n", msg)
if err := can.Tx(0x105, 8, []byte{0x00, 0, 0, 0, 0, 0, 0, 0}); err != nil {
println(err.Error())
}
msg, err = ReadFrame(can)
if err != nil {
println(err.Error())
}
fmt.Printf("%#v\n", msg)
for {
if err := can.Tx(0x107, 8, []byte{0x01, 0x01, 0x02, 0x04, 0x55, 0, 0, 0}); err != nil {
println(err.Error())
}
msg, err = ReadFrame(can)
if err != nil {
println(err.Error())
continue
}
fmt.Printf("%#v\n", msg)
if err := can.Tx(0x32, 8, []byte{0x00, 0x00, 0, 0, 0, 0, 0, 0}); err != nil {
println(err.Error())
}
led.Low()
time.Sleep(5 * time.Millisecond)
led.High()
time.Sleep(5 * time.Millisecond)
}
}
ビルドと書き込み
ビルドのみ
tinygo build -target pico -o sample.elf .
ビルド&書き込み
tinygo flash -target pico .
まとめ
- DDTのCANインターフェース利用にMCP2515が便利
- TinyGoにはドライバーが提供されているので利用も簡単