Help with PWM input from encoder

Hello, new to the board, I am struggling reading the output from a 10 bit encoder ( … /shaft/ma3)

I am using the example code pulsein2 for testing purposes. When using a 64 CPR Encoder (one of the Pololu motors with attached encoders) I am able to read both frequency and duty cycle on the lcd. If I use the MA3 PWM encoder I can only read the duty cycle, the frequency simply displays an arbitrary number which does not change as the encoder is rotated. I also note that the “HIGH” and “LOW” pulse states are not present when using the MA3 encoder. Is this a resolution issue (10 bit)?

Any advice appreciated,

Hello, golf,

You did not mention which of our products you are using, but it sounds like you have one of our Orangutan robot controllers (and the pulsein2 example should work the same on all of them).

You should note that the two encoders you are using operate on completely different principles. The encoders attached to our gearmotors are quadrature encoders, which report relative position by simply outputting high or low signals according to the position of the shaft, while the MA3 appears to provide an absolute position reading by varying the duty cycle of a fixed-frequency PWM signal. You are probably seeing the frequency reported as about 1000 Hz, which is what the MA3’s datasheet specifies as the PWM frequency for the 10-bit version.

Also, the pulsein2 program only reports “Pin HIGH” or “Pin LOW” if the pin has stopped on that state for at least 300 ms. Since the PWM signal from the RMA3 is active even when you are not rotating it, there is never a pause long enough for the pin state to be reported on the LCD.

As long as the duty cycle and frequency reported by pulsein2 matches what you would expect from the RMA3 datasheet, I think it is giving you the expected results.

- Kevin

Thanks Kevin, yes it is the Orangutan 1284p board. I do realize the difference between the two encoders, I require aboslute indication for my project and landed on the MA3. The problem is I do not get any meaningful reading for frequency with the MA3 using the code for Pulsein2. I just get a static number. (988 which correspondes to your comment about 1000 hz but my understanding of the pulsein2 HZ is that is should calculate the frequency of the encoder shaft rotation) With the quadrature encoder the frequency updates as I turn the motor shaft at varying speeds, with the MA3 wired to the same port I get the duty cycle (position) but no indication of change in frequency as I rotate the encoder input shaft. (the lcd indicates 989 steady state). Additionally with the quadrature encoder when the shaft speed is stopped for 300 ms the lcd display reverts to the “High” or “Low” state as per the code. With the MA3 in a stopped state the lcd is left on the frequency and duty cycle display as if it is receiving new pulses.


This is only true for a tachometer, which is functionally the same as one channel of a quadrature encoder. You say that you realize the difference between the two encoders, but I think you are still fundamentally misunderstanding how the MA3 works and just how different it is from a quadrature encoder.

The PulseIn library simply measures the duration of a digital pulse, and the pulsein2 example does some math with those readings to compute the frequency and duty cycle of the signal on a particular input. When you feed it the signal from one channel of a quadrature encoder, the signal frequency is directly proportional to the rotation speed, and the duty cycle is usually approximately a constant (ideally near 50%). However, the signal from your MA3 encoder is entirely different. It is a fixed-frequency signal (1000 Hz, completely independent of the rotation rate of your motor shaft) with a duty cycle that corresponds to the absolute position of the encoder. In this case, the pulsein2 example will always report a frequency of 1000 Hz because that is the frequency of the signal you have connected. Does this make sense?

What you care about when using the MA3 encoder is the duty cycle, so you should be paying attention to that value as the shaft rotates. If you want to calculate the shaft’s rotation speed, you need to take two readings (of the duty cycle), subtract them, and divide the result by the amount of time that passed between from the first reading to the second (i.e. compute the change in position over time). Note that because of the way the encoder works, you will always have to have at least one millisecond between consecutive readings.

As Kevin explained, when you are using a quadrature encoder, stopping the motor causes the pulses to stop and the input signal to become a steady high or steady low, which triggers a PulseIn “high” or “low” state after 300 ms. However, even when the MA3 is stationary, it is still outputting a 1000 Hz signal with a duty cycle corresponding to the encoder position, so the Orangutan actually is receiving new pulses. You should not be expecting the signal from a stationary MA3 encoder to be the same as the signal from a stationary quadrature encoder.

- Ben

Thanks Ben, that does make sense to me. I will take a shot at writing the algorithm to compute the speed of the encoder shaft. The project I am working on demands the aboslute position which was my primary focus, I want to add speed of the encoder shaft and was hoping to do it without adding an additional piece of hardware. I was not aware of the difference as to how the encoders worked.

You really shouldn’t need an extra piece of hardware to get the shaft speed. Please let me know if you run into trouble computing the speed from your MA3 encoder.

- Ben

