Ситуация следующая. Две меги2560 с Xbee модулями. Одна из них "пульт" с кучей кнопок, lcd и ethernet шилдом. Другая "приёмник/исполнитель" без обвеса (кроме Xbee). Пульт посылает команды: COV00t0000 CCV00t0000 Первый байт "C" показывает что пришла команда, также это может быть "R" - запрос или "S" - ответ на запрос. Два следующих байта "OV" или "CV" - команда, которую нужно выполнить "OV" - подать сигнал "HIGH" на выход... "CV" - подать сигнал "LOW" на выход... Далее два байта - индекс, под которым в массиве хранится pin, на который должно послать сигнал Далее "t" (time) - в общем не несущий смысла разделитель, но если его нет - команда перестанет выполняться и вылетит ошибка После чего четыре байта - время, в течение которого будет посылаться сигнал "HIGH" или "0" - тогда этот сигнал будет посылаться всегда. Исполнитель, приняв команду (т.е. "C"), правильно определяет OV и CV, а приняв "00" (индекс) переводит его из String в int (str.toInt()) и получает - 0. Тоже со временем. Всё работает, но получив вторую команду он уже из "00" получает - 000. Тоже со временем. При этом команда не выполняется. Я записал принятые команды в файл на mSD, вот что вышло: CCV0t0 - первая команда COV000t0000 - вторая команда (откуда взялся третий ноль в индексе я ума не приложу) Хотя все числа были перевидены в Int... Все последующие команды также не выполняются, хотя если пульт держать включённым, а исполнитель перезапустить, то первая команда опять выполнится как надо, а остальные опять "пролетят". Значит проблема в исполнителе, но где? Код формировки запроса на пульте: Код (Text): void valve(int valve, boolean open_valve, int time = 0){ //Изменяет состояние lcd.clear(); lcd.print("\x4F\xB2\x70\x61\xB2\x6F\xBF\xBA\x61""..."); //Обработка... String query = "C"; if(open_valve) query += "OV"; else query += "CV"; if(valve < 10) query += "0" + String(valve); else query += String(valve); query += "t"; if(time < 10) query += "000" +String(time); else if(time >= 10 && time < 100) query += "00" + String(time); else if(time >= 100 && time < 1000) query += "0" + String(time); else if(time >= 1000 && time < 10000) query += String(time); Serial.print(query); prepare_lcd("valve select"); mod = "valve select"; } Код обработки команды: Код (Text): void loop(){ if(Serial.available() > 0){ File f = SD.open("test.txt", FILE_WRITE); serial_hendler(f); f.close(); } } void serial_hendler(File f){ char input_byte = Serial.read(); f.print(input_byte); if(input_byte == 'C') command_handler(f); } void command_handler(File f){ boolean command_cot = false; boolean valve_open; String command = ""; command += char(Serial.read()); command += char(Serial.read()); f.print(command); if(command == "OV"){ valve_open = true; command_cot == true; } if(command == "CV"){ valve_open = false; command_cot == true; } if(command == "OV" || command == "CV"){ String str_valve = ""; str_valve += char(Serial.read()); str_valve += char(Serial.read()); int valve = str_valve.toInt(); f.print(valve); char t = char(Serial.read()); if(t == 't'){ f.print(t); String str_time = ""; str_time += char(Serial.read()); str_time += char(Serial.read()); str_time += char(Serial.read()); str_time += char(Serial.read()); int time = str_time.toInt(); f.print(time); valve_control(valve, valve_open, time); } else{ } } } void valve_control(int valve, boolean VO, int time){ int valve_pin = valves[valve]; valve_open[valve] = VO; valve_time[valve] = time; if(time > 0) time_is_on = true; digitalWrite(valve_pin, VO); }
Предположу, что дело вот в чём. При включении приёмника он пару секунд тупит и поэтому в Serial успевает скопиться полные 10 байт сообщения и он их прожёвывает как вы и хотели. Далее. Приходит один байт. Вы попадаете в serial_hendler (handler, кстати), пишите байт в файл, идёте в command_handler, пытаетесь считать пару следующих байт, а фигушки — их ещё нет; функция возвращается ни с чем. Далее подходит второй байл, вы опять в serial_hendler, байт != 'C' — вы печатаете его в файл и выходите и так далее байт за байтом. В общем, попробуйте вместо: if(Serial.available() > 0) использовать #define MESSAGE_LENGTH 10 if(Serial.available() >= MESSAGE_LENGTH)
Точно! В это то и проблема. Я и сам хотел сделать ожидание с помощью пустого while, но из-за ошибки я подсознательно отложил это дело на потом Спасибо, nailxx.