В настоящее время я работаю над проектом № 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 секунд ++ до того, как изменения в потенциометре проявятся на ноутбуке / обработке.
Почему уменьшение скорости связи (до определенной точки) уменьшает временную задержку, а ее увеличение увеличивает временную задержку? Кроме того, могу ли я сделать это почти мгновенно?
источник
loop()
. Вполне возможно, что ваша программа обработки не работает достаточно быстро, чтобы идти в ногу с ней. Попробуйте добавить задержкуloop()
в ваш код Arduino, чтобы замедлить его; напримерdelay(50)
.Ответы:
Вы выводите чтение каждый раз вокруг Arduino
loop()
, поэтому кажется вероятным, что ваша программа обработки работает недостаточно быстро, чтобы идти в ногу с ней. Попробуйте добавить задержку вloop()
код Arduino, чтобы замедлить его, например:Насколько я знаю, обработка предназначена для работы с постоянной частотой кадров, которую можно изменить с помощью
frameRate()
функции. По умолчанию это 60 кадров в секунду, хотя он может работать медленнее на старых системах (или там, где вы используете интенсивную программу). Вы можете проверить, насколько быстро он работает, прочитавframeRate
переменную.Введение задержки в 50 миллисекунд в цикл Arduino означает, что она будет обновляться чуть менее 20 раз в секунду. Это означает, что он должен быть достаточно быстрым для целей пользовательского интерфейса, но также должен соответствовать возможностям вашей программы обработки.
Что касается скорости передачи данных (скорости передачи данных), то ее изменение на произвольные величины может привести к непредсказуемым результатам. Это связано с тем, что аппаратное обеспечение будет поддерживать только определенные скорости, а попытка использовать что-либо еще может привести к искажению данных на другом конце.
Serial.begin()
Документация имеет более подробную информацию о поддерживаемых скоростях передачи данных.источник
Как уже указывалось, ваш Arduino говорит слишком много, слишком быстро. Добавление
delay()
замедлит это, но все еще продолжает кричать на Processing. В идеале вы хотите, чтобы Processing запрашивала значение, когда это удобно, а затем получила один ответ от вашего Arduino.Введите
SerialEvent()
.В отличие
loop()
от Arduino иdraw()
Processing, все внутриserialEvent()
выполняется только тогда, когда в последовательном буфере есть что-то новое. Таким образом, вместо того, чтобы обрабатывать вопросы как можно быстрее, а ваш Arduino кричит еще быстрее, они могут вести приятный, вежливый (асинхронный) разговор.И Обработка, и Arduino имеют серийный Ивент. Это serialEvent () на Arduino и serialEvent () в обработке. Используя serialEvent с обеих сторон, вот что произойдет:
Обработка отправляет символ в последовательное соединение. Это может быть любой символ, но если мы предопределим его, мы можем отфильтровать любые нежелательные запросы, вызванные, например, шумовым сигналом. Для этого примера давайте отправим
V
каждый раз, когда мы хотим новое чтение вашего потметра. После того, как персонаж отправлен, мы продолжаем нашу работу как обычно. Не дожидаясь ответа здесь!На стороне Arduino ничего не происходит, пока он не получит данные в последовательный буфер. Он проверяет, является ли входящий символ
V
, и, к счастью для нас, это так. Arduino считывает значение расходомера один раз, выводит это значение в последовательный раз и возвращается к охлаждению, максимизируя расслабление. Подсказка: завершите значение символом (*
в нашем случае). Это поможет вам в следующем шаге.Обработка выполняет свои обычные пиксельные операции с интерфейсом, когда внезапно возникают
помехи в принудительном добавленииновых данных в последовательный буфер. Он переключается наserialEvent()
и начинает читать последовательные данные, пока*
не встретится наше завершение . Зная наверняка, что это последний символ, который стоит прочитать, теперь мы можем сохранить входящее значение в переменной, которая хранит чтение Arduino.Вот и все. Обработка теперь знает новое значение датчика и продолжает то, что мы говорим, чтобы сделать. Тем временем ваш Arduino наслаждается погодой или обдумывает свое существование, пока не поступят последовательные данные.
источник
Ваш цикл опроса работает на полной скорости вашего процессора и записывает в последовательный порт в каждом раунде.
Таким образом, вы пишете намного чаще в последовательный порт, чем он может обработать.
Порт записывает данные так быстро, как вы его настроили, и буферизует данные, которые поступают из вашей программы слишком быстро , чтобы записать их как можно скорее. Если буфер заполнен, он просто сбрасывает новые данные.
Здесь важно то, что он будет сохранять порядок значений: это буфер FIFO , работающий в порядке «первый вошел / первый вышел».
Что происходит:
цикл заполняет буфер порта и сохраняет его на 100% заполненным.
Если вы включите потенциометр, измененное значение будет записано в конец буфера , порт будет работать как можно быстрее, чтобы выписать все элементы в буфере, которые все еще имеют старое значение.
И, наконец, значение, которое вас интересует. Самое актуальное значение, которое мы хотели увидеть сразу, было в конце FIFO, и первый вход / первый выход также означает последний вход / последний выход. Противоположность того, что мы хотим.
Максимальная частота, на которую имеет смысл читать ваши данные, - это частота, на которую вы можете записать их, поэтому вам следует использовать как минимум задержку, достаточную для записи байтов при текущей скорости порта.
В качестве другой независимой меры для предотвращения такого рода задержки в целом,
вы могли бы дополнительно установить буфер записи порта на минимум.
Это может привести к тому, что данные будут отбрасываться гораздо раньше, вместо того, чтобы сначала выполнять буферизацию.
Конечно, во многих приложениях это не то, что вам нужно; Если повезет, это может сработать в любом случае вначале и стать нестабильным в некоторых ситуациях, когда временные характеристики меняются в зависимости от таких факторов, как загрузка процессора, и только некоторые случайные выборки данных сбрасываются. Большой буфер обычно ведет себя гораздо более детерминированно, поэтому по умолчанию используйте большой буфер .
источник
Вместо постоянной отправки последовательных данных отправляйте данные только в том случае, если значение потенциометра изменилось за определенный порог.
источник
loop()
не заполнение выходного буфера равными выборками, это хорошо. Но он все еще работает на полной скорости процессора, которая может быть в 100 раз быстрее, чем это необходимо. Это означает, что он все еще может быстро заполнить буфер до предела, если входные данные часто изменяются, например, из-за шума вышеthreshold
или непрерывного изменения высокого разрешения (что не имеет место в примере приложения здесь)Два простых решения, которые гарантированно сработают для всех, кто еще ищет: -
Увеличьте задержку до 50-100 миллисекунд.
Добавьте это после
Serial.begin(9600)
вsetup()
;Шаг второй - самый важный. Это сработало для меня только после того, как я добавил вышеуказанный код. Это не упоминается очень часто на многих других форумах, которые я просматривал, когда у меня была точно такая же проблема.
источник