Serial.read в ардуино
- Войдите на сайт для отправки комментариев
Втр, 08/11/2011 - 14:29
Serial.read - эта функция считывает числа с сериал монитора, но когда пишешь программу, чтобы она считывала бцквы компилятор выдает ошибку.Разве эта функция может считывать только числа?
вот код программы :
int a = 0 // задаю переменную void setup(){ Serial.begin(9600); pinMode(13,OUTPUT); } void loop(){ while(Serial.available() == 0){ } int a = Serial.read() - '0'; if(a == 1){ digitalWrite(13,HIGH); } else if (a == low){ // если в сериал мониторе написать "LOW" digitalWrite(13,LOW); // выключить диод на выводе 13 } else { Serial.println("I cannot understand";) } Serial.flush(); }
Подправил вид кода программы. Adessit
Скорее всего дело в том, что переменная "а" имеет неверный тип (int числовой) :)
int a = 0 // задаю переменную
Где точка с запятой, завершающая оператор?
else if (a == low){ // если в сериал мониторе написать "LOW"
digitalWrite(13,LOW); // выключить диод на выводе 13
}
почему low в нижнем регистре?
else {
Serial.println("I cannot understand";)
}
где правая круглая скобка перед точкой с запятой?
и зачем правая круглая скобка после точки с запятой?
Ответив на эти вопросы вы, возможно и на свой основной вопрос найдете ответ ;)
Проверил эту версию первой. Как ни странно, IDE Arduino вполне благосклонно отнеслась к этому обстоятельству.
где правая круглая скобка перед точкой с запятой?
и зачем правая круглая скобка после точки с запятой?
Ответив на эти вопросы вы, возможно и на свой основной вопрос найдете ответ ;)
Это получилось случайно
написал вот так:
Пишу 1 диод горит.Пишу low диод не горит.Пишу ерунду а в сериал мониторе вместо того чтобы писаться "I cannot understand" пешится "low" и диод не горит.
написал вот так:
1: char* a = {"abc"}; // задаю переменную
[...]
2: char a = {Serial.read()- '0'};
[...]
3: else if ("a == low"){ // если в сериал мониторе написать "LOW" я ее использую не, как константу
[...]
Пишу 1 диод горит.Пишу low диод не горит.Пишу ерунду а в сериал мониторе вместо того чтобы писаться "I cannot understand" пешится "low" и диод не горит.
Пункт 1: тут вами определена строковая переменная переменная длиной 4 байта (3 символа и завершающий "\0")
Пункт 2: в функции loop() определена новая строковая переменная непонятной длины, область видимости которой - функция loop(). Т.е. везде, кроме loop(), данные записываются/считываются в глобальную переменную a длиной 4 байта, определенную в первой строке программы (пункт 1), а внутри loop() эта глобальная переменная "заслоняется" локальной с тем же именем - весьма плохой стиль программирования чреватый самыми разнообразными проблемами в дальнейшем.
Пункт 3: Вообще-то, правильнее было бы написать else if(a=="low"), так как в текущем варианте в этой ветви сравнения стоит выражение, не равное нулю, а стало быть, ИСТИНА. И поэтому данная ветвь будет ВСЕГДА выполняться, за исключением варианта a=="1".
Но даже если вы и напишете if(a=="low"), то чуда не произойдет, и эта ветвь не будет срабатывать в нужный вам момент (ввод слова "low"). Потому что чуть раньше - в момент присвоения переменной a значения, пришедшего по последовательному каналу, вы вычли из него '0'. Зачем??? Бездумно скопировали из какого-то кода? Ну что же, получили вполне ожидаемый результат - неработающую логику.
Так что:
Избавьтесь от двойного определения одноименных переменных
Применяйте к переменным только операции, соответствующие их типу - ну не должна переменная работать то как целое, то как строка. Замучаетесь потом отлавливать ошибки.
Учите матчасть (синтаксис языка, описание микроконтроллера, ...)
Спасибо буду пробывать.
Потому что чуть раньше - в момент присвоения переменной a значения, пришедшего по последовательному каналу, вы вычли из него '0'. Зачем???
пОТОМУ ЧТО ИЗНАЧАЛЬНО Я ХОТЕЛ ВЫВОДИТЬ ЭТУ ПЕРЕМЕННУЮ В СЕРИАЛ МОНИТОРЕ,.А если бы я не вычел ноль у меня место 1 выходило бы 49 и т.д.
Для этого не надо было вычитать из полученного произвольного символа код символа '0'. Достаточно лишь определить переменную как char.
А '0' вычитают обычно для того, чтобы оперировать цифрами 0...9 вместо поступающих по каналу связи символов '0'...'9', то есть с прямо противоположной целью.
Можете пожалуйста ввести исправления в мой код.Пишу ерунду в сериал мониторе вместо того чтобы писаться "I cannot understand" пишится "low" вот в чем моя проблема.
char* a; // задаю переменную
void setup(){
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop(){
while(Serial.available() == 0){
}
char a = {Serial.read()- '0'};
if(a == 1 ){
digitalWrite(13,HIGH);
Serial.println(1);
}
else if ("a == low"){ // если в сериал мониторе написать "LOW" я ее использую не, как константу
digitalWrite(13,LOW); // выключить диод на выводе 13
Serial.println("low");
}
else {
Serial.println("I cannot understand");
}
Serial.flush();
}
почему не работает вот эта часть кода:else {
Serial.println("I cannot understand");
}
Можете пожалуйста ввести исправления в мой код.Пишу ерунду в сериал мониторе вместо того чтобы писаться "I cannot understand" пишится "low" вот в чем моя проблема.
1: char* a; // задаю переменную
2: char a = {Serial.read()- '0'};
3: if(a == 1 ){
digitalWrite(13,HIGH);
Serial.println(1);
}
4: else if ("a == low"){ // если в сериал мониторе написать "LOW" я ее использую не, как константу
}
1: Тут все более-менее нормально, хотя едва ли оптимально в условиях куцей оперативной памяти ATMega. Лучше написать что-нибудь вроде char a[]="xxx"; // декларация с одновременным выделением необходимого для корректной работы объема памяти
2: Вместо char a={serial.read()-'0'} напишите просто a=serial.read();
Во-первых, объявление локальной переменной здесь ничем не оправдано.
Во-вторых фигурные скобки совершенно излишни.
В-третьих вычитания кода символа '0' не требуется. Все равно дальше вы практически не оперируете целыми числами.
3: Вместо if(a==1) пишите if(a=='1') (или если компилятор заругается - if(a=="1")), ведь переменная а объявлена типа char.
4. вместо else if("a==low")... напишите else if(a=="low") . Сейчас здесь просто бессмыслица стоит
Теперь когда пишишь low в сериал мониторе пишится "I cannot understand"
char* a ="{aaa}"; // задаю переменную
void setup(){
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop(){
while(Serial.available() == 0){
}
char a = Serial.read();
if(a == '1' ){
digitalWrite(13,HIGH);
Serial.println(1);
}
else if (a == 'low'){ // если в сериал мониторе написать "LOW" я ее использую не, как константу
digitalWrite(13,LOW); // выключить диод на выводе 13
Serial.println("low");
}
else{
Serial.println("I cannot understand");
}
Serial.flush();
}
Сразу после
char a = Serial.read();
поставьте
Serial.println(a);
(кстати после этого можете выкинуть три оператора вывода констант в ветвях конструкции if-else)
И будете видеть, с какой же информацией работает ваша программа.
А дальше - читайте, как правильно принимать потоки данных по последовательному интерфейсу.
Я знаю что исправлять ошибки сложнее чем писать программу заново.Значит вот рабочая часть программы :
char* a ="{aaa}"; // задаю переменную
void setup(){
Serial.begin(9600);
pinMode(13,OUTPUT);
}
void loop(){
while(Serial.available() == 0){
}
char a = Serial.read();
if(a == '1' ){
digitalWrite(13,HIGH);
Serial.println(a);
}
else if ('a == low'){ // если в сериал мониторе написать "LOW" я ее использую не, как константу
digitalWrite(13,LOW); // выключить диод на выводе 13
Serial.println("low");
}
Serial.flush();
}
Значит я хочу чтобы когда я писал ерунду в сериал мониторе появлялась надпись "I cannot understand".Пожалуйста помогите правильно написать программу.Мои предыдущие попытки привели к не правильной работе программы.Заранее благодарен.
Значит я хочу чтобы когда я писал ерунду в сериал мониторе появлялась надпись "I cannot understand".
Введите, как я предлагал в своем последнем посте, инструкцию Serial.println(a); после char a=Serial.read();
И, запустив программу, введите low.
И увидев, что же получает контроллер, вы, может быть,поймете, в каком направлении надо копать.
Как вы сами сказали "Исправлять ошибки сложнее, чем писать программу" - поэтому учитесь находить и исправлять их. Конечно, можно помочь вам "правильно написать программу". Но уверяю вас - программа, написанная и отлаженная самостоятельно (ну, естественно, помощь в отладке вы получите - от меня или кого нибудь другого) даст вам гораздо больше, чем готовое решение.
А пока подсказка (вы это увидите сами, подставив вышеуказанную инструкцию): проблема в том, что ваш алгоритм способен принимать отдельные байты, но не их последовательности.
Сам я разобраться не могу(новичок в программировании).Я сделал как вы сказали step962 теперь когда пишешь слово пишется только первая буква.Пожалуйста помогите.
Ну слава богу - теперь вы хоть понимаете, что проблема в том, что не получается принять всю строку.
Как же это сделать?
Возьмем кусок из начала функции loop()
и перепишем его:
Что мы тут делаем?
Ожидаем появления на входе последовательного канала первого передаваемого символа.
Даем пакету данных шанс прийти полностью. Одновременно готовимся к приему последовательности символов.
Переписываем все, что есть в буфере UART в нашу строковую переменную. Здесь можно было бы и указателями побаловаться, но эффективность и быстрота кода нам не нужна - мы должны помнить о том, что символы по UART-каналу поступают достаточно медленно и всегда есть опасность достичь конца принятой (в настоящий момент) строки до конца передачи всего пакета данных. Поэтому здесь можно даже небольшой delay дополнительно воткнуть, если вдруг на последующем отладочном выводе вы начнете получать не всю набранную строку.
А это и есть наш отладочный вывод.
Дальше должны стоять ваши конструкции If, хотя здесь больше подошел бы switch.
Думаю, что после этого вам удастся увидеть чуть больше одного символа в COM-мониторе.
Хотя желаемого результата вы еще не получите. Почему? Почитайте о представлении строк в Си - может быть, разберетесь сами. Нет - ждите продолжения...
Спасибо работает.Правда иногда в сериал мониторе пишется то, что я пишу, а иногда появляются дополнительные символы, но с этим я сам разберусь.
Спасибо работает.Правда иногда в сериал мониторе пишется то, что я пишу, а иногда появляются дополнительные символы, но с этим я сам разберусь.
Как я писал в предыдущем посте,
... желаемого результата вы еще не получите. Почему? Почитайте о представлении строк в Си ...
На будущее, господин akz при вставке кода в форум, есть специальная кнопка "Code"сверху поля ввода.
int a = (int) kakaya_to_stroka;
Это называется "явное приведение типов".
Можно еще atoi () функцию использовать, но для этого сторонние серъёзные либы нужны - она лучше работает.
На будущее, господин akz при вставке кода в форум, есть специальная кнопка "Code"сверху поля ввода.
Буду знать.
Добились ли Вы каких либо результатов? У меня аналогичная задача, а о представлении строк в Си понятия не имею и не понял ничего в этом. Код который привел step962 работает но не полностью, буфер не очищается и если послать сначала 5 символов а затем 3, возвращается сначала те же 5 символов, а потом 3 отправленные плюс 2 последних из первой посылки. как это побороть я не знаю. Подскажите пожалуйста.
и перепишем его:
Что мы ту
и перепишем его еще раз:
Что мы тут делаем? Да то же самое, что и раньше. Только дополнительно - после считывания принятых символов - ставим в конец строки символ конца строки (уж извините за тавтологию).
Спасибо, вечером попробую
Хотя если я правильно понимаю, то массив будет заполняться всем содержимым буфера, и если я пошлю 3 символа, то serial.read() вернетвсе равно 5 символов и к ним мы добавим символ конца строки. Может мне поможет команда Serial.flush(), если я правильно понял она очищает буфер.
Если честно у меня тогда ничего не получилось и я забросил и даже забыл об этом(потому что товарищ step962 никогда не выкладывет код до конца).Сейчас под рукой нет ардуино, как только будет я проверю код.
Попробовал код step962, кажется работает как надо, хотя механизм я так и не понял.
http://www.faludi.com/itp_coursework/meshnetworking/XBee/XBee_program_Ar...
Здесь реализовано то что нужно, у меня заработало по полной.
Помогите улучшить код. В ходе экспериментов, понял, что сериалу нужно время для принятия всей строки.
Сделал задержку 5 милисек (1 милисек на 1 символ), всё работает хорошо, но мне нужна высокая производительность, если кто подскажет как оптимизировать этот алгоритм, буду благодарен. Вообще по сериалу отсылается строка цифр известной длины. Как с наименьшими потерями перевести эту строку в цифры?
И попутно вопрос, как записывать данные на компе? В эксель или блокнот. Скачал программу www.mikmo.dk/gobetwino.html пока не разбирался, подскажите направление работы.
Помогите улучшить код. В ходе экспериментов, понял, что сериалу нужно время для принятия всей строки.
Это вы правильно заметили. Может быть вы еще не заметили, но в функции setup() обычно стоит строка
Serial.begin(9600);
Так вот, если прочитать об этой функции, то можно узнать, что передаваемый ей единственный параметр - это скорость, на которой будет осуществляться обмен данными по UART со стороны мк. Эти скорости стандартизованы. Кроме 9600 (9600 бит в секунду, по 9 битов на передаваемый байт - получаем около 1000 символов в секунду, то есть по миллисекунде на символ) имеются еще скорости 14400, 19200, и т.д., в качестве максимальной приводят обычно 115200, но есть и еще более высокие - почитайте даташит на мк.
Сделал задержку 5 милисек (1 милисек на 1 символ), всё работает хорошо, но мне нужна высокая производительность, если кто подскажет как оптимизировать этот алгоритм, буду благодарен. Вообще по сериалу отсылается строка цифр известной длины. Как с наименьшими потерями перевести эту строку в цифры?
Как "оптимизировать", вы теперь, может быть, догадаетесь, почитав рекомендованные вещи. Символ 'цифра' преобразовать в цифру просто - из символа необходимо вычесть код символьного представления нуля. Проще всего это сделать так:
v = c-'0';
Для '0' получим 0, для '1' -1 и так далее до '9' (для этого сивола получится, естественно, 9).
Ну, а как собрать из отдельных цифирей число - это, надеюсь, вы помните из школьного курса?
И попутно вопрос, как записывать данные на компе? В эксель или блокнот. Скачал программу www.mikmo.dk/gobetwino.html пока не разбирался, подскажите направление работы.
Это пусть кто-нибудь другой подсказывает.
ну если "строка цифр известной длины", то гораздо лучше вычитывать из Serail именно такое количество символов. По одному.
Ведь если, с компа, эту строку будет слать человек, а не софт (например вы в отладочных целях), то за 5 милесекунд он может и не успеть ее набрать. Сделайте счетки типа readedCounter и
Дальше, нужно там где "обрабатываем символ" собрать эти поступающие по очереди цифры в одно число.
Думаю вы сможете это сделать, если решите следующую алгебраическую задачу. Дано два числа a=2 и b=5. Вопрос какие арефметические операции (не строковые) нужно выполнить над этими числами, что-бы получить число 25?
Вот в дальнейшем "a" это будет ваш "накопитель" в котором вы собираете число, а "b" новый символ который нужно обработать.
спасибо за ответы. про сериал, да я как то забыл)
вот ещё пример простейшего кода, на мой взгляд самое то, для приема сериал, и перевода в цифры.
Про Excel. www.mikmo.dk/gobetwino.html Эта программа позволяет легко и просто записывать данные из сериал порта в файл, текстовый, эксель и ещё какие то)) внутри инструкция, на английском но вообщем понятная, за полчасика освоил.
Все это очень интересно но не могу понять зачем вы организуете циклы для записи данных из буфера?
Я налаживаю связь между ардуиной и матлабом через usb и у меня хорошо работает такой код:
Все хорошо принимается и отсылается назад. Плюс ардуина распознает ключ "ABC".
А вот если я начинаю организовывать циклы типа упоминавшихся ранее:
или
то начинает твориться что-то непонятное.
Подзодреваю что просто ошибаетесь когда думаете "ардуина распознает ключ".
Переменная message имеет размер один байт. Строка 'ABC' - имеет размер три байта (плюс символ конца строки). Один байт никогда не будет равен трем байтам.
В строке 20-ть, сделайте, вместо диода, Serial.println("Key detected"); Откройте сериал монитор, пошлите в него ABC и услышите в ответ "тишина", а не "Key detected".
А "непонятное" творится потому что вы, скорее всего, не проверяете что принятый символ находит в диапазоне от 48 до 57. И пытаетесь декодить буквы и служебные символы (перевод строки и т.п.) . Для которых выражение Serial.read() - '0' , естесвенно не имеет смысла.
Ну и задачи перевести в строку в число в вашем коде решить не возможно. Можете например послать в сериал строку '357', принять ее ардуиной, прибавить к нему три, умножить на два и вернуть результат в serial (должно вернутся 720) ? Без конвертации принятой строки в число - это не выйдет. А для этого нужен массив или вот этот result = result * 10 + ...
Вообщем-то, не помню с какой версии arduinoIDE для этого, у Serial есть вспомогательный метод Serial.parseInt(), который может взять на себя эту черновую работу (но внутри у него - все тоже самое), но его не всегда можно применить (напрмер когда данные идут очень медленно и паралельно с приемом нужно еще что-то делать).
Во первых, 'одинарные ковычки' применяются для обозначения одного символа, а не строки, строка обозначается "двойными ковычками" так что что у вас на самом деле получается при объявлении 'ABC' не известно.
Во вторых, назад ваш код отсылает только первый символ принятого "ключа", в вашем случае это буква А.
Ну а в третих, весь ваш код можно заменить на код ниже, работать будет точно также.
Спасибо что ответили. Да все плохо :)
Подскажите где взять хорошее описание работы с serial? Стандартное описание из ardino совсем никуда не годится.
Спасибо что ответили. Да все плохо :)
Подскажите где взять хорошее описание работы с serial? Стандартное описание из ardino совсем никуда не годится.
Что значит "никуда не годится"? Вполне себе нормальная документация. Даже не плохая. Ну "не все переведено", тогда на "оригинал" смотреть http://arduino.cc/en/Reference/HomePage
А еще примеры всякие с arduinoIDE идут.
Оно может показаться "темным лесом" если вы пробуете "перепрыгнуть ступеньку". Не имея "програмерской базы" (четкого понимания что такое типы, переменные, фунции, операторы управления и т.п.) начали работать с "более комплексными примерами". Попробуйте начать чтение документации не с Serial а c боле базовых вещей. Какие-то книжки почитать, даже не обязательно "по ардуине", а просто по "какому-нибудь С подобному языку" (или просто по C/C++).
Можете погулить какие-то книги типа "Arduino cookbook" - сборники решений "типовых задач", но, опять-таки не имея базы понять-применить их будет не просто.
Может кто все таки поделится книжкой.
А пока я переписал код вот так:
В принципе назад в матлаб сообщения приходят, но во-первых, ардуина не расспознает команду ABC. Почему? А во-вторых, если длина сообщения больше 3, например 4, то оставшиеся символы сообщения заполняются кодом 255 плюс приходит одно лишнее сообщение. Вот пример ответа на "ABC1" в кодах ASCII:
65 66 67 49 255 255 211 4 3
От куда берется одно лишнее сообщение?
Да вы правы, конкретно с Си опыта не хватает. Однако родное описание все таки не дотягивает...
Нашел какую-то книжку, там вроде есть более детальное описание раздела serial. Может тоже кому понядобится.
>Может кто все таки поделится книжкой.
Гугл поделится.
И еще почитайте раздел сайта программирование. Особенно про string (который с маленькой буквы!).
String с большой, тут можно было и не использовать. обойтись массивами. только message тогда нужно было-бы сделать в 4-ре байта. и, после прочтения трех байт из сериал, в конце добалять message[3]=0; (это признак конца строки, в C, все сишный функции "расчитывают" на его существование). Тогда, для сравнение, не нужно было-бы создавать новый объект String, а можно было-бы воспользоваться функций strcmp(message,"ABC")==0
Далее - совершенно не понятно желание везде натыкать delay() :)
Предназначение его в строке 10 - для меня полная загадка. Разве что "терпение вырабатывать".
А в строке 08 - видимо "для того что-бы следующий байт успел прийти. Но "по феншую" это лучше так не делать (а если его дольше не будет? А если, наоборот будет быстрее - значит "тупим в пустую"). Феншуйно будет выкинуть delay из строки 08, и сделать так:
Тогда вы будете "тупить" ровно столько сколько нужно. До тех пор пока не прийдут данные. Ни больше, ни меньше (правда если они вообще не прийдут.... скетч будет стоять и ждать).
Далее. Все-таки почитайте про Serial в оригинале. Там есть такая функция как Serial.readBytes(). Которую и придумал что-бы сделать всю эту черновую работу за вас.
Она вполне может заменить весь ваш цикл. Serial.readBytes(message,3). Она сама озаботится и "подождать следующий байт" и "прерватся если вышел таймаут". Возвращает она сколько байт "удалось прочитать в буффер".
>но во-первых, ардуина не расспознает команду ABC. Почему?
ну вот скорее всего потому что вы забыли про необходимость нуля в конце строки. Вот оно и "поперло дальше" по памяти пока не наткнулось на какой-то ноль и поняло что "строка закончилас". Вот попробуте, из любопытсва, сделать вывести длину этого вашего String(message). Скорее всего там будет что-то больше 3 (вообщем пока случайно не попадется ноль).
Во вторых - отложите матлаб в сторону. Добейтесь "Key detected" посылая руками в Serial мониторе.
Нашел какую-то книжку, там вроде есть более детальное описание раздела serial. Может тоже кому понядобится.
Да подождите с Serial. У вас же не с ним проблема явно. А с непонимаем строк. Про стороки, массивы, указатели читайте, а потом про сериал.
А пока я переписал код вот так:
В принципе назад в матлаб сообщения приходят, но во-первых, ардуина не расспознает команду ABC. Почему?
Потому что строки в Си завершаются символом '\0'. У вас под трехсимвольную строку выделено три байта. Места под "правильный" завершающий нуль уже нет. Стало быть, проверка будет производиться наудачу - до встречи первой ячейки в памяти, которая - совершенно случайно - имеет значение 0. Хотите добиться правильного сравнения строк - прочитайте-таки о строках Си (хотя бы основы) и, вооружившись почерпнутыми там знаниями - записывайте в четвертый элемент массива message значение 0:
message[3]='\0'; // (после выхода из цикла, в котором вы принимаете поступающие по UART символы)
И - во избежание нежелательных побочных эффектов - не пользуйтесь при определении массивов переменными:
не char message[len]; (где len - переменная, определенная строкой выше)
а char message[LEN]; (где LEN - константа, определенная в заголовке программы: #define LEN 3)
А вообще я не очень понимаю что вы хотите "читать про Serial". Что-бы работать с сериал, достаточно прочитать документацию на три функции begin, read,write . В редких случаях может потребоваться flush.
Все остальные функции Serial - это "помогайки-обертки" над этими базовыми. Используя пару read/write можно принять что угодно и передать что угодно и как угодно.
Спасибо СИнсеи :)
Конкретно про serial мне многое не понятно: размер буфера serial, как в буфере накапливаются символы, как буфер очищается и тп. Согласитесь в родном описании про это ни слова. Ладно почитаем.
А вы кстати не пользуетесь обычным компилятором Си для отладки? Просто с ардуины тяжело получить обратную связь. Этакий черный ящик. Я пока только по лампочкам могу определять отработку тех или иных блоков программы: зашел в условие - зажег лампу.
> Конкретно про serial мне многое не понятно:
>размер буфера serial,
достаточно в каталоге ArduinoIDE пройти в поддиректорию hardware/arduino/cores/arduino - здесь хранятся "родные" исходники Arduino - и открыть файл HardwareSerial.cpp. В нем, немного покопавшись, вы найдете ответ на этот вопрос: у камней с RAM<1K приемный буфер имеет длину 32 байта, у всех остальных - 128
Кстати, о длине буфера сказано в описании метода Serial.available/
>как в буфере накапливаются символы,
Что вам даст ответ на этот вопрос? Вы хотите напрямую обращаться к буферу, не пользуясь имеющимися у класса методами?
Ну, а если для общего развития, то буфер организован в виде очереди: поступающие символы записываются в хвост очереди, вы - методом Serial.read считываете их из головы очереди. Два имеющиеся в составе класса указателя указывают (кто бы мог подумать?) на голову и хвост очереди. Хотите узнать побольше об организации очереди? Почитайте в Сети о классе Queue.
>как буфер очищается
метод Serial.flush
>и тп. Согласитесь в родном описании про это ни слова.
Естественно, не соглашусь
>Ладно почитаем.
Вот это правильно.
А вы кстати не пользуетесь обычным компилятором Си для отладки? Просто с ардуины тяжело получить обратную связь. Этакий черный ящик. Я пока только по лампочкам могу определять отработку тех или иных блоков программы: зашел в условие - зажег лампу.
И кстати комплятор Си тут ничем не поможет. Задача компилятора переводить "человеческий язык" в машинные коды.
Отлаживать может - среда разработки. Но, для этого она должна иметь, в своем составе, либо эмулятор целевого процессора, либо сам процессор должен на железном уровне поддерживать отладку. Уметь останавливаться и по специальным интерфейсам (JTAG и и же с ними) сообщать компу "что там в нем происходит".
AMTEL-камни, на которых построенна ардуина - не имеют такой фичи. Остается "эмуляция". Насколько я знаю всякие WinAvr и т.п. - не содержат эмуляции.
Эмуляция возможно программами типа http://www.virtualbreadboard.com/ , но "она денег стоит" и честно говоря я так, до конца и не понял по описанию и отзывам). А "честно эмулирует процессор" или, все-таки, запускает ардуиновкий код как java-программу (а значит отладка может сильно отличатся от реальности).
Еще дебажить можно в Proteus (гуглится как это делать). Пробовал - работает. Но "поигрался и положил". Когда идет "реальная работа" проще воткнуть Serial.println в интересующие место, чем заморачиватся с ним.
Вот тут еще есть список симуляторов:
http://www.arduino.com.au/Simulator-for-Arduino.html
Попробовал первый - вроде ниче так. Правда у него крайне кисло с эмуляцией внешнего оборудования, но за те деньги что он счас продается - думаю взять сегодня/завтра. Авось пригодится. Остальные - честно говоря не смотрел особо. Если хотите - можете все перепробывать. Поделитесь впечатлениями.
Но вообщем мое IMHO что "нужен дебагер" - это привычка/стереотипы с "большого компа". На том уровне сложностей ардуиновских скетчей в 99% хватает диодов и Serial что-бы понять "что там происходит".
или я устал или в конец отупел. но подскажите почему не очищается Serial.available:
Я поправил описание Serial.flush() Начиная с версии Arduino 1.0 логика работы функции изменилась. Теперь она ожидает окончание отправки данных.
а какая-же функция на самом деле будет очищать буфер?
ну или какой хитростью мне достигнуть результата? нужно считать символы из сериалМонитора в массив и вывести его