arduino와 컴퓨터의 처리 스케치 사이의 지연을 줄입니다.


13

나는 현재 Arduino 프로젝트 북의 프로젝트 # 14에 있습니다.

Arduino를 사용하여 랩톱에서 처리 스케치를 제어하려고합니다. 이는 전위차계를 사용하여 이미지의 배경을 제어하여 수행됩니다.

아두 이노 코드 :

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

void loop(){
  Serial.write(analogRead(A0)/4);
}

가공 :

//imports serial library
import processing.serial.*;
//setups the serial object
Serial myPort;
//creates an object for the image
PImage logo;
//variable to store background color
int bgcolor = 0;

void setup(){
  colorMode(HSB,255);
  logo = loadImage("http://arduino.cc/logo.png");
  size(logo.width,logo.height);
  println("Available serial ports");
  println(Serial.list());
  myPort = new Serial(this,Serial.list()[0],9600);
}
//equivalent of arduino's loop function
void draw(){
  if(myPort.available() > 0)
  {
    bgcolor = myPort.read();
    println(bgcolor);
  }

  background(bgcolor,255,255);
  image(logo,0,0);
}

이제 코드가 작동하고 전위차계를 돌리면 배경색이 변하는 동안 전위차계 를 돌리고 배경색이 변하는 것을 보는 것과 처리의 직렬 모니터에서 Arduino / 포텐쇼미터의 값이 변하는 것에는 차이가 있습니다.

내가 시도한 것 :

  • 직렬 통신 속도 변경

직렬 통신 속도 (예 : 약 100)를 줄이면 전위차계를 돌리고 랩톱에서 속도가 바뀌는 것을 보는 데 걸리는 지연이 약 1 초로 줄어드는 것을 알았습니다. 그러나 직렬 통신 속도를 더 낮추면 (예 : 값 1) 지연이 다시 증가합니다.

반대로, 표준 속도 9600에서, 전위차계의 변화가 랩탑 / 프로세싱에 나타나기 전에 약 5 초 ++의 지연이 큽니다.

통신 속도를 낮추면 (특정 지점까지) 왜 시간 지연이 줄어들고 증가하면 시간 지연이 증가합니까? 어쨌든 내가 거의 즉각적으로 만들 수 있습니까?


3
Arduino에서 매번 판독 값을 출력합니다 loop(). 처리 프로그램이 그 속도에 따라 충분히 빠르게 실행되지 않을 수 있습니다. loop()Arduino 코드에서 지연 시간을 두어 느리게하십시오. 예 delay(50).
Peter Bloomfield 2016 년

안녕 피터, 신속한 답변 감사합니다, 약간의 지연을 추가하면 실제로 내 문제를 해결했습니다. 그래도 또 다른 작은 질문이지만, 나중에 다시 처리되지 않도록 처리 프로그램의 속도를 결정할 수있는 방법이 있습니까? 아니면 더 나은 랩톱 / 처리 속도를 얻는 것이 문제를 해결합니까? ? 통신 (250)의 속도 또는 아두 이노에서 판독 300 개 혼란을 입력 않는 이유 또한, (내가 얻는 독서는 독서와 제로 예 147,0,147,0 사이에 어긋나)
케네스 .J

답변:


11

Arduino loop()에서 매번 판독 값을 출력 하므로 처리 프로그램이 그 속도를 따라 잡을만큼 충분히 실행되지 않는 것 같습니다. loop()Arduino 코드에 지연을 넣어 속도를 줄이십시오.

void loop(){
    Serial.write(analogRead(A0)/4);
    delay(50);
}

내가 아는 한, Processing은 frameRate()함수를 사용하여 수정할 수있는 일관된 프레임 속도로 실행하는 것을 목표로합니다 . 기본적으로 초당 60 프레임이지만 구형 시스템 (또는 집중 프로그램을 실행하는 시스템)에서는 느리게 실행될 수 있습니다. frameRate변수 를 읽으면 얼마나 빨리 실행되는지 확인할 수 있습니다 .

Arduino 루프에 50 밀리 초 지연을 도입하면 초당 20 회 미만으로 약간 업데이트됩니다. 즉, 사용자 인터페이스 용도로는 충분히 빠르지 만 처리 프로그램의 기능 내에 있어야합니다.

