본문 바로가기
Embedded SW/[Infineon] Embedded SW Project

[Infineon] 20. Aurix (TC23x) DC모터를 Encoder를 통해 속도 측정

by 방구석 임베디드 2021. 6. 28.
반응형

FIT0450으로 엔코더가 장착된 모터이다.

https://wiki.dfrobot.com/Micro_DC_Motor_with_Encoder-SJ01_SKU__FIT0450

 

Micro_DC_Motor_with_Encoder-SJ01_SKU__FIT0450-DFRobot

Introduction This is the DFRobot Micro DC geared motor with encoder. It is a motor with a 120:1 gearbox and an integrated quadrature encoder that provides a resolution of 16 pulse single per round giving a maximum output of 1920 within one round. With an A

wiki.dfrobot.com

아래 빨강색으로 칠해진 부분이 한바퀴 회전하면 Pulse를 생성하게 된다.

다시 한번 Spec을 확인해 보도록 하자!

  • Gear ratio: 120:1
  • No-load speed @ 6V: 160 rpm
  • No-load speed @ 3V: 60 rpm
  • No-load current @ 6V: 0.17A
  • No-load current @ 3V: 0.14A
  • Max Stall current: 2.8A
  • Max Stall torque: 0.8kgf.cm
  • Rated torque: 0.2kgf.cm
  • Encoder operating voltage: 4.5~7.5V
  • Motor operating voltage: 3~7.5V (Rated voltage 6V)
  • Operating ambient temperature: -10 ~ +60℃

바퀴가 한바퀴돌때 저빨강색 엔코더는 120번을 돈다.

그리고 엔코더가 한바퀴 돌때 8개의 Pulse가 생성되게 된다.

따라서

자동차 바퀴 한바퀴에 120*8 = 960번의 펄스가 생기는 것이다.

 

x : 펄스수

n : 자동차 바퀴 회전수

8*120 : 1 = x(펄스수) : n(바퀴)

x = n * (8*120)

n = x/(8*120)

100ms동안 n바퀴 돌았다면

1초에 10*n

60초에 60*10*n

RPM = (x*60*10)/(8*120)

 

따라서 100ms동안 획득한 rising edge 펄스수를 x 라고 하면

RPM 계산식은 (x*60*10)/(8*120) 이 된다.

 

오케이! 그렇다면 지금부터 Pulse수를 어떻게 MCU가 측정할지를 확인해 보도록 하자!

우선, Input Capture를 이용하여 Rising Edge에 ISR를 띄워 Cnt를 1씩 증가하는 방법을 사용하는 것이다.

 

이것을 수행하기 위해서는 GTM의 TIM모듈을 이용하여 Rising Edge일때 ISR이 뜨도록 설계해주면 될것 같다.

그러면 어떻게 GTM TIM을 초기화 해야하는 것일까?

 

static void GtmTim0Init(void)
{
    float32_t temp = 0.0f;
    
    IfxGtm_PinMap_setTimTin(&IfxGtm_TIM0_0_TIN26_P33_4_IN, IfxPort_InputMode_pullDown);

    GTM_TIM0_CH0_CTRL.B.TIM_MODE = 2u; 
    GTM_TIM0_CH0_CTRL.B.ISL = 0u;
    GTM_TIM0_CH0_CTRL.B.DSL = 1u;

    GTM_TIM0_CH0_CTRL.B.FLT_EN = 1;
    temp = 2.0f * TOM_BASE_FREQ;

    GTM_TIM0_CH0_FLT_RE.B.FLT_RE = (uint32_t)temp;
    GTM_TIM0_CH0_CTRL.B.FLT_MODE_RE = (uint8_t)IfxGtm_Tim_FilterMode_individualDeglitchTime;
    GTM_TIM0_CH0_CTRL.B.FLT_CTR_RE = (uint8_t)IfxGtm_Tim_FilterCounter_upDown;

    SRC_GTMTIM00.B.SRE = 1;
    SRC_GTMTIM00.B.SRPN = 200u;
    GTM_TIM0_CH0_CNT.U = 0;
    GTM_TIM0_CH0_IRQ_EN.U = 0x1;
    GTM_TIM0_CH0_CTRL.B.TIM_EN = 1;
    GTM_IRQ_MODE.B.IRQ_MODE = 2;
    GTM_TIM0_CH0_IRQ_MODE.B.IRQ_MODE = 2;    
}

1. IfxGtm_PinMap_setTimTin(&IfxGtm_TIM0_0_TIN26_P33_4_IN, IfxPort_InputMode_pullDown);

 

