Как отправить переменные, не являющиеся символами через Serial
Я пытаюсь создать графический интерфейс, который отправляет данные из обработки в arduino через последовательный интерфейс. С помощью пары ребят я придумал базовую структуру, которая отправляет идентификатор переменной, значение переменной и символ завершения (\n). Пока все так хорошо!
Однако [arduino reference][1] советует использовать char только
для хранения символов. Как бы я отправил байт
или int
по последовательному каналу, все еще имея возможность использовать символ завершения, чтобы убедиться, что все работает так, как ожидалось?
правка: Используя код arduino из ответа Эдгара ниже и следующий код обработки, я получаю ошибку "не удалось разобрать значение".
import processing.serial.*;
SerialConnection serialConnection;
boolean data_processed = false;
char[] var_array = new char[31];
char var_id;
char var_val;
char space = ' ';
char termchar = '\n';
void setup() {
serialConnection = new SerialConnection(this, 9600);
}
void draw() {
serialConnection.startSerialCommunication();
if (serialConnection.isReady) {
var_id = 'a';
var_val = 127;
serialConnection.serialPort.write(var_id);
serialConnection.serialPort.write(space);
serialConnection.serialPort.write(var_val);
serialConnection.serialPort.write(termchar);
delay(50);
while (serialConnection.serialPort.available() > 0) {
for (int i = 0; i < 30; i++) {
char inchar = serialConnection.serialPort.readChar();
var_array[i] = inchar;
print(var_array[i]);
}
}
}
}
1 ответ
Лучший ответ:
Если вы хотите отправить числовые значения на ардуино, самый простой вариант -отправить их в формате ASCII-текста. Таким образом, вы просто отправляете символы.
Предположим, например, простой текстовый протокол вида
foo 42
bar 5678
baz -12
Каждое сообщение состоит из имени переменной, за которым следует ее числовое значение.
Имя и значение a разделены пробелом. Каждое сообщение
завершается строчной передачей ('\n'
).
Чтобы разобрать сообщение, сначала нужно разбить его на
пробел. Для этого очень удобна функция strsep()
. Затем
вы должны разобрать вторую часть сообщения (значение) как целое
число. Я бы использовал strtol()
для этой работы. Складывая все
вместе:
void process(char *message) {
char *name = strsep(&message, " "); // разбить на пробел
if (!message) {
Serial.println("Error: no value given");
return;
}
char *endp; // конец числового значения
long value = strtol(message, &endp, 0);
if (endp == message) {
Serial.println("Error: could not parse value");
return;
}
/* Successfully parsed. */
Serial.print(name);
Serial.print(" received value ");
Serial.println(value);
}
Обратите внимание, что существуют некоторые проверки на вменяемость, чтобы убедиться, что сообщение действительно соответствует ожидаемому формату. Очевидно, что вы должны заменить последние три строки чем-то более значимым для вашего приложения.
Пример скетча с использованием этого:
void setup() {
Serial.begin(9600);
}
void loop() {
static char buffer[40];
static size_t buffer_pos = 0;
while (Serial.available()) {
char c = Serial.read();
if (c == '\n') { // конец сообщения
buffer[buffer_pos] = '\0'; // завершение строки
process(buffer);
buffer_pos = 0; // сброс для следующего сообщения
} else if (buffer_pos < sizeof buffer - 1) {
buffer[buffer_pos++] = c; // буфер символа
}
}
}
Спасибо за ответ, Эдгар! Извините за задержку с ответом, хотелось пройти через все. Я очень ценю пример кода. Кроме того, я даже не знал, что эти функции существуют. Если я правильно понимаю, что происходит, вы передаете адрес буферного массива функции процесса, которая разыменовывает его, а затем передается в функции str? Что меня смущает, так это то, что похоже, что функция process принимает один символ в качестве аргумента, но на самом деле она обрабатывает весь буферный массив. Это нормальное поведение C при использовании указателей на массивы или специфично для функций str..?, @Zhelyazko Grudov
Кроме того, эти функции имеют двойные указатели. Это безумие., @Zhelyazko Grudov
Наконец, мне нравится, насколько элегантен этот код, здесь есть чему поучиться!, @Zhelyazko Grudov
@ZhelyazkoGrudov: Re “Если я правильно понимаю, что происходит, вы проходите по адресу буферного массива”: Точно. Всякий раз, когда вы передаете массив функции в C или C++, он “распадается” на указатель на его первый элемент. Это поведение “распада на указатель” является общим: оно влияет на все массивы всякий раз, когда вы делаете с ними что-то в основном. Все функции str*()
ожидают указателя на первый элемент массива char
с нулевым окончанием. Специфика их заключается в том, что они интерпретируют первый найденный нулевой символ
как конец строки., @Edgar Bonet
Здорово это знать! Спасибо за объяснение., @Zhelyazko Grudov
Извините, что снова беспокою вас, Эдгар, я столкнулся с ошибкой "не удалось разобрать значение", хотя, насколько я понимаю, я отправляю данные в правильном формате. Я отредактировал вопрос, чтобы включить код обработки, который я использую., @Zhelyazko Grudov
@ZhelyazkoGrudov: Ваш код обработки отправляет escape-символ (ASCII-код 127) вместо "127". Arduino ожидает строку ASCII: попробуйте отправить 1", затем
2", затем "7". Я не знаю обработки, но более чем вероятно, что у него есть метод, аналогичный Arduino print ()
, который будет форматировать число в ASCII для вас. Затем вы можете написать что-то вроде " serialConnection.SerialPort.print(127);`. Я не знаю точного названия этого метода. Если вам нужно спросить, поищите какой-нибудь форум, имеющий отношение к обработке (не здесь)., @Edgar Bonet
Большое вам спасибо, что нашли время ответить еще раз, Эдгар. Я очень, очень ценю это., @Zhelyazko Grudov
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- В чем разница между Serial.write и Serial.print? И когда они используются?
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Программы построения последовательных данных
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Очистить существующий массив при получении новой последовательной команды
https://www.arduino.cc/reference/en/language/variables/data-types/char/, @jsotola