CAN weirdness


This may be electrical, but I doubt it. I’m using the pyfrc & wpilib from a couple weeks ago. Not sure of the actual rev number, though.

I have 4 CAN units connected to TalonSRX devices. If I create a new TalonSRX() one at a time and drive it (joystick), I can drive each motor just fine.

However, if I put the Talons into SpeedControllerGroups, and then create a DifferentialDrive from the SCGs, then the 1st CAN/Talon in the daisy-chain doesn’t work - but the other 3 do. IE the joystick drives 3 of the 4 motors; and the one that’s not moving is the 1st unit in the daisychain.

My $$ is on some misconfiguration, but I’m at a loss for how to debug this.

Anyone seen anything like this?


Can you please post some sample code showing what you are doing in your test?


You could also try jumbling the chain and see if it follows the controller. If the same controller doesn’t work, then it’s probably a code/ can id issue. If it’s the first one in the chain again, then I would check the wiring, however due to the the way the can bus works, if it were a wiring issue the other units shouldn’t work in most cases.


Have you tried running this in simulation yet? That will quickly point out whether it’s a software issue or a hardware issue.


AFAIK, you cannot use motor controllers from CTRE in SpeedControllerGroup, if they are not a part of WPILib. I’d be happy to be mistaken…


If that’s a limitation (not sure), I doubt it would apply to RobotPy given that everything is dynamically typed.


Just to verify - did you assign distinct addresses to the individual controllers? If I recall correctly, the WPIlib CAN software is capable of working through a few duplicates, but will saturate somewhere around four.


I thought the same thing (even considered making my own wrapper class), but then I found that there is a class named WPI_TalonSRX that does just that. It basically just implements SpeedController and extends TalonSRX, allowing for it to be in a SpeedControllerGroup.


@oleitersdorf beat me to a response, but just for emphasis:

This is true for the TalonSRX and VictorSPX classes.

That’s why we have the WPI_TalonSRX and WPI_VictorSPX classes - they extend their respective base class and implement SpeedController/Sendable/etc. to be compatible with WPILib features if you want to use them.


Sorry about that, I thought you were going to reply about something else.

If you’re using python then run it in simulator (as suggested by @virtuald); if you’re using java or cpp then I’d recommend this:
What I usually do to debug CAN issues with the TalonSRX is to check what SmartDashboard/Shuffleboard says that you are sending to the Talon (visible by adding the Talon to the display through LiveWindow, or by using something along the lines of SmartDashboard.put(‘Talon1’, talonObject1) for each talon). If the Shuffleboard/SmartDashboard shows that all talons are supposed to get power, and one of them does not, then you know its a problem with the CAN / talon configuration. However, if you see that one of them isn’t getting power, then you know it’s a problem with your code — in which case if you publish it here, I’d be happy to help you find the bug.


Since this user is using Python, it’ll be a lot less effort to just run the code in the builtin simulator and do essentially the same thing, as it will show you the power values of all your TalonSRX.


Oh I didn’t know that python had a built in simulator, so yes running it there probably would be easier. Makes me want to switch over to python…


@virtuald Thanks for the tips - will look into this.

FWIW, here’s the code. motorSetup does things like setInverted, setSafetyEnabled, etc. After this, I’m just calling ArcadeDrive on the driveTrain variable. CAN_[L|R][F|R]motor is 0,1,2,3 as the device ids on the can bus; set via the roborio web interface. (note this was with the 2018 control system… I’m updating to 2019 as well speak)

self.LF_motor = ctre.WPI_TalonSRX(robotmap.CAN_LFmotor)
self.RF_motor = ctre.WPI_TalonSRX(robotmap.CAN_RFmotor)
self.LR_motor = ctre.WPI_TalonSRX(robotmap.CAN_LRmotor)
self.RR_motor = ctre.WPI_TalonSRX(robotmap.CAN_RRmotor)
self.leftSCG = wpilib.SpeedControllerGroup(self.LF_motor, self.RF_motor)
self.rightSCG = wpilib.SpeedControllerGroup(self.RF_motor, self.RR_motor)
self.driveTrain =, self.rightSCG)


