본문 바로가기

[TI]/MSPM0G5187

[MSPM0G5187-SM] USB CDC - TinyEngine NPU 엣지 AI구현을 위한 6축 IMU 센서 데이터 수집

MSPM0G5187의 특징으로 USB 기능과 TinyEngine NPU 기능인데 NPU 기능을 활용하면 엣지 AI구현 할수 있다. AI 구현을 위한 첫번째 단계로 데이터 수집이므로 USB로 IMU 센서 데이터를 수집할 수 있는 코드를 작성해 보자.

 

MSPM0G5187 USB CDC 테스트 예제 코드와 MSPM0G5187 I2C 테스트 코드를 이용하여 IMU센서 데이터터를 수집할 수 있는 코드를 작성하자

 

우선 MSPM0G5187 에서 USB CDC로 printf 함수가 동작하도록 fputc, fputs 함수를 재정의 한다. 

#define USB0_INST            0

int fputc(int ch, FILE *f)
{
    if ( tud_cdc_n_connected(USB0_INST) )
    {
     tud_cdc_n_write_char(USB0_INST, ch);
     tud_cdc_n_write_flush(USB0_INST); 
    }
    
    return (ch);
}

int fputs(const char* restrict s, FILE* restrict stream) 
{
    uint16_t i,len;
    len = strlen(s);

    if ( tud_cdc_n_connected(USB0_INST) )
    {
        for(i=0;i<len;i++)
        {
            tud_cdc_n_write_char(USB0_INST, s[i]);
        }

        tud_cdc_n_write_flush(USB0_INST); 
    }

    return len;
}

int puts(const char* _ptr)
{
    int count = fputs(_ptr,stdout);

    count += fputs("\n",stdout);

    return count;
}

 

 

IMU 센서는 LSM6DSR 센서 모듈을 이용하고 간단히 가속도 값을 읽어 오는 함수를 작성하자.

#define LSM6DSR_ADDR        (0x6B << 1)

#define WHO_AM_I            0x0F
#define CTRL1_XL            0x10
#define CTRL2_G             0x11
#define CTRL3_C             0x12
#define CTRL4_C             0x13
#define CTRL6_C             0x15
#define CTRL7_G             0x16
#define CTRL8_XL            0x17

#define OUTX_L_G            0x22
#define OUTX_L_A            0x28


static void LSM6DSR_Write(uint8_t reg, uint8_t data)
{
    i2c_write_reg(LSM6DSR_ADDR, reg, data);
}

uint8_t LSM6DSR_Init(void)
{
    uint8_t id;

    // 1. WHO_AM_I 확인
    id = i2c_read_reg(LSM6DSR_ADDR, WHO_AM_I);  

    if (id != 0x6B)return 0;  // 센서 확인 실패

    // 2. SW Reset
    LSM6DSR_Write(CTRL3_C, 0x01);
    delay_ms(50);

    // 3. Block Data Update + Auto Increment
    LSM6DSR_Write(CTRL3_C, 0x44);
    // BDU=1, IF_INC=1

    // 4. Accelerometer 설정
    // ODR=104Hz (0x40), FS=±2g (00)
    LSM6DSR_Write(CTRL1_XL, 0x40);

    // 5. Gyroscope 설정
    // ODR=104Hz (0x40), FS=2000dps (0x0C)
    LSM6DSR_Write(CTRL2_G, 0x4C);

    // 6. Gyro 필터 설정
    LSM6DSR_Write(CTRL7_G, 0x00);  // 기본 HPF off

    // 7. Accel 필터 설정 (LPF2)
    LSM6DSR_Write(CTRL8_XL, 0x09); 
    // LPF2 enable + bandwidth 설정

    // 8. 추가 안정 설정
    LSM6DSR_Write(CTRL4_C, 0x00);
    LSM6DSR_Write(CTRL6_C, 0x00);

    delay_ms(10);

    return 1;  // 성공
}

typedef struct {
    int16_t ax, ay, az;
    int16_t gx, gy, gz;
} IMU_Data_t;



void LSM6DSR_Read(uint8_t addr, uint8_t reg, IMU_Data_t *imu)
{
    uint8_t buf[12];

    i2c_read_buf(addr, reg, buf, 12);

    imu->gx = (int16_t)(buf[1] << 8 | buf[0]);
    imu->gy = (int16_t)(buf[3] << 8 | buf[2]);
    imu->gz = (int16_t)(buf[5] << 8 | buf[4]);

    imu->ax = (int16_t)(buf[7] << 8 | buf[6]);
    imu->ay = (int16_t)(buf[9] << 8 | buf[8]);
    imu->az = (int16_t)(buf[11] << 8 | buf[10]);
}

 

 

이제 IMU 센서 데이터를 읽어와 USB CDC로 출력하는 예제 코드를 작성해 보자.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bsp/board_api.h"
#include "ti_msp_dl_config.h"
#include "tusb.h"

enum {
    BLINK_NOT_MOUNTED = 250,
    BLINK_MOUNTED     = 1000,
    BLINK_SUSPENDED   = 2500,
};

static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;

static void led_blinking_task(void);
static void USB_to_UART_task(void);

//Size of the data received via USB
#define BUFF_SIZE (64)
uint8_t gDataBuff[BUFF_SIZE];

int main(void)
{
    SYSCFG_DL_init();

    board_init();
    LSM6DSR_Init();

    // init device stack on configured roothub port
    tusb_rhport_init_t dev_init = {
        .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO};

    tusb_init(BOARD_TUD_RHPORT, &dev_init);

    while (1) {
        tud_task();  // tinyusb device task
        USB_to_UART_task();
        imu_read_task();
    }
}


void imu_read_task(void)
{
    static uint32_t start_ms = 0;
    static bool led_state    = false;

    if (board_millis() - start_ms < imu_interval_ms)
        return;
    start_ms += imu_interval_ms;

	LSM6DSR_Read(LSM6DSR_ADDR, OUTX_L_G, &imu_data);
    printf("%d, %d, %d\r\n", imu_data.ax, imu_data.ay, imu_data.az);
}

 

 

이제 MSPM0G5187을 이용하여  I2C 센서 데이터를 읽어오고 USB CDC를 이용하여 printf로 데이터 출력 하는 기본 코드를 작성했다. 이를 이용하여 MSPM0G5187의 TinyEngine NPU를 테스트 해 보면 좋을것 같다.