Pular para o conteúdo principal

Primeiros Passos com Motores Stackforce Série X

Este artigo apresentará como começar a usar os motores da série Stackforce e como utilizá-los com C++ e Python no reComputer Jetson Super.

Especificações

Aqui está a tabela completa com todos os parâmetros preenchidos para todos os modelos de motor:

Parâmetro60108108
Tensão Nominal24V24V
Corrente Nominal10.5A7.5A
Potência Nominal240W180W
Torque Nominal5 Nm7.5 Nm
Torque de Pico11 Nm22 Nm
Velocidade Nominal120 RPM110 RPM
Velocidade Máxima270 RPM320 RPM
Taxa de Engrenagem8:18:1
Protocolo de ComunicaçãoMIT ProtocolMIT Protocol
Modos de ControleControle de Posição, Velocidade, TorqueControle de Posição, Velocidade, Torque
Diâmetro Externo80 mm97 mm
Espessura47 mm46 mm
Peso392 g ±10%395 g ±5%
Resistência de Fase0.48 Ω ±10%0.439 Ω ±10%
Indutância de Fase368 μH ±10%403 μH ±10%

Principais Recursos

  1. Alto Torque de Saída
  2. Controle em Modo MIT
  3. Realimentação por Encoder Magnético
  4. Design Compacto e Leve
  5. Suporte para Comunicação CAN Bus de Alta Velocidade
  6. Aplicações Versáteis

Guia de Introdução

Preparações Antes do Uso

Em um PC com Sistema Windows

O CANID e o CANMode do motor são ambos modificados via porta serial. O motor é enviado com um CANID padrão de 0x01 e CANMode de CAN2.0 a 1Mbps.

Fiação da Porta Serial

Conecte V, G, T, R respectivamente ao VCC (3.3V), GND, RX, TX do módulo de comunicação serial (RX e TX devem ser conectados cruzados). Como mostrado na figura abaixo:

Modificando o CANID

Defina a taxa de baud da porta serial para 1Mbps.

O CANID a ser enviado é 0x**, e o ID definido é 0x**, com um limite máximo de 0x7F. Após definir o CANID com sucesso, o seguinte log será impresso:

dica

Você pode definir o CANID:0x01 para facilitar o teste no código subsequente.

Modificando o Modo CAN

Envie CANMODE:0 ou CANMODE:1 via porta serial.

CANMODE:0 representa o modo CAN2.0 (1Mbps), enquanto CANMODE:1 representa o modo CANFD (5Mbps).

A modificação bem-sucedida do modo CAN é mostrada nas figuras abaixo:

dica

Você pode definir o CANMODE:0 para facilitar o teste no código subsequente.

Usando o reComputer Mini Jetson Orin para Controlar Motores

As interfaces de comunicação CAN mais comuns para motores no mercado são XT30 (2+2) e conectores JST. Nossos dispositivos reComputer Mini Jetson Orin e reComputer Robotics são equipados com interfaces XT30 (2+2) duplas e interfaces CAN baseadas em JST, proporcionando compatibilidade perfeita.

reComputer Mini:

reComputer Robotics

Para informações mais detalhadas sobre o uso do CAN, consulte este wiki.

Habilitando a Interface CAN

Etapa 1: Antes de usar CAN0 e CAN1, remova a tampa inferior e defina os dois resistores terminais de 120Ω para a posição ON.

Desligue a chave seletora do resistor terminal de comunicação CAN de 120Ω integrado no motor.

dica

Se o Recomputer Mini não tiver definido o resistor terminal de 120Ω para ON, você pode optar por ligar a chave seletora do resistor terminal de comunicação CAN do motor.

Etapa 2: Conecte o motor diretamente ao CAN0 do reComputer Mini por meio da interface XT30 (2+2).

dica

Como o design da interface CAN do reComputer Mini é oposto ao da interface CAN do motor, é necessária soldagem manual para inverter as linhas de dados.

Considerando a alta tensão e corrente exigidas pelo motor, recomenda-se comprar um adaptador de energia de 24V 300W para alimentar o reComputer Mini para acionar um único motor. Se for necessário conectar mais motores, pode-se adquirir um adaptador de energia de maior potência de acordo com a necessidade.

