SerialEvent работает на нано, но не работает на mega

Всем привет!
Есть код, в теле которого есть прерывание по uart

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
      if (inChar == '\n') {
      //if (inChar == 'a') {
      stringComplete = true;
    }
  }
}

заливаю этот код в нано - все отлично работает.

Заливаю его же без каких-либо вообще изменений в мегу - не работает.
Может какие-то аппаратные особенности? подключено все верно.

этот код даже не компилируется, поясните, как вы его заливаете? из лейки что ли?

Пардон, это конечно кусок кода.
Я не знаю, нужен ли весь код. Выложу чуть ниже.
Суть такая: собрал, отлаживал на нано. Нано связана с одноплатником на линуксе по уарту.
все работает. все отлично.

Спаял готовый образец (на меге) - она ничего не принимает…почему?
может быть какая-то аппаратная несовместимость?

одноплатник работает от 3.3В , те логический уровень = 1 = 3.3в на пине. может этого мало меге?

код:

String inputString = "";      // a String to hold incoming data
bool stringComplete = false;  // whether the string is complete

byte id01 = 0; //Переменная температуры нагрева при косвенном нагреве
byte id02 = 0; //Переменная температуры включения косвенного нагрева
bool id03 = 0; //Использовать косвенный нагрев
bool id04 = 0; //Запрет косвенного нагрева
byte id05 = 0; //Переменная температура нагрева при электронагреве
bool id06 = 0; //Использовать электронагрев
bool id07 = 0; //Использовать таймер
byte id08 = 0; //Таймер включения электронагрева
byte id09 = 0; //Таймер выключения электронагрева
byte id10 = 0; //Температура включения рециркуляции
bool id11 = 0; //Использовать рециркуляцию при работе электронагрева
bool id12 = 0; //Использовать таймер для рециркуляции
byte id13 = 0; //Таймер включения рециркуляции
byte id14 = 0; //Таймер выключения рециркуляции
byte id15 = 0; //Установка текущего времени
byte id16 = 0; //пароль
bool id17 = 0; 
bool id18 = 0; //Флаг работы косвенного нагрева
bool id19 = 0; //Флаг работы электронагрева
bool id20 = 0; //Флаг работы косвенного нагрева
bool id21 = 0; //Кнопка СТОП режим работы
bool id22 = 0; //Кнопка АВТОМАТ режим работы
bool id23 = 0; //Кнопка ЭЛЕКТРО режим работы
bool id24 = 0; //Кнопка КОВЕННЫЙ режим работы
bool id25 = 0; //Кнопка СТОП рециркуляция
bool id26 = 0; //Кнопка АВТОМАТ рециркуляция
bool id27 = 0; //Кнопка ВКЛ рециркуляция
byte id28 = 0; //Температура воды в бойлере
byte id29 = 0; //Температура теплоносителя
byte id30 = 0; //Влажность воздуха
byte id31 = 0; //Температура воздуха


byte H_Sta_REC = 0;  //Часы запуска рециркуляции
byte M_Sta_REC = 0;  //минуты запуска рециркуляции
byte H_Sto_REC = 0;  //Часы стоп рециркуляции
byte M_Sto_REC = 0;  //минуты стоп рециркуляции
bool REC_Timer = 0;      //Флаг включения таймера рециркуляции
bool REC_Timer_FLAG = 0; //Флаг срабатывания таймера рециркуляции
bool REC = 0;        //Флаг включения рециркуляции
bool REC_TEN_FLAG = 0;    //флаг работы рециркуляции при работе от электротэна
bool REC_Temp_FLAG = 0;   //флаг работы рециркуляции при работе от температуры воды




byte H_Sta_TEN = 0;  //Часы запуска нагрева ТЭНом
byte M_Sta_TEN = 0;  //минуты запуска нагрева ТЭНом
byte H_Sto_TEN = 0;  //Часы стоп нагрева ТЭНом
byte M_Sto_TEN = 0;  //минуты стоп нагрева ТЭНом
bool TEN_Timer = 0;      //Флаг включения таймера нагрева ТЭНом
bool TEN_Timer_FLAG = 0; //Флаг срабатывания таймера нагрева ТЭНом
bool TEN = 0;            //Флаг включения нагрева ТЭНом
bool TEN_Temp_FLAG = 0;  //флаг работы нагрева ТЭНом при работе от температуры воды
bool TEN_E = 0;          //флаг работы
bool TEN_FLAG = 0;       //флаг работы



