Уменьшение задержки между ардуином и эскизом обработки на моем компьютере

В настоящее время я работаю над проектом № 14 проекта проекта Arduino.

Я пытаюсь контролировать эскиз обработки на своем ноутбуке, используя мой Arduino. Это достигается с помощью потенциометра для управления фоном изображения.

Код 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 секунд до того, как изменения в потенциометре появятся на ноутбуке /обработке.

Почему уменьшение скорости связи (до определенной точки) уменьшает задержку времени, а увеличение увеличивает задержку времени? Кроме того, есть ли в любом случае я могу сделать это мгновенно?

12 голосов | спросил Kenneth .J 4 J0000006Europe/Moscow 2014, 16:27:35

5 ответов


11

Вы выводите чтение каждый раз вокруг цикла Arduino loop(), поэтому кажется, что ваша программа обработки не работает достаточно быстро, чтобы не отставать от нее. Попробуйте поместить задержку в цикл loop() в коде Arduino, чтобы замедлить его, например:

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

Насколько я знаю, обработка нацелена на выполнение с постоянной частотой кадров, которую вы можете изменить с помощью frameRate() . По умолчанию он составляет 60 кадров в секунду, хотя он может работать медленнее на старых системах (или там, где вы работаете с интенсивной программой). Вы можете проверить, как быстро он работает, прочитав переменную frameRate .

Ввод 50-миллисекундной задержки в петлю Arduino означает, что она будет обновляться чуть менее 20 раз в секунду. Это означает, что он должен быть достаточно быстрым для пользовательского интерфейса, но также должен быть в пределах возможностей вашей программы обработки.

Что касается скорости передачи (скорости передачи), то ее корректировка произвольными суммами может иметь непредсказуемые результаты. Это связано с тем, что аппаратное обеспечение будет поддерживать только определенные скорости, и попытка использовать что-либо еще может привести к искажению данных на другом конце. В документации Serial.begin() содержится дополнительная информация о поддерживаемых скоростях передачи.

ответил Peter Bloomfield 4 J0000006Europe/Moscow 2014, 18:25:41
13

Как уже указывалось, ваш Arduino говорит слишком много слишком быстро. Добавление delay() замедлит его, но все равно он продолжает кричать на обработку. В идеале вы хотите, чтобы обработка запрашивала значение, когда это удобно, а затем получает один ответ от вашего Arduino.

Введите SerialEvent().

В отличие от loop() на вашем Arduino и draw() в процессе обработки все внутри serialEvent() вызывается только тогда, когда есть что-то новое в последовательном буфере. Поэтому вместо того, чтобы обрабатывать вопросы как можно быстрее, и ваш Arduino кричит назад еще быстрее, они могут иметь приятный, вежливый (асинхронный) разговор.

Как у Processing, так и Arduino есть serialEvent. Это serialEvent () на Arduino и это serialEvent () в обработке. Используя serialEvent с обеих сторон, это то, что произойдет:

  1. Обработка отправляет символ в последовательное соединение. Это может быть любой символ, но если мы предопределим его, мы можем отфильтровать любые нежелательные запросы, вызванные, например, шумный сигнал. В этом примере давайте отправим V каждый раз, когда мы хотим получить новое показание вашего счетчика. После отправки персонажа мы продолжаем наш бизнес, как обычно. Не ожидайте ответа здесь!

  2. На стороне Arduino ничего не происходит, пока он не получит данные в последовательном буфере. Он проверяет, является ли входящий символ V, и нам повезло, это так. Arduino один раз считывает значение потенциометра, выводит это значение на последовательный один раз и возвращается к охлаждению, максимируя расслабление. Protip: завершите значение символом (* в нашем случае). Это поможет вам в следующем шаге.

  3. Обработка делает свой обычный интерфейсный бизнес-пиксель, когда внезапно возникает нарушение в силе новых данных в последовательном буфере. Он переключается на serialEvent() и начинает чтение последовательных данных, пока не будет найден наш завершающий *. Зная наверняка, это был последний символ, который стоит прочитать, теперь мы можем сохранить входящее значение в переменной, которая хранит показания Ардуино.

  4. Вот и все. Теперь обработка знала новое значение датчика и продолжает то, что мы говорим. Между тем, ваш Arduino наслаждается погодой или созерцает ее существование до тех пор, пока не появятся входящие серийные данные.

ответил Tom 6 J0000006Europe/Moscow 2014, 16:32:35
7

Ваш цикл опроса работает на полной скорости вашего процессора, и записывается в последовательный порт в каждом раунде.

Таким образом, вы чаще записываете путь к последовательному порту, чем он может обрабатывать.

Порт записывает данные так же быстро, как вы его настроили, и данные буфера , которые поступают из вашей программы слишком быстро , чтобы записать его как можно скорее , Это буфер заполнен, он просто опускает новые данные.

Важно то, что он сохранит порядок значений: это FIFO buffer , работающий в порядке First In /First Out.

Что происходит:
Цикл заполняет буфер порта и сохраняет его на 100%.
Если вы повернете потенциометр, измененное значение get будет записано в конец буфера , порт будет работать так быстро, как можно, чтобы выписать все элементы в буфере, которые все еще имеют старое значение.

И, наконец, значение, которое вас интересует. Самое текущее значение, которое мы хотели увидеть сразу, было в конце FIFO, и сначала в /first out также означает last in /last out. Противоположность тому, что мы хотим.

Максимальная частота, с которой имеет смысл читать ваши данные, - это частота, которую вы можете записать, поэтому вы должны использовать хотя бы задержку, достаточную для записи байтов на текущей скорости порта.


В качестве другой, независимой меры для предотвращения такой задержки в целом,
 вы можете дополнительно установить буфер записи порта на минимум.

Это приведет к тому, что данные будут удалены намного раньше, а не сначала буферизации.

Конечно, во многих приложениях это не то, что вам нужно; С неудачей он может работать в любом случае в начале и нестабилен в некоторых ситуациях, когда изменения времени основаны на таких вещах, как загрузка процессора, и есть только некоторые случайные выборки данных , которые удаляются. Большой буфер обычно ведет себя гораздо более детерминированным, поэтому использовать по умолчанию большой буфер .

ответил Volker Siegel 4 J0000006Europe/Moscow 2014, 22:08:59
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);
  }
}
ответил Daniel Eisterhold 5 J0000006Europe/Moscow 2014, 06:50:25
0

Два простых решения, гарантированные для тех, кто все еще ищет: -

  1. Увеличьте задержку до 50-100 миллисекунд.

  2. Добавьте это после Serial.begin(9600) в setup();

    Serial.setTimeout(50);
    

Шаг второй - самый важный. Это работало для меня только после того, как я добавил вышеприведенный код. Это часто не упоминается во многих других форумах, которые я просматривал, когда у меня была такая же проблема.

ответил Rishi Swethan 3 J0000006Europe/Moscow 2017, 01:35:34

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132