Error at com.revrobotics.CANSparkMaxLowLevel:A CANSparkMax instance has already been created with this device ID

Hi everyone, our team keeps having this error code when plugging the SparkMax Controller.

Error at com.revrobotics.CANSparkMaxLowLevel.(CANSparkMaxLowLevel.java:137): Unhandled exception: java.lang.IllegalStateException: A CANSparkMax instance has already been created with this device ID: 8
at com.revrobotics.CANSparkMaxLowLevel.(CANSparkMaxLowLevel.java:137)
at com.revrobotics.CANSparkMax.(CANSparkMax.java:191)

We have tried pretty much every debugging step and nothing seems to work. We have the controller plugged into the CAN bus with other CTRE controllers and we have updated them, reassigned ID’s and burned them to memory using the REV Client API. We unplugged the CAN BUS and followed every other solution offered here on Chief Delphi, and yet the same error code. It happens even when simulating the code. Any ideas or solutions would be very appreciated.
Cheers!

That error message occurs when you are using duplicate IDs in code. So somewhere you’re creating two CANSparkMax with ID 8 in your program. There isn’t much we can do without seeing the whole source, but make sure all your CAN IDs in code are correct and that you aren’t creating multiple instances of any subsystems.

1 Like

There is only one device with this ID, we even tried to hardcode it with no success, I’ll post the code

package frc.robot.subsystems;

import com.revrobotics.CANSparkMax;
import com.revrobotics.CANSparkMax.IdleMode;
import com.revrobotics.CANSparkMaxLowLevel.MotorType;

import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants;

public class Wrist_SS extends SubsystemBase {
  /** Creates a new Arm_SS. */

private final CANSparkMax m_WristMotor;

  public Wrist_SS() {
    //_armMotor = new CANSparkMax(Constants.BP_Constants.kArmMotorPort8, MotorType.kBrushless);
    m_WristMotor = new CANSparkMax(Constants.Wrist_Constants.kWristMotorPort8, MotorType.kBrushless);

  }
  @Override
  public void periodic() {
    // This method will be called once per scheduler run
  }
 
  public void WristLeft() {
    m_WristMotor.set(0.3);
  }
  public void WristRight() {
    m_WristMotor.set(-0.3);
  }
  public void wristStop(){
    m_WristMotor.stopMotor();  
  }
}

----------------------------------
Constants declaration 
 public static class Wrist_Constants {
    public static final int kWristMotorPort8 = 8;
  }

I can’t say for sure unless I could see the whole source code but my best guess is that you might be creating multiple instances of the subsystem. Check your commands and make sure you are not creating new instances of the subsystem and instead are passing in the existing subsystem from robotcontainer.

1 Like

I’ll make sure to double-check the number of instances created.

RockosBos, you were right, I just found that two instances of the same controller were being created at once, one in the Subsystem and the other in the Command.

public WristFWD_CMD(Wrist_SS p_Wrist_SS) {

    mWrist_SS = new Wrist_SS(); //here is the error 
    addRequirements(p_Wrist_SS);
  }

Silly and stupid mistake, thanks a lot for helping me figure it out.
The moral is, always make sure to thoroughly double checked every bit of the code.

1 Like

We trace the usage of a class to the console. Helps answer questions like “Why didn’t it work? - It was never executed’” or “Why is there a duplicate resource error message? - It was executed multiple times.”

You can use similar code in an instance constructor for slightly different information to catch the duplications (remove the block static qualifier).

package frc.robot.subsystems;

import java.lang.invoke.MethodHandles;

/**
 * Use this class as a template to create other subsystems.
 */
public class ExampleSubsystem extends Subsystem4237
{
    // This string gets the full name of the class, including the package name
    private static final String fullClassName = MethodHandles.lookup().lookupClass().getCanonicalName();

    // *** STATIC INITIALIZATION BLOCK ***
    // This block of code is run first when the class is loaded
    static
    {
        System.out.println("Loading: " + fullClassName);
    }

Make your subsystems singletons

Throw an error on excessive instantiations - don’t mask faulty logic by ignoring it.

Singletons are a completely valid way of interfacing with subsystems it’s not a “mask” for “faulty logic”

If you need an instance of a subsystem then chances are you’ll probably just pass it into the method anyways so instead of doing that why not just use a singleton to have direct access to the instance? I can’t think of many ways of creating bugs because I have a singleton after personally only benefiting from their convenience. If you have bugs because you’re using a singleton it was probably destined to happen.

Absolutely true and I prefer to control my destiny to see bugs sooner than later. I’m sure everyone feels that way so I’m surprised that our learned, highly experienced software engineer @kreeve threw a “?” at me without explanation (my team likes to learn from others). [Last night team mentors spotted team students making OPs error of inappropriate duplicate references to subsystems so it’s a hot button for me today. Our code review staved off errors.]

My initial response and :question: react were sent from my phone while I was at the gym, here’s a more detailed explanation:

A singleton (wiki link for anyone reading who hasn’t seen the term before) actually is a nice way to throw an error on excessive instantiations. However, it throws the errors at compile time, so you don’t have to wait until you already have code running on simulation or Rio to see the issues!

Excellent example and good advice. Thank you.

My team is following the WPILib documentation Dependency Injection and don’t want the students to make even a hint of GetInstance or new which they are wont to do.

Dependency injection is great, and it should be used heavily! If you define your command as class MyCommand and have a constructor that takes a MySubsystem, you can still still inject the Singleton instance from Robot.java by doing Command cmd = new MyCommand(MySubsystem.getInstance()).

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