우선 pin을 할당하였다. 33.4번 pin을 GTM TIM 모듈로 사용하였다.

 

 

default pull down, 아래로 깔려 있다가 High사 되면 그 Edge를 Detect 하자는 것이다.

 

2. GTM_TIM0_CH0_CTRL.B.TIM_MODE = 2u; 

Rising이 발생하면 ISR (Event)를 발생하도록 하기위하여 TIM_MODE를 2로 설정할 것이다.

 

3. GTM_TIM0_CH0_CTRL.B.ISL = 0u;

1을 설정하면 모든 Egde마다 ISR이 발생한다. 0을 넣으면 active signal이 될때 ISR이 발생한다.

따라서 0으로 설정한다. 나는 Rising Edge만을 Detection 하여 ISR이 띄워지기를 원하기 때문이다. 

 

4. GTM_TIM0_CH0_CTRL.B.DSL = 1u;

Rising Edge일때 ISR이 띄워지도록 설정한다.

 

5. GTM_TIM0_CH0_CTRL.B.FLT_EN = 1;

노이즈를 Detection하면 안되니까, GTM TIM안에서 Hardware로 구현되어 있는 필터를 사용하자!

  

6. temp = 2.0f * TOM_BASE_FREQ;
   GTM_TIM0_CH0_FLT_RE.B.FLT_RE = (uint32_t)temp;

2.0f를 곱한 것은 

#define TOM_BASE_FREQ    (100000000.0f/256.0f)

(256/100000000)*2 = 0.00000512

즉, 5.12us만큼의 필터를 걸어준 것이다.

 

7. GTM_TIM0_CH0_CTRL.B.FLT_MODE_RE = (uint8_t)IfxGtm_Tim_FilterMode_individualDeglitchTime;

필터는 2종류가 있다. 이중에서 나느 indiviual de-glitch mode를 사용할것이다.


8. GTM_TIM0_CH0_CTRL.B.FLT_CTR_RE = (uint8_t)IfxGtm_Tim_FilterCounter_upDown;
그리고 나는 de-glitch mode에서 upDown 방식을 사용할것이다.

 

9. 이제 Interrupt 설정을 하도록 하자!
 SRC_GTMTIM00.B.SRE = 1;

인터럽트를 Enable 해주고
 SRC_GTMTIM00.B.SRPN = 200u;

그리고 나서, Interrupt의 우선순위를 넣는다.

 

10. GTM_TIM0_CH0_CNT.U = 0;

TIM의 CNT 레지스터의 값은 0으로 초기화 시키도록 하자!

TIM에서는 사용하지 않을 것이다.

 

11. GTM_TIM0_CH0_IRQ_EN.U = 0x1;

GTM TIM 인터럽트를 Enable 시켜주고!    

 

12. GTM_TIM0_CH0_CTRL.B.TIM_EN = 1;

TIM0 모듈의 0번 채널을 Enable 시켜준다.


12. GTM_IRQ_MODE.B.IRQ_MODE = 2;

13. GTM_TIM0_CH0_IRQ_MODE.B.IRQ_MODE = 2; 

모드를 Pulse-Notify mode를 선택한다.

초기화의 흐름을 확인하였다.

지금부터, 실제로 연결을 시켜서 동작을 확인해 보도록 하자!

엔코더 측정 부분을 Logic Analzer로 찍어보면 다은과 같이 나오는 것을 알수 있다.

현재, 아래는 Duty 50%를 주었을때 엔코더에서 생성된 Pulse 파형을 나타내고 있다.

나는 TIM을 이용하여 Rising Edge일때 ISR를 발생하여 Cnt를 증가시킬것이다.

void TIM0_IntHandler(void)
{
    IfxCpu_enableInterrupts();
    ulPulseCnt++;
}

그리고 100ms 마다 증가된 Cnt를 이용하여 RPM을 계산하고

Cnt는 0으로 Clear 시켜 주었다.

fSenseMotorRpm = ((float32_t)ulPulseCnt*60.0f*10.0f)/(8.0f*120.0f);
ulPulseCnt = 0u;

이제 이렇게 측정된 값을 그래프로 확인해 보도록 하자!

이것을 수행하기 위해서는 UART를 이용하여 그래픽으로 그림을 그릴수 있는 SerialPlot을 사용하는 것이 필요하다!

다음장에서 SerialPlot을 이용하여 그림을 그려 보도록 하자!

반응형

댓글