byte Water_T = 0;    //текущая температура воды в бойлере
bool Zotta = 0;      //флаг работы электрокотла




byte H_Sta_EL = 0; //Часы запуска электронагревателя
byte M_Sta_EL = 0; //минуты запуска электронагревателя
byte H_Sto_EL = 0; //Часы стоп электронагревателя
byte M_Sto_EL = 0; //минуты стоп электронагревателя


byte Hour = 0; //текущее время, часы
byte Min = 0; //текущее время, минуты




void setup() {
  // put your setup code here, to run once:
    Serial.begin(115200);
}

void loop() {

 //"$##*99I01*02T22:23*22I99999*33I12345678*"

if (stringComplete) {                                         //Если строка принята, то выполняем ее разбор
char inputBuffer[inputString.length()];                       //Создаем массив символов, длинной = длинепринятой строки
inputString.toCharArray(inputBuffer, inputString.length());   //Преобразуем строку в массив 
char *str;                                                    //создадим ссылку str на массив символов
char *buf = inputBuffer;                                      //создадим ссылку buf на массив символов inputBuffer
  while ((str = strtok_r(buf, "*", &buf)) != NULL)            //разбираем принятую строку по разделителю *
    {
     //Serial.println(str);

if (str[2]=='I'){                 //проверка принятого блока на то, что принятые данные - число
byte n = 3;                       //переменная, обозначающая какой символ по счету в полученной строке является символом-разделителем (I)
char* DATA = str + n;             //Указатель на массив DATA начинающийся с n-го символа массива str
byte input_id = atoi(str);        //Преобразуем массив символов ID в число и присваем это число переменной input_id
uint16_t input_data = atoi(DATA); //преобразование массива DATA в число и присвоение его переменной input_data. Для значений менее 32 767 использовать uint16_t input_data = atoi(DATA);
if ((1<=input_id<=99)&&(0<=input_data<=9999))  //проверяем, попадают ли принятые данные допустимые пределы
{
if((input_id==1)&&(id01!=input_data)&&(30<=input_data)&&(input_data<=85)){id01=input_data;}else{if((input_id==1)&&(input_data<=30)){id01=30;}else{if((input_id==1)){id01=85;};};};
if((input_id==2)&&(id02!=input_data)&&(30<=input_data)&&(input_data<=85)){id02=input_data;}else{if((input_id==2)&&(input_data<=30)){id02=30;}else{if((input_id==2)){id02=85;};};};

if((input_id==3)&&(id03!=input_data)){id03=input_data;};
if((input_id==4)&&(id04!=input_data)){id04=input_data;};
if((input_id==5)&&(id05!=input_data)){id05=input_data;};
if((input_id==6)&&(id06!=input_data)){id06=input_data;};
if((input_id==7)&&(id07!=input_data)){id07=input_data;};
if((input_id==8)&&(id08!=input_data)){id08=input_data;};
if((input_id==9)&&(id09!=input_data)){id09=input_data;};
if((input_id==10)&&(id10!=input_data)){id10=input_data;};
if((input_id==11)&&(id11!=input_data)){id11=input_data;};
if((input_id==12)&&(id12!=input_data)){id12=input_data;};
if((input_id==13)&&(id13!=input_data)){id13=input_data;};
if((input_id==14)&&(id14!=input_data)){id14=input_data;};
if((input_id==15)&&(id15!=input_data)){id15=input_data;};
if((input_id==16)&&(id16!=input_data)){id16=input_data;};

if((input_id==21)&&(id21!=input_data)&&(input_data==1)){id21=input_data;id22=0;id23=0;id24=0;}; //обработка нажатия кнопки СТОП нагрев воды
if((input_id==22)&&(id22!=input_data)&&(input_data==1)){id22=input_data;id21=0;id23=0;id24=0;}; //обработка нажатия кнопки АВТОМАТ нагрев воды
if((input_id==23)&&(id23!=input_data)&&(input_data==1)){id23=input_data;id21=0;id22=0;id24=0;}; //обработка нажатия кнопки ЭЛЕКТРО нагрев воды
if((input_id==24)&&(id24!=input_data)&&(input_data==1)){id24=input_data;id21=0;id22=0;id23=0;}; //обработка нажатия кнопки КОСВЕННЫЙ нагрев воды
if((input_id==25)&&(id25!=input_data)&&(input_data==1)){id25=input_data;id26=0;id27=0;};        //обработка нажатия кнопки СТОП рециркуляции
if((input_id==26)&&(id26!=input_data)&&(input_data==1)){id26=input_data;id25=0;id27=0;};        //обработка нажатия кнопки АВТОМАТ рециркуляции
if((input_id==27)&&(id27!=input_data)&&(input_data==1)){id27=input_data;id25=0;id26=0;};        //обработка нажатия кнопки ВКЛ рециркуляции

};
/*
Serial.print("id=");
Serial.println(input_id);
Serial.print("DATA=");
Serial.println(input_data);
Serial.println(" ");
} else {Serial.println(" ");};*/
};

if ((str[2]=='T') && (str[5] == ':')){ //проверка принятого блока на то, что принятые данные - время
byte n = 3;                            //переменная, обозначающая какой символ по счету в полученной строке является символом-разделителем (T)
byte m = 6;                            //переменная, обозначающая какой символ по счету в полученной строке является символом-разделителем (:) часов и минут
char* HOUR = str + n;                  //Указатель на массив HOUR начинающийся с n-го символа массива str для хранения часов
char* MIN = str + m;                   //Указатель на массив HOUR начинающийся с n-го символа массива str для хранения часов
byte input_id = atoi(str);             //Преобразуем массив символов ID в число и присваем это число переменной input_id
uint16_t hour_data = atoi(HOUR);       //преобразование массива DATA в число и присвоение его переменной input_data. Для значений менее 32 767 использовать uint16_t input_data = atoi(DATA);
uint16_t min_data = atoi(MIN);         //преобразование массива DATA в число и присвоение его переменной input_data. Для значений менее 32 767 использовать uint16_t input_data = atoi(DATA);
if ((1<=input_id<=99)&&(0<=hour_data<=24)&&(0<=min_data<=24))  //проверяем, попадают ли принятые данные допустимые пределы
{

};

/*
Serial.print("id=");
Serial.println(input_id);
Serial.print("Часы=");
Serial.println(hour_data);
Serial.print("Минуты=");
Serial.println(min_data);
Serial.println(" ");*/

} else {/*Serial.println(" ");*/};
    }






//!!!Блок обработки таймера нагрева от ТЭНА---------------------------------------------------------------------------------------------
if(H_Sta_TEN > H_Sto_TEN){
  if((Hour == H_Sta_TEN)&&(Min < H_Sta_TEN)){TEN_Timer = 0;}
  else{
    if((Hour < H_Sta_TEN)&&(Hour>H_Sto_TEN)){TEN_Timer = 0;}
    else{
      if((Hour == H_Sto_TEN)&&(Min >= H_Sto_TEN)){TEN_Timer = 0;}else{TEN_Timer = 1;};
    };
  };
}
else{
  if(H_Sta_TEN < H_Sto_TEN){
  if((Hour == H_Sta_TEN)&&(Min >= H_Sta_TEN)){TEN_Timer = 1;}
  else{
    if((Hour > H_Sta_TEN)&&(Hour < H_Sto_TEN)){TEN_Timer = 1;}
    else{
      if((Hour == H_Sto_TEN)&&(Min < H_Sto_TEN)){TEN_Timer = 1;}else{TEN_Timer = 0;};
    };
  };
}
else{
  if(H_Sta_TEN == H_Sto_TEN){
  if(M_Sta_TEN < M_Sto_TEN){
    if((Min >= M_Sta_TEN)&&(Min < M_Sto_TEN)&&(Hour == H_Sta_TEN)){TEN_Timer = 1;}else{TEN_Timer = 0;};
   };
  if(M_Sta_TEN > M_Sto_TEN){
    if((Min < M_Sta_TEN)&&(Min >= M_Sto_TEN)&&(Hour == H_Sta_TEN)){TEN_Timer = 0;}else{TEN_Timer = 1;};
   };
  if (M_Sta_TEN == M_Sto_TEN){
    TEN_Timer=0; 
  };
};
};
};
//!!!конец блока обработки таймера нагрева от ТЭНА----------------------------------------------------------------------------------------










//!!!Блок обработки таймера рециркуляции--------------------------------------------------------------------------------------------------
if(H_Sta_REC > H_Sto_REC){
  if((Hour == H_Sta_REC)&&(Min < H_Sta_REC)){REC_Timer = 0;}
  else{
    if((Hour < H_Sta_REC)&&(Hour>H_Sto_REC)){REC_Timer = 0;}
    else{
      if((Hour == H_Sto_REC)&&(Min >= H_Sto_REC)){REC_Timer = 0;}else{REC_Timer = 1;};
    };
  };
}
else{
  if(H_Sta_REC < H_Sto_REC){
  if((Hour == H_Sta_REC)&&(Min >= H_Sta_REC)){REC_Timer = 1;}
  else{
    if((Hour > H_Sta_REC)&&(Hour < H_Sto_REC)){REC_Timer = 1;}
    else{
      if((Hour == H_Sto_REC)&&(Min < H_Sto_REC)){REC_Timer = 1;}else{REC_Timer = 0;};
    };
  };
}
else{
  if(H_Sta_REC == H_Sto_REC){
  if(M_Sta_REC < M_Sto_REC){
    if((Min >= M_Sta_REC)&&(Min < M_Sto_REC)&&(Hour == H_Sta_REC)){REC_Timer = 1;}else{REC_Timer = 0;};
   };
  if(M_Sta_REC > M_Sto_REC){
    if((Min < M_Sta_REC)&&(Min >= M_Sto_REC)&&(Hour == H_Sta_REC)){REC_Timer = 0;}else{REC_Timer = 1;};
   };
  if (M_Sta_REC == M_Sto_REC){
    REC_Timer=0; 
  };
};
};
};
//!!!конец блока обработки таймера рециркуляции--------------------------------------------------------------------------------------------------

//!!!Блок обработки логики рециркуляции----------------------------------------------------------------------------------------------------------
if(id25==1){                      //id25 - кнопка СТОП рециркуляции
REC = 0;                          //остановить рециркуляцию
}
else{ if(id27==1){                //id27 - кнопка ВКЛ рециркуляции
REC = 1;                          //включить рециркуляцию
}
else{ if(id26==1){ //Код при работе в автомате id11 - работа при электронагрева
      if (id11 == 1){REC_TEN_FLAG = TEN_FLAG;}else{REC_TEN_FLAG = 1;};             // опция работать или нет при нагреве воды ТЭНом
      if (id12 == 1){REC_Timer_FLAG=REC_Timer;}else{REC_Timer_FLAG = 1;};         // опция учитывать таймер рециркуляции
      if (id10 >= Water_T){REC_Temp_FLAG = 1;}else{REC_Temp_FLAG = 0;};           // опция работы при температуре выше температуры воды
      if (REC_TEN_FLAG && REC_Timer_FLAG && REC_Temp_FLAG){REC = 1;}else{REC = 0;};
};
};
};
//!!!Конец блока обработки логики рециркуляции---------------------------------------------------------------------------------------------------








id30 = random(100);


Serial.print("$$*"); //отправляем символ начала строки
Serial.print(id01);
Serial.print("*");
Serial.print(id02);
Serial.print("*");
Serial.print(id03);
Serial.print("*");
Serial.print(id04);
Serial.print("*");
Serial.print(id05);
Serial.print("*");
Serial.print(id06);
Serial.print("*");
Serial.print(id07);
Serial.print("*");
Serial.print(id08);
Serial.print("*");
Serial.print(id09);
Serial.print("*");
Serial.print(id10);
Serial.print("*");
Serial.print(id11);
Serial.print("*");
Serial.print(id12);
Serial.print("*");
Serial.print(id13);
Serial.print("*");
Serial.print(id14);
Serial.print("*");
Serial.print(id15);
Serial.print("*");
Serial.print(id16);
Serial.print("*");
Serial.print(id17);
Serial.print("*");
Serial.print(id18);
Serial.print("*");
Serial.print(id19);
Serial.print("*");
Serial.print(id20);
Serial.print("*");
Serial.print(id21);
Serial.print("*");
Serial.print(id22);
Serial.print("*");
Serial.print(id23);
Serial.print("*");
Serial.print(id24);
Serial.print("*");
Serial.print(id25);
Serial.print("*");
Serial.print(id26);
Serial.print("*");
Serial.print(id27);
Serial.print("*");
Serial.print(id28);
Serial.print("*");
Serial.print(id29);
Serial.print("*");
Serial.print(id30);
Serial.println("*");

Serial.println(inputString);
inputString ="";
stringComplete = false;

  };


}



