CANSEND? CANDO! Controlling gripper motor via handtyping CAN protocol messages (Linux / Steadywin)

I got a gripper from some very nice SteadyWin folks at the boston robotics expo (part of boston robotics week / boston tech week) and finally got it working last week!!

 

After chatting with the steadywin folks on wechat, I got a link to their wiki.

The relevant pages are

How motor talk = registers

The way these quasi direct-drive (QDD — has small planetary gearbox, not direct drive) brushless DC (BLDC) motors with integrated controllers (driver is built into the housing) work: you write to a register to control the motor and read from the register to get statuses.

On to the practical part:

Hardware setup

The XT30(2+2) consists of the fat motor power wires and two small signal wires. [6]

Plug in the cable, then connect to 1) the power supply and 2) the USBCAN device.

** Connect USB CAN to laptop. **

** Turn on power to motor **

A bit messy, but this is what it looked like.

 

Software setup 

I got this working in Linux with the Steadywin motors.

In a nutshell:

$ uv venv
$ uv pip install python-can

$ sudo slcand -o -c -s8 /dev/ttyACM2  # [1]
$ sudo ip link set can0 up txqueuelen 1000 # [2]

# In a new terminal:
$ candump can0 # Listen to all the CAN messages back and forth

CANSEND? CANDO!

Sending CAN commands by hand

The overall flow

Check the motor is talks back and where it thinks it is using #280204 (should get a response from the motor), #21000103FFFFFF (set to position control), #34000101FFFFFF (set position to zero so we don’t get unexpected big movement — this needs to happen while torque is off, and we should get 01 in response, not 00), #00020101FFFFFF (torque on), #14020400040000 (command a position), #00020100FFFFFF (torque off).

The commands I used


cansend can0 001#01                  # ping — confirm it answers
cansend can0 001#02                  # status
cansend can0 001#280204              # read position
cansend can0 001#21000103FFFFFF      # mode = position (0x03, FFFFFF is for padding)
cansend can0 001#280204              # read position
cansend can0 001#34000101FFFFFF      # [3] set position to zero -- should get 01 as response, not 00 ! 
cansend can0 001#280204              # read position
cansend can0 001#00020101FFFFFF      # torque on (0x01)
cansend can0 001#14020400040000      # goal +1024
cansend can0 001#280204              # read position
cansend can0 001#00020100FFFFFF      # torque off (0x00)
cansend can0 001#02                  # check motor still alive. I use this because it's easy to remember

 

SUCCESS!!!!!!!111111!!!

The first high was when the motor actually talked back, the second was when it finally moved !!!!!!!!!!!!111111111!!!!!!!!!!!!!1

Parenthetical Notes

[1] Use sudo dmesg | tail to find the port, you’ll see something like […] ttyACM2: USB ACM device. (See later section on udev for how to fix it so the address doesn’t change each time you plugin the device).

[2] The TX Queue length increases the buffer so that while the motor is still processing a command, incoming commands may not get dropped. AFAIK.

[3] Reading candump. The successful reply looks like the following, where (can0 = the interface, 001 = motor CAN id, [1] for length of message, 01 for message — aka success)

can0  001   [1]  01

[6]  Iif you’re fancy you can terminate the XT30(2+2) data wire in wire ferrules with a crimper, then they fit nicely into the usb can headers)

UR5 on wheels: 80-20 and 3d prints

ur5 mount

Dane helped source a ton of 80-20 to make a nice wheeled mount for the UR5 (a really nice one tbh) so it doesn’t take over the entire living room all the time. Then we needed to actually attach the arm to the base. I remember around miters we would sometimes hang up mistakes as a funny sort of hall-of-shame. So here’s my pic. I did a 20 hr print (dat 70% infill 10 wall loops yo) that turned out to have indexing issues. Then I was like “heck it we’ll do the simplest possible mount”, dropped the indexing pins, checked the convenient ur5 base had room for the socket cap heads, and printed a … flat block with 8 holes in it. Hey. I’m far from a shop and far from free aluminum blocks, don’t have a saw, and just needed the robot off the floor for a bit (couchsurfer woo). I spent an hour printing the middle blue one, and then realized I’d measured to the inside with calipers then spec’d to the centers with CAD.The next one I was a bit smarter and printed it with no top wall, extrude cuts, and it printed in ~17 minutes. Hold it up to the robot arm:

Yay it checks out! Here’s my 3d printed block attached to the 80-20 lol. I think as a fresh grad I would have felt bad about it. Now I’m years out of my PhD (?!), feel less like I need to prove anything to anyone (i can just point to other stuff I’ve done), and don’t care so long as it gets the job done and I can move on to what I want to work on.

And now mounted. when the robot arm cracks the 3d print, flings itself off of the base, and sends me to the ER, you can tell me “I told you so”

slow website, cpu / mem at 100%? — banning IPs on aws lightsail

this is a note-to-self about a bandaid:

back / debug story

Periodically and increasingly frequently over the last few years my website would get super slow and I would just restart mysql. usually then things were happy. This time I restarted mysql and also restarted the entire server and it was still laggy (thanks possibly llm scrapers?)

( One time I was looking up project prior art and an LLM confidently linked to my blog post as prior work, but specified my friend by full name as the author lol )

Turns out the issue was actually just some bot attack exhausting server resources, per @gongomgra https://github.com/bitnami/vms/issues/420#issuecomment-1288922908

Diagnose the IP by tailing the apache access log:

Running: tail -n 100000 access_log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10 | awk '{print $1}'
In: /opt/bitnami/apache2/logs/

7432 34.32.72.73
1039 144.76.32.235
206 <turned out to be my own ip oops lol, connected to my phone hotspot to undo>

per aqyno 

Ban the IP with iptables:

sudo iptables -A INPUT -p all -s 1.2.3.4 -j DROP 
# to undo:
sudo iptables -D INPUT -p all -s 1.2.3.4 -j DROP

Note that this is not persistent across reboot.

Also note this is because my instances is so old I can’t upgrade easily nor apt install anything anymore (eg the usual fail2ban, ufw, etc.), but I’m too lazy to do a wordpress migration right now. 

Obviously a band-aid since some new ip will come around in a day or a week. But meh, happy with how fast my website runs again, briefly. A little sad that this probably costs me like $3/month in hosting costs though :///

projects blog (nouyang)