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

적외선 센서를 이용한 장애물 탐지 차량 주행 (TC275 MCU)

by 방구석 임베디드 2021. 12. 21.
반응형

안녕하세요.

오늘은 이제 적외선 센서로 장애물을 탐지하는 차량을 주행해 보도록 하겠습니다.

 

참고로 이 글은 계속 연재하는 글이여서,

처음부터 보시려면 아래 링크를 참조해 주세요.

 

1) 임베디드 SW, MCU에 대한 정리 (feat. 임베디드 SW 비전)

https://embeddedchallenge.tistory.com/210

2) MCU 개발 장비 구매 방법 정리 (인피니언 MCU TC275 Lite)

https://embeddedchallenge.tistory.com/211

3) 임베디드 SW 개발 환경 세팅 방법 정리 (소스코드 편집기, 컴파일러, 디버거 환경 설정 방법)

https://embeddedchallenge.tistory.com/212

4) 인피니언 IDE Tool 사용방법 정리 (프로젝트 생성 및 다운로드 수행)

https://embeddedchallenge.tistory.com/219

5) 인피니언 MCU LED Blinking (TC275 GPIO 설정)

https://embeddedchallenge.tistory.com/225

6) 인피니언 MCU Clock, 오실레이터 에 대한 이해 (TC275 보드에서 확인)

https://embeddedchallenge.tistory.com/226

7) 인피니언 MCU PLL 설정 및 주변기기 Clock 설정 (TC275)

https://embeddedchallenge.tistory.com/227

8) 인피니언 MCU 인터럽트/Interrupt 설정 (TC275 동작 확인)

https://embeddedchallenge.tistory.com/228

9) 스케줄링(scheduling)에 대한 정리, 인피니언 MCU Scheduler 설계 정리

https://embeddedchallenge.tistory.com/229

10) PWM이란 무엇인가? 인피니언 MCU를 이용한 PWM 설계 수행

https://embeddedchallenge.tistory.com/232

11) Motor Driver L298N 사용법 정리 (인피니언 MCU 개발)

https://embeddedchallenge.tistory.com/235

12) DC모터 드라이버 설계, RC카 전진,후진,회전 설계 (인피니언 MCU PWM, GPIO 설정)

https://embeddedchallenge.tistory.com/236

13) UART 통신 정리, UART 통신 MCU 설계 (인피니언 MCU)

https://embeddedchallenge.tistory.com/237

14) Teraterm 시리얼 통신 터미널 프로그램 사용법, 다운로드 방법 (feat 허큘리스)

https://embeddedchallenge.tistory.com/238

15) Logic analyzer 사용법 (saleae 로직 분석기 사용법 정리)

https://embeddedchallenge.tistory.com/239

16) UART 통신 MCU Driver 초기화 설계 및 동작 확인 (Tx, Rx Interrupt)

https://embeddedchallenge.tistory.com/240

17) ADC 설명 정리 및 인피니언 MCU ADC 설계 요소 정리

https://embeddedchallenge.tistory.com/241

18) ADC를 이용하여 GP2Y0A21YK 적외선 센서 거리 측정 (TC275 MCU)

https://embeddedchallenge.tistory.com/264

 

그러면 아래와 같이 오른쪽 적외선센서는 ADC 1번채널에

그리고 왼쪽 적외선센서는 ADC 2번채널에 연결을 합니다.

그리고, 아래와 같이 1ms 주기로 ADC Data를 획득합니다.

이 Raw Data를 이용하여 간단한 알고리즘을 만들어 봅니다.

코드는 간단합니다.

왼쪽 오른쪽 적외선센서의 장애물이 탐지가 되면

왼쪽으로 회전을 하는것입니다.

그리고 적외선센서의 장애물이 시야에서 사라지게 된다면, 멈춰어서는 아주 간단한 로직입니다.

void Unit_WirelessControl(void)
{
    uint8_t u8nuWirelessCmd = 0u;
    SensorAdcRaw* pstSensorAdcRaw = MidAdc_GetAdcGroup0SenseRaw();
    static uint8_t ucWarningFlag = 0u;
    
    if(pstSensorAdcRaw->InfRaySense1_Raw >= 2200u || pstSensorAdcRaw->InfRaySense2_Raw >= 2200u)
    {
        u8nuWirelessCmd = 'a';
        ucWarningFlag = 1u;
    }
    else
    {
        if(ucWarningFlag == 1u)
        {
            gu32nuAscRxData = 's';
            ucWarningFlag = 0u;
        }
        u8nuWirelessCmd = (uint8_t)gu32nuAscRxData;
    }
      
    if(u8nuWirelessCmd == 'w')    /*Forward*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_FWD);
        Unit_MotorRearDirectionCtl(MOTOR_FWD);
    }
    else if(u8nuWirelessCmd == 'd') /*TurnRight*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_TURN_RIGHT);    
        Unit_MotorRearDirectionCtl(MOTOR_TURN_RIGHT);
    }
    else if(u8nuWirelessCmd == 'a') /*TurnLeft*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_TURN_LEFT);    
        Unit_MotorRearDirectionCtl(MOTOR_TURN_LEFT);
    }
    else if(u8nuWirelessCmd == 'x') /*Reverse*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_REVERSE);    
        Unit_MotorRearDirectionCtl(MOTOR_REVERSE);
    }    
    else if(u8nuWirelessCmd == 's') /*Stop*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_STOP);    
        Unit_MotorRearDirectionCtl(MOTOR_STOP);
    }
    else
    {
        /*No Code*/
    }  
}