void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
      if (inChar == '\n') {
      //if (inChar == 'a') {
      stringComplete = true;
    }
  }
}

врете вы , не может этот код работать , у вас скобка лишняя

Работает код. только что его залил в нано. все ок.

значит код который вы залили и который выложили , не один и тот же , в котором выложили - в сообщении #3 лишняя скобка

не знаю как работать, но после форматирования все скобки на месте и компилируется без проблем.
поосторожнее с такими заявлениями…

в notepad++ скобка в строчке 349 никчему не соответствует ¯_(ツ)_/¯

upd : а не, мой косяк ,после влючения подсветки синтаксиса - все сложилось

у вас другая строчка 349?

код рабочий и проверенный, хоть и в разарботке.
если его скомпилировать и открыть монитор порта и далее ввести в поле ввода $$#* и нажать энтер, то программа выдаст ответ.

по какой-то причине мега не принимает запрос.
может быть сигнал с амплитудой 3.3В для меги мало?
Большая скорость 115200? (хотя нормальная)

да , другая ,точно такая же как и у ТС в 3ем сообщении

я копирую кнопкой “копировать” в правом верхнем углу в поле кода в сообщении

из монитора порта с мегой общения нет а с наной есть ? или с обеими есть из монитора порта и нет с мегой только из распбери пай с мегой ?

