Using Kevin's PWM outputs for a quieter drive system.

Now that the crisis is over for a while, my mind wanders to paths not followed. Specifically, using Kevin’s PWM 12,13,14,15 outputs.

The fact that our drive system always sounds very “cruncy” with the banebot gearboxes when moving at anything less than full speed, made me start to wonder if using the custom PWM code would help.

I’m guessing that the default 38Hz rate could be part of the problem, but unless I call the PWM() function more often than during teleop(), even the “precise” PWMs give me the same quality… right?

Please educate me somone… is there an easy way to use PWM() faster than the default rate to give me “smoother” main wheel drive.

Also, I do have a steering motor this year, so getting better control over this motor would be helpfull. Since it’s based on a pot feedback, I guess I could use the PWM() call inside the code that checks for a new A2D value…

Reasonable??

Phil.

Phil,

The PWM outputs on the robot we’re so fond of don’t actually spit out a true PWM signal that you would directly use for controlling a motor. They spit out a pulse train of 1ms to 2ms pulses. The Victors interpret this as 100% reverse to 100% forward and PWM their outputs accordingly at their own PWM frequency. So in answer to your question, you can’t make your motors quieter by sending the pulses faster, you can only update their speed faster than the standard 38Hz.

You could however call Kevin’s PWM function faster to gain slightly better control over your steering or any other feedback controlled system. Most systems on our robots have bandwidths less than 38Hz, so the gain isn’t going to be huge, but you should see an improvement. You should keep in mind however that you can only update the victors at around 120Hz max, so be certain you don’t call the function any faster than that.

That’s usefull information, since with servos, the actual output drive IS directly related to the RC’s PWM frequency (many servos use the PWM leading edge to initiate the drive signal)

So that begs the question…: What is the PWM Output frequency of a Victor? and: Why does my transmission sound so cruncy at low power.

The noise starts well before the GBox’s output shaft starts moving, so I assume it’s an oscillation detectable at the motot’s output shaft.

Phil.

With regards to your gearbox - they are LOUD. Grease the heck out of them with some good thick grease, put a motor on them and run them with no load for a bit to break them in. They aren’t going to get a whole lot quieter though.

Kevin -
Is 120Hz the actual max update rate on the victors? Is this published info or do you just know off hand.

We desperately need more control on our drive motors this year but the 40Hz loop is wayy wayy wayy too slow. I’m not sure if 120Hz would even help.

This is what I heard from one of the IFI guys when we were discussing my PWM code. I’m not sure if it’s published or not.

There is something seriously wrong if you can’t control a ~100 pound robot using KOP motors at a 100Hz control rate. Are you using encoders to determine velocity? Remember, the higher the control rate, the less you know about your velocity (Heisenberg was a very intelligent fellow :slight_smile: ).

-Kevin

Tom,

IFI seems a little conflicted about exactly how fast you can update the vics. This FAQ says the update rate is 120 Hz.

However, This other FAQ says that the vic requires the signal line to be held low for 8ms between pulses. Which actually works out to 100 Hz, considering the 2 ms high pulse for full forward condition. So I think you’d be safe setting up a timer and updating the PWMs at 100 Hz in your x_Spin() function. IFI also says that there maybe be a delay before the change is reflected on the output, so it might behoove you to set up a test rig and monitor the output on a decent digital storage o-scope.

I’ll note that 57 had a fast update loop on our shooter wheel a few years back. We ran it at about 75 Hz, if I recall correctly. Our update rate was actually primarily limited by how quickly it was reasonable to sample our encoder. If you’re going the standard route of counting encoder ticks per unit of time to get velocity, getting a 100 step resolution at 100 Hz means you’re servicing 10000 interrupts per second. We had a fun trick to get around this without any extra hardware, but it’s only good for 1 encoder and it’s non-directional to boot.

Using current sensors, not position feedback. We’ve been trying to use some back emf based control to take out the back drive and slop in the KOP motors.

It’s been on the back burner for a while and someday I’ll get around to finish coding it, but a really neat trick is to not measure the number of encoder ticks per unit time, but to measure the amount of time between ticks instead. Using your example, you could use the internal 10MHz timer to give you a *one part in a thousand resolution in velocity at a control rate of 10KHz!. *If you don’t need to control at 10KHz, you can forward predict the number of ticks to accumulate for a, say, 100Hz control rate, which will give you an incredible velocity resolution of about one part in 100,000. I’ve used this technique in a few applications for my day gig, with pretty stellar results. Pretty cool, eh?

-Kevin

To continue my recent trend of totally sidetracking threads…

