Help needed with programming Control Panel spinner

Hello everyone. Team 8051 is trying to detect the amount of spins that the control panel has by using the color sensor to detect color. Basically, we created variables fro the amounts of blues, greens, reds and yellows that it it finds. We then basically used an if statement where if the total of all of the colors counted is 9, then it will count one spin because there are a total of 8 colors plus the one color that would bring the wheel back to the first color. According to the smart board panel, this code works in counting spins when we get rid of the if statement that requires “getRawButton(1)” in the robot Periodic method. The point of the if statement though is to halt the process of counting the colors and spins everything until after the button is pressed, this way we can wait until the robot is actually at the control panel until it starts counting. Do you guys have any suggestions on how we could make the robot count accurately while still having it only call the method when raw button one is pressed?(raw button one is A by the way). Also, do you think the control panel could accurately detect/count color even when the wheel is spinning at high speeds? We’ve only tested it with low speeds so far so admittedly I’m a little concerned. I appreciate any and all advice that you all have.

Robot.java:
/----------------------------------------------------------------------------/
/* Copyright © 2018 FIRST. All Rights Reserved. /
/
Open Source Software - may be modified and shared by FRC teams. The code /
/
must be accompanied by the FIRST BSD license file in the root directory of /
/
the project. /
/
----------------------------------------------------------------------------*/
package frc.team8051;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.command.Scheduler;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import frc.team8051.commands.drivebase.TestDrive;
import frc.team8051.sensors.DrivebaseEncoder;
import frc.team8051.sensors.Gyro;
import frc.team8051.services.OI;
import frc.team8051.subsystems.ColorSensor;
import frc.team8051.subsystems.DifferentialDriveBase;
import frc.team8051.subsystems.Drivebase;
public class Robot extends TimedRobot {
private static Robot robot;
private Drivebase drivebase;
private OI oi;
private TestDrive testDrive;
private DifferentialDriveBase differentialDriveBase;
private DrivebaseEncoder drivebaseEncoder;
private Gyro gyro;
private ColorSensor colorSensor;
// private final I2C.Port i2cPort = I2C.Port.kOnboard;
//private final ColorSensorV3 m_colorSensor = new ColorSensorV3(i2cPort);
//private final ColorMatch m_colorMatcher = new ColorMatch();
//private final Color kBlueTarget = ColorMatch.makeColor(0.143, 0.427, 0.429);
//private final Color kGreenTarget = ColorMatch.makeColor(0.197, 0.561, 0.240);
//private final Color kRedTarget = ColorMatch.makeColor(0.561, 0.232, 0.114);
//private final Color kYellowTarget = ColorMatch.makeColor(0.361, 0.524, 0.113);

Robot() {
    robot = this;
    oi = new OI();
    differentialDriveBase = new DifferentialDriveBase();
    drivebaseEncoder = new DrivebaseEncoder();
    gyro = new Gyro();
    gyro.calibrate();

    colorSensor = new ColorSensor();

}

@Override
public void robotInit() {
    oi.initializeBind();
    testDrive = new TestDrive();
     colorSensor.initializeColor();
     colorSensor.setToZero();
}

@Override
public void robotPeriodic() {
    Scheduler.getInstance().run();
   if(oi.joystick.getRawButton(1)){
        colorSensor.SenseColor();
   }
}

@Override
public void autonomousInit() {
}

@Override
public void autonomousPeriodic() {
}

@Override
public void teleopInit() {
    System.out.println("Running teleopInit()");
    Scheduler.getInstance().add(testDrive);
}
    @Override
    public void teleopPeriodic () {

// System.out.println("encoder left " + drivebaseEncoder.getLeftSensorReading() +
// " encoder right " + drivebaseEncoder.getRightSensorReading());
Scheduler.getInstance().run();
System.out.println(“remove this”);
}

    @Override
    public void testPeriodic () {

    }

    public static Robot getInstance () {
        if (robot == null)
            robot = new Robot();

        return robot;
    }

    public OI getOI () {
        return oi;
    }

    public Drivebase getDrivebase () {
        return drivebase;
    }

    public DifferentialDrive getDifferentialDrive () {
        return differentialDriveBase.getDifferentialDrive();
    }

