2016-11-18 10 views
0

나는 Arduino와 APC220 무선 송수신기를 가지고있다. SoftwareSerial 클래스를 사용하여 APC의 데이터를 읽는 라이브러리를 작성하고 있습니다. 나는 원래 읽을 수있는 데이터가없는 경우에도 i 변수가 증가하기 때문에 seg 오류를 일으키는 아래의 (잘못된) 코드로 시작했습니다. 데이터가 즉시 사용 가능할 때 우연히 작업이 발생한 경우이 기능을 실행하는 데 약 6 밀리 초가 걸렸습니다. i++; 문을 적절한 위치 (바로 위에있는 닫는 중괄호 위)에 넣으면이 함수는 실행하는 데 270 밀리 초가 걸립니다. 이 기능에서는 속도가 매우 중요하므로 시간이 크게 늘어나는 이유에 대해 궁금해합니다. 아래의 코드를 Arduino 함수 실행 시간

buffchar buff[10];로 선언하고 sSerial이 SoftwareSerial

unsigned long updateLocation(Marker* marker) { 
    this->sSerial->print('~'); 
    //initiate request from vision system 
    this->sSerial->flush(); 
    this->sSerial->print('#'); 
    this->sSerial->print(marker->num); 
    this->sSerial->print('*'); 
    this->sSerial->flush(); 
    unsigned long start = millis(); 
    int state = 0, i = 0; 
    while((millis() - start) < 600) { 
     if(this->sSerial->available()) { 
      buff[i] = this->sSerial->read(); 
      if(buff[i] == ',') { 
       buff[i] = 0; 
       switch(state) { 
        case 0: 
         i = -1; 
         state++; 
         break; 
        case 1: 
         marker->x = atof(buff); 
         i = -1; 
         state++; 
         break; 
        case 2: 
         marker->y = atof(buff); 
         i = -1; 
         state++; 
         break; 
        case 3: 
         marker->theta = atof(buff); 
         i = -1; 
         return (millis() - start); 
         break; 
        default: 
         return 0; 
         break; 
       } 
      } 
      // Correct location for i++; takes 270 ms to execute 
     } 
     // Incorrect location for i++; Takes 6 ms to execute 
     i++; 
    } 
    this->sSerial->print('~'); 
    this->sSerial->flush(); 
    return 0; 
} 
+0

'i ++;'가 OK와 NOK로 작동하는 코드에'//'주석을 추가하고 기간에 대한 세부 정보를 추가 할 수 있습니까? –

답변

0

의 인스턴스 데이터 준비가 있다고 가정하고 sSerial에서 기다리고, i++의 배치에 효과적인 차이가 없습니다.

대부분의 경우 데이터가 준비되지 않았다고 말했습니다. i++의 잘못된 위치로 인해 i은 segfault를 발생시키는 buff 크기보다 빠르게 커집니다.

올바른 배치로 코드 블록이 최대 600ms 동안 들어 오면 충분한 데이터가 들어 와서 case 3에 도달하고 돌아옵니다. 평균적으로, 당신은 그것이 일어나기까지 270ms가 걸리는 것을보고 있습니다.

시리얼에서 읽는 대신 문자열에서 직접 작동하는 동일한 기능을 타이밍함으로써이 이론을 직접 테스트 할 수 있습니다.

a) 전송 속도를 높일 수 있습니다. b) 사용할 수있는보다 효율적인 소프트웨어 직렬 구현이 있는지 확인하십시오. c) 하드웨어 직렬로 전환하십시오. 현재 디버깅 출력을 위해 하드웨어 시리얼만을 사용하고 있다면,이를 전환 할 수 있습니다. FTDI 어댑터 (eBay에 6-10 달러)를 사용하여 소프트웨어 시리얼을 USB에 연결하고 시간에 민감한 기능을 위해 하드웨어 시리얼을 예약하십시오.

대기 시간 전체를 차단하지 않도록 코드를 다시 구성 할 수도 있습니다. 사용할 수있는 것을 읽고 전역으로 저장하고 메인 루프로 돌아가서 데이터를 다시 사용할 수있을 때까지 다른 작업을 수행 할 수 있습니다.

편집 : 이제 APC220은 최대 9600 보오입니다. 속도가 매우 느려서 병 목이 소프트웨어 직렬이 아닐 수도 있습니다 (하지만 테스트해야합니다). 병 목이 단순히 보오율이라면 시스템이 대기 상태 인 동안 작업 할 수있는 다른 것이 있으면 입력 대기를 차단하지 않도록 코드를 최적화해야합니다.

+0

함수는 주 코드가 계속하기 위해받는 정보를 필요로하기 때문에 의도적으로 블로킹하도록 설계되었습니다. 'i ++'의 잘못된 배치가 사용되었을 때, segault가 발생하지 않은 경우 실행하는데 6ms가 걸렸다. 이것은 함수 CAN이 빠르게 작동하지만, 어떤 이유 때문에'i ++ '이 정확한 위치로 이동되었습니다. 내가 생각할 수있는 유일한 것은'while'에서 상수 증가분의 컴파일러 최적화입니다. –

+0

다시 생각해 보면, 데이터가 다가올 때까지 기다리지 않아도 빨리 작동 할 것입니다. 나는 당신이 나의 이론을 테스트 할 수있는 방법을 제안했다 - 직렬 읽기를 제거하고 당신이 기대하는 데이터처럼 보이는 문자열을 함수에 전달하기 만하면된다. – imjosh