Ребята, да какая разница - уже поняли, что все ок с кодом.
Сейчас установил, что с меги на уарт одноплатника все приходит.
Получается, что мега не видит запрос. остается только версия с 3.3в, которые мега не воспринмиает? кто как думает? кто сталкивался с подобным?

суть прогаммы такая: ардуина получает запрос и как только его получила - отправляет ответ. те без полученного запроса - ответа - нет.
в качестве одноплатника - оранж пи зеро. на нем вэбсервер и на нем есть контроль принятой строки, те ответа от ардуины. пока все в процессе отладки.

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

прошиваю в мегу - и тишина. запрос не приходит, соответсвенно ответа - нет. в мониторе порта принудительно начинаю вводить запросы (эмулирую оранж) и она отвечает. ответ виден на оранж.

странно…

@denissyslo,

так Вы никогда не отладитесь. У Вас проблема с чем? С serialEvent? Так наюха в Вашем коде всё остальное, что а) сбивает с толку; б) мешает восприятию; в) может как-то влиять.

Когда возникает проблема, необходимо писать короткий проверочный код, в котором проявляется проблема и нет ничего лишнего. В Вашем случае это будет строк сорок - не больше.

Попробуйте написать такой код и погоняйте его. Почти наверняка вопрос снимется сам собой, а если нет, то любой (я, например) запустит его у себя, посмотрит, и, возможно, поможет.

