Лучший способ отправить логическое значение (1/0) в приложение Windows в режиме реального времени

У меня есть Arduino Mega, подключенная к датчику освещенности, который считывает состояние индикаторной лампы машины. У меня есть приложение C++, которое управляет машиной, и я хотел бы, чтобы Arduino отправляла приложению статус светового индикатора в режиме реального времени, чтобы приложение могло управлять машиной.

По сути, я просто хочу постоянно отправлять "1" или "0"; через последовательный монитор в приложение C++. Каким будет лучший способ сделать это? Меня смущает разница между serial.Write() и serial.Print(), что более оптимально для этого приложения?

, 👍1

Обсуждение

какая задержка приемлема?, @jsotola

«Я просто хочу постоянно отправлять «1» или «0»… имеет смысл отправлять данные при переходе и отправлять данные пульса в остальное время, @jsotola

вам нужно определить «лучший», прежде чем на вопрос будет дан ответ, @jsotola

Поскольку «оптимальный» — это уже превосходная степень, «более оптимального» не существует. :-D, @the busybee


3 ответа


2

Serial.write отправляет двоичные данные, тогда как Serial.print отправляет данные ASCII. Так что это зависит от того, хотите ли вы, чтобы Windows получала ASCII 0 и 1 или двоичные 0 и 1.

Я бы посоветовал вам использовать печать и отправку данных ASCII.

,

4

Может показаться хорошей идеей отправить "0" или "1"; в режиме реального времени для быстрого ответа, но это может оказаться контрпродуктивным.

Во-первых, вы рассылаете последовательные данные, что может немного замедлить работу принимающей машины. С другой стороны, если частота дискретизации выше скорости передачи данных, то буфер отправки заполнится, и отправляемые данные будут "старыми". Допустим, размер буфера составляет 64 байта, тогда данные, отправляемые (и, следовательно, получаемые Windows), могут быть 64 байта назад, а не в реальном времени.

Я бы предложил отправить "1" (с печатью, а не с записью), когда индикатор горит, а затем ничего, пока вы не обнаружите, что индикатор выключен, затем отправьте «0». То же самое касается перехода обратно во включенное состояние. Таким образом, поток последовательных данных просто указывает на переходы, а не на текущее состояние. Это значительно сокращает объем данных и снижает вероятность их потери или устаревания.

И на всякий случай отправляйте текущее состояние (0 или 1) примерно каждую секунду, на тот случай, если прослушивающая сторона только что была включена.

,

Это имеет смысл, меня волнует только то, когда свет включается, поэтому мне нужно только сообщить приложению, что свет включен, по умолчанию свет выключен. Спасибо!, @Max Bluhm


4

Я согласен с обоими предыдущими ответами. Ник Гаммон дает отличный совет о том, как справиться с этой ситуацией, а Рохит Гупта расскажет вам суть write() против print(). Я хотел бы остановиться на этом write() / Однако различие между print().

Эти методы API Arduino могут сбить с толку, поскольку они много разные подписи.

запись()

Давайте сначала рассмотрим write(), так как это самый простой из них:

size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);

Они предназначены для отправки одного байта и массива байтов. соответственно. Вы можете отправлять произвольные байты, что обычно называется «двоичные данные». Обратите внимание, что любые данные, включая текст, являются двоичными: термин двоичный здесь просто означает отсутствие ограничений на байт, которые вы можете отправить.

size_t write(const char *buffer, size_t size);

Это то же самое, что и предыдущее, для случая, когда буфер имеет введите «массив символов». Он по-прежнему может отправлять произвольные данные.

size_t write(const char *str);

Это версия для отправки C-строк, то есть буферов с нулевым завершением. Он не может отправить нулевой байт, так как этот байт интерпретируется как терминатор строки. Таким образом, нецелесообразно отправлять двоичные файлы (в смысле «произвольных») данных. По этой причине я считаю, что включение эта перегрузка — ошибка разработчиков API, и я бы избегайте этого, отдавая предпочтение print(), который для этого типа аргумента делает то же самое.

Обратите внимание, что в каждом случае write() принимает предоставленные вами данные и отправляет как есть. Никаких попыток форматировать его каким-либо образом не предпринимается.

печать()

Как заявил Рохит Гупта, print() предназначен для отправки текста. Если вы иметь некоторые данные для отправки, которые представляют собой текст для начала (например, литерал string), print() отправляет его как есть и, таким образом, очень похоже на запись(). Это относится к следующим перегрузкам:

size_t print(const String &);  // отправляет объект String
size_t print(const char[]);    // отправляет C-строку
size_t print(char);            // отправляет один символ

Тогда у вас есть несколько перегрузок для печати различных типов чисел. Все из них используется преобразование двоичного кода в текст. Два оставшихся перегрузки, включающие __FlashStringHelper и Printable, являются слишком технически, и я не буду обсуждать их здесь.

Сравнение

Все операторы ниже делают одно и то же: они отправляют "A" сквозь последовательный порт:

Serial.write(65);        // отправляет байт с двоичным значением 65
Serial.write('A');       // ASCII-код 'A' равен 65
Serial.print('A');       // символ печатается() путем отправки его как есть
Serial.print(char(65));  // 'A' — это сокращение для char(65)
Serial.print("A");       // строка из одного символа

Все приведенные ниже утверждения отправляют "65" через последовательный порт:

Serial.write(54); Serial.write(53);    // отправляем два двоичных значения
Serial.write('6'); Serial.write('5');  // ASCII('6') = 54...
Serial.write("65");       // отправляет текст в предварительно отформатированный буфер
Serial.print("65");       // такой же
Serial.print(65);         // print() выполняет преобразование числа в текст
Serial.print(int('A'));   // такой же

Как правило, я рекомендую всегда использовать print() для отправки текста, и используйте write() только для отправки данных, которые (надежно известны быть) текст.

,

Да, отлично. Я изо всех сил пытаюсь объяснить разницу между двоичным и недвоичным кодом. Например, "00110001", возможно, является двоичным, однако это строка ASCII с двоичными цифрами. Однако (в C++) 0b00110001 является двоичным в другом смысле., @Nick Gammon