I’ve thought about going that route myself, actually, but I’ve been put off by the inherent difficulties of measuring slow speeds with that method. Resolution at top speed is actually lower than resolution at slower speeds. If your top speed is 10 RPS and you’ve got a 100 pulse per rev encoder, the time between pulses would be 1 ms. So you prescale your timer to count at, say, 10 microseconds. That means your time to speed conversion is 1000/ticks = RPS. So at 100 ticks, speed = 10 RPS, at 101 ticks, speed = 9.9 RPS, 1 tick difference = .1 RPS. At 1000 ticks, 1 tick difference = .001 RPS. And at this conversion rate, the slowest speed you can measure (easily) is 1000/65536 = 0.015 RPS. That’s a pretty good range, provided 1% resolution at your top end is adequate. The main problem with the concept as a whole is that your update rate slows down the slower you’re moving. At 1 RPS, you’d be updating every 10 ms. Or once a control cycle if you’re working at 100 Hz. At .25 RPS, it’s once every fourth control cycle and so on. So I think it’d be optimistic to expect a PID based off this to maintain 0 velocity.

Programmatically, my main problem is that unless you’ve got extra logic in there, things get screwy if you’re moving at less than 0.015 RPS. If you roll over the 16-bit timer, it suddenly looks like you’ve only taken 1 microsecond between pulses and you’re suddenly traveling at ludicrous speed. So you’d have to have extra logic tracking how often you’ve rolled it over, etc. And, of course, the encoder jiggling while you’re at rest would make it look like your robot was traveling at a fair clip as well, and etc, etc, etc.

So, mostly, it’d be a fair amount of effort to work up this code, I think. At least it would be to get it efficient and fast. That plus the prospect of a totally new and different control system next year has pretty much completely sapped me of any will to work on it. Except, of course, that composing this post already started the process of hammering out the logic and structure and working around at least some of the problems… I’m actually pretty sure you could make it work fairly reliably off your Port B Encoder jiggle-resistant logic…

Inquiring minds want to know:

Which of you Kevin’s originated Kevin’s PWM code: Sevcik or Watson. :confused:

OK, I didn’t search. So shoot me already. Wait…

It may be clearer when I admit that I’ve always implemented this functionality in a FPGA, not software. There is little difference though. Measuring low velocities isn’t really a problem because you can expand the sixteen bit timer to any width by incrementing the upper bits in the ISR. Secondly, if you know your pressent velocity, you can forward predict the number of ticks to let go by before you calculate your next update.

-Kevin

Yes, I agree that FPGAs, uninhibited PICs, MCUs, etc would all make implementing just about anything a lot easier. :smiley:
And yeah, I was in fact already thinking about how I’d be incrementing a char as the timer was overflowing to expand my bits somewhat. I hadn’t considered predicting a reasonable number of encoder ticks to measure over, however. That’d definitely be the way to make it work. More complicated, but not terribly. And pretty fast if you’re changing the ticks by powers of two so you can just use bit shifts and masks…

I can’t believe one of my own team mentors doesn’t know this… heh. Sadly, this doesn’t mean I get to take credit. As far as I know, Mr. Watson is responsible for the all the “Kevin” labeled code around FIRST parts. So much so that I default to it in advising anyone wanting to use MPLAB to program their robot, since it just works. For the version I used during Aim High, I adapted some code posted by… Someone I can’t seem to search up at the moment. It didn’t have Dubya’s fancy gains, offsets, and range expansion, however.

And yes, that will be the first and last time I’ll refer to Mr. Watson that way. It does get a might trying giving programming workshops and noting that, no, I didn’t write the code. Nor am I in possession of the kevin.org domain name. Unless Watson foolishly forgets to renew his registration by… ummm… 05:00, March 27th, 2017. Cause, yeah… I know I’d never remember something that far in the future.

Kind of off topic, but related to my previous post:

I think I may have found another error in the control scheme I suggested before. It seems I was oversampling the ADC a bit too much and getting some slow readings.

motor = setpoint + ( amps * gain ) ; 

To debug and tune we set the motor to a certain base fake velocity, and tuned the gain so that when we applied friction to the wheel it would keep the same real velocity. The problem that arose was the wheel would keep the velocity it needed, but would take about .5 seconds to “spin up” when the friction was applied and another .5 to “spin down” after the friction was released. At first we attributed this to the 40Hz control frequency (which im still partially blaming), but now I’m guessing I can attribute this to the laggy ADC readings.

Kevin^2, any comments?

