직렬 통신을위한 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 만 가지고 접근을 깜박하는 데 사용됩니다 millisecondCountersecondCounter순간을 임의의 메인 루프에서 트리거 이벤트를 할 수 있습니다 (그러나 정확하게 시간 초과).


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.