Complications with servo motor

Hello I’ve been having a difficult time on the concept of how to program a micro servo motor with WPILib, Forgive me if I do not provide enough context on this situation, but to start me and my team will be participating in FIRST’s “Quack Attack” on December 1st.

Me and my team plan on utilizing servo motors(which has been soldered onto the Romi) in order to move several parts on a smaller FRC Romi bot, but in order to do so you must program the Romi through WPILib.

Generally I am unaware on what I must do but am open to suggested solutions.

If I have made any mistakes please feel free to correct for I am just humbly the village idiot. :slight_smile:

Have you looked at: Repeatable Low Power Movement - Controlling Servos with WPILib — FIRST Robotics Competition documentation

I don’t know anything about what servos you are using. That may be the same situation that you are in thus your question.

I start by seeing what information there is on the servos. For example, there is a robot arm kit documentation here. I see there are possibly 2 different kinds of servos on the Romi. Searching the entire document shows one of them has range of

about 500 µs (fully open) to 2400 µs (fully closed)

You need to find this information for the servos you are using.

Next is how to tell WPILib PWM class what you want. That class documentation has these comments:

**

  • Class implements the PWM generation in the FPGA.
  • The values supplied as arguments for PWM outputs range from -1.0 to 1.0. They are mapped to

  • the hardware dependent values, in this case 0-2000 for the FPGA. Changes are immediately sent to
  • the FPGA, and the update occurs at the next FPGA cycle (5.005ms). There is no delay.
  • As of revision 0.1.10 of the FPGA, the FPGA interprets the 0-2000 values as follows: - 2000 =

  • maximum pulse width - 1999 to 1001 = linear scaling from “full forward” to “center” - 1000 =
  • center value - 999 to 2 = linear scaling from “center” to “full reverse” - 1 = minimum pulse
  • width (currently .5ms) - 0 = disabled (i.e. PWM output is held low)
    */

Set the bounds with the method:

/**

  • Set the bounds on the PWM pulse widths. This sets the bounds on the PWM values for a particular
  • type of controller. The values determine the upper and lower speeds as well as the deadband
  • bracket.
  • @param max The max PWM pulse width in ms
  • @param deadbandMax The high end of the deadband range pulse width in ms
  • @param center The center (off) pulse width in ms
  • @param deadbandMin The low end of the deadband pulse width in ms
  • @param min The minimum pulse width in ms
    /
    public void setBounds(
    double max, double deadbandMax, double center, double deadbandMin, double min) {
    PWMJNI.setPWMConfig(m_handle, max, deadbandMax, center, deadbandMin, min);
    }
    Some older or at least slower servos can’t keep up with 5 ms period and the PWM signal has to be slowed. I have seen servos that needed slower signals. I have no idea if hte Romi does but to stat with I’d assume the servos are fast enough in teh normal mode. If things aren’t working try slower:
    /
    *
  • Slow down the PWM signal for old devices.
  • @param mult The period multiplier to apply to this channel
    */
    public void setPeriodMultiplier(PeriodMultiplier mult) {
    switch (mult) {
    case k4X:
    // Squelch 3 out of 4 outputs
    PWMJNI.setPWMPeriodScale(m_handle, 3);
    break;
    case k2X:
    // Squelch 1 out of 2 outputs
    PWMJNI.setPWMPeriodScale(m_handle, 1);
    break;
    case k1X:
    // Don’t squelch any outputs
    PWMJNI.setPWMPeriodScale(m_handle, 0);
    break;
    default:
    // Cannot hit this, limited by PeriodMultiplier enum
    }
    }

I’d do a lot of experimenting with the simplest code possible to operate the servos. I’d also search GitHub or others for sample code on using the servos on the Romi.

I find this and others:
Servo bounds don’t fully support Romi Gripper #116

Also check out any Romi documentation in the WPILib documents.

Let’s hope a Romi expert contributes better than I have but if not, maybe this stuff will help you a little and keep you going in the right direction. I don’t have a Romi at home so I can’t try anything.

1 Like

Thank you so much for clarifying what we need to do, have a great day!

Sorry for the flagged comment before the initial message I sent wasn’t specific enough, the servo motor we are using to be exact is the micro servo 9g motor. What we are looking for is simply just move the motor, also thank you for the information before it helped us immensely.

1 Like

Bingo! Definitely helped thank you.

Maybe I guessed right on what kind of servo you are talking about.

full range of motion of the gripper servo should correspond to pulse widths from about 500 µs (fully open) to 2400 µs (fully closed). Please note that there could be some unit-to-unit variation in the servos, so if you notice some buzzing when there is no load on the servo, you might try adjusting these values.

The other servos in the documents say:

Similarly, based on the assembly instructions, the full range of the lift servo should be from 1000 µs (fully raised) to 1900 µs (fully lowered), and the full range of the pivot servo should be from 1200 µs (fully down) to 1900 µs (fully up). Again, this might differ slightly due to unit-to-unit variation in the servo

If you need a little more help, please tell us if it is the Romi Pololu robotics arm and gripper that you have.

