Мы сделать, фактически, делаем вывод массива символов. То есть работает как с C-шной текстовой сторокой. У которой ОБЯЗАТЕЛЬНО должен быть признак конца строки - нулевой байт. IMHO полагатся тут на memset - плохая идея, лучше делать mas[i]=0 после заполнения массива.
А еще нужно обязательно проверять что i<31 (помнить что еще один байт нужен под ноль).
Подскажите пожалуйста как сделать такое, по UART приходит строка вида "-12,3", это данные о температуре, как мне эти данные разложить по символьно, каждый в свою переменную, что-бы на выходе получить такое?
Спасибо, примерно так я себе это и представлял, кроме очистки буфера. На счет массива думал, но отложу на потом, когда буду оптимизировать, быстродействие не требуется.
А шо тут думать? Тут прыгать нужно. Тем более что массив тут нужен не для "оптимизации", а что-бы код не выглядел ужасно и был пригоден для сопровождения.
"Избегать дублирования" - первейшая заповедь. Ну ведь банально должно быть лениво копи-пастать строчки. Ну или, предположим, после Serial.read() вы еще и что-то сделать с этим байтом захотите? 5-ть строчек править? Или вывести это все в Serial, опять 5-ть одинаковых строк делать? А если завтра потребуется не 5-ть, а 15-ть?
Тем более, что перейти на массив - принципиальной разницы - нет. Нужно просто не боятся, пойти в раздел проргамирование и почитать про массивы. Никуда вы от них не денетесь, если собрались програмирование ардуины осваивать.
А перейти к работе с массивом можно было-бы так (тот же самый код, пока с дублированием)
Такая проблемка. Хочу ардуиной подключиться к телефору по СОМ-порту (0 и 1 пины). Пока пробую отработку команд при помощи монитора порта. Есть такой кусок кода, где нужно подключиться к порту, отправить ему команду "АТ" и получить "ОК" (который на текущий момент я сам руками ввожу в мониторе), и потом, если всё прошло успешно продолжить посылать в порт комманды и получать "ответы". Дошёл до момента, когда полученный ответ (в данном случае "ОК") нужно обработать (т.е. сравнить) и уже дальше что-то делать (например, зажечь светодиод). Операция сравнения не получается. Видимо полученный "ОК" не такой.
int ledPin = 13; // мигаем если всё ОК
int xBytes = 0; // количество получаемых байт информации
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("AT");
while(!Serial.available()) {}
delay(250); // без задержки Serial.available() получает только 1 байт
xBytes = Serial.available();
int i;
char message[xBytes]; // будущая информация "из порта" (в байтах символов)
for (i=0; i<xBytes; i++) {
message[i] = Serial.read();
}
if (String(message) == "OK") {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
Serial.println("Error!");
}
Serial.flush();
}
Кусок всего кода выше, а вот момент который меня смущает:
if (String(message) == "OK")
Вставлял в разных местах и Serial.println(String(message)) и Serial.println(message) для проверки того, что там получилось. Вроде бы "ОК" как "ОК". Но где-то косяк, видимо с переводом строки или 1 битом в конце. Как это "победить"?
Вопрос "в догонку".... а помёт ли в будущем телефон посылаемую "АТ" команду, а то сомнения какие-то вдруг появились.
Serial.println - вам будет не достаточно. С ним вы не видите "невидимые символы" (символы с кодами меньше 32 Ascii Table - ASCII character codes and html, octal, hex and decimal chart conversion). Так что, что-бы видеть действительно свою строку - вам нужно по этому message пробегатся циклом и выводить именно коды символов, а не сами символы.
После 14-той строки вставте
Seria.println(message[i],DEC); Serial.print(",")
Что-бы увидеть все что там есть на самом деле.
И скорее всего вы увидите (как вы и заподозрили), в конце два лишних кода 10 (новая строка) и/или 13 (возврат каретки).
Естественно - их нужно выбрасывать перед тем как начинать работать с полученной строкой. Но не просто выбрасывать - а заменять на символ окончания строки - символ с кодом 0. Что-бы ваш message[] стал корректной Си-ной строкой. Что-бы было понятно где ее конец. А без этого все строковые функции - будут работать только в случае везения.
Вообщем не помню сколько постов назад я уже упоминал, что "в топку String". Ну не родной он для Си. Вроде как "проще в использовании", а жрет память и постоянно туда-сюда конвертировать приходится. Так что его просто-та - обманчива. Как видите разбиратся с string все равно нужно. Даже если потом вы планируете конвертировать его String. Все равно "понимать нужно" и в итоге простота оборачивается "маскировкой грабель". А если вы сделали нормальную сишную строку, то непонятно зачем вообще String нужен. Две сишные строки уже прекрасно стандартная функция strcmp сравнить может.
И кстати подход "читаем сколько байт в буффере" - потенциально глючный. Строка может и не успеть передатся целиком к моменту проверких Serial.available. Лучше подходить так:
1. Если в Serial есть хоть что-то - читаем 1 байт.
2. Если он \r - тупо игнорим его
3. Если он \n - заменяем его на символ нуля (и ложим в буффер), считаем что строка считалась целиком и начинаем работу с ней
4. Если он что-то другое - сохраняем его в буффер и ждем следующего символа.
Сделал проще. В принципе мне нужно по сути только ловить "ОК" от "противоположной стороны"... её я получю как long int a = 7975 (которую получаю в цикле как message=message*100+Serial.read(); ), т.е. как перевод символов в разные кодировки: О->79 и К->75.
Походу дело сразу же трабла (так сказать "на будущее" - строка же может быть и длинной, и переменная, определённая как long int не достаточна, какую использовать?).
Далее обычным if (a == 7975) {} else {} определяю "что с этим делать". В мониторе порта в Ардуине всё нормально работает. Затем я подключился к Ардуине Huperterminal-ом (штатным из Windows XP).
Всё что я отправляю как Serial.println() (например, Serial.println("AT")), он получает, переводит курсор на новую строку.... но "ответить" мне не даёт... я не могу написать ничего в терминале. От чего вопрос.... либо необходим символ/команда, которая бы разрешила мне ответить (перейти в режим отправки/слушания), либо....???
Тогда же как ответит устройство, к которому я собираюсь подключиться???
Может нельзя подключаться к Ардуино через "тоже соединение, что и программирую", хотя он видит стандартный СОМ-порт, который как я понимаю полный аналог Rx-Tx на 0 и 1 "ножках"... или нет?
String inData;
void setup()
{
Serial.begin(9600);
}
void loop() {
inData = "";
if (Serial.available() > 0) {
int h = Serial.available();
// if you are getting escape -characters try h--; here
for (int i = 0; i < h; i++) {
inData += (char)Serial.read();
}
// if you are getting escape -characters try Serial.read(); here
}
//print it out
Serial.println(inData);
delay(1000);
if (String(inData) == "test")
{
Serial.println("TESTIIIING");
}
}
Конкретно про serial мне многое не понятно: размер буфера serial, как в буфере накапливаются символы, как буфер очищается и тп.
Это Вам надо про FIFO и прочие основы работы UART-чипов почитать. Писатели документации на ардуину не могу все начинать "с нуля". :)
А вы кстати не пользуетесь обычным компилятором Си для отладки? Просто с ардуины тяжело получить обратную связь.
Как "тяжело"? Serial.print в программном коде и пишите отладку через сериал-консоль...
короче удалось сделать только таким способом. без delay не работает :(
а какая-же функция на самом деле будет очищать буфер?
ну или какой хитростью мне достигнуть результата? нужно считать символы из сериалМонитора в массив и вывести его
Так считайте их в массив! И выведите!
Пока - судя по скетчу - вы лишь проверяете их поступление...
Где вызов функции Serial.read()?
Мы сделать, фактически, делаем вывод массива символов. То есть работает как с C-шной текстовой сторокой. У которой ОБЯЗАТЕЛЬНО должен быть признак конца строки - нулевой байт. IMHO полагатся тут на memset - плохая идея, лучше делать mas[i]=0 после заполнения массива.
А еще нужно обязательно проверять что i<31 (помнить что еще один байт нужен под ноль).
Подскажите пожалуйста как сделать такое, по UART приходит строка вида "-12,3", это данные о температуре, как мне эти данные разложить по символьно, каждый в свою переменную, что-бы на выходе получить такое?
Но я бы на вашем месте воспользовался массивом и заполнял бы в цикле.
Спасибо, примерно так я себе это и представлял, кроме очистки буфера. На счет массива думал, но отложу на потом, когда буду оптимизировать, быстродействие не требуется.
А шо тут думать? Тут прыгать нужно. Тем более что массив тут нужен не для "оптимизации", а что-бы код не выглядел ужасно и был пригоден для сопровождения.
"Избегать дублирования" - первейшая заповедь. Ну ведь банально должно быть лениво копи-пастать строчки. Ну или, предположим, после Serial.read() вы еще и что-то сделать с этим байтом захотите? 5-ть строчек править? Или вывести это все в Serial, опять 5-ть одинаковых строк делать? А если завтра потребуется не 5-ть, а 15-ть?
Тем более, что перейти на массив - принципиальной разницы - нет. Нужно просто не боятся, пойти в раздел проргамирование и почитать про массивы. Никуда вы от них не денетесь, если собрались програмирование ардуины осваивать.
А перейти к работе с массивом можно было-бы так (тот же самый код, пока с дублированием)
Сильно сложней?
Зато теперь, можно избавить от дублирования, как и говорил Максим "читать циклом".
Осталось только избавится от магической цифры 5-ть. Написать где-то вверху скетча
И поправить код в такой вид:
И все.
Теперь, если нам нужно будет не 5-ть, а 25-ть читать, мы исправим всего одну строчку. Вместо "#define SAY_TOTAL 5" напишем "#define SAY_TOTAL 25"
А сам код - даже менять не нужно будет. Будет работать с большим количеством.
Спасибо за развернутый ответ, обязательно попробую. Но чую появятся еще вопросы по другому поводу.
Такая проблемка. Хочу ардуиной подключиться к телефору по СОМ-порту (0 и 1 пины). Пока пробую отработку команд при помощи монитора порта. Есть такой кусок кода, где нужно подключиться к порту, отправить ему команду "АТ" и получить "ОК" (который на текущий момент я сам руками ввожу в мониторе), и потом, если всё прошло успешно продолжить посылать в порт комманды и получать "ответы". Дошёл до момента, когда полученный ответ (в данном случае "ОК") нужно обработать (т.е. сравнить) и уже дальше что-то делать (например, зажечь светодиод). Операция сравнения не получается. Видимо полученный "ОК" не такой.
Кусок всего кода выше, а вот момент который меня смущает:
Вставлял в разных местах и Serial.println(String(message)) и Serial.println(message) для проверки того, что там получилось. Вроде бы "ОК" как "ОК". Но где-то косяк, видимо с переводом строки или 1 битом в конце. Как это "победить"?
Вопрос "в догонку".... а помёт ли в будущем телефон посылаемую "АТ" команду, а то сомнения какие-то вдруг появились.
Serial.println - вам будет не достаточно. С ним вы не видите "невидимые символы" (символы с кодами меньше 32 Ascii Table - ASCII character codes and html, octal, hex and decimal chart conversion). Так что, что-бы видеть действительно свою строку - вам нужно по этому message пробегатся циклом и выводить именно коды символов, а не сами символы.
После 14-той строки вставте
Что-бы увидеть все что там есть на самом деле.
И скорее всего вы увидите (как вы и заподозрили), в конце два лишних кода 10 (новая строка) и/или 13 (возврат каретки).
Естественно - их нужно выбрасывать перед тем как начинать работать с полученной строкой. Но не просто выбрасывать - а заменять на символ окончания строки - символ с кодом 0. Что-бы ваш message[] стал корректной Си-ной строкой. Что-бы было понятно где ее конец. А без этого все строковые функции - будут работать только в случае везения.
Вообщем не помню сколько постов назад я уже упоминал, что "в топку String". Ну не родной он для Си. Вроде как "проще в использовании", а жрет память и постоянно туда-сюда конвертировать приходится. Так что его просто-та - обманчива. Как видите разбиратся с string все равно нужно. Даже если потом вы планируете конвертировать его String. Все равно "понимать нужно" и в итоге простота оборачивается "маскировкой грабель". А если вы сделали нормальную сишную строку, то непонятно зачем вообще String нужен. Две сишные строки уже прекрасно стандартная функция strcmp сравнить может.
И кстати подход "читаем сколько байт в буффере" - потенциально глючный. Строка может и не успеть передатся целиком к моменту проверких Serial.available. Лучше подходить так:
1. Если в Serial есть хоть что-то - читаем 1 байт.
2. Если он \r - тупо игнорим его
3. Если он \n - заменяем его на символ нуля (и ложим в буффер), считаем что строка считалась целиком и начинаем работу с ней
4. Если он что-то другое - сохраняем его в буффер и ждем следующего символа.
Сделал проще. В принципе мне нужно по сути только ловить "ОК" от "противоположной стороны"... её я получю как long int a = 7975 (которую получаю в цикле как message=message*100+Serial.read(); ), т.е. как перевод символов в разные кодировки: О->79 и К->75.
Походу дело сразу же трабла (так сказать "на будущее" - строка же может быть и длинной, и переменная, определённая как long int не достаточна, какую использовать?).
Далее обычным if (a == 7975) {} else {} определяю "что с этим делать". В мониторе порта в Ардуине всё нормально работает. Затем я подключился к Ардуине Huperterminal-ом (штатным из Windows XP).
Всё что я отправляю как Serial.println() (например, Serial.println("AT")), он получает, переводит курсор на новую строку.... но "ответить" мне не даёт... я не могу написать ничего в терминале. От чего вопрос.... либо необходим символ/команда, которая бы разрешила мне ответить (перейти в режим отправки/слушания), либо....???
Тогда же как ответит устройство, к которому я собираюсь подключиться???
Может нельзя подключаться к Ардуино через "тоже соединение, что и программирую", хотя он видит стандартный СОМ-порт, который как я понимаю полный аналог Rx-Tx на 0 и 1 "ножках"... или нет?
sayi_d[0] = Serial.read();
sayi_d[1] = Serial.read();
а между чтениями разве не надо задержку?
Как проверить что пришло в байте?
Данный блок не компилится, для теста шлю 3 байта на Ардуину, принимаю в массив.
а 2 байта с массива [1] и [2] надо как-то склеить в один WORD
Спасибо!
я извиняюсь за некропостерство, но вопрос достаточно мелкий чтобы делать отдельную тему и связан с этим.
мне не совсем понятно что приходит в сериал монитор
это слегка измененный код из Reference. я в сериал мониторе ввожу "1". ответ приходит в виде
I received: 1
I received:
Откуда берется пустая сторока, я же ввел одно значение? Даже если ввести 50 значений, всеравно они выведутся посторочно плюс одна пустая строка
Сообщение #61
Откуда берется пустая сторока, я же ввел одно значение?
Отсюда.
В правом нижнем углу монитора установите No line ending.