Rotary Encoder with PULSEIN?
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Rotary Encoder with PULSEIN?
I rigged up an RPM sensor with a QRD1114 IR reflective photo detector and encoder disk I printed using Excel. Is it possible to measure time between the High and Low states from encoder using the PULSEIN function without using Interrupts as suggested by application note AN221?
My goal is to measure the transfer function (RPM-Output to DutyCycle-Input) for the motors on my gbot90 project as part of deriving a Kalman filter. So I need to measure RPM vs. time. The encoder disk has 36 segments, and the max RPM is about 300. The plan is to use the PULSEIN function and deduce RPM. Separately, to capture the corresponding time-stamp, I'll capture RCTicks. Not sure how to store and recover this data though. Appreciate your comments.
My goal is to measure the transfer function (RPM-Output to DutyCycle-Input) for the motors on my gbot90 project as part of deriving a Kalman filter. So I need to measure RPM vs. time. The encoder disk has 36 segments, and the max RPM is about 300. The plan is to use the PULSEIN function and deduce RPM. Separately, to capture the corresponding time-stamp, I'll capture RCTicks. Not sure how to store and recover this data though. Appreciate your comments.
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Okay, on a ZX-40N device, I tried both 1) the PULSEIN approach, and 2) the High-state Count approach. PULSEIN only worked intermittingly (not sure if its my code or the hardware), whereas Counting seemed robust. I hoped PULSEIN would work because the subroutine-call returns the time-width of the High state. My concern with Counting is obtaining an accurate time-width from RCTicks in the presence of conditional statements in my code.
Once I figure out the time-width issue, the next big challenge will be capturing the RPM time history. Serial output from debug.print may not be fast enough. What is the fastest method for outputting time histories? Thanks.
Once I figure out the time-width issue, the next big challenge will be capturing the RPM time history. Serial output from debug.print may not be fast enough. What is the fastest method for outputting time histories? Thanks.
Is there a reason that you did not also try InputCapture()?liam.zbasic wrote:I tried both 1) the PULSEIN approach, and 2) the High-state Count approach.
Log the data to RAM and output it after the test run has completed. If that can't be done, then your best bet is to encode the data in some way so as to reduce the byte volume without losing information.liam.zbasic wrote:What is the fastest method for outputting time histories?
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
I defined a 1-D integer array with 1,000 elements to capture the encoder High counts. I'm figuring 1 second of time-history data at a sample rate of ~1,000Hz should be adequate. Anyway, I was surprised the compiler did not echo back an increase in RAM with the array. I'm using a ZX-40N device. The program ran correctly, although the array contained zeros beyond the ~200th element. Is this a case of "overfilling the RAM"? Thanks.
The RAM use that is reported is the amount that is statically allocated, i.e. defined at the module level or with the Static attribute inside a procedure. Data items defined without the Static attribute inside a procedure are dynamically allocated, i.e. allocated on the stack at run-time. The size of such dynamically allocated variables are not reflected in the RAM use that is reported because they only exist while the particular procedure is executing.liam.zbasic wrote:I was surprised the compiler did not echo back an increase in RAM with the array.
Note that the dynamically allocated variables do contribute to the required task stack size. However, in a single-task environment the default is to allocate all otherwise-unallocated RAM to the Main() task stack. As long as the required minimum size is met you won't see any compiler warnings.
- Don Kinzer
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
Here a plot of RPM vs. DutyCycle for the Tamiya 72101 geared motor with a VNH2SP30 Motor Driver. My measurements agree with the Tamiya spec using an IR encoder with a ZX-40N device. Now, the next step is to measure RPM for a step input. From what I've gathered, I suspect the motors will be too responsive for the decoder to work. I printed a encoder with 32 segments pasted to a CD disk, but that may not be enough. But if I add too many segments, the encoder may not read the time-width correctly. So I'm thinking of coupling a very small ungeared motor to the Tamiya output shaft and measure voltage generated by the small motor, which will infer RPM. I'll first calibrate the small motor output voltage to RPM as before. Is this a valid approach? Appreciate your comments.
- Attachments
-
- RPM vs. DutyCycle
- rpm_vs_duty.png (5.79 KiB) Viewed 13580 times
You probably know this, but there is a way to measure back-EMF form the motor and this is an indication of RPM.
I do not know all the details, but I think it involves momentarily turning off the power to the motor and simultaneously measure the voltage that the motor generates as it freewheels.
Maybe this could be useful to you?
-Tony
I do not know all the details, but I think it involves momentarily turning off the power to the motor and simultaneously measure the voltage that the motor generates as it freewheels.
Maybe this could be useful to you?
-Tony
I'm unclear what you mean by step input. Do you mean a sudden large change in drive power?liam.zbasic wrote:... the next step is to measure RPM for a step input...
Unless your encoder code isn't interrupt-based and the processor is bogged down doing something else, it should be many orders of speed faster than anything the mechanical motor could do, even full-blast acceleration, and should therefore be quite capable of sensing every scale edge and accurately timing the period since the previous edge.... I suspect the motors will be too responsive for the decoder to work.
One technique I use is to tie an interrupt line to ICP and use an XOR gate to compare the scale sensor output to a bit that the interrupt handler code outputs, which is the previous sensor state. The XOR output goes high when the scale state changes; simultaneously, the ICP latches a current free-running timer count which then represents the period since the previous edge (which inversely follows the encoder shaft speed) and interrupts the processor. Since it is interrupt-based, your processor can be doing other stuff; the interrupt code can provide both shaft position and current velocity variables. This method is very fast.
Tony mentioned back-EMF which can be made to work on PWM'd drives, but that is an analog solution and does not provide position except by integration of apparent velocity - an inexact result.
To be thorough, one other technique requires sensing the motor commutator noise, which is directly related to motor shaft speed. A shaft position count can be derived very accurately, but the circuitry to do that is not trivial.
Of course, you could use stepper motors instead of brushed motors, and be in absolute control of the motor shaft position, direction and speed. No feedback is usually necessary and stepper driver boards can make your code quite simple.
Tom
-
- Posts: 163
- Joined: 24 March 2008, 23:33 PM
- Location: Southern California (Blue)
I finally got a chance to characterize the Tamiya-72101 motors for my gbot90 project. The gbot90 is a self balancing robot with PID feedback control:
http://www.youtube.com/watch?v=bxx14Xe2iNg
I want to characterize the motors to improve the feedback control system. Right now I assume the motors respond instantaneously, so the goal is to measure the motor transfer function to quantify the RPM response to throttle input. The throttle is PWM duty cycle.
To characterize the motors, I input a step function (0 duty cycle to 100% duty cycle in ~0sec) and measured the RPM response vs. time. I learned the hard way that using IR encoders was not practical because the Tamiya-72101 motors were too responsive. So instead, I coupled a separate geared motor/generator (with low mechanical resistance) to the Tamiya shaft. It was geared to generate adequate voltage. The output was routed to a separate ZX-40N device to measure RPM response in terms of voltage. See attached image for setup:
The ZX-40N zbasic code has two basic arrays: one for time (via GetElapsedMicroTime) and the other for generator voltage (via GetADC). I set the array size to 400 elements and that nearly used up all the available RAM, but was enough to capture the step response shown in attached image #2. The response signature was very repeatable after 5 trials.
In short, it shows the Tamiya motor reach full RPM in about ~0.09sec. I was surprised to see how oscillatory the responses would be, but I learned that it’s an artifact of the generator. I verified this by running the Tamiya motor at constant RPM (100% duty cycle) and recorded the response. See attached image #3. Even at constant RPM, the generator shows a oscillatory response with a clear mean and consistent amplitude likely correlated to generator RPM. Bottom line is that enough data was gathered to fair out a decent transfer function. I suppose some capacitors on the generator will tame the oscillations?
http://www.youtube.com/watch?v=bxx14Xe2iNg
I want to characterize the motors to improve the feedback control system. Right now I assume the motors respond instantaneously, so the goal is to measure the motor transfer function to quantify the RPM response to throttle input. The throttle is PWM duty cycle.
To characterize the motors, I input a step function (0 duty cycle to 100% duty cycle in ~0sec) and measured the RPM response vs. time. I learned the hard way that using IR encoders was not practical because the Tamiya-72101 motors were too responsive. So instead, I coupled a separate geared motor/generator (with low mechanical resistance) to the Tamiya shaft. It was geared to generate adequate voltage. The output was routed to a separate ZX-40N device to measure RPM response in terms of voltage. See attached image for setup:
The ZX-40N zbasic code has two basic arrays: one for time (via GetElapsedMicroTime) and the other for generator voltage (via GetADC). I set the array size to 400 elements and that nearly used up all the available RAM, but was enough to capture the step response shown in attached image #2. The response signature was very repeatable after 5 trials.
In short, it shows the Tamiya motor reach full RPM in about ~0.09sec. I was surprised to see how oscillatory the responses would be, but I learned that it’s an artifact of the generator. I verified this by running the Tamiya motor at constant RPM (100% duty cycle) and recorded the response. See attached image #3. Even at constant RPM, the generator shows a oscillatory response with a clear mean and consistent amplitude likely correlated to generator RPM. Bottom line is that enough data was gathered to fair out a decent transfer function. I suppose some capacitors on the generator will tame the oscillations?
- Attachments
-
- Constant RPM
- tamiya72101_constant_rpm.jpg (70.94 KiB) Viewed 13168 times
-
- Step Response
- tamiya72101_step_response.jpg (66.41 KiB) Viewed 13167 times
-
- Motor Characterization Setup
- tamiya72101_char_setup.jpg (75.34 KiB) Viewed 13167 times