Очистка последовательных данных для новых входящих значений
Я пытаюсь извлечь числа из строки, отправленной через последовательный порт, а затем преобразовать числа в целочисленные значения, которые я могу использовать для арифметических операций или переключать светодиод. Но проблема в том, что мне нужно отправить строку дважды, прежде чем модуль сможет ее получить.
Я отправляю через последовательный монитор и Bluetooth.
Пример: если я сначала включу модуль и отправлю напряжение 100 через последовательный монитор, он напечатает напряжение 0 вместо напряжения 100.
Но если я снова отправлю напряжение 100, то теперь будет напечатано напряжение 100, и светодиод переключится.
Теперь, если я решу изменить строку и отправить напряжение 50, оно все равно будет печатать напряжение 100 вместо напряжения 50.
Если я снова отправлю напряжение 50, оно теперь напечатает напряжение 50.
Похоже, что предыдущая строка печатается для каждой новой строки, отправленной в последовательный порт.
Поэтому мне пришлось дважды отправить одну и ту же строку, чтобы устройство ее приняло.
Как я могу отправить строку один раз, чтобы модуль получил ее и распечатал по последовательному каналу? Я не хочу отправлять строку дважды.
Смотрите мой код и результаты ниже, любая помощь будет полезна.
Результаты кода на последовательном мониторе с включенной автопрокруткой:
При подключении питания.
voltage: 0
voltage: 0
voltage: 0
voltage: 0
voltage: 0
Когда я отправил «напряжение 100».
voltage: 0
voltage: 0
voltage: 0
voltage: 0
voltage: 0
Затем я отправил «напряжение 100»; снова.
напряжение: 100
напряжение: 100
напряжение: 100
напряжение: 100
Отправлено «напряжение 50».
voltage: 100
voltage: 100
voltage: 100
voltage: 100
Отправлено «напряжение 50»; снова.
voltage: 100
voltage: 100
voltage: 100
voltage: 100
Отправлено «напряжение 120».
voltage: 50
voltage: 50
voltage: 50
voltage: 50
Отправлено «напряжение 120 В»; снова.
voltage: 50
voltage: 50
voltage: 50
voltage: 50
Это мой код:
voltage: 120
voltage: 120
voltage: 120
voltage: 120
@bquark, 👍0
Обсуждение2 ответа
Трудно помочь, не зная точно, какие символы отправляются и почему. Если предположить, что отправляется именно это:
"voltage 24\n"
"voltage 24\n"
"voltage 55\n"
"voltage 55\n"
Тогда мы можем предположить, как отреагирует код:
- Код будет принимать 7 новых символов.
- Восьмой символ — это пробел (0x20), поэтому код выводит «напряжение». (не упомянуто в вопросе).
- Эта строка проверена и признана совпадений. Следовательно, код попытается преобразовать символы «вольта» в соответствующие символы. (символы в позициях от 0 до 4) в целое число. Скорее всего, это не удастся, и функция, скорее всего, вернет ноль. Итак, это распечатано: «Напряжение: напряжение OK0». (ноль упоминается в вопросе, а «вольта» - нет).
- Код будет принимать неизвестное количество символов, вероятно, «20». Но поскольку в строке, скорее всего, нет пробелов (0x20), они не обрабатываются, как указано выше.
- Затем процесс повторяется.
Из вопроса ясно, что ожидаемые числа в конечном итоге печатаются. Итак, есть проблема с вышеизложенным. Либо предполагаемое поведение неверно, либо полученная строка отличается от ожидаемой.
Если предположить, что вместо этого отправляется именно это:
"voltage 24 \n"
"voltage 24 \n"
"voltage 55 \n"
"voltage 55 \n"
Тогда ожидаемый результат изменится на:
"voltage"
"voltage: volta OK0"
"24"
"voltage: 24 OK24"
"voltage"
"voltage: volta OK0"
"24"
"voltage: 24 OK24"
"voltage"
"voltage: volta OK0"
"55"
"voltage: 55 OK55"
"voltage"
"voltage: volta OK0"
"55"
"voltage: 55 OK55"
Несмотря на то, что этот вывод все же не полностью соответствует формулировке вопроса.
Итак...
- Отредактируйте свой вопрос, чтобы было понятно, что программа распечатывает, или скопируйте и вставьте выходные данные программы в вопрос. Этот ответ можно изменить, если вопрос отредактирован.
- В отличие от общения человека с компьютером, общение между компьютерами лучше всего делать коротким и без промежутков. Пробелы затрудняют анализ и часто приводят к проблемам с кодированием. Лучше использовать такие символы, как ":" или "," для разделения слов и цифр.
- Предполагается, что строка, скажем, «напряжение 24»; получено, оно не подлежит обработке до тех пор, пока не будет получено полностью. Попробуйте закончить строку, например, ";". Затем проверяем этот символ, а не пробел. Также настройте параметры substring(), чтобы выбрать число. Вероятно, прохождение 8 & 9 приведет к ожидаемым значениям.
Спасибо за ответ st2000. Хорошо, я отредактировал вопрос и внес некоторые изменения в код. Я надеюсь, что вы или кто-либо из вас сможете увидеть проблему, если они еще раз взглянут на этот вопрос., @bquark
Это происходит в неправильном направлении. Вам следует удалить и протестировать только ту часть кода, которая ведет себя неожиданно. Вместо этого вы добавили больше кода. Не многие захотят просматривать больше кода, чем необходимо, чтобы справиться с неожиданным поведением. Кроме того, уверены ли вы, что выходные данные ведут себя так же хорошо, как указано в описании вашего вопроса? Пожалуйста, вырежьте и вставьте точный результат, который вы получаете из своей программы. Я был бы удивлён, если бы выглядел так же, как ваше описание., @st2000
Результаты кода такие, как я уже сказал, если в последовательном мониторе Arduino включена автопрокрутка. Я также уклонился и вставил результаты в вопрос, как вы предложили. Пожалуйста, проверьте... Спасибо., @bquark
Что ж, теперь у вас есть 2 ответа. Мы оба говорим, что вам не следует анализировать данные с пробелами. Я думаю, что эта строка «Serial.println(readString); //выводит строку на последовательный порт» должна распечатать больше, чем вы вырезали и вставили. Если у меня будет время, я могу попытаться запустить ваш код. Хотя бы ради того, чтобы посмотреть, смогу ли я получить тот же результат, который вы вырезали и вставили в вопрос., @st2000
@ st2000, не анализируя пробелы, я предположил, что вы и занятая пчела имели в виду, что строка, отправленная в модуль, не должна иметь пробелов между ними. Например, «напряжение 100» вместо «напряжение 100». Обратите внимание, что я уже пробовал это, но не помогло. Я также изменил эту строку кода if( c == ' ') на if(c == '\n'). Это тоже не сработало., @bquark
Я слышу тебя. Хорошо, у меня есть только моменты (на данный момент). Короче говоря, когда компьютеры разговаривают с компьютером, это должно быть очень предсказуемо и легко анализироваться. Отсутствие чего-либо между полями — это нехорошо. Если бы я отправлял только напряжение, омы и амперы, то я бы уменьшил передачу до «v:24;». Затем проанализируйте ":" и найдите ";" чтобы положить этому конец. Это решает ряд проблем. Один из них (и я не упоминал об этом раньше) состоит из 1, 2 или 3 символов, представляющих допустимое число. Код в его нынешнем виде всегда предполагает 4 символа. Но что он делает, когда передается «1»?, @st2000
... ответ? Это может сработать, когда передается «1». Но вы полагаетесь на ToInt(), чтобы сделать что-то, чего он не может сделать. То есть вы предполагаете, что строка закончится на '\n', и вы предполагаете, что ToInt() завершит перевод из символов в целое число, когда увидит '\n', несмотря на то, что вы явно говорите: «преобразуйте следующие 4 символа». до целого числа»., @st2000
Ошибка кроется в вашем алгоритме сбора команды. В вашем скетче в качестве разделителя между входящими сообщениями используется пробел ' '
.
После первой передачи «напряжения 100» результирующей строкой в readString
будет «напряжение»
. Метод indexOf()
возвращает индекс 0, поскольку ключевое слово соответствует. Таким образом, ваш скетч пытается проанализировать целое число по первым символам этой строки, но это не удается и возвращает ноль. Поэтому напряжение печатается как «0».
При каждой следующей передаче происходит следующее. Например, давайте посмотрим на вашу вторую передачу «Напряжение 100». Результирующей строкой в readString
будет "100\nнапряжение"
или "100\r\nнапряжение"
, в зависимости от конца строки. линейный маркер. Он состоит из оставшейся части предыдущей передачи и начала текущей передачи. Метод indexOf()
возвращает положительное значение, большее нуля, в качестве индекса. Таким образом, ваш скетч пытается проанализировать целое число из первых символов этой строки, что на этот раз удается и возвращает 100. Но это значение предыдущей передачи. Поэтому напряжение теперь печатается как «100».
Решение состоит в том, чтобы удалить пробел в качестве разделителя и вместо этого использовать маркер конца строки. Прочитайте полную передачу в readString
. Затем проверьте ключевое слово и проанализируйте более позднюю часть. Фактическая реализация оставлена в качестве поучительного упражнения.
@ the busybee, спасибо за понимание. По крайней мере, теперь я точно знаю, откуда возникла проблема. Я пойду и проведу небольшое исследование того, как извлечь числа из строки, возможно, я использую другой метод, поскольку он не дал желаемого результата., @bquark
Да, чтение документации и других скетчей дает больше, чем готовое решение. Кстати, предлагаемый способ поблагодарить — отметить ответ. Пожалуйста, прочитайте всплывающее окно с галочкой. Однако смело ждите другого, лучшего ответа., @the busybee
- Arduino Serial.ReadString() проблема
- Очистка строкового буфера с помощью memset после последовательного чтения
- String() против char для простого управления потоком
- Как анализировать многострочные последовательные данные с неизвестным количеством строк?
- Проблема с очисткой строки, считанной из последовательного буфера
- Найдите ОК или ОШИБКУ в последовательной строке
- Новичок, изучающий Serial.readString()
- Команда через последовательный монитор не работает должным образом в Arduino
do_something(1000000); // делаем некоторую задержку
...int do_something(int moment)
1000000 не вписывается в целое число (в зависимости от того, какой Arduino вы используете, о чем вы не сообщили)., @Nick GammonКакой Ардуино вы используете?, @Nick Gammon
Если вы хотите отложить что-то, есть функция «задержка»., @Nick Gammon
Да, иногда я использовал функцию задержки библиотеки, но получал аналогичные результаты. Я увеличил значение момента только для того, чтобы уменьшить скорость печати результата на последовательном терминале. Микроконтроллер — stm32f103c8t6. Я программирую его с помощью arduino ide через 2-проводной последовательный порт., @bquark