If it isn’t, then share with us all the text on the servo which usually includes the manufacturer, model number, and indication of continuous or positional.

It’s more of a scooper in which the motor would turn and thus make the scooper capable of picking up the ducks, Also when looking at the example code for Repeatable Low Power Movement it’s fairly vague. If there are any links to examples or simply GitHub repos please feel free to share them.

Here’s some old test code I have for a servo. I don’t have the servo at home and I don’t remember if it is a continuous type or hard stop with position feedback.

import edu.wpi.first.wpilibj.Servo;
import edu.wpi.first.hal.PWMConfigDataResult;

private final static Servo servo = new Servo(0);

@Override
public void teleopPeriodic() {

 setDisplayServo(0.5); // refresh the servo position

}

private void setDisplayServo(final double position) {

    PWMConfigDataResult a;

    a = servo.getRawBounds();

    System.out.format("%d %d %d %d %d\n",
      a.center,
      a.deadbandMax,
      a.deadbandMin,
      a.max,
      a.min);

    servo.set(position);
  
    a = servo.getRawBounds();

    System.out.format("%d %d %d %d %d\n",
      a.center,
      a.deadbandMax,
      a.deadbandMin,
      a.max,
      a.min);

    System.out.println("Servo raw " + servo.getRaw());

}

Thank you, while going over some documentation I’ve come to conclusion on several factors. Firstly we must program the servo motor to be rotational as its initial purpose, but when coming in terms to the actual programming I grow a bit confused. In WPILib the Romi’s build is already built, and I assume that we can add onto that code in order to actually move the motor but I’m not sure where to implement this code nor what packages or libraries to import on its behalf.

I think our assumption was you have a WPILib Romi program running to your satisfaction and want to add the servo movement to that existing program.

If you are starting from scratch with using the WPILib Romi and have never done it before and have no code, then all I can suggest is read the Romi Documentation and look at these two examples - one command-based and the other iterativeRobot.

  1. In your VSCode create a new project from the WPILib Java Example RomiReference
    or
  2. Copy the project MyRomi

Thank you for your response and analysis on my current situation it has truly helped me understand much more about FRC robotics, though the github you sent me is Romi’s standard build on WPILib. If I was to program the Romi to be capable of executing the code and activating the motor, do I create a seperate folder in the Build (RomiReference) or simply add it to an existing one such as the (java/frc/robot) pathway?

Since you mentioned the RomiReference I assume you want to do command-based. You could add to the example project (I named it RomiCommand) Java files

  • servo subsystem class to the \RomiCommand\src\main\java\frc\robot\subsystems folder
  • servo command class to the \RomiCommand\src\main\java\frc\robot\commands folder
  • instantiate the above classes in RobotContainer class.

Place the reference to the command where you want to execute it.

Yes of course thank you!

Update:

While following your advice and following FIRST’s Repeatable Low Power Movement guide, I created a small piece of code for the servo’s subsystems file under the subsystems folder (which is utilized to rotate it, such as the angle and positioning) but while I have a grasp for the subsystems what should be put inside the following command class?

Code(If wish to review):

Screen Shot 2022-11-27 at 2.27.19 PM

I don’t mean to insult your intelligence but you do know you need a lot of code for the most basic robot program be it iterativeRobot or command-based robot?

For iterativeRobot you put your movement operations in a periodic method such as teleopPeriodic().

For command-based you define a subsystem say DuckGrasper that includes servo and whatever else you need and then define commands using that subsystem such as resetStartingPosition like the code you show.

If you’ve never done WPILib programming then you need the lessons like Zero to Robot and the Command-based lessons.

We’ve reached my limited ability to help by remote. I can’t explain any better than I have. Maybe you need an experienced programmer to go through this with you. You could accomplish in an hour what I cannot do since I lack the knowledge, prepared lessons, and the Romi with servo.

I’m not insulted in the slightest just new to FRC programming, thanks for the help though

I’m not sure you’ll be able to grab a Duck before your competition but you could start with the Romi example in WPILib, delete all the stuff you don’t need and add your servo code. You seem to be an avid reader - you have lots to read!

Of course, In the meantime, I will start to do more research on command base programming and learn how to tie that into the servo. Thank you for your help through this process, it was greatly appreciated.

With the Romi arm servos, we found the only way to get the servo to work properly was to use the Servo.setAngle() method. See this post with some discussion.

Here is a link to a repo where we added code to control a Romi arm to the RomiReference example project. Here is the diff that shows the code added to control the arm. The arm has three servos, one to raise/lower the arm, one to tilt the arm, and one for the gripper.

There are two basic parts to this code:

  • The Arm subsystem has the basic code that knows how to control the servos. You can set them to a specific position with the setX methods, or you can incrementally open or close them with the openX or closeX methods.
  • There is a command that figures out what to do and uses the subsystem to make it happen. In the command’s execute method, it checks the XBox controller buttons and tells the subsystem what to do. (Alternatively, this could be done using Triggers instead of a command.)

Finally, don’t forget that you have to configure the IO ports for PWM!

1 Like

Andy, getting a runtime error ? on your code from the last thread you posted.

java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.

dave