Очистка последовательных данных для новых входящих значений

Я пытаюсь извлечь числа из строки, отправленной через последовательный порт, а затем преобразовать числа в целочисленные значения, которые я могу использовать для арифметических операций или переключать светодиод. Но проблема в том, что мне нужно отправить строку дважды, прежде чем модуль сможет ее получить.

Я отправляю через последовательный монитор и 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

, 👍0

Обсуждение

do_something(1000000); // делаем некоторую задержку ... int do_something(int moment) 1000000 не вписывается в целое число (в зависимости от того, какой Arduino вы используете, о чем вы не сообщили)., @Nick Gammon

Какой Ардуино вы используете?, @Nick Gammon

Если вы хотите отложить что-то, есть функция «задержка»., @Nick Gammon

Да, иногда я использовал функцию задержки библиотеки, но получал аналогичные результаты. Я увеличил значение момента только для того, чтобы уменьшить скорость печати результата на последовательном терминале. Микроконтроллер — stm32f103c8t6. Я программирую его с помощью arduino ide через 2-проводной последовательный порт., @bquark


2 ответа


0

Трудно помочь, не зная точно, какие символы отправляются и почему. Если предположить, что отправляется именно это:

"voltage 24\n"
"voltage 24\n"
"voltage 55\n"
"voltage 55\n"

Тогда мы можем предположить, как отреагирует код:

  1. Код будет принимать 7 новых символов.
  2. Восьмой символ — это пробел (0x20), поэтому код выводит «напряжение». (не упомянуто в вопросе).
  3. Эта строка проверена и признана совпадений. Следовательно, код попытается преобразовать символы «вольта» в соответствующие символы. (символы в позициях от 0 до 4) в целое число. Скорее всего, это не удастся, и функция, скорее всего, вернет ноль. Итак, это распечатано: «Напряжение: напряжение OK0». (ноль упоминается в вопросе, а «вольта» - нет).
  4. Код будет принимать неизвестное количество символов, вероятно, «20». Но поскольку в строке, скорее всего, нет пробелов (0x20), они не обрабатываются, как указано выше.
  5. Затем процесс повторяется.

Из вопроса ясно, что ожидаемые числа в конечном итоге печатаются. Итак, есть проблема с вышеизложенным. Либо предполагаемое поведение неверно, либо полученная строка отличается от ожидаемой.

Если предположить, что вместо этого отправляется именно это:

"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


1

Ошибка кроется в вашем алгоритме сбора команды. В вашем скетче в качестве разделителя между входящими сообщениями используется пробел ' '.

После первой передачи «напряжения 100» результирующей строкой в readString будет «напряжение». Метод indexOf() возвращает индекс 0, поскольку ключевое слово соответствует. Таким образом, ваш скетч пытается проанализировать целое число по первым символам этой строки, но это не удается и возвращает ноль. Поэтому напряжение печатается как «0».

При каждой следующей передаче происходит следующее. Например, давайте посмотрим на вашу вторую передачу «Напряжение 100». Результирующей строкой в readString будет "100\nнапряжение" или "100\r\nнапряжение", в зависимости от конца строки. линейный маркер. Он состоит из оставшейся части предыдущей передачи и начала текущей передачи. Метод indexOf() возвращает положительное значение, большее нуля, в качестве индекса. Таким образом, ваш скетч пытается проанализировать целое число из первых символов этой строки, что на этот раз удается и возвращает 100. Но это значение предыдущей передачи. Поэтому напряжение теперь печатается как «100».

Решение состоит в том, чтобы удалить пробел в качестве разделителя и вместо этого использовать маркер конца строки. Прочитайте полную передачу в readString. Затем проверьте ключевое слово и проанализируйте более позднюю часть. Фактическая реализация оставлена в качестве поучительного упражнения.

,

@ the busybee, спасибо за понимание. По крайней мере, теперь я точно знаю, откуда возникла проблема. Я пойду и проведу небольшое исследование того, как извлечь числа из строки, возможно, я использую другой метод, поскольку он не дал желаемого результата., @bquark

Да, чтение документации и других скетчей дает больше, чем готовое решение. Кстати, предлагаемый способ поблагодарить — отметить ответ. Пожалуйста, прочитайте всплывающее окно с галочкой. Однако смело ждите другого, лучшего ответа., @the busybee