Пока же у Вас код на 350+ строк, Вы и сами в нём не разберётесь и другой никто разбираться не полезет.

Попробуйте сделать как я сказал, увидите результат.

1 лайк

Хороший совет.
Между делом запускал такой код для проверки первым делом:


void setup() {
  Serial.begin(115200);
}

void loop() {
  if (Serial.available()) {      // If anything comes in Serial (USB),
    Serial1.write(Serial.read());   // read it and send it out Serial1 (pins 0 & 1)
  }
}

он тоже не работает, те сигнализирует о том, что ничего не принимается.
Я сначала был уверен. что это программная проблема, каким-то образом, хотя все ок.

Но сейчас сижу паяю - адаптер с 3.3в на 5в. почему-то уверен, что баг аппаратный. Хотя пол огике должно работать…

спаял. не работает. через адаптер так же не видно запроса. странно.

какой-то полтергейст. мега (уже три штуки перепробовал) не видит входящих символов на уарте от одноплатника. пробовал через адаптер 5В-3.3В (адаптер проверил на свистке -все ок).
Может как-то надо уарт на меге дополнительно настраивать? Я уже хз что думать

Через softwareSerial все работает, но кривовато (скорость большая 115200 похоже). А вот на аппартаном - ни в какую.

На меге больше одного железного уарта

  • Последовательная шина: 0 (RX) и 1 (TX); Последовательная шина 1: 19 (RX) и 18 (TX); Последовательная шина 2: 17 (RX) и 16 (TX); Последовательная шина 3: 15 (RX) и 14 (TX). Выводы используются для получения (RX) и передачи (TX) данных TTL. Выводы 0 и 1 подключены к соответствующим выводам микросхемы последовательной шины ATmega8U2.

Попробуйте поставить задержку 20-50 мс между чтением и записью в сериал через переменную. Давно было дело, но в каком то проекте именно это помогло.