Проблема с очисткой строки, считанной из последовательного буфера
Я пытаюсь переместить шаговый двигатель
, когда на Arduino Mega 2560
отправляется определенная команда. Эта команда считывается посимвольно и сохраняется в строковой переменной
. Всякий раз, когда отправляется новая команда, должно выполняться действие. Однако этого не происходит, и я считаю, что проблема в чтении отправленной команды. Пробовал очищать символьные и строковые переменные, но безрезультатно. Скетч должен запускать цикл, который перемещает двигатель по часовой стрелке
или против часовой стрелки
в соответствии с отправленной командой, которая может быть "crx*"
для по часовой стрелке или "clx*"
против часовой стрелки, где "*"
– критерий остановки чтения символов.
Любые предложения, что делать?
Скрипт:
void(* resetFunc) (void) = 0;//Сброс хода
// Шаговый двигатель X
const int stepPinX = 2; //X.ШАГ
const int dirPinX = 5; // Х.КАТАЛОГ
const int pinEnable = 8;
// Чтение строки
char c;
String readString; //основная захваченная строка
// Единичные шаги
double av_len = 1.029; //Средняя длина
double interval;
int cnt_steps = 0;
const int num_d = 200;//параметризованный шаг
int fact = int(num_d / av_len);
int unit_len = fact * 1;//единица длины (1 мм)
void setup()
{
// Устанавливает контакты как выходы
pinMode(stepPinX, OUTPUT);
pinMode(dirPinX, OUTPUT);
pinMode(pinEnable, OUTPUT);
digitalWrite(pinEnable, HIGH);//блокировка драйвера на щите ЧПУ
Serial.begin(115200);
Serial.setTimeout(1);
while (1) {
while ( (Serial.available() == 0) )
{
}
if (Serial.available()) {
c = Serial.read(); //получает один байт из последовательного буфера
//Serial.println(readString);
if (c == '*') {
Serial.println(readString);//тестовый ответ
if (readString == "crx") {
cnt_steps = cnt_steps + 1;
Serial.println(cnt_steps);
digitalWrite(pinEnable, LOW);
digitalWrite(dirPinX, HIGH);
for (int x = 0; x < unit_len; x++) {
digitalWrite(stepPinX, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinX, LOW);
delayMicroseconds(500);
}
}
else if (readString == "clx") {
cnt_steps += -1;
Serial.println(cnt_steps);
digitalWrite(pinEnable, LOW);
digitalWrite(dirPinX, LOW);
for (int x = 0; x < unit_len; x++) {
digitalWrite(stepPinX, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinX, LOW);
delayMicroseconds(500);
}
}
digitalWrite(pinEnable, HIGH);//блокировка драйвера на щите ЧПУ
c = (char)0;
Serial.flush();
readString = "";
//resetFunc();
}
else {
readString += c; // делает строку readString
}
}
}
}
void loop() {
}
@Yan Araújo, 👍0
Обсуждение2 ответа
Лучший ответ:
При отправке текстовых команд на Arduino обычно определяется
«линейный протокол»: каждая команда передается как одна строка,
с окончанием строки, означающим конец команды. Общая линия
окончания: возврат каретки (CR = '\r'
= 0x0d
= 13), перевод строки (LF =
'\n'
= 0x0a
= 10) и последовательность CR+LF.
Монитор последовательного порта Arduino поддерживает это соглашение. автоматическое добавление строки, заканчивающейся при нажатии «Отправить». Эта линия окончание может быть настроено на один из следующих вариантов:
- Нет окончания строки
- Новая строка (означает «перевод строки»)
- Возврат каретки
- Оба NL и amp; CR (но на самом деле CR отправляется перед LF)
В вашем случае вы решили использовать '*'
в качестве завершения команды.
характер. Чтобы это работало, вы должны выбрать «Без окончания строки» и добавить
«*» явно указывает на команду. В качестве альтернативы вы можете рассмотреть
изменить свой скетч так, чтобы он ожидал '\r'
или '\n'
, что является
более стандартный способ завершения команды.
В дополнение к хорошим отзывам, которые вы уже получили, я предлагаю это.
Что касается Arduino, знайте разницу между массивами String string и char — об этом много, например, https://forum.arduino.cc/t/string-vs-string-vs-char-arrays-correct-approach/537468 . Многие не хотят иметь дело с капризами String, но их использование может быть удобным.
Запустите этот код:
String readstring = "xxx";
void setup() {
Serial.begin(115200);
}
void loop() {
if (Serial.available()) {
readstring = Serial.readStringUntil('/n');
Serial.print(readstring);
Serial.println(" received");
if (readstring.equals("crx")) {
// двигаться против часовой стрелки
Serial.println("moving counter clockwise");
// против часовой стрелки() <-- ваша функция
}
else if (readstring.equals("clx") ) {
// двигаться по часовой стрелке
Serial.println("moving clockwise");
// по часовой стрелке() <-- ваша функция
}
else {
// неверная команда
Serial.println("Bad command received - no action");
// badcommand() <-- ваша функция
}
}
}
Если вы добавите функции для шагового двигателя, он может делать то, что вы хотите, в ограниченном контексте и с использованием последовательного монитора Arduino для ввода. Посмотрите на результат.
Обратите внимание, что для последовательного монитора установлено значение "без окончания строки". Завершающий символ '/n' предоставляется вашим вводом в монитор последовательного порта. Он будет делать то, что вы хотите, но опять же, многие советуют вам держаться подальше от String.
- Очистка строкового буфера с помощью memset после последовательного чтения
- Создание строк с символами UTF-8 из данных
- Очистка последовательных данных для новых входящих значений
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- форматирование строк в Arduino для вывода
- Очень простая операция Arduino Uno Serial.readString()
- Arduino Преобразование std:string в String
Что вы отправляете в свой скетч? Что он печатает обратно на последовательный порт?, @Edgar Bonet
@EdgarBonet Я отправляю команды
"crx*"
для вращения по часовой стрелке и"cry*"
против часовой стрелки, а"*"
является критерием остановки чтения символов. Скетч не должен ничего печатать, но я попросил его распечатать отправленные команды, чтобы проверить правильность чтения, @Yan Araújo1. Этот скетч не понимает
"cry*"
: он ожидает либо"crx*"
, либо"clx*"
. 2. Насчет «_Скетч ничего не должен печатать_»: Должен. Тут и там естьSerial.println()
. Позвольте мне еще раз спросить: что он печатает в последовательный порт?, @Edgar Bonet@EdgarBonet Не обращайте внимания на «крик*». Это была опечатка. Правильным является
"clx*"
. При получении одной из вышеупомянутых команд скетч должен выполнить циклы, содержащиеся в условиях, как показано в скрипте.Serial.println()
предназначен исключительно для того, чтобы убедиться, что выполняется последовательное чтение символов. Можно комментировать. В зависимости от условий скетч воздействует на «цифровые порты» 2, 5 и 8 через «петли»., @Yan Araújo@EdgarBonet Что происходит, так это то, что скетч выполняет «циклы» только после того, как «первая команда» отправляется через «последовательный». Если я попробую "второй раз", ничего не произойдет. Это как если бы
последовательное чтение
не соответствовало ни одному из условий"crx*"
или"clx*"
., @Yan AraújoКак вы отправляете команды на скетч? Вы используете последовательный монитор Arduino? Если да, то настроили ли вы окончание строки?, @Edgar Bonet
@EdgarBonet Проблема в конце строки. Ваше предположение было правильным. Большое спасибо!, @Yan Araújo