    public DrivebaseEncoder getDrivebaseEncoder () {
        return drivebaseEncoder;
    }

    public Gyro getGyro () {
        return gyro;
    }
}

ColorSennsor.java
package frc.team8051.subsystems;
import com.revrobotics.ColorMatch;
import com.revrobotics.ColorMatchResult;
import com.revrobotics.ColorSensorV3;
import edu.wpi.first.wpilibj.I2C;
import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj.util.Color;
public class ColorSensor extends Subsystem {
private static ColorMatch m_colorMatcher = new ColorMatch();
private static Color kBlueTarget= ColorMatch.makeColor(0.143, 0.427, 0.429);
private static Color kGreenTarget= ColorMatch.makeColor(0.197, 0.561, 0.240);
private static Color kRedTarget= ColorMatch.makeColor(0.561, 0.232, 0.114);
private static Color kYellowTarget = ColorMatch.makeColor(0.361, 0.524, 0.113);
private final I2C.Port i2cPort = I2C.Port.kOnboard;
private final ColorSensorV3 m_colorSensor = new ColorSensorV3(i2cPort);
private int numberOfTimesSpun = 0;
private int numberOfBlues = 0;
private int numberOfReds = 0;
private int numberOfYellows = 0;
private int numberOfGreens = 0;
private String PreviousColor = “”;
private int ColorCounter = -1;
private String currentColor = “”;

 @Override
 protected void initDefaultCommand() {

 }


 public static void initializeColor(){
     m_colorMatcher.addColorMatch(kBlueTarget);
     m_colorMatcher.addColorMatch(kGreenTarget);
     m_colorMatcher.addColorMatch(kRedTarget);
     m_colorMatcher.addColorMatch(kYellowTarget);
 }
 public void setToZero(){
     numberOfTimesSpun = 0;
     numberOfBlues = 0;
     numberOfReds = 0;
     numberOfYellows = 0;
     numberOfGreens = 0;
 }
 
 public void SenseColor() {

         Color detectedColor = m_colorSensor.getColor();
         String colorString;
         ColorMatchResult match = m_colorMatcher.matchClosestColor(detectedColor);

         if (match.color == kBlueTarget) {
                     colorString = "Blue";
                     if(ColorCounter != -1){
                         PreviousColor = currentColor;
                     }
                     if(ColorCounter == -1){
                         ColorCounter +=1;
                     }
                     currentColor = "Blue";
                     if(currentColor != PreviousColor){
                         currentColor = "Blue";
                         numberOfBlues +=1;
                 }
         }
         else if (match.color == kRedTarget) {
             colorString = "Red";
             if(ColorCounter != -1){
                 PreviousColor = currentColor;
             }
             if(ColorCounter == -1){
                 ColorCounter +=1;
             }
             currentColor = "Red";
             if(currentColor != PreviousColor){
                 currentColor = "Red";
                 numberOfReds +=1;
             }
         }
         else if (match.color == kGreenTarget) {
             colorString = "Green";
             if(ColorCounter != -1){
                 PreviousColor = currentColor;
             }
             if(ColorCounter == -1){
                 ColorCounter +=1;
             }
             currentColor = "Green";
             if(currentColor != PreviousColor){
                 currentColor = "Green";
                 numberOfGreens +=1;
             }
         } else if (match.color == kYellowTarget) {
             colorString = "Yellow";
             if(ColorCounter != -1){
                 PreviousColor = currentColor;
             }
             if(ColorCounter == -1){
                 ColorCounter +=1;
             }
             currentColor = "Yellow";
             if(currentColor != PreviousColor){
                 currentColor = "Yellow";
                 numberOfYellows +=1;
             }
         } else {
             colorString = "Unknown";
         }
         SmartDashboard.putNumber("Red", detectedColor.red);
         SmartDashboard.putNumber("Green", detectedColor.green);
         SmartDashboard.putNumber("Blue", detectedColor.blue);
         SmartDashboard.putNumber("Confidence", match.confidence);
         SmartDashboard.putString("Detected Color", colorString);
         SmartDashboard.putString("Current Color", currentColor);
         SmartDashboard.putString("Previous Color", PreviousColor);
         SmartDashboard.putNumber("Blues", numberOfBlues);
         SmartDashboard.putNumber("Reds", numberOfReds);
         SmartDashboard.putNumber("Greens", numberOfGreens);
         SmartDashboard.putNumber("Yellows", numberOfYellows);
         SmartDashboard.putNumber("Spins", numberOfTimesSpun);
         if (numberOfBlues + numberOfGreens + numberOfReds + numberOfYellows == 9) {
             numberOfTimesSpun += 1;
             numberOfYellows = 0;
             numberOfReds = 0;
             numberOfBlues = 0;
             numberOfGreens = 0;
             System.out.println("Spins: " + numberOfTimesSpun);
              }
      }

}

