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.
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.
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.
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.
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.
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.
In your VSCode create a new project from the WPILib Java Example RomiReference
or
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?
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?
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 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.)