전송 속도 (통신 속도)에 관한 한, 임의의 양으로 조정하면 예측할 수없는 결과가 나올 수 있습니다. 하드웨어가 특정 속도 만 지원하기 때문에 다른 것을 사용하려고하면 데이터가 다른 쪽에서 깨져 보일 수 있습니다. 이 Serial.begin()문서에는 지원되는 전송 속도에 대한 추가 정보가 있습니다.


14

이미 지적했듯이 Arduino가 너무 빨리 말하고 있습니다. 추가 delay()하면 속도가 느려지지만 여전히 처리 중입니다. 이상적으로는 Processing이 편리한 시간에 값을 요청한 다음 Arduino에서 하나의 답변을 받기를 원합니다.

를 입력하십시오 SerialEvent().

loop()Arduino 및 draw()처리 와 달리 serialEvent()직렬 버퍼에 새로운 것이있을 때만 내부의 모든 것이 사라집니다. 따라서 가능한 빨리 질문을 처리하고 Arduino가 더 빨리 소리를 지르는 대신 멋진 정중 한 (비동기) 대화를 나눌 수 있습니다.

Processing과 Arduino에는 serialEvent가 있습니다. 이것은 아두 이노에 serialEvent ()는이 처리 serialEvent ()이다. 양쪽에서 serialEvent를 사용하면 다음과 같은 일이 발생합니다.

  1. 처리는 문자를 직렬 연결로 보냅니다. 이것은 임의의 문자가 될 수 있지만, 미리 결정하면 노이즈 신호와 같은 원치 않는 요청을 걸러 낼 수 있습니다. 이 예에서는 V전위차계를 새로 읽을 때마다 보내도록 하겠습니다. 캐릭터가 전송 된 후, 우리는 평소처럼 사업을 계속합니다. 답을 기다리지 마십시오!

  2. Arduino 측에서는 직렬 버퍼에서 데이터를 수신 할 때까지 아무 일도 일어나지 않습니다. 들어오는 문자가인지 확인 V하고 운이 좋았습니다. Arduino는 전위차계의 값을 한 번 읽은 다음 해당 값을 직렬로 한 번 출력 한 후 식히고 다시 냉장을 유지합니다. 팁 : 문자로 값을 종료하십시오 ( *이 경우). 다음 단계에서 도움이됩니다.

  3. 직렬 버퍼에서 새로운 데이터를 강제로 방해 하는 경우 갑자기 처리가 규칙적인 인터페이스 픽셀 비즈니스를 수행하고 있습니다. serialEvent()종료 될 때까지로 전환 하고 직렬 데이터 읽기를 시작합니다 *. 이것이 마지막으로 읽을 가치가있는 문자임을 알면 이제 입력 값을 Arduino의 판독 값을 저장하는 변수에 저장할 수 있습니다.

  4. 그게 다야. 프로세싱은 이제 새로운 센서 값을 알고 우리가 지시 한대로 진행합니다. 한편, Arduino는 날씨 데이터를 즐기거나 시리얼 데이터가 수신 될 때까지 날씨를 고려하고 있습니다.


1
그리고 당신이 그것을하는 동안 커패시터를 전위차계와 병렬로 놓습니다. 이렇게하면 DAC 입력의 약간의 변경이 매끄럽게 진행되어 처리시 불안한 움직임을 방지 할 수 있습니다.
Tom

이 멋진 (그리고 의인화 된) 답변에 감사드립니다!
Zeta.Investigator

실제로 USB를 통해 질문하는 것이 좋습니다. 이는 USB가 직렬 포트 보다 대기 시간 이 훨씬 길기 때문에 질문을하고 응답을 기다리는 것은 특히 높은 전송 속도로 수행 할 수있는 것과 비교할 때보 다 더 많은 시간이 걸리는 작업입니다. Arduino를 조금 더 빠르게 실행시키는 것이 좋습니다 (링크의 직렬 부분을 포화시키지 않아야 함). 처리 스케치는 Arduino 데이터가 사용 가능 해지면 데이터를 비우고 필요할 때 사용할 수 있도록 마지막 완전한 값을 유지해야합니다.
Chris Stratton

7

폴링 루프는 프로세서의 최고 속도로 실행되며 각 라운드의 직렬 포트에 씁니다.

이렇게하면 처리 할 수있는 것보다 직렬 포트에 더 자주 쓰는 것입니다.

