STM32 - Encoder Mode - przeliczanie wartości

Język C dla mikrokontrolerów ARM
ODPOWIEDZ
ps19
Użytkownik
Posty: 21
Rejestracja: 16 paź 2017, 21:42
Lokalizacja: Opole

STM32 - Encoder Mode - przeliczanie wartości

Post autor: ps19 »

Witam,

Mam taki mały prosty problem, uruchomiłem encoder mode w stm32f4, działa bez problemu, dodałem poszerzenie zakresu z 16 bit na 32 bity, przy osiągnięciu przez licznik wartości maksymalnej 16 bitowej bez znaku.
Problem leży w tym że przy przejściu wartości z zera na 65535 (0xFFFF), że moja implementacja nie działa - pewnie błąd w logiczny, ale go nie widzę.
  1. typedef struct {
  2.     uint32_t timerImpulsesPresent, timerImpulsesMul, timerImpulsesOverflowsMul;
  3.     int32_t timerImpulsesDiff, timerImpulsesTemp;
  4.     int32_t timerImpulsesTotal, timerImpulsesOld;
  5.     uint8_t direction;
  6.     uint16_t cntVal;
  7.     float distanceMilimeters;
  8.     float distanceMeters;
  9.     float speedMilimeters;
  10.  
  11.     float translationMilimeters;
  12.     float rotationMilimeters;
  13.  
  14. } encoderTypedef;
  1. static void encoderTimerInit(TIM_TypeDef *tim)
  2. {
  3.     __IO uint32_t arrVal = 0xFFFF;
  4.     __IO uint32_t ccmr1Val = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0 |
  5.             TIM_CCMR1_IC1F_3 | TIM_CCMR1_IC1F_0 |
  6.             TIM_CCMR1_IC2F_3 | TIM_CCMR1_IC2F_0;
  7.     __IO uint32_t smcrVal = TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0;
  8.     __IO uint32_t dierVal = TIM_DIER_UIE;
  9.     __IO uint32_t cr1Val = TIM_CR1_CEN;
  10.  
  11.     //ENC2
  12.     tim->ARR = arrVal;
  13.     tim->CCMR1 =  ccmr1Val;
  14.     TIM_ENC_RIGHT->CCER = TIM_CCER_CC1P;
  15.     tim->SMCR = smcrVal;
  16.     tim->DIER = dierVal;
  17.     tim->CR1 |= cr1Val;
  18. }
  1. void encoderInterruptHandler(encoderTypedef *enc, TIM_TypeDef *tim)
  2. {
  3.     if(tim->SR & TIM_SR_UIF)
  4.     {
  5.         if(tim->CNT == 0xFFFF && enc->timerImpulsesOld > tim->CNT)
  6.         {
  7.             enc->timerImpulsesOverflowsMul++;
  8.             enc->timerImpulsesMul = UINT16_MAX*enc->timerImpulsesOverflowsMul;
  9.         }
  10.         else
  11.         {
  12.             enc->timerImpulsesOverflowsMul = 0;
  13.             enc->timerImpulsesMul = 0;
  14.         }
  15.         tim->SR &= ~TIM_SR_UIF;
  16.     }
  17. }
  18.  
  19. void TIM3_IRQHandler(void) //left
  20. {
  21.     encoderInterruptHandler(&encoderLeft, TIM_ENC_LEFT);
  22. }
  23. void TIM4_IRQHandler(void) //right
  24. {
  25.     encoderInterruptHandler(&encoderRight, TIM_ENC_RIGHT);
  26. }
  27.  
  28. void encoderMilimeterSpeedRead(encoderTypedef *enc, TIM_TypeDef *tim)
  29. {
  30.     //const float mmPerTick = 360.0F/ENCODER_TICKS;
  31.     const float wheelPerimeter = M_PI*WHEEL_DIAMETER;
  32.     const float constructionParam = wheelPerimeter/ENCODER_TICKS;
  33.  
  34.     enc->timerImpulsesOld = enc->timerImpulsesPresent;
  35.     enc->timerImpulsesPresent = tim->CNT;
  36.     enc->timerImpulsesDiff = (enc->timerImpulsesPresent - enc->timerImpulsesOld);
  37.     enc->timerImpulsesTemp = abs(enc->timerImpulsesPresent - enc->timerImpulsesTemp);
  38.  
  39.     if(enc->timerImpulsesDiff < 0 || (enc->timerImpulsesTemp >= INT16_MAX && enc->timerImpulsesMul == 0))
  40.     {
  41.         enc->timerImpulsesTotal = 0xFFFF - enc->timerImpulsesPresent;
  42.     }
  43.     else
  44.     {
  45.         enc->timerImpulsesTotal = enc->timerImpulsesPresent + enc->timerImpulsesMul;
  46.         enc->timerImpulsesTemp = enc->timerImpulsesTotal;
  47.     }
  48.  
  49.  
  50.     enc->distanceMilimeters = (constructionParam*enc->timerImpulsesTotal);
  51.     enc->distanceMeters = enc->distanceMilimeters/1000;
  52. }
  53. void ProcessEncoders(void)
  54. {
  55.     encoderMilimeterSpeedRead(&encoderLeft, TIM_ENC_LEFT);
  56.     encoderMilimeterSpeedRead(&encoderRight, TIM_ENC_RIGHT);
  57. }
Do testów funkcja ProcessEncoders wywoływana jest z częstotliwością 100 Hz.
ODPOWIEDZ

Wróć do „C dla ARM”