My team is building an offseason robot (for showing off at recruiting events) consisting of a basic west coast drive frame with a recliner chair mounted on top. The person sitting in the recliner holds the joystick to control the “robot”. (We’re calling it the world’s fastest couch.) Having an entire Windows computer with its own independent battery sitting on the robot communicating via WiFi to the same robot seemed a little silly to us, plus we wanted to learn something new, so we decided to replace the entire RoboRIO/driver station combo with a Raspberry Pi with a Waveshare CAN bus controller attached. We were hoping to write some custom Python code that would take input from a USB joystick and talk to the motor controllers directly via the CAN hat. Information on how to control the CTRE devices from anything that isn’t a RoboRIO running the official FRC firmware is remarkably sparse, and if CTRE has published documentation on the communication protocols their devices use below the library level, or source code to their Phoenix libraries for the RoboRIO, I can’t find it.
Has anyone tried this before? If so, how did you get it working?
Are there any available resources for this protocol, or getting the actual Phoenix libraries to work on a non-roboRIO CAN bus, or would we be better off rigging up a CAN bus sniffer and trying to reverse engineer it? I’m up for that if necessary, but if there’s an easier way I’d really rather not.
We actually natively support our devices outside of FRC for any generic socketcan adapter, or a CANivore. We also publish examples on our GitHub: CTR Electronics · GitHub
Information can be found in the installation section in our documentation. If you find some information lacking, please let us know.
Or if you are using an v5 device such as an SRX:
Unfortunately, we do not publish our CAN framing due to incidents of IP theft in the past.
One thing that you’re probably about to hear a lot of: SAFETY needs to be paramount for this type of build. You may have a fast robot+recliner with a person on top of it. What could happen if someone is on it tooling around in a parking lot and hits a car bump stop?
I can think of at least 3 failure modes that could result in serious injury, or fatality. All three have methods of preventing the failure or minimizing the injury. I would suggest taking a look at those methods…
Taking wireless control out of the loop is a step in a safer direction (minimizes control lag, makes it much harder for someone to remotely gain control). But the hardware should probably follow suit. There were two or three threads a few months ago about building robots with chairs on them (or wheelchairs), and the safety implications thereof. If you can’t find them I’m sure someone will link them soon enough.
I would say I’m sorry for the minor thread hijack, but I don’t apologize for trying to make sure people are safe.
Thank you for the prompt response! By the way, I didn’t see any examples or documentation on communicating with the CTREPDP (read battery voltage, motor current etc.) Did I miss that somewhere?
Been there, done that. I had tried a CANIvore attached to my jetson nano running Phoenix 6 python library controlling motor. I had also tried CANable controlling motors, all with success. If you use robotpy with CTRE libraries, the experience should be pretty similar. All documents on phoenix library should work.
I would also point out that as you needs to disable FRC lock (if those motor had attached to roboRIO before) and send hartbeat packet (feed enable) to keep your motor moving, These are safety feature built in to CTRE’s stuff.
You will have to design a safe way to have your robot disabled in case your software run into some issue. Some of the cheapest way of doing this is hooking up a wireless relay box to your respberry pi’s power lead but in the end it is up to you to evaluate the best way to impliment safety feature.
We did think about that. Since we’re not confident that the motors will actually stop if the Pi locks up, we’re mounting the master battery interruptor (switch between the battery and the PDP) somewhere the person in the recliner can easily press it.
Actually you could use some of these setup in FRC, if you had read team 195’s ROS implementation. But there will be some limit.
You have to have roboRIO attached, sending Enable packet to CAN network per
R714 Control CAN motor controllers from the roboRIO. Each CAN motor controller must be controlled withsignal inputs sourced from the roboRIO and passed via either a PWM (wired per R713) or CAN bus(either directly or daisy-chained via another CAN bus device) signal, but both shall not be wiredsimultaneously on the same device.
As long as the CAN bus is wired legally so that the heartbeat from the roboRIO is
maintained, all closed loop control features of the CAN motor controller may be
used. (That is, commands originating from the roboRIO to configure, enable, and
specify an operating point for all CAN motor controller closed loop modes fit the
intent of R701).
You can’t have a joystick hooked up or wirelessly connected directly to your coprocessor so you will need to pass those values.
You have to be prepared in case your coprocessor dies or crashes during match.
But this setup do have a lot of advantage. For example, if you write a custom vision stack in C++, having coprocessor controlling motors directly could means lower latency. But most of these don’t have a big enough community support as not a lot of team are using these. Still, these are interesting learning experience.
@daltzsmith Thanks for this resource! I have successfully brought up the Pi HAT as a SocketCAN device and successfully communicated with my CTRE devices. I’ve also successfully installed the CTREphoenix6 Python library and gotten it to speak over the CAN bus. However, now I am facing a new problem.
When I open the Python interpreter and import the CTRE library, it initializes its diagnostic server which I can then connect to via Phoenix Tuner from another computer. From there, I can see the all the motor controllers connected to my Pi, and even turn the motors on. It all works great! The problem arises when I try to control the same motor via Python. I can create a TalonFX object in Python, and I can use it to read the motor voltage, encoder position, etc. of the motor (and I can verify that this works by spinning the motor with my fingers and noticing the value changes), but when I send a command from Python to start the motor, the CTRE library returns “OK”, but nothing happens. If I start the motor via Phoenix Tuner and try to stop it via Python, it keeps spinning.
I believe this is because I have to “enable the robot” via Python somehow. How do I do this?
EDIT: never mind, I figured it out. I factory reset the motor controller to clear its FRC lock, and called phoenix6.unmanaged.feed_enable(...) to keep it running, as detailed here.
So you want a “Treadmill” style contact key. The system won’t power on if the magnetic key the user has clipped to them is removed from its proper spot. The clip has a shortish cord so if they fall off in theory it’ll pull the clip away from the powered item with them and turn it off.
Of course this requires the user to actually use the clip properly (or not bypass it with another magnet), but at least you’re giving them a better way to stop, and if they choose to ignore it that’s on them.
The red part is a magnet and picked up by a hall effect sensor/relay combo that will safely, but immediately decelerate the motor when it moves out of range (coast mode possibly), even if the main power is still active.
Speaking of PDP. Since PDP don’t have CAN-FD support, (I never tried) but will I have issue if I connect a PDP under a CANivore? I suppose this won’t work and I should use a seprate CAN bus for it if this is the case.
@daltzsmith Thanks for your help so far! I’ve been able to successfully control some Talon FX motors from my Pi with no issues. However, these motors are expensive and in short supply around our lab, so we’d prefer to reserve them for robots we actually compete with. For an off-season robot designed purely for promotional purposes, we thought we’d reuse some Victor SPX motor controllers that we have lying around from previous seasons. Unfortunately these do not seem to be supported by the phoenix6 Python library at all, and installing the phoenix5 library on the Pi is proving difficult. I’ve discovered that it seems to be packaged on PyPI under robotpy-ctre, however there is no ARM Linux build of the wpilib package on which it depends, and it will not install. Considering the RoboRIO itself is an ARM Linux computer, I am fairly certain such a build exists. Do you have any pointers as to how I would go about deploying it to my Pi?
looking at the CTRE linux example https://github.com/CrossTheRoadElec/Phoenix5-Linux-Example?tab=readme-ov-file
it looks like they use a CANable adapter which are all out of stock. Im not seeing many other options outside of Aliexpress which ive heard mixed reviews from and looks like it will take 3 weeks for me to get the part. Has anyone used any other socketCAN adapters with success?
I’ve used this one, it works well. (note that the FD capability of this adapter will not work with CTRE can devices, but the CAN 2.0B mode will work fine)
it would need to be a socketCAN device correct? I have a MCP2515 CAN module that i can see the CAN msgs from the victor but having some trouble getting their example code to spin a motor