perigo

Esta fonte de alimentação é apenas para aprendizagem e teste com um único motor. Para múltiplos motores, projete uma placa de alimentação separada e isole a alimentação do Jetson da alimentação do motor para evitar que uma corrente alta passe diretamente pelo Jetson.

Habilitando a Comunicação CAN do Jetson

Abra um terminal e insira o seguinte comando para puxar o pino GPIO para nível alto e ativar o CAN0:

gpioset --mode=wait 0 43=0

Se estiver usando o CAN1 com a interface JST, puxe o pino 106 para nível alto.

gpioset --mode=wait 0 106=0

Mantenha este terminal aberto, inicie um novo terminal e configure o CAN0.

sudo modprobe mttcan
sudo ip link set can0 type can bitrate 1000000
sudo ip link set can0 up

Configurando o Ambiente C++ e Python

Etapa 1: Clone o SDK.

git clone https://github.com/Seeed-Projects/Stackforce-Motor-SDK.git 

Etapa 2: O SDK do driver requer as seguintes dependências. Para Debian Linux, elas podem ser instaladas com os seguintes comandos:

sudo apt-get install -y build-essential cmake
sudo apt install linux-modules-extra-5.15.0-1025-nvidia-tegra # For Jetson Jetpack 6.0

Se forem necessárias ligações Python, instale adicionalmente Python 3, pip e pybind11:

sudo apt-get install -y python3 python3-pip python3-pybind11 python3-setuptools

Após instalar as dependências, siga as etapas abaixo para instalar o SDK do driver como uma biblioteca C++ ou um pacote Python. Ambos usarão CMake para compilar o código C++.

Controle de Motor e Recebimento de Dados

C++

main.cpp
#include <chrono>
#include <cstdint>
#include <cmath>
#include <cstdio>
#include <thread>
#include "CAN_comm.h"
#include "config.h"

MIT devicesState[4];

uint32_t sendNum; // for testing send speed
uint32_t recNum;

MIT MITCtrlParam;

uint16_t sendCounter = 0;
bool motorEnable = true;
int receivedNumber = 0;
uint64_t prev_ts = 0;
float t = 0.0f;
float targetJointAngle = 0.0f; // Target joint angle (can be modified at runtime via input)

namespace {
uint64_t micros_steady(){
using namespace std::chrono;
return duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
}
}

void setup() {
std::printf("SF Motor Control (Jetson) start\n");
CANInit();
enable(0x01); // Enable motor with ID 0x01 <- Change ID to control different motors
prev_ts = micros_steady();
t = 0.0f;
}

uint16_t printCount = 0;
uint16_t recCount = 0;

void loop() {

recCANMessage();

// Check for new joint angle input
// (Check once every 1000 loops to avoid frequent blocking input calls)
static uint16_t inputCheckCount = 0;
if(++inputCheckCount >= 1000){
inputCheckCount = 0;
float newAngle;
if(std::scanf("%f", &newAngle) == 1){
targetJointAngle = newAngle;
std::printf("Target joint angle updated: %.3f rad\n", newAngle);
}
}

static int IDswitch = 0x01; // <- Change ID to control different motors
uint64_t current_ts = micros_steady();

/*
* Function:
* Update control parameters based on time difference and send MIT command.
*
* Parameters:
* - current_ts: current timestamp
* - prev_ts : previous timestamp
* - t : time variable used for sine/cosine calculations
* - MITCtrlParam:
* Control parameter structure including position, velocity,
* position gain (Kp), velocity gain (Kd), and torque
* - IDswitch : motor ID selector
*
* Return:
* None
*/
if(current_ts - prev_ts >= 1000){ // 1 ms control period
// Update time variable (increase by 1 ms)
t += 0.001;

// Set control parameters:
// target position, target velocity, position gain, velocity gain, and torque
MITCtrlParam.pos = targetJointAngle;
MITCtrlParam.vel = 0;
MITCtrlParam.kp = 0.5;
MITCtrlParam.kd = 0.3;
MITCtrlParam.tor = 0;

// Update previous timestamp
prev_ts = current_ts;

// IDswitch++;
// If IDswitch exceeds 0x04, reset it to 0x01
// if(IDswitch > 0x04){
// IDswitch = 0x01;
// }

sendMITCommand(IDswitch, MITCtrlParam); // Send MIT command

printCount++;
if(printCount >= 100){
printCount = 0;
// Only print when IDswitch is 0x01
// Print commanded position/velocity and actual motor position/velocity
if(IDswitch == 0x01){
std::printf( "[CMD] pos: %6.3f rad vel: %6.3f rad/s | " "[FB] pos: %6.3f rad vel: %6.3f rad/s\n", MITCtrlParam.pos, MITCtrlParam.vel, devicesState[IDswitch - 1].pos, devicesState[IDswitch - 1].vel );
}
}
}

std::this_thread::sleep_for(std::chrono::milliseconds(1));
}

