cancel
Showing results for 
Search instead for 
Did you mean: 

Encoder configuration giving erroneous speed

furqan
Associate II
Posted on August 16, 2014 at 13:49

Hi, I am trying to measure the rpm of a geared DC motor. The manufacturer claims a speed of 500rpm at 12V but my calculations give a speed of around 1600rpm! The gear ratio is 19:1.

I have written the following code to measure the speed:

//Systick setup for 1ms

void Delay(__IO uint32_t nTime)

{

  TimingDelay = nTime;

  while(TimingDelay != 0);

}

void TimingDelay_Decrement(void)

{

  if (TimingDelay != 0x00)

  {

    TimingDelay--;

  }

}

void SysTick_Init(void){

    while (SysTick_Config(SystemCoreClock / 1000) != 0) {

    }

}

void SysTick_Handler(void){

    TimingDelay_Decrement();

}

//Initializing Timers for encoder interface

void InitENTim(void){

    

    RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM4, ENABLE);

    RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE);

    

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;

    TIM_TimeBaseStructure.TIM_ClockDivision=0;

    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

   

    TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

   

    

    TIM_Cmd(TIM4,ENABLE);

    TIM_Cmd(TIM2,ENABLE);

    encodersReset(); //function to reset counter values

    

}

//The function to read the encoder and get Count

void encoderRead(void){

    

    oldrightEncoder = TIM_GetCounter(TIM4);

    Delay(10); //This should be a 10ms delay (according to my Systick config as written above)

    rightEncoder = TIM_GetCounter(TIM4);

    rightCount = rightEncoder - oldrightEncoder; //I am getting the difference in counts after 10ms

    totalrightCount += rightCount;

    

    

    oldleftEncoder = TIM_GetCounter(TIM4); //Encoder;

    Delay(10);

    leftEncoder = TIM_GetCounter(TIM4);

    leftCount = leftEncoder - oldleftEncoder;

    totalleftCount += leftCount;

    

}

//function to calculate speeds

void encoderCalculate(void){

    volatile float a,b,x,y,z; //just some variables for ensuring I didnt make a mistake in simple maths

    

    x = rightCount/64; //my encoder gives 64 counts per revolution when detecting both edges of both channels.

    y = 1/x;

    z = y*0.01; //This 0.01 is for the 10ms delay that I had for getting the difference in Count

    a = 60/z;

    b = a/19; //accounting for the gear ratio (19:1)

    rightspeed = b;

    

    x = leftCount/64;

    y = 1/x;

    z = y*0.01;

    a = 60/z;

    b = a/19;

    leftspeed = b;

  

}

Is there any chance there is some sort of conflict in timing of the encoder timer and the systick timer? Obviously, there is some sort of a timing problem. Kindly help as I have been stuck on this problem for a quiet a long while.

#stm32 #tim #encoder
4 REPLIES 4
Posted on August 17, 2014 at 02:22

The smarter way would to be to not use delays, but rather do your reading in the SysTick interrupt, or every 10th one if that suits your needs.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
furqan
Associate II
Posted on August 17, 2014 at 10:13

I have used timer interrupts as well to measure speed and have obtained the same value. The only thing I can think of is that the signal levels from the encoder are not right for the micro-controller. I observed a change in speed calculated when I varied the voltage applied to the encoder (and hence its output peak voltage). 

jj2
Associate II
Posted on August 18, 2014 at 00:06

T.F.: ''...think the signal levels from the encoder are not right for the micro-controller.''

Shouldn't a simple review of encoder spec vs. MCU ''encoder input'' spec minimize that quandry?

You're silent as to your use of scope to confirm proper encoder outputs - both signal level & shape. 

Is the encoder powered from the same source as the MCU?  Are the grounds common?  (have you double checked?)

Unstated is the encoder's ability to output a lower frequency pulse (index) which is provided @ each motor revolution.  This should be simple to read via a basic MCU timer - eliminating the encoder (at this stage) from your measurement process.  More acquired data is your friend - may signal correctness (or the opposite) of your measurement methods... 

Iirc - you note a roughly 3:1 ''encoder frequency vs. motor spec'' discrepancy.  Might that motor spec be confined to some specified motor load - and motor voltage?  Should you deviate from those conditions the motor is unlikely to match the listed spec... 

furqan
Associate II
Posted on August 18, 2014 at 05:32

I have checked the encoder's output on an oscilloscope and it gives a very good square wave and the speed from the output on oscilloscope is near the manufacturer's claim. The only problem is that the MCU's maximum voltage on it's pins is 3.3V while the minimum voltage that can be given to the encoder is 3.5 volts (hence the output wave's peak value).

The MCU get's its power supply from the USB cable from my computer as I have to perform debugging. But their grounds are common (connected a pin from GND of uC to the circuit GND).