One suggestion I have is thinking about the pattern (order) of the colors. As long as you spin the control panel one direction, you will know each subsequent color to look for. This will eliminate false positives at higher speeds. Basically put the color pattern in an array and go through each color in the array one by one as you pass over each color with the sensor and count as you go. This solved our teams problem of getting green popping up between blue and yellow at high speed as well as other issues. I have a code repo for this but try it out first and message me if you need any push in the right direction.

1 Like

Thanks for the suggestion Dilan. We haven’t been able to test it out at highs peeds yet so I’m not sure if we’ll have the false positives problem or not. However, I thought about making an array but the sequence too but how were you able to make an array that holds all the possible sequences? Wouldn’t the sequence of the colors that you would expect to see when you turn the control panel change based on which color you start with? Also, do you think our code what result in false positives as we approach higher speeds?

Thanks again,
Team 8051

Your colorsensor.java and Robot.java seem to be the same.

2 Likes

Sorry mistake. Will update shortly

I don’t know how you’re checking it now, but it seems like you basically just need to take the pattern of the colours on the wheel and do some simple counting to figure out the number of rotations. A suggestion for polling the colour sensor (shameless plug here), but this year we decided to use ultrasonic sensors for some stuff, and we needed a way to poll them, so I wrote this simple poller class (https://github.com/FRC3161/WoodieFlowers2020/blob/master/src/main/java/frc/robot/subsystems/ball/feeder/UltrasonicPoller.java). It uses my team’s libraries so you may need to change it a bit for pure WPILib code (or just use our libraries). It can be implemented in this situation with a little tuning for your purpose. The code is meh atm but I’ve been tied up with so many other things. If you do end up using it, keep checking back as there will be improvements throughout the season :slight_smile:.

What I did is before spinning, retrieve what color the color sensor is reading. I start the sequence from that particular color in the array.

It will only addcount if the next color sensed matches with the next one in sequence of the array. We did 24 counts (equivalent to a 3 rotations) because our motor controller is set on coast.

Ohhh that’s interesting. I think I see what you did. I updated the post to so now you can see the actual color sensor code. So my code works thus far bit it’s just lafgs a lottt when I add the raw button conditional in the robot class. Do you have any suggestions for how I can alleviate this?

Could you explain further on what lags specifically. And you are saying the button press conditional is causing this?

You might check out our code too, https://github.com/amhsrobotics4681/2020-First-Rise/blob/master/workspace/2020%20FIRST%20Rise/src/main/java/frc/robot/Wheel.java

and if i understand correctly, you want to press button A once and have the robot spin the wheel 4 times by itself / have the robot go to a color by itself?

Basically, without the conditional, The Smart board shows all the variables being added up correctly in the spins being detected correctly with no delay But once we added the conditional, It took like 10 seconds for it to detect and add a color.

Basically yes, we’re trying to make it so that once button A is pressed, The robot will begin detecting colors and spins. That’s why we tried to use the conditional. However, once we added the conditional, Will you notice a 10-second delay between the variables being updated correctly on the smart board. We’re not sure what to do to fix it but thanks for linking me your code. I really appreciate it.

That is unusual, our teams code uses a button to start as well. here is the link to our repo. Code is a bit sloppy I must admit but it works for the control panel.

Rotation Control - Shockwave 4546

You can see all our button binds in OI.java, we also have our position control binded to a button along with the rotation control to another button.

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