int main(){
setup();

while(true){
loop();
}

disable(0x01); // Disable motor with ID 0x01
return 0;
}
cd build
cmake ..
make

O executável compilado estará localizado em build/sfmotor_control. Execute o programa:

./sfmotor_control

O programa, por padrão, controla o motor com ID 0x01. Durante a operação, você pode inserir o valor do ângulo alvo (em radianos) pelo teclado. Ele também recebe dados de retorno sobre o ângulo e a velocidade angular do motor.

Python

main.py
import sys
import time
import select

# Import core control module (assumes sf_can_controller.py is in the same directory)
from sf_can_controller import MotorController

# --- Core Configuration ---
IFACE = "can0"
MOTOR_ID = 1 # <- Change ID to control different motors
UPDATE_RATE_HZ = 100.0
PRINT_EVERY = 2
INITIAL_TARGET_DEG = 0.0

# --- Main Control Loop ---
def run_simple_test() -> None:
"""Run a simplified position control loop."""

# 1. Initialization
update_period = 1.0 / UPDATE_RATE_HZ
target_rad = INITIAL_TARGET_DEG

KP, KD = 0.5, 0.3 # Default MIT parameters

controller = MotorController(interface=IFACE, motor_id=MOTOR_ID)
print(f"--- SF Motor Test Start ---")
print(f"Interface: {IFACE}, ID: {MOTOR_ID}, Rate: {UPDATE_RATE_HZ} Hz")

# 2. Enable motor
controller.enable()

last_send_time = time.perf_counter()
print_counter = 0

inputCheckCount = 0

# 3. Main loop
while True:
controller.poll_rx()
current_state = controller.get_motor_state()

now = time.perf_counter()

# --- Periodic input check (every 500 loops) ---
inputCheckCount += 1
if inputCheckCount >= 500:
inputCheckCount = 0

# Blocking I/O waiting for user input (this will pause the control loop)
# Note: If the input is not a number, a ValueError will be raised.
line = input("Please enter target joint angle: ").strip()
if line:
angle_deg = float(line)
target_rad = angle_deg
print(f"Target joint angle updated: {angle_deg:.3f} deg")

# Periodically send MIT command
if now - last_send_time >= update_period:
last_send_time = now

# Send target position command
controller.send_mit_command(
pos=target_rad,
vel=0.0,
kp=KP,
kd=KD,
tor=0.0
)

# Print motor state
print_counter += 1
if print_counter >= PRINT_EVERY:
print_counter = 0
print(
f"Cmd={target_rad:.2f} | "
f"Pos={current_state.pos:.2f} (Vel={current_state.vel:.2f})"
)

time.sleep(0.001)


if __name__ == "__main__":
# Run test
run_simple_test()

O script Python está localizado no diretório script/ e pode ser executado diretamente, sem compilação.

python main.py 

O programa, por padrão, controla o motor com ID 0x01. Durante a operação, você pode inserir o valor do ângulo alvo (em radianos) pelo teclado. Ele também recebe dados de retorno sobre o ângulo e a velocidade angular do motor.

Citação

Step 6010

Step 8108

8108 Motor_Curve

6010Motor_Document.pdf

8108Motor_Document.pdf

Suporte Técnico e Discussão de Produto

Obrigado por escolher nossos produtos! Estamos aqui para oferecer diferentes formas de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

Loading Comments...