SoftwareSerial и HC-06. Получение цельных данных
- Войдите на сайт для отправки комментариев
Пт, 26/01/2018 - 10:23
Добрый день, уважаемые форумчане!
Есть последовательность команд типа: $l123;d25;r7859;moff# ,где
$ - начало команд ; - разделитель между отдельными командами l,d,r,moff - типы команд 123,25,7859 - значение команды # - конец списка команд
Количество команд в последовательности не имеет жесткого ограничения. Необходимо получить последовательность целиком. В этом проблема.
Пытался двигаться в этом направлении:
void loop() {
if(mySerial.available()>0){
symbol = mySerial.read();
incomingByte = symbol;
if(incomingByte !=-1){
command = command + symbol;
}
}
}
С двумя символами способ работает, но когда посылаю 3 символа, то последний не отображается. Если посылаю 4, то появляются кракозябры. Видимо, не успевает долетать информация или я её неправильно оргнизую. Подскажите пожалуйста, в каком направлении двигаться для решения это задачи? Использовать readBytes()?
Ну, по этому куску ничего не скажешь. Каких типов command , incomingByte и symbol ? Почему Вы нигде не проверяеете на конец посылки (#)? Что значит " посылаю 3 символа"? Символа или команды?
В общем, если хотите нормального обсуждения, делайте пример работающего скетча на десяток строк в котором Вы принимаете ntrcn и печатаете в сериал. Пишите что вводите в мониторе порта и что потом печатается (последнее копипастом). Тогда можно будет о чём-то говорить. Сейчас же ... хрустальные шары на этом форуме запрещены, так что ...
Можно этой штукой считать
Serial.readBytesUntil(character, buffer, length)
А можно просто в цикле читать и складывать в буфер пока не встретили #. Потом уже спокойно разбирать пакет (или обнаружить что это был и не пакет а что-то "искаженное").
ЕвгенийП, хотел проверить возможность получения трех символов(которые не относятся к поставленной задаче), но даже три символа нормально считать не удалось.
Penni, в readBytesUntil() необходимо указывать кол-во байтов, которые нужно считать, а это неизвестно.
Буду пробовать считывать до '#', хотя вчера вечером такое пытался релизовать, но программа не находила символ '#'. Скорее всего сам ошибку допустил. Буду смотреть.
Какой-то размер вы все равно будите для буфера приемного указывать, например, 30-50 байт, чтобы точно любой пакет влез. Вот это число и указывайте в readBytesUntil. Она прервется по любому из трех событий, встретили символ конца, прочитали всю длину либо вышел таймаут. В идеальном варианте она всегда будет прерываться по символу #
Если без всяких проверок на ошибки при приеме и прочего, то вот так, примерно
#define IN_BUFFER_SIZE 50 char inBuffer[IN_BUFFER_SIZE]; void setup() { Serial.begin(9600); } void loop() { if(Serial.available()) { memset(inBuffer, '\0', IN_BUFFER_SIZE); Serial.readBytesUntil('#', inBuffer, IN_BUFFER_SIZE); char * pch = strtok (inBuffer,"$;#"); while (pch != NULL) { Serial.println(pch); pch = strtok (NULL, "$;#"); } } }но даже три символа нормально считать не удалось.
Мой текст
Остаётся в силе.
Penni, спасибо большое! Изучил Ваш код, теперь всё работает.
Только если между (13 и 14) и (15 и 16) строчками в коде из сообщения #5 делаю вывод сообщения в порт через .println(), то появляются крокозябры в принятой команде.. Не знаю чем это можно объяснить. В моей программме нет необходимости в этих частях что-то выводить, но всё же особенность заинтересовала. Был бы благодарен, если кто-нибудь смог бы ткнуть меня носом в нужном направлении.
Пока что тестирую обработку принятой команды, поэтому часть кода Penni не использую. В качестве входных данных использую команду "u100". Получаю команду, записываю в inBuffer и вызываю функцию goMove(), которая занимается обработкой команды. Записываю char* pch в String command, потому что со String привык работать, а вот char* для меня дикий зверь.
Проблема в том, что не выполняется(видимо) код из строк 22, 26, 27. Пробовал ставить в разные места - результат не меняется: в ответ ничего не приходит и, соответственно, код в switch() не выполняется. Подскажите пожалуйста, в чём я допустил ошибку?
SoftwareSerial mySerial(51, 50); const int IN_BUFFER_SIZE = 64; char inBuffer[IN_BUFFER_SIZE]; void loop() { if(mySerial.available()>0){ memset(inBuffer, '\0', IN_BUFFER_SIZE); mySerial.readBytesUntil('#', inBuffer, IN_BUFFER_SIZE); goMove(inBuffer); } } void goMove(char* pch){ String command = pch; mySerial.println("command: " + command); if(isDigit(command.charAt(1))){ String str_value = ""; int value = 0; for(int k=1; k<command.length(); k++){ str_value = str_value + pch[k]; } mySerial.println("charAt(): " + command.charAt(0)); mySerial.println("str_value: " + str_value); value = str_value.toInt(); mySerial.println("value: " + value); mySerial.println("charAt(): " + command.charAt(0)); switch(command.charAt(0)){ case 'u': movement.to_up(value); case 'd': movement.to_down(value); case 'l': movement.to_left(value); case 'r': movement.to_right(value); } } }Во-первый: зачем Вы в 20 строке опять берете pch если у вас уже в 13 строке всё взято и дальше только со String можно работать. Заменяете в 20 строке pch[k] на command.charAt(k) и все будет хорошо.
Во-вторых: конструкции вида mySerial.println("charAt(): " + command.charAt(0)); не поддерживаются. Надо либо писать шаблон и выводить как в си через << либо заменять на print и println.
В-третьих: после каждого case надо ставить break; иначе будите выполнять все кейзы после верного.
Ну и PS: String Вам тут совсем не нужен, гуглите cstring и используйте. Плюс atoi.
Penni, большое спасибо! Теперь всё работает. Без Вас бы ничего у меня не получилось.