직렬 통신을위한 Arduino의 고정밀 타이밍


11

Arduino Uno를 사용하여 직렬 포트를 통해 Python에 시간 및 전압 정보를 보내 플로팅합니다. 그러나 연속 타임 스탬프 사이의 간격 타이밍은 시간이 지남에 따라 증가하여 플로팅에 영향을 미칩니다. 이것은 보오율이 9600으로 설정 될 때 특히 그렇습니다. 여기서 초기 시간 차이는 1320 일 수 있으며 비교적 짧은 시간 후에 16400으로 증가합니다. 이 속도를 최대 115200bps로 설정하면 상대적으로 장시간 전송 한 후에도 약 1340에서 1500까지 변경이 느리고 눈에 띄지 않습니다. 모든 시간은 마이크로 초로 제공됩니다.

이 효과를 줄이거 나 없앨 수 있는지, 왜 존재하는지 이해할 수 없는지 알고 싶습니다. 인터럽트 및 지연에 대한 내용을 읽었지만 전자 장치의 복잡성을 충분히 인식하지 못하고 알고 싶습니다.

  1. 타이밍에서 더 높은 정밀도를 얻을 수 있습니까?
  2. 이 타이밍 변화의 원인은 무엇입니까?

여기 내가 현재 가지고있는 것입니다 :

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;    

byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

"정확한"은 무슨 뜻입니까? 카운터가 제공하는 시간은 상당히 정확하고 정확하며 좋은 해상도입니다. 시간이 결정 론적이어야합니까 (즉, 항상 동일 함)?
— Cybergibbons

사과, 예, 나는 그것이 의미하는 것으로 생각합니다. 그들 사이의 차이가 일관성이 있고 그렇지 않은 이유, 그렇지 않은 이유
— user3284376

Arduino가 아닌 PC쪽에 타임 스탬프를 추가하거나 RTC (실시간 시계) 모듈을 사용하십시오. RTC 모듈은 다양한 웹 스토어에서 찾기에 매우 저렴합니다. 스토어가 데이터 시트에 연결되어 있는지 확인하십시오. 또 다른 방법은 타이머를 프로그래밍하고 인터럽트 서비스 루틴을 사용하여 정확한 타이밍을 얻는 것입니다.
— jippie

무엇을 eHealth.getECG()합니까? 그 전화는 항상 같은 시간 동안 지속됩니까?
— jfpoilpret

"상대적으로 짧은 기간"이 지속되는 시간을 지정할 수 있습니까? Arduino를 다시 시작한 후에도 항상 동일합니까?
— jfpoilpret

답변:


4

타이머와 ISR (인터럽트 서비스 루틴)을 사용하여 타이밍을보다 정확하게 만듭니다.

내 1ms 시간 인터럽트 개념 증명을 살펴보십시오 . 아이디어는 시스템에서 다른 이벤트를 트리거하는 데 사용할 수있는 상당히 정확한 1ms '하트 비트'를 갖도록하는 것입니다. POC를 새로운 변수에 ½Hz에서 LED 만 가지고 접근을 깜박하는 데 사용됩니다 millisecondCounter및 secondCounter순간을 임의의 메인 루프에서 트리거 이벤트를 할 수 있습니다 (그러나 정확하게 시간 초과).


2
PoC는 매우 흥미롭지 만 인터럽트가 활성화 된 상태에서 2 바이트 값을 읽는다는 점에서 결함이 있습니다 (고정하기 쉽다 loop()).이 값은 ISR에 의해 수정됩니다. loop()ISR에 의한 수정 도중에 잘못된 값 을 읽는 것이 발생할 수 있습니다 . 귀하의 블로그에 이에 대한 의견을 게시했습니다.
— jfpoilpret

@jfpoilpret 흥미로운 점은 RAM에서 값을 검색하는 도중에 인터럽트가 발생한다고 생각하지 않았습니다. 오늘 저녁 해체를 확인하고 기사를 업데이트하겠습니다. 아마 다른 기사를 써야 할 좋은 이유 : o)
— jippie

PoC에서 샘플을 만들었으며 UNO에서 10 초마다 한 번씩 문제가 발생하는 것을 볼 수 있습니다. 그러나 물론 실제로 그것은 당신이하는 일에 크게 의존합니다 loop(): 내 샘플은 밀리 초 값을 얻었으며 이전 읽기 값으로 무시하고 차이가 0보다 크면 (카운터를 0으로 재설정) 메시지를 표시합니다.
— jfpoilpret

