Rotary Encoder with PULSEIN?

Discussion specific to the DIP and TQFP packaged ZX devices like the ZX-40, ZX-44, ZX-32 and ZX-328 series. The differences between these devices is primarily the packaging and pinout so most issues will apply to all devices.
Post Reply
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Rotary Encoder with PULSEIN?

Post by liam.zbasic »

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.
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

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.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

liam.zbasic wrote:I tried both 1) the PULSEIN approach, and 2) the High-state Count approach.
Is there a reason that you did not also try InputCapture()?
liam.zbasic wrote:What is the fastest method for outputting time histories?
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.
- Don Kinzer
GTBecker
Posts: 616
Joined: 17 January 2006, 19:59 PM
Location: Cape Coral

Post by GTBecker »

> ... not sure if its my code or the hardware...

Ha! I've been blaming the hardware for 45 years, and I've never been right - unless it was my own design or I blew the hardware up, anyway. I am continually fascinated how code can mimic apparent hardware problems.
Tom
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

dkinzer wrote:Is there a reason that you did not also try InputCapture()?
Ignore that question. I was thinking about a different issue.
- Don Kinzer
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

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.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

liam.zbasic wrote:I was surprised the compiler did not echo back an increase in RAM with the array.
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.

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
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

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. DutyCycle
rpm_vs_duty.png (5.79 KiB) Viewed 13580 times
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

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
GTBecker
Posts: 616
Joined: 17 January 2006, 19:59 PM
Location: Cape Coral

Post by GTBecker »

liam.zbasic wrote:... the next step is to measure RPM for a step input...
I'm unclear what you mean by step input. Do you mean a sudden large change in drive power?
... I suspect the motors will be too responsive for the decoder to work.
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.

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
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

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?
Attachments
Constant RPM
Constant RPM
tamiya72101_constant_rpm.jpg (70.94 KiB) Viewed 13168 times
Step Response
Step Response
tamiya72101_step_response.jpg (66.41 KiB) Viewed 13167 times
Motor Characterization Setup
Motor Characterization Setup
tamiya72101_char_setup.jpg (75.34 KiB) Viewed 13167 times
Post Reply