[TI]/LM3S2xxx2009. 4. 13. 08:00

[LM3S2965] QEI 테스트

[LM3S2965] QEI 테스트


Lunminary Micro QEI특징
Position integrator that tracks the encoder position
Velocity capture using built-in timer
QEISPEED, QEIPOS레지스터가 각각 독립적으로 구동할 수 있다. (QEIPOS는 QEISPEED보다 먼저 Enable해야 함)

인터럽트 소스
- Index pulse
- Velocity-timer expiration
- Direction change
- Quadrature error detection





QEI모듈은   quadrature phase 모드와 clock/direction 모드를 지원한다.
quadrature phase모드
엔코더는 90도 위상을 가진 두개의 2개의 클럭을 생성한다. 각 에지를 이용해 회전 방향을 결정한다.

clock/direction 모드

엔코더는 클럭신호를 생성한다. direction 신호가 엔코더의 방향을 결정한다.
 
QEI Control (QEICTL) 레지스터의 SigMode bit비트로 모드를 설정할 수 있다.
Luminary 제공함수 QEIConfigure 함수로 설정 가능하다.
 
QEIConfigure(QEI0_BASE, QEI_CONFIG_QUADRATURE |QEI_CONFIG_CAPTURE_A, 1000);

QEI Control (QEICTL)
#define QEI_CONFIG_CAPTURE_A    0x00000000  // Count on ChA edges only
#define QEI_CONFIG_CAPTURE_A_B  0x00000008  // Count on ChA and ChB edges
#define QEI_CONFIG_NO_RESET     0x00000000  // Do not reset on index pulse
#define QEI_CONFIG_RESET_IDX    0x00000010  // Reset position on index pulse
#define QEI_CONFIG_QUADRATURE    0x00000000  // ChA and ChB are quadrature
#define QEI_CONFIG_CLOCK_DIR    0x00000004  // ChA and ChB are clock and dir
#define QEI_CONFIG_NO_SWAP      0x00000000  // Do not swap ChA and ChB
#define QEI_CONFIG_SWAP         0x00000002  // Swap ChA and ChB
 
PhA의 에지(혹은 PhA, PhB두 에지)에서 QEIPOS레지스터 값을 업데이트 한다.
PhA후 PhB가 오는 정방향일 경우 QEIPOS값은 증가되고 PhB후 PhA가 오는 역방향일 경우 QEIPOS값은 감소된다.

QEI 타이밍도



QEI 초기화 함수
static void InitQEI(void)
{
   //Set Clock
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI);
   
    // Configure the QEI pins.
    GPIOPinTypeQEI(QEI_PHA_PORT, QEI_PHA_PIN);
    GPIOPinTypeQEI(QEI_PHB_PORT, QEI_PHB_PIN);
    GPIOPinTypeQEI(QEI_IDX_PORT, QEI_IDX_PIN);
 
    // Configure the QEI module.
    QEIConfigure(QEI0_BASE, QEI_CONFIG_QUADRATURE|QEI_CONFIG_CAPTURE_A, 1000);
   
    // Initialize the QEI position to zero.
    QEIPositionSet(QEI0_BASE, 0);
    // Enable the QEI module.
    QEIEnable(QEI0_BASE);
}

QEI POS값 출력
각 Edge마다 1씩 증가 하므로 엔코더 1클릭당 2펄스씩 증가한다.
   pos = QEIPositionGet(QEI0_BASE);
   dir = QEIDirectionGet(QEI0_BASE);
   DebugPrint("pos=%d %ld\r\n", dir, pos);

출력결과
pos=-1 262
pos=-1 266
pos=-1 265
pos=-1 264
pos=-1 264
pos=-1 262


Motor Driver 보드의 LM3S2965 QEI핀맵



QEI1 모듈 사용할때 주의 사항
QEI SysCtlPeripheralEnable() 함수를 호출하지 않으면 홀딩되는 현상이 발생한다. <- QEI인자 확인할것
    //----------------------------------------------------------------------------- 
    //QEI 1 Config

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI1); 
 
    // Configure the QEI pins.
    GPIOPinTypeQEI(QEI1_PHA_PORT, QEI1_PHA_PIN);
    GPIOPinTypeQEI(QEI1_PHB_PORT, QEI1_PHB_PIN);
    GPIOPinTypeQEI(QEI1_IDX_PORT, QEI1_IDX_PIN);
 
    // Configure the QEI module.
    QEIConfigure(QEI1_BASE, QEI_CONFIG_QUADRATURE | QEI_CONFIG_CAPTURE_A, 0xffffffff);//ENCODER_MAX_POS); 
    // Initialize the QEI position to zero.
    QEIPositionSet(QEI1_BASE, 0);
    // Enable the QEI module.
    QEIEnable(QEI1_BASE);
    //----------------------------------------------------------------------------- 
Posted by nexp

댓글을 달아 주세요

[TI]/LM3S2xxx2009. 3. 23. 18:15

[LM3S2965] 모터 드라이버 보드 테스트 - 모터 정역, PWM 테스트

