Последовательная связь очень медленная через некоторое время

Я работаю над узлом для блендера, чтобы управлять Arduino. Я заметил, что через некоторое время он работает очень медленно, поэтому я изолировал проблему. Это хорошо для поддержания 60 кадров в секунду, а затем примерно через 40 секунд (довольно точно) оно по какой-то причине падает до довольно точного 1 кадра в секунду.

Что может происходить?

import serial
import time

ser = serial.Serial('COM3', 115200)

c = 0

while True:
    c+=1
    print("ok ", c)
    numIn = "100n"
    ser.write(numIn.encode('ascii'))
    time.sleep(1./60)

код Arduino:

// особая благодарность Нику Гэммону

const unsigned int MAX_INPUT = 50;


unsigned long delay_time = 300;
unsigned long last_toggle_time = 0;
int current_state = LOW;

void setup () {
  Serial.begin (115200);
  pinMode(12, OUTPUT);

} 


void process_data (const char * data) {
  Serial.println (data);
  delay_time = atoi(data);
} 

void processIncomingByte (const byte inByte) {
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;

  switch (inByte) {

    case 'n':   // конец текста
      input_line [input_pos] = 0;  // завершающий нулевой байт
      process_data (input_line);
      input_pos = 0;
      break;

    case 'r':   
      break;

    default:
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

  } 
} 

void loop() {

  while (Serial.available () > 0) {
    processIncomingByte (Serial.read ());
  }

  unsigned long m  = millis();

  if (m > last_toggle_time + delay_time) {
      current_state = current_state == HIGH ? LOW : HIGH;
      digitalWrite(12, current_state);         
      last_toggle_time = m;
  }

}  

, 👍0

Обсуждение

Подсказка: отметьте «if (m > last_toggle_time + delay_time)» и что произойдет, когда millis() переносится как int?, @Mikael Patel

Я изменил его на unsigned long, и это все еще так., @clankill3r

Кроме того, проблема не в моргании, с этим все в порядке. Это последовательная связь, которая замедляется., @clankill3r

Что произойдет, если вы удалите Serial.print() из process_data()? Что ваш скрипт Python делает с последовательным вводом?, @Mikael Patel

Круто, если я уберу отпечаток, то проблема исчезнет. Однако в конечном итоге я хочу, чтобы python читал ввод. Теперь python зависает на ser.readLine(). Может новая тема для зависания?, @clankill3r

Теперь нам нужно объяснение, а не сразу переходить к следующему вопросу :) В чем была проблема, на самом деле? Arduino печатает. Сценарий хоста (Python) не читается, а внутренние буферы USB/USART заполнены. А что происходит на стороне Arduino при заполнении выходного буфера Serial? Проверьте код - он с открытым исходным кодом :), @Mikael Patel

BW: Будьте хорошим пользователем stackexchange, напишите ответ и отметьте этот вопрос как отвеченный., @Mikael Patel

Я думаю, это происходит с секундной задержкой :), @clankill3r

@MikaelPatel «Последовательные» выходные данные, невостребованные хостом, потенциально могут быть причиной замедления только в случае платы Leonardo или чего-то еще, где USB реализован непосредственно в процессоре приложения, и даже там это немного неопределенно. Это **определенно не** случай для Uno или чего-то еще, где прикладной процессор имеет соединение UART с преобразователем USB, так как в этом случае данные UART передаются вслепую, независимо от того, может ли приемник их обрабатывать или нет. ., @Chris Stratton

Пожалуйста, укажите, какой Arduino вы используете. Респонденты не понимают, будут ли исходящие сообщения блокироваться, если вы заполните буфер., @Nick Gammon

Я просто хочу отметить, что вы используете n в качестве разделителя довольно необычным образом. В моем коде это были \n и \r (новая строка и возврат каретки). Когда вы выполняете «Serial.println (data)», вы добавляете еще два байта (println добавляет возврат каретки и перевод строки), поэтому вы печатаете 6 байтов на каждые четыре полученных вами. Меня совсем не удивляет, что что-то заполняется через 40 секунд, однако при скорости 115200 бод это не должно быть проблемой для 60 x 6 байт., @Nick Gammon

Битовый удар с циклом задержки перед отправкой следующего бита. Переменная цикла задержки должна быть протестирована, чтобы не быть слишком быстрой. Синхронизируйте его со скоростью передачи данных. Я разработал продукт под торговой маркой «Bit Banger», который представлял собой последовательный контроллер ввода-вывода до того, как вы родились в 1997 году. С другой стороны, может помочь то, что Моей первой настоящей работой была технология периферийных контроллеров для 16-битной компьютерной компании в начале 70-х. Intel только что выпустила 4-битный слайсер 4004. К 74 году они вышли с tge 8080. Гарри, @Harry Regician


1 ответ


Лучший ответ:

0

Если вы печатаете с Arduino на последовательный порт и не читаете его, буфер заполняется. Заставляя его идти с секундной задержкой. Поэтому убедитесь, что вы тоже читаете, когда отправляете данные.

По какой-то причине требуется короткий сон между сном и чтением. В противном случае он зависнет.

import serial
from time import sleep

ser = serial.Serial('COM3', 115200)
sleep(1)

c = 0

while True:
    c+=1
    print("ok ", c)
    numIn = "100"
    ser.write((numIn + '\r\n').encode())
    sleep(1./120)

    inp = ser.readline()
    print(inp.decode("utf-8"))
    sleep(1./120)
,

Теория, лежащая в основе этого ответа, весьма сомнительна, и если у вас есть обычный Arduino типа Uno или что-то с отдельным USB-последовательным преобразователем, это невозможно., @Chris Stratton