Hi Ben, I have recently purchased the JRK 21v12 motor controller to give me more flexibility with my project (I wanted the higher amperage as well as the PID functionality. I am using absolute analog encoders for the inputs on my project and I can get excellent control of my motors with the JRK. My project requires a non-linear relationship between my target and feedback inputs. When I was using the motor drivers on the Orangutan SVP board I was able to create the target as a motor set point and use that as the output for the motor control. Now that I am using the JRK I need to supply the analog input. I am using an “ARRAY” to create the non-linear relationship that I desire for the target. In my code “c” represents the target that I want to send to the ''rx" pin on the JRK. I would like to do this by configuring one of the other analog I/O pins as my output but I can find no references as to how to accomplish this? Is it possible? Thanks Ben

#include <pololu/orangutan.h>
int main()                    

	clear(); // Clear the LCD.  

   int potref = (analog_read(1)/16);   // determine the trimpot position of reference encoder in 64 increments through 360 degrees
   int potfl = (analog_read(0)/16);  //determine the trimpot position of follower encoder
   int c;  //for calling initial array  
   int delta1 = (c - potfl);  //delta between desired position and actual position in first array
   int array[64]; 

    c = array[potref];

//Array at 180 degrees
array[0]=8; array[1]=6; array[2]=4; array[3]=4; array[4]=4; array[5]=4; array[6]=4; array[7]=4; 
array[8]=4; array[9]=4; array[10]=6; array[11]=8; array[12]=9; array[13]=9; array[14]=10; array[15]=10; 
array[16]=11; array[17]=11; array[18]=12; array[19]=13; array[20]=14; array[21]=15; array[22]=16; array[23]=18; 
array[24]=19; array[25]=20; array[26]=21; array[27]=20; array[28]=19; array[29]=18; array[30]=17; array[31]=16; 
array[32]=17; array[33]=20; array[34]=22; array[35]=22; array[36]=23; array[37]=23; array[38]=24; array[39]=25; 
array[40]=26; array[41]=27; array[42]=27; array[43]=28; array[44]=29; array[45]=30; array[46]=31; array[47]=32; 
array[48]=33; array[49]=33; array[50]=32; array[51]=30; array[52]=28; array[53]=28; array[54]=28; array[55]=28; 
array[56]=28; array[57]=27; array[58]=22; array[59]=18; array[60]=14; array[61]=12; array[62]=12; array[63]=12; 

 lcd_goto_xy(0, 0);
    print("Ref ");
    print_long(potref);    // print the reference trim pot position (0 - 64)
    print(" ");           // overwrite any left over digits
    lcd_goto_xy(0, 1);
    print("C=  ");
    print_long(c);     // print the following trim pot position (0 - 64)
    print("    ");           // overwrite any left over digits
    lcd_goto_xy(8, 0);
    print("Fol ");
    print_long(potfl);    // print the trim pot position (0 - 64)
    print("    ");           // overwrite any left over digits//lcd_goto_xy(8, 1);



It sounds like you are asking how to generate an analog voltage from an Orangutan I/O line. This is not easy to do, and I don’t think it’s the approach you should be taking (you are converting a digital value to analog only to have the jrk convert it back to digital). Why not just send the target value to the jrk using serial communication?

Also, there is a shortcut to initializing arrays that you might find easier to use than what you’re doing now:

int array[64] = {8, 6, 4, 4, 4, 4, 4, 4,
4, 4, 6, ... };

- Ben

thanks for the tip on the array’s, in my actual code I am using several different ones that are called based on the calculated speed of the reference encocder. This will make it a lot quicker to modify them.

I did note the ability to create a serial connection between the JRK and the SVP boards but I thought there would be a simple “analog_write()” function. I have not worked with serial comm but if it will allow me to send the computed target to the JRK that is what I need to do. I will start working through the documentation, you may get another question or two… Thanks Again


Generally speaking, you need a microcontroller with a DAC (digital-to-analog converter) if you want to be able to output an analog voltage. These aren’t as common as ADCs (analog-to-digital converters), so you usually get MCUs with a slew of analog inputs but few (or no) analog outputs. The Arduino has a function called analogWrite(), but it is poorly named because it just outputs a digital PWM signal, not a true analog voltage (you would need to run it through an external circuit, such as an RC filter, to convert it into something that could be used with the jrk’s analog input).

If you don’t want to use serial, the next best option would probably be to use the jrk’s RC interface, which accepts the same signals as are used to control RC hobby servos. There are several examples out there of generating servo control pulses with Orangutans.

Please don’t hesitate to ask if you have more questions.

- Ben

Thanks Ben, I will give the serial comm a try. I did experiment using the PWM outputs on the SVP and was able to get some results, but not as good as a direct target input from the encoder to the RX pin on the JRK. One question, ultimately I will want to control more than 1 JRK board from the SVP. Will I be able to do this via a serial connection? (my project has multiple motors and each is positioned by a different calculated target) When I thought I could provide the target via a calculated output from one of the I/O’s I envisioned using multiple I/O’s as my method of providing targets to each JRK. I know I can use a dedicated SVP for each motor but that is bit clumsy.

On the PWM solution (which as more than enought outputs for my project) should I be able to get an accurate target calculated for the full 360 degree rotation of the motor? When I was playing around with it I was able to get around 30 degrees of either side of center (which is very similar to most of my RC servo travels)but did not seem as stable as the analog input directly from the encoder. Should I be able to get the full 360 degree target from the PWM?



You can chain multiple jrks on the same serial bus (see the section on daisy-chaining for more information).

I don’t really understand what you’re asking. Your choice of input method should have no effect on what level of result is achievable; they’re just three different ways of supplying the jrk with your target, and you should be able to achieve quite a bit of customization using the jrk’s input, feedback, and output scaling. But as I said before, you should not expect a PWM output to work with the jrk’s analog input as a PWM is not an analog voltage.

- Ben

Thanks for your help Ben, I was able to get the PWM servo control to provide the target for the JRK as determined by my array’s and I am controling 4 gear motors accurately. The JRK’s PID functionality is very slick. I am not certain why my initial try was not successful but I am thinking it had something to do with the scaling on the JRK that I was not interperating correctly. I now have accurate 360 degree control over each motor.

Much appreciated Ben


I’m very glad to hear you have things working; thank you for letting us know!

- Ben