I’m going to say it’s not related to your ADC oversampling. Blaming it on the ADC oversampling implies that the ADC code is taking a moving average of the analog input and thus damping the current feedback signal, but this simply isn’t how the ADC code works. I think you’re just seeing the mechanical dynamics of the system coupled with a slow control loop and delayed response from the Vics. I’d say you can compensate by increasing the PWM loop rate like we’ve been talking about and very carefully bumping up your gains. IR compensation is a little tricky since the electrical dynamics of the system are an few orders of magnitude faster than the mechanical dynamics. If you increase your gain too much, the IR compensation starts overshooting and you get chatter in your motor and it sounds even worse than they usually do. So I’d say speed up the loop and tweak up your gains till things start sounding off, then back them down a little and just assume that’s the best you’re going to do.

Since I stared this thread, it has been interesting to watch and learn.

Something that I have learned while playing with the “IFI” vs “Kevin” PWM outputs is that there is appreciable less delay between request and response with the Kevin code.

Case in point, at the beginning of auto mode, my code starts setting the position of the steering motor. On the bench (since I didn’t have a feedback pot hooked up) the RC called for motion on the steering motor right away.

I just had a Victor hooked up and I was looking at the indicator LED.

I am using the process_gyro() loop to detect when new feedback is available, and I was setting BOTH the pwm5 and pwm15 at the same point in the code.

So, with the victor plugged into pwm5, I click on Auto mode, and a heart-beat later, the Victor light goes off. However with the victor plugged into pwm15, the victor light goes off almost instantly after I click auto on (no perceivable delay).

The difference seems much longer than anything associated with a fraction of a normal OI update cycle (perhaps as much as 100-200ms) , so I’m confused but pleased. I think our steering will be tighter in the future using pwm15. I even decided to move 2 of our 4 wheels controler to the upper range as well.

I finaly stumbled across the reason for my noisy drive train.

The problem ended up being caused by noisy throttle inputs on the OI.
The noise that was being seen by the OI was bouncing the motor speed in and out of the deadband of the Victor when a slow speed was being requested.

My joystick deadband logic may have been part of the problem…

I first check to see if the input is outside the deadband, and if so,I subtract the deadband from the current reading. This then gives me a speed signal that is continous all the way to zero.

Unfortunately, this also makes the output to the victor continous from zero up, so any noise on the joystick can bounce the victor in and out of it’s minimal activation signal, thus causing the motor to start and stop based on the joystick noise. This rapid on-off action was being transmitted into the gearbox and causing all sorts of ugly noises.

Rather than re-offsetting the levels, and possibly changing the other characteristics of the signal, I now just pass the joystick requests through a FIR filter (like oversampling the RC inputs), and so the victor doesn’t see the noise. Suddenly I have a MUCH quieter drive system… YAY…

Phil.

As a note:

I have played around with the victors to figure out what the highest update rate is, and have found for some older Victors the 100Hz rate is pushing it a little. The drives will occasionally give you random motor outputs at this rate.

We have been using high update/high resolution pwm for a few years now, with much success.

As to the 100Hz/120Hz thing: If I remember right, the IFI advertised maximum signal input is 100Hz and the chop output is 120Hz regardless of input frequency.

Anyhow, here’s my question, and I’m hoping someone can answer it for me as I’ve asked IFI before: IFI offers only one drive, the Victor 883, with a 2KHz chop frequency. One common thread between many FIRST robots is their angry buzzing noise (from the 120Hz chop) that they all make, as opposed to the more intelligent sounding high frequency hum common among industrial servomotors and the like.

What I’m wondering is, why doesn’t IFI use a higher chop frequency? Also, why not allow shorter pulses for the PWM input to get a higher update frequency? The microchip timers are capable of doing shorter pulses without any loss of accuracy/resolution. Alternatively, perhaps using PWM as an interface to the motor drives isn’t the best idea for rapid updates anyways. Maybe some kind of simple serial bus? Since the victor’s don’t have to give any feedback, it could be as simple as a dip switch on each one to specify an address, then just use good ol TTL serial. (At 115200baud, at maximum capacity you should be able to send 4800 24-bit values/second (8-bit address and 16-bit data), or, run 16 victors at an update rate of 300Hz)

The major advantage of higher frequency chopping (2KHz+) with very low output duty cycle capability would be the ability to finally do high speed variable dynamic braking, without the robot looking like you just threw a wrench in it.

-q

p.s. I’m not saying you can’t do dynamic braking with the current drives, our robot does this this year and I’m sure others do as well, however, I would like to be able to do it more smoothly than is currently possible with the victor drives.

Phil,

The difference in delay between the “IFI” PWMs and “Kevin’s” is because PWMs 1-12 are generated by the master processor, while PWMs 13-16 are generated by the user processor. The master processor PWMs will only occur after the communication has taken place between the two (roughly every 26.2 milliseconds), while the user processor PWMs are generated immediately. More details about this delay can be found here.

Mike