@jfpoilpret는 실제로 그것을 눈치 채지 못했습니다. 나는 고양이의 음식 통을 모니터링하고 고양이가 실망 할 때 LED 플래시를 만들기 위해 하트 비트로 사용합니다 ...; o) 미래에 ISR을 사용하는 방식을 확실히 바꿀 것입니다.
— jippie

1
ATMEGA16U2 블록에 연결된 크리스털과 ATMEGA328P-PU에 연결된 공진기를 보여줍니다. 16U2는 직렬 인터페이스 용이며 328P는 "The Arduino"입니다. 흥미롭게도 16U2는 클럭을 다른 칩 (예 : 328P)으로 푸시 할 수 있습니다.
— Udo Klein

3

직렬 쓰기 타이밍의 "일관성"에 영향을 줄 수있는 몇 가지 사항을 생각할 수 있습니다.

  • 인쇄 할 데이터의 크기

이것은 가장 분명하게 생각할 수 있지만 실제로 인쇄할수록 처리하는 데 더 많은 시간이 소요됩니다.

솔루션 : 문자열을 알려진 길이의 문자열로 인쇄 형식화하십시오.

  • 버퍼링 된 시리얼 사용

유닉스에서는 버퍼링되거나 버퍼링되지 않은 방법으로 직렬 포트에 액세스 할 수 있습니다. 버퍼링 방식을 오랫동안 사용하면 버퍼가 가득 차면 약간 느려질 수 있습니다. 일반적으로 데이터를 읽는 것보다 데이터가 더 빨리 수신 될 때 발생합니다.

해결 방법 : 버퍼되지 않은 직렬 회선을 사용하십시오 ( 예 : Darwin / OSX에서는 /dev/cu.usbmodemXXX대신 /dev/tty.usbmodemXXX)

  • 타이머의 우선 순위

TC 인터럽트를 사용하는 것처럼 보이고 AVR은 인터럽트 처리 방식에 우선 순위가 있으며 Atmega328의 우선 순위를 모르며 가장 문서화 된 기능 중 하나가 아니므로 알 수 없습니다. TC0 대 UART 인터럽트는 얼마나 안전합니까?

해결 방법 : 설명서 / 데이터 시트에서 인터럽트 우선 순위에 대해 자세히 살펴보고 필요한 경우 타이머를 변경하십시오. 다른 타이머를 실행하지 않고도 테스트를 수행 할 수 있습니다.

  • 읽고있는 데이터는 시간이 지남에 따라 읽는 데 시간이 더 걸립니다.

일부 드라이버는 이전 값에 대해 평균화하거나 일부 작업을 수행해야하므로 측정하는 값이 많을수록 버퍼가 길고 버퍼의 최대 크기에 도달 할 때까지 값을 계산하는 데 시간이 더 걸립니다.

해결 방법 : 사용중인 라이브러리의 소스 코드를보고 최적화하고 계산이있는 경우 계산을 제거하거나 처리 시간을 늘리십시오.

  • arduino 프레임 워크 오버 헤드 방지

당신은하지만 만약 정말 아두 이노에서 직렬 출력을 최적화하려면, 당신은 아두 이노 오버 헤드를 사용하지 않아야합니다 ...하지만 그것의 방법으로 덜 우아하고 편안한 사용.

누락 된 다른 점이 있다고 확신하지만, 더 자세히 파기 전에 확인해야 할 첫 번째 사항입니다.

HTH


2

코드에는 후속 측정에서 출력 지속 시간이 포함됩니다. 따라서 출력 길이에 따라 다른 시간을 측정하게됩니다. 고정 길이 출력으로 포맷하여 고정 할 수 있습니다.

다음 문제는 UNO의 타임베이스가 매우 열악하다는 것입니다. 다른 Arduino 유형과 DCF77 시간 기준 의 비교를 보려면 여기를 살펴보십시오 .

결론 : 정확한 타이밍이 필요한 경우 Arduino를 크리스탈로 얻거나 RTC로 이동하십시오. DS3231 / DS3232 RTC는 일반적으로 기본적으로 2ppm 정확도를 달성하므로 강력히 권장합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.