Hi, i am a new programmer for my team and i am having problems with using the data from the encoder in the program. i have confirmed the encoder works with a multi-meter. the encoder is a us Digital e4p.
this is the relevant part of my code please help:
class RobotOscar : public IterativeRobot
{
// RobotDrive myRobotDrive; // robot drive system
This looks nice. Now, my question is how to integrate this with a PIDController and Jaguar to make a speed-based/rpm-based PID Control. We played with modifying PIDOutput() in a super-class of Jaguar such that it ‘accumulated’ rather than just sending the total_error to the Jag which effectively stops the Jag when you get to an error of zero (hence a positional PID controller as it is today)…
Seems that LOTS of people would want to be able to do this, but I wasn’t able to find such a thing this year and so we tried creating our own and didn’t have luck.
It’s pretty easy actually. WPILib makes this easy for you.
We actually had two motors, so…
template<class T>
T coerce(T val, T min, T max) {
if (val < min) {
return min;
}
else if (val > max) {
return max;
}
else {
return val;
}
}
class two_jags : public PIDOutput {
private:
Jaguar& jag1;
Jaguar& jag2;
float speed;
public:
two_jags(Jaguar& a, Jaguar& b) : jag1(a), jag2(b), speed(0.0) {}
void PIDWrite(float output) {
speed = coerce(output + speed, -1.0f, 1.0f);
jag1.PIDWrite(speed);
jag2.PIDWrite(speed);
}
void reset() {
speed = 0.0;
}
};
Some integration code (note that we were working with a counter hooked up to a hall effect sensor detecting a single magnet in the wheel, so one tick was one rotation):
two_jags jags(jag1, jag2);
freq_pid freq(cnt);
PIDController shooter_ctl(0.005, 0.0, 0.002, freq, jags);
shooter_ctl.SetTolerance(4.0); //accept a 4% steady state error
shooter_ctl.SetInputRange(0.0, 75.0); //our max freq was 75 hz
shooter_ctl.SetOutputRange(-0.25, 0.25); //only ramp a little at a time
//...
void enable_shooters(float freq) {
jags.reset(); //zero out the accumulator
shooter_ctl.SetSetpoint(freq);
shooter_ctl.Enable();
}
You can do more stuff, like adding in a startup burst to get it close and then enable the PID controller to fine tune the speed. We ended up with a quarter second burst of full power before we started the PID controller. Make sure you set the starting speed (two_jags::speed) to your startup speed before, otherwise you’ll put the motors back to zero power and defeat the whole purpose of the start speed.
Since you are using two motors, you should define the two motors in a sync group so you can synchronize them. BTW, I think you have a typo in the parameter of two_jags:: PIDWrite(float output);
I think that the problem you are having is a side effect of wiring only the A channel. I think that in order to get the encoder to work with just the A channel, you will need to ensure that it is a “1x” encoder. (Note that I’ve never tried this, we always hook up both the A and B channels, even if we are only using “1x” counting.) To use 1X counting, when you initialize the Encoder, you will need to use a line like the following:
To get the encoder to work with only one channel connected, you should use the Counter class instead of the Encoder class.
In the Counter class, you can specify either 1x or 2x decoding. I think it works this way: With 1x, it counts rising edges only. With 2x, it counts both rising and falling edges.