Do you have any new devices on your CAN network. I highly advise against using CAN ID 0 because it is the default CAN-ID.


Hi All - finally had a partial chance to look at this.

First off, I updated everything, WPILIB, CRTE, CAN Firmware, etc to the latest. I also assigned addresses 1-4 (it was 0-3). No change in behavior. When using ctre.WPI_TalonSRX motors, SpeedControllerGroups and DifferentialDrive, the first CAN on the bus does not move the motor, yet if I do a single WPI_TalonSRX, it works fine.

Remember - the CAN in question is the 1st CAN device on the daisy chain.

Previously, I had tried moving the offending CAN output to a different motor. IE, if CAN_1 -> Motor_1 and motor 1 doesn’t spin, then when CAN_1 -> Motor_2, what happens? In this case, Motor_2 doesn’t spin.

From all of this, I conclude the problem is with the software configuration of the CAN itself, not the device/electrical wiring.

Tomorrow, I’ll take @virtuald advice and try the simulator. Will report findings.


I tried the following program in simulation (slight modification of the tank-drive example) and it works without any issues:

#!/usr/bin/env python3
    This is a demo program showing the use of the RobotDrive class,
    specifically it contains the code necessary to operate a robot with
    tank drive.

import wpilib
from import DifferentialDrive
import ctre

class MyRobot(wpilib.IterativeRobot):
    def robotInit(self):
        """Robot initialization function"""

        # object that handles basic drive operations
        self.frontLeftMotor = ctre.WPI_TalonSRX(0)
        self.rearLeftMotor = ctre.WPI_TalonSRX(1)
        self.frontRightMotor = ctre.WPI_TalonSRX(2)
        self.rearRightMotor = ctre.WPI_TalonSRX(3)

        self.left = wpilib.SpeedControllerGroup(self.frontLeftMotor, self.rearLeftMotor)
        self.right = wpilib.SpeedControllerGroup(
            self.frontRightMotor, self.rearRightMotor

        self.myRobot = DifferentialDrive(self.left, self.right)

        # joysticks 1 & 2 on the driver station
        self.leftStick = wpilib.Joystick(0)
        self.rightStick = wpilib.Joystick(1)

    def teleopInit(self):
        """Executed at the start of teleop mode"""

    def teleopPeriodic(self):
        """Runs the motors with tank steering"""
        self.myRobot.tankDrive(self.leftStick.getY() * -1, self.rightStick.getY() * -1)

if __name__ == "__main__":

From this experiment I conclude it’s either something your robot code is doing, or it’s a hardware issue. Please try this sample program without significant modifications and let me know what you find.


This is not a problem that should take a week to troubleshoot, which means I think something obvious is getting missed.

If you haven’t already, follow the bring-up procedure below…
… including the Tuner drive part, and the C++/Java part. Yes I know you prefer python, but its been a week and you are still stuck.

Then build your diff drive in C++/Java, and test…

If all that works, then switch to Python and retest. You’ll likely discover and fix problems along the way.


Good advice, some minor corrections…

  • Phoenix API has SRX/SPX/PIgeon/CANifier
  • Neither of the above supports duplicates at all.
  • Phoenix Tuner must be used to set IDs
  • Phoenix Tuner can deal with duplicates (up to a point) so you can set IDs.

General doc link


Thank you all - yes - I found the problem. Typo in my code.

Note the left speed controller group - Left front and right front. Not left rear. Which was the motor giving me problems. So, problem solved.

Thanks to @virtuald for the tip to use the simulator. Very helpful.

@ozrien - the reason this took so long is that I’m the mentor, and work full time. Squeezing in the spare minutes to do the investigation between work assignments, getting the rio’s re-imaged, etc took its toll. I do apologize for the delay.


Fair enough - being a mentor is tough. No worries - I just want teams to succeed. Teams don’t have a lot of time as it is.