그렇다면 이제 어떻게 동작을 하는지 살펴 보도록 하겠습니다.

 

장애물을 감지하고 왼쪽으로 회전하고, 멈추어 서는것을 볼수 있습니다.

그렇다면 이제 다음으로 동작할 위치를 확보하였으니, 

멈추어서는것이 아니라, 다시 직진을 수행하도록 코드를 수정해 보도록 하겠습니다.

코드는 아래 부분만 수정하였습니다.

그러면 이제 어떻게 동작하는지 동영상을 통해서 확인해 보도록 하겠습니다.

 

나름, 장애물을 피해서 동작하는 자율주행자동차가 되었습니다.

그런데 계속 왼쪽으로 회전을 하다보니, 위와 같이 반복되어 빙빙 도는 현상이 발견이 되었습니다.

이러한 현상을 개선하기 위해서는 어떻게 코드를 수정하면 좋을 까요?

 

아래와 같이 코드를 수정하였습니다.

void Unit_WirelessControl(void)
{
    uint8_t u8nuWirelessCmd = 0u;
    SensorAdcRaw* pstSensorAdcRaw = MidAdc_GetAdcGroup0SenseRaw();
    static uint8_t ucWarningFlag = 0u;
    static uint8_t ucFirstDetectionFlag = 0u;
    
    if(pstSensorAdcRaw->InfRaySense1_Raw >= 2200u || pstSensorAdcRaw->InfRaySense2_Raw >= 2200u)
    {
        if(ucFirstDetectionFlag == 0u)
        {
            if(pstSensorAdcRaw->InfRaySense1_Raw > pstSensorAdcRaw->InfRaySense2_Raw) 
            {
                u8nuWirelessCmd = 'a'; /*TurnLeft*/
            }
            else
            {
                u8nuWirelessCmd = 'd'; /*TurnRight*/
            }
            ucFirstDetectionFlag = 1u;
            ucWarningFlag = 1u;
        }
    }
    else
    {    
        if(ucWarningFlag == 1u)
        {
            gu32nuAscRxData = 'w';
            ucWarningFlag = 0u;
            ucFirstDetectionFlag = 0u;
        }
        u8nuWirelessCmd = (uint8_t)gu32nuAscRxData;
    }
      
    if(u8nuWirelessCmd == 'w')    /*Forward*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_FWD);
        Unit_MotorRearDirectionCtl(MOTOR_FWD);
    }
    else if(u8nuWirelessCmd == 'd') /*TurnRight*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_TURN_RIGHT);    
        Unit_MotorRearDirectionCtl(MOTOR_TURN_RIGHT);
    }
    else if(u8nuWirelessCmd == 'a') /*TurnLeft*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_TURN_LEFT);    
        Unit_MotorRearDirectionCtl(MOTOR_TURN_LEFT);
    }
    else if(u8nuWirelessCmd == 'x') /*Reverse*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_REVERSE);    
        Unit_MotorRearDirectionCtl(MOTOR_REVERSE);
    }    
    else if(u8nuWirelessCmd == 's') /*Stop*/
    {
        Unit_MotorFrontDirectionCtl(MOTOR_STOP);    
        Unit_MotorRearDirectionCtl(MOTOR_STOP);
    }
    else
    {
        /*No Code*/
    }  
}

결국 오른쪽 장애물이 더 크게 감지가 되면 왼쪽으로 회전하고

왼쪽 장애물이 더 크게 감지가 되면 오른쪽으로 회전하는 코드입니다.

 

그러면 최종적으로 어떻게 동작하는지를 살펴 보도록 하겠습니다.

 

오케이 좋습니다.

이제 빙빙도는 현상은 사라졌습니다.

이제 한번 집안을 마음껏 돌아다녀 보도록 하겠습니다.

 

이제 아주 똑똑하게 동작을 합니다.

그런데, 정면으로 장애물을 감지하였을때, 

마지막에 멈추어 서는 것을 볼수 있습니다.

 

이제 이 현상을 어떻게 개선하면 좋을지 생각해 볼겠습니다.

오늘 글은 이것으로 마치도록 하겠습니다.

반응형

댓글