[LM3S2965] 모터 드라이버 보드 테스트 - 모터 정역, PWM 테스트



LuminaryMicro사의 LM3S2965를 이용하여 모터 드라이버 보드 제어 테스트를 진행 했다.
드라이버 스펙상 30A까지 가능하다고 하는데.. 부하를 걸어봐야 알겠지만 일단 간단한 모터 제어먼저 시작.


Pinmap

INA1 – PB.4

INB1 – PB.5

PWM1 – PG.2(pwm : 10Khz)


테스트 동영상
PWM 으로 모터 속도 제어 및 정역제어 테스트




Mobie Robot Body Test

")//]]>


Posted by nexp

댓글을 달아 주세요

[TI]/LM3S2xxx2009. 3. 13. 17:26

[LM3S2965] 모터 드라이버 베이스 보드 제작

[LM3S2965] 모터 드라이버 베이스 보드 제작


Luminary Micro사의 Cortex-M3코어 LM3S2965 보드를 이용한 모터제어 베이스 보드를 제작 했다.
LM3S2965는 2채널 Encoder, PWM 6, ADC, CAN 이터페이스를 내장하여 모터 제어용으로 사용하기 좋아 모터 드라이버 테스트 용으로 만들어 보았다.


Motor Driver 보드의 LM3S2965 QEI핀맵



Motor PWM 핀맵
Motor2 -> PWM2, PB3, PG4
Motor3 -> PWM3, PF5, PF6






Posted by nexp

댓글을 달아 주세요

[TI]/LM3S2xxx2009. 3. 6. 21:02

[LM3S2965] 관련자료

[LM3S2965] 관련자료



예제소스
Posted by nexp
TAG LM3S2965

댓글을 달아 주세요

[TI]/LM3S2xxx2009. 3. 5. 17:27

[LM3S2965] PWM 제어

[LM3S2965] PWM 제어




Luminary Micro Cortex-M3 LM3S2965 PWM
예제소스코드
pwmgen.zip



PWM초기화 함수
void PwmInit(void)
{
    // Enable the peripherals used by this example.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
 

    //
    // Set GPIO D0 and D1 as PWM pins.  They are used to output the PWM0 and
    // PWM1 signals.
    //
    GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_2 | GPIO_PIN_3);

    //
    // Compute the PWM period based on the system clock.
    //
    ulPeriod = SysCtlClockGet() / 50000;

    //
    // Set the PWM period to 50 kHz.
    //
    PWMGenConfigure(PWM_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, ulPeriod);

    //
    // Set PWM0 to a duty cycle of 25% and PWM1 to a duty cycle of 75%.
    //
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, ulPeriod/4);
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, ulPeriod * 3 / 4);

    //
    // Enable the PWM0 and PWM1 output signals.
    //
    PWMOutputState(PWM_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT, true);

    //
    // Enable the PWM generator.
    //
    PWMGenEnable(PWM_BASE, PWM_GEN_0);
}


PWM출력 함수
void PWMPulseWidthSet(unsigned long ulBase, unsigned long ulPWMOut, unsigned long ulWidth)
{
    unsigned long ulGenBase, ulReg;

    //
    // Check the arguments.
    //
    ASSERT(ulBase == PWM_BASE);
    ASSERT(PWMOutValid(ulPWMOut));

    //
    // Compute the generator's base address.
    //
    ulGenBase = PWM_OUT_BADDR(ulBase, ulPWMOut);

    //
    // If the counter is in up/down count mode, divide the width by two.
    //
    if(HWREG(ulGenBase + PWM_O_X_CTL) & PWM_X_CTL_MODE)
    {
        ulWidth /= 2;
    }

    //
    // Get the period.
    //
    ulReg = HWREG(ulGenBase + PWM_O_X_LOAD);

    //
    // Make sure the width is not too large.
    //
    ASSERT(ulWidth < ulReg);

    //
    // Compute the compare value.
    //
    ulReg = ulReg - ulWidth;

    //
    // Write to the appropriate registers.
    //
    if(PWM_IS_OUTPUT_ODD(ulPWMOut))
    {
        HWREG(ulGenBase + PWM_O_X_CMPB) = ulReg;
    }
    else
    {
        HWREG(ulGenBase + PWM_O_X_CMPA) = ulReg;
    }
}

Luminary Micro에서 제공하는 함수는 상당히 복잡하다. 범용으로 사용하기 쉽게 제작하긴 했지만... 쉽다는 장점으로 속도에서는 상당한 문제가 있다.
특히나 모터제어와 같이 PWM출력을 주기적으로 변경해야 하는 루틴이 많을경우 AVR보다 더 느려질 수도 있다.

그래서 PWM 제어 함수를 따로 만들었다.
void PwmSet(unsigned int Speed)
{
   HWREG(PWM_OUT_BADDR(PWM_BASE, PWM_OUT_0) + PWM_O_X_CMPA) = PWM_MAX_VALUE - Speed;
}


테스트 동영상

Posted by nexp

댓글을 달아 주세요