포트는 데이터를 구성한대로 빨리 기록하고 프로그램에서 들어오는 데이터너무 빨리 버퍼링 하여 가능한 빨리 기록합니다. 버퍼가 가득 차면 새 데이터가 삭제됩니다.

여기서 중요한 것은 값의 순서를 유지한다는 것입니다. FIFO 버퍼 이며 선입 선출 방식 으로 작동합니다.

: 무슨 일입니다
루프 포트 버퍼를 채우고, 100 % 전체를 유지합니다.
전위차계를 돌리면 변경된 값 이 버퍼의 끝에 기록됩니다. 포트는 버퍼의 모든 요소를 ​​쓸 수있는 한 빨리 작동합니다. 이전 값은 여전히 ​​존재합니다.

그리고 마지막으로 관심있는 가치. 우리가보고 싶었던 가장 최근의 가치는 FIFO의 끝 부분에 있었으며, 선입 선출은 마지막 입 / 퇴근을 의미합니다. 우리가 원하는 것과 반대입니다.

데이터를 읽을 수있는 최대 주파수는 데이터를 쓸 수있는 주파수이므로, 현재 포트 속도로 바이트를 쓸 수있을 정도로 긴 지연을 사용해야합니다.


이러한 종류의 지연을 방지하기위한 독립적 인 또 다른 방법으로
포트의 쓰기 버퍼를 최소로 추가로 설정할 수 있습니다.

이로 인해 데이터를 먼저 버퍼링하는 대신 데이터가 훨씬 빨리 삭제됩니다.

물론 많은 응용 분야에서 필요한 것은 아닙니다. 불운으로 인해 처음에는 어쨌든 작동 할 수 있으며 프로세서로드와 같은 사항에 따라 타이밍이 변경되고 일부 무작위 데이터 샘플 만 삭제되는 경우가 있습니다. 큰 버퍼는 일반적으로 훨씬 결정 론적으로 동작하므로 기본적으로 큰 버퍼를 사용하십시오 .


올바른 생각이지만 "버퍼가 가득 차서 새 데이터를 삭제하는 것"이라는 문장에는 맞지 않습니다. 버퍼가 채워지면, 나가는 버퍼에 공간이있을 때까지 쓰기 블록이 아니라 쓰기 블록이 삭제됩니다. 이것은 입력과 출력이 곧 같은 평균 속도로 흐르지 만 버퍼 사이에 대기 시간이 있다는 것을 의미합니다.
Chris Stratton

6

직렬 데이터를 지속적으로 전송하는 대신 전위차계 값이 특정 임계 값 이상으로 변경된 경우에만 데이터를 전송하십시오.

int oldValue = 0;
const int threshold = 5;

void setup()
{
  Serial.begin(9600);
  pinMode(A0, INPUT)
}

void loop()
{
  if(oldValue >= analogRead(A0)+threshold || oldValue <= analogRead(A0)-threshold)
  {
    Serial.println(analogRead(A0));
    oldValue = analogRead(A0);
  }
}

1
그것은 loop()출력 버퍼를 동일한 샘플로 채우지 않는 것입니다. 그러나 여전히 프로세서의 최고 속도로 실행되며 필요한 속도의 100 배가 될 수 있습니다. 즉, 입력이 자주 변경되는 경우 (예 : 위의 잡음 threshold또는 고해상도의 지속적인 변경) (여기서는 예시 애플리케이션에서는 해당되지 않음) 에도 여전히 버퍼를 한계까지 빠르게 채울 수 있습니다.
Volker Siegel

0

여전히 찾고있는 사람이라면 누구나 작동 할 수있는 두 가지 간단한 솔루션 :-

  1. 지연 시간을 50에서 100 밀리 초로 늘리십시오.

  2. Serial.begin(9600)in 뒤에 이것을 추가하십시오 setup().

    Serial.setTimeout(50);

2 단계가 가장 중요합니다. 위의 코드를 추가 한 후에 만 ​​작동했습니다. 이것은 똑같은 문제가있을 때 보았던 많은 다른 포럼에서 자주 언급되지 않습니다.


이것은 다소 잘못되었습니다. setTimeout () 메소드는 출력이 아닌 입력에 적용됩니다. arduino.cc/en/Serial/SetTimeout
Chris Stratton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.