Yet another CAN / Swerve Help Post: CAN you dig it?

Alright, I’ve tried and tried to find the ONE post that is going to help us solve our swerve/can woes this year before posting this. We don’t think this is a coding logic issue, because redeploying code 4-5 more time corrects the issue. We believe it’s due to seeding our CANCoders absolute position. Our CANCoder logic checks to see the Initialization strategy, before seeding the angle. Unfortunately, it seems every time we boot the CANCoders start off, or default to Boot To Zero. We thought this was a value that was persistent during restarts, but we’re not finding that to be accurate.

And from a post referenced below, we have also encountered the issue of our compressor turning off and on every half a second or so, which makes us think we are using too much CAN.

This year our swerve bot is running on 14 talonFXs, 4 CANCoders, 1 Rev PCH and 1 Rev PDH for a total of 20 CAN devices. Yep, this is bad. What have we tried so far:

  • Setting all of our CAN Status frames to 5000 ms
  • Cleaning up repetitive code that would communicate with control frames as much as possible
  • Breaking the CAN frame and measuring resistance on both sides. Both resistances, measured to be 120 ohms.

Here’s are the next things we may try:

  • Moving things off the can-bus. This hurts my soul, we’re turning a smart-motor into a dumb motor
  • Changing from CANCoders to SRX Mag Encoders
  • Moving 1/2 or a 2/3rds of the can bus to CANivores. Also hurts my sould to spend $300-600 to fix this problem
  • What has your team done to fix this problem???

I was so excited this year about pushing our team to “Smart Motoring everything”. But now, I’m slightly regretting my smart motoring advocacy.

Quoting @Thad_House

I actually did some fun math the other day. With a 1Mbps, the average frc can frame is ~140 bits. That’s 7000 messages per second, assuming no collisions and no space between sends. Since that’s an impossible assumption, you probably can send a max of 5000. If you have 20 devices, each device is allocated 250 messages per second. Assuming a 10ms frame time for the control frame, that’s 100 of those 250. That means all the status frames combined must be less then 150 frames per second. If you leave a single status frame at 10ms as well, that leaves you 50 messages per second. On something like a falcon, the 9 other status frames sent at the slowest speed (255ms) is 36 frames. So you’re at 236 of your 250. And that’s with 20 devices. That leaves ~280 frames left over. That’s enough for 2 cancoders…

The math just makes it really hard to approach 20+ devices on the built in can. It’s just not a fast enough bus.

2 Likes

Ctre had the CANivore that is useful for cases like this. I believe that it only works with the talonFx and cancoder and the new pigeon. So you would have to wire two different CAN busses one for the rev and one for ctre. Ctre says that with 35 devices the can usage is around 50% for it’s new CANivore.

1 Like

It’s a good bet that CAN utilization is a (or even The) problem you are seeing. You have listed the obvious mitigations. Also, check that your CAN wiring is very solid and clean.

Is there a way to measure or characterize proper wiring and connections other than looking at each connection? We don’t necessarily have a good o-scope at school.

It has been for us, although we just set it from phoenix tuner and never touch cancoders from code. Is there a stray ConfigFactoryDefault call? Are you checking for errors from the calls to the cancoders? If your code doesn’t check for errors, it could be silently failing for some reason or another.

Pretty sure the max value is 255msec. Might want to verify that there’s also no error here.

Also, make sure PCH and PDH firmware is up to date, just to be safe

3 Likes

I use an Analog Discovery 2 (an o-scope). I’ve seen some pretty marginal CAN busses. Things have been made fairly robust with retransmissions, etc. – which serves to hide problems in some cases.

Yeah we did too. But the making sure to set it in the code if we read it and find that it’s “bootToZero” which is like every time.

 
 ​        ​public​ ​void​ ​zeroSwerveAngle​() { 
 ​            ​if​( mSteeringSensor​.​configGetSensorInitializationStrategy(​1000​)​.​value ​==​ ​SensorInitializationStrategy​.​BootToZero​.​value) { 
 ​                ​if​(mSteeringSensor​.​configSensorInitializationStrategy(​SensorInitializationStrategy​.​BootToAbsolutePosition​,​1000​)​.​value​!=​ErrorCode​.​OK​.​value) { 
 ​                    ​System​.​out​.​println(​"​ERROR: COULDN'T SET THE INITIALIZATION STRATEGY! CANCODER: ​"​ ​+​ mSteeringSensor​.​getDeviceID()); 
 ​                } ​else​ { 
 ​                    ​System​.​out​.​println(​"​ERROR: INITIALIZATION STRATEGY SET! REBOOT ROBOT! CANCODER: ​"​ ​+​ mSteeringSensor​.​getDeviceID()); 
 ​                    mSteeringMotor​.​setSelectedSensorPosition(mSteeringSensor​.​getPosition(),​0​,​1000​); 
 ​                    ​System​.​out​.​println(​"​ZEROED SENSOR VALUES FOR CANCODER ​"​ ​+​ mSteeringSensor​.​getDeviceID() ​+​ ​"​ ​"​ ​+​ mSteeringSensor​.​getPosition() ​+​ ​"​ ​"​ ​+​ mSteeringSensor​.​getAbsolutePosition()); 
 ​                } 
 ​            } ​else​ ​if​(hasSwerveZeroingOccurred ​||​ mSteeringMotor​.​setSelectedSensorPosition(mSteeringSensor​.​getPosition(),​0​,​1000​)​.​value​==​0​){ 
 ​                hasSwerveZeroingOccurred ​=​ ​true​; 
 ​                ​System​.​out​.​println(​"​ZEROED SENSOR VALUES FOR CANCODER ​"​ ​+​ mSteeringSensor​.​getDeviceID() ​+​ ​"​ ​"​ ​+​ mSteeringSensor​.​getPosition() ​+​ ​"​ ​"​ ​+​ mSteeringSensor​.​getAbsolutePosition()); 
 ​            } ​else​ { 
 ​                ​System​.​out​.​println(​"​ERROR: COULDNT ZERO MODULE: ​"​ ​+​ mSteeringMotor​.​getDeviceID()); 
 ​            }    
 ​             
 ​        }

Thanks for the reminder! We have done this as well, and couldn’t find anything to correct.

I have had an exchange with CTRE. It’s not going to solve our CAN issue problem completely, but it will at least eliminate some of the red herrings in our code:

It looks like there’s a bug with our configGetSensorInitializationStrategy method that got missed, and I used the generic method when I was testing it over the phone with you.

The workaround is to use the generic getParamEnum and pass ParamValue.eSensorInitStrategy, 0 as the parameters.

“if((int)mSteeringSensor.configGetParameter(ParamEnum.eSensorInitStrategy, 0, 1000) == SensorInitializationStrategy.BootToZero.value) {”

We’ve got the issue tracked so we’ll fix it and publish a new release, but in the meantime the workaround should work.

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.