ATtiny841 не выполняет код как ардуино НАНО_328

Доброго времени суток! Написал код для удаленного управления Вебастой на авто в АрдуиноИДЕ.
На ардуино НАНО 328чип, код работает как надо с аппаратным плюс программным последовательным портом. Но мне нужно два аппаратных порта, так как на програмном не нашел как включить бит проверки четности, поэтому глаз пал на ATtiny841. К сожалению код на тиньке не работает так как на НАНО.
Программирую тиньку USBasp без бутлоудера, резонатор использовал 8 и 16 МГц. Ядро для тиньки разные пробывал, результат одинаков. Проблема в том что код на тиньки как то теряет данные котрые необходимо отправлять по первому порту, да и с приемом то же проблемы.

1. //#include <SoftwareSerial.h>  // Библиотека програмной реализации обмена по UART-протоколу для ардуино
2. //SoftwareSerial Serial1(5, 6);  // RX, TX 
3. uint32_t time_call = 0;    // переменная для запоминания времени кода был начат вызов
4. String _response = "";     // Переменная для хранения ответов модуля
5. uint8_t countTry = 0;      // переменная хранения количество неудачных попыток ввода кода
6. uint8_t countByte_Rx = 0;  // переменная хранящая количество принятых байт
7. uint8_t countByte_Tx = 0;  // переменная хранящая количество переданных байт
8. bool set_call = 0;         // флаг установки вызова
9. bool act_call = 0;         // флаг активного вызова
10. byte recive[15];                        // массив для хранения и обработки приходящих сообщений  от Вебасты
11. #define sec 10000                       // уставка периуда отпраки сообщения поддержания работы
12. #define sec_call 20000                  // уставка максимального времени вызова
13. #define timeOUT 5000            //  таймаут ожидания ответа от модема
14. #define NumberPhone "ATD+79775559988;"  // номер телефона на который будут совершаться звонки
15. #define PASSWORD_USER 99                // пароль (для евеличения кол-во символов пароля требуется изменить допустимое кол-во введенных \
16.                                         // символов в строке кода:"else if (result.length() <= 3) {" и используемые символы для пароля \
17.                                         // в "if (result.substring(2, 4).toInt() == PASSWORD) {")
18. // для ATtiny841:
19. #define LED_GREEN PA0         // пин для подключения сетодиода индикатора что МК не завис
20. #define LED_PIN_1 PA7         // пин для подключения сетодиода индикатора что что команда вкл Вебасты прошла
21. #define RESET_PIN_SIM800 PA6  // пин для сброса сим800
22. //  для Ардуино:
23. /*
24. #define LED_GREEN 12         // пин для подключения сетодиода индикатора что МК не завис
25. #define LED_PIN_1 13         // пин для подключения сетодиода индикатора что что команда вкл Вебасты прошла
26. #define RESET_PIN_SIM800 11  // пин для сброса сим800
27. */
28. #define per_proverki_sim800 3000  // период отправки сообщения модему для проверки что он не завис, ожидаем ответ
29. #define per_indikaci 3000         // период между индикацией  сколько раз модем был перезагружен
30. byte requestON[5] = { 0x34, 0x03, 0x21, 0x00, 0x00 };
31. String result = "";  // Переменная для хранения вводимых данных
32. uint32_t time_proverki_sim800 = 0;  //переменная для периода отправки сообщения модему для проверки что он не завис
33. uint32_t time_LED_GREEN = 0;
34. int count_reset = 0;  // счетчик перезагрузок модема

35. void setup() {
36.   pinMode(RESET_PIN_SIM800, OUTPUT);
37.   digitalWrite(RESET_PIN_SIM800, HIGH);
38.   pinMode(LED_PIN_1, OUTPUT);  // Настройка пина подключения светодиода на выxод
39.   pinMode(LED_GREEN, OUTPUT);
40.   digitalWrite(LED_GREEN, HIGH);
41.   Serial.begin(9600);
42.   Serial1.begin(2400);
43.   Serial.println("Start");
44.   Serial.setTimeout(300);
45.   //delay(6000);
46.   digitalWrite(LED_GREEN, LOW);
47.   _response = sendATCommand("AT", true);             // Проверка общего статуса
48.   _response = sendATCommand("AT+DDET=1,0,0", true);  // Включаем DTMF
49.   Serial.println("END Setup");
50. }

51. void loop() {
52.   if (time_LED_GREEN <= millis()) {
53.     for (int i = 1; i <= count_reset; i++) {
54.       digitalWrite(LED_GREEN, HIGH);
55.       delay(300);
56.       digitalWrite(LED_GREEN, LOW);
57.       delay(300);
58.     }
59.     time_LED_GREEN = millis() + per_indikaci;
60.   }
61.   if (time_proverki_sim800 <= millis()) {
62.     _response = sendATCommand("AT Proverka", true);  // Проверка общего статуса
63.     if (_response == 0) {
64.       count_reset++;
65.       digitalWrite(RESET_PIN_SIM800, LOW);
66.       delay(100);
67.       digitalWrite(RESET_PIN_SIM800, HIGH);
68.       //delay(6000);  // даем время GSM модулю начать работу
69.       _response = sendATCommand("AT reset", true);       // Проверка общего статуса
70.       _response = sendATCommand("AT+DDET=1,0,0", true);  // Включаем DTMF
71.     }
72.     time_proverki_sim800 = millis() + per_proverki_sim800;
73.   }

74.   if (Serial.available()) {      // Если модем, что-то отправил...
75.     _response = waitResponse();  // Получаем ответ от модема для анализа
76.     int index = -1;
77.     do {                                  // Перебираем построчно каждый пришедший ответ
78.       index = _response.indexOf("\r\n");  // Получаем идекс переноса строки
79.       String submsg = "";
80.       if (index > -1) {                              // Если перенос строки есть, значит
81.         submsg = _response.substring(0, index);      // Получаем первую строку
82.         _response = _response.substring(index + 2);  // И убираем её из пачки
83.       } else {                                       // Если больше переносов нет
84.         submsg = _response;                          // Последняя строка - это все, что осталось от пачки
85.         _response = "";                              // Пачку обнуляем
86.       }
87.       submsg.trim();                               // Убираем пробельные символы справа и слева
88.       if (submsg != "") {                          // Если строка значимая (не пустая), то распознаем уже её
89.         if (submsg.startsWith("+DTMF:")) {         // Если ответ начинается с "+DTMF:" тогда:
90.           String symbol = submsg.substring(7, 8);  // Выдергиваем символ с 7 позиции длиной 1 (по 8)
91.           //Serial.println(symbol);
92.           processingDTMF(symbol);                // Логику выносим для удобства в отдельную функцию
93.         } else if (submsg.startsWith("RING")) {  // При входящем звонке...
94.           sendATCommand("ATA", true);            // ...отвечаем (поднимаем трубку)
95.           result = "";   // очищаем строку от возможных данных
96.           set_call = 1;  // устанавливаем флаг установки вызова
97.           countTry = 0;  // При каждом звонке, сбрасываем счетчик попыток
98.         }
99.       }
100.     } while (index > -1);  // Пока индекс переноса строки действителен
101.   }
102.   if (set_call == 1) {
103.     time_call = millis() + sec_call;  // установка максимального времени вызова
104.     set_call = 0;                     // устанавливаем флаг неактивный вызов*
105.     act_call = 1;                     // устанавливаем флаг активного вызова
106.   }
107.   if ((time_call <= millis()) && (act_call == 1)) {  // если вызов превысил установленное время и был активным
108.     act_call = 0;
109.     result = "";
110.     Serial.println("ATH");  // кладем трубку(прекращаем вызов)
111.   }
112.   data_Rx(0);
113.   if (((recive[7] == 0xA1) && (recive[9] == 0xEE)) || ((recive[8] == 0xC4) && (recive[10] == 0x84))) {
114.     static uint32_t p_tx_podd = 0;  // переменная для запоминания времени когда было отправлено сообщение поддерж раб Вебасто
115.     if (p_tx_podd < millis()) {
116.       memset(recive, 0x00, countByte_Rx);
117.       podderzhanie();
118.       p_tx_podd = millis() + sec;
119.     }
120.   } else if (((recive[8] == 0xFF) && (recive[9] == 0x7B)) || ((recive[9] == 0xFF) && (recive[10] == 0x7B)) || ((recive[6] == 0x90) && (recive[7] == 0xD1))) {
121.     digitalWrite(LED_PIN_1, LOW);
122.     delay(400);
123.     memset(recive, 0x00, countByte_Rx);
124.     sendATCommand(NumberPhone, true);  // набираем свой номер телефона
125.     set_call = 1;  // устанавливаем флаг установки звонка
126.   }
127. }

128. String sendATCommand(String cmd_GSM, bool waiting) {
129.   //String sendATCommand(String cmd_GSM) {
130.   String _resp = "";  // Переменная для хранения результата
131.   Serial.println("1");
132.   Serial.println(cmd_GSM);  // Отправляем команду модулю
133.   Serial.println("2");
134.   if (waiting) {             // Если необходимо дождаться ответа...
135.     _resp = waitResponse();  // ... ждем, когда будет передан ответ
136.                              // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
137.     //if (_resp.startsWith(cmd_GSM)) {  // Убираем из ответа дублирующуюся команду
138.     //  _resp = _resp.substring(_resp.indexOf("\r\n", cmd_GSM.length()) + 2);
139.     //}
140.   }
141.   return _resp;  // Возвращаем результат. Пусто, если проблема
142. }

143. String waitResponse() {                                     // Функция ожидания ответа и возврата полученного результата
144.   String _resp = "";                                        // Переменная для хранения результата
145.   uint32_t _timeout = millis() + timeOUT;                      // Переменная для отслеживания таймаута (10 секунд)
146.   while (!Serial.available() && (millis() < _timeout)) {};  // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...
147.   if (Serial.available() > 0) {                             // Если есть, что считывать...
148.     _resp = Serial.readString();                            // ... считываем и запоминаем
149.     //Serial.println("1" + _resp);
150.   }
151.   //  else {                                              // Если пришел таймаут, то...
152.   //    FROGI.println("Timeout...");                     // ... оповещаем об этом и...
153.   //  }
154.   return _resp;  // ... возвращаем результат. Пусто, если проблема
155. }

156. // Отдельная функция для логики DTMF
157. void processingDTMF(String symbol) {
158.   if (symbol == "#") {                                      // если введен символ #, то проверяем введенный код
159.     if (result.substring(2, 4).toInt() == PASSWORD_USER) {  //преобразуем 2 и 3 символ из пришедшей строки в целочисленный тип данных и сверяем с паролем, далее если пароль верный
160.       byte val_time = result.substring(0, 2).toInt();       // преобразуем 0 и 1 символ из пришедшей строки в целочисленный тип данных
161.       if ((val_time > 14) && (val_time < 100)) {            // сравниваем больше оно 14  и меньше ли 100, так как это время для работы Вебасты
162.         setWBSTState(HIGH, val_time);  // отправляем в функцию состояния вебасты флаг на включение и запрошенное время работы
163.         countTry = 0;                  // Обнуляем счетчик неудачных попыток ввода кода
164.       } else if (val_time == 0) {      // если введенное значение равно 0, то
165.         Serial.println("ATH");         // кладем трубку(прекращаем вызов)
166.         act_call = 0;                  // выключаем флаг активного звонка
167.         setWBSTState(LOW, 0x00);       // отправляем в функцию состояния вебасты флаг на вЫключение
168.         countTry = 0;                  // Обнуляем счетчик неудачных попыток ввода кода
169.       }
170.     } else {                    // если пароль неверный
171.       countTry += 1;            // Увеличиваем счетчик неудачных попыток на 1
172.       if (countTry == 3) {      // если счетчик неуд.попыток равен 3
173.         Serial.println("ATH");  // кладем трубку(прекращаем вызов)
174.         act_call = 0;           // выключаем флаг активного звонка
175.         countTry = 0;           // Обнуляем счетчик неудачных попыток ввода кода
176.       }
177.     }
178.     result = "";  // После каждой решетки сбрасываем вводимую комбинацию
179.   }
180.   else if (result.length() <= 6) {  //если количество символов в result <= 6
181.     result += symbol;               // Все, что приходит, собираем в одну строку
182.   } else {
183.     result = "";  // Сбрасываем вводимую комбинацию при вводе большем кол-ве чем кол-во разрешенных символов(это блокировка против роста строки) и при введенной решетки
184.   }
185. }

186. void data_Rx(int o) {  // функция приема сообщений от Вебасты
187.   if (Serial1.available()) {                  // Если есть, что считывать...
188.     delay(100);                               // ждем пока все придет
189.     countByte_Rx = Serial1.available();       // запоминаем сколько байт в буфере
190.     Serial1.readBytes(recive, countByte_Rx);  // считываем из буфера приема
191.     byte checksum = 0x00;
192.     for (uint8_t i = countByte_Tx; i < countByte_Rx - 1; i++) {
193.       checksum = checksum ^ recive[i];  // расчет чексуммы ксор входных данных
194.     }
195.     if (checksum != recive[countByte_Rx - 1]) {  // если расчитанная КС не равно последнему байту сообщения, то данные повреждены и мы их стираем
196.       memset(recive, 0x00, countByte_Rx);
197.       switch (o) {
198.         case 1:
199.           ON_Wbst();
200.           break;
201.         case 2:
202.           podderzhanie();
203.           break;
204.         case 3:
205.           OFF_Wbst();
206.           break;
207.           //default:
208.           // выполняется, если не выбрана ни одна альтернатива
209.           // default необязателен
210.       }
211.     }
212.   }
213. }

214. void podderzhanie() {
215.   byte msg_podd[6] = { 0x34, 0x04, 0x44, 0x21, 0x00, 0x55 };  // Сообщение для поддержания работы, без него котел отключится, отправлять не реже 15 секунд
216.   Serial1.write(msg_podd, 6);
217.   memset(recive, 0x00, countByte_Rx);
218.   countByte_Tx = 6;
219.   delay(400);
220.   data_Rx(2);
221. }

222. void setWBSTState(bool state, byte request_TimerWork) {  // Функция изменения состояния Вебасты (ВКЛ\ВЫКЛ)
223.   digitalWrite(LED_PIN_1, state);
224.   if (state == LOW) {
225.     OFF_Wbst();
226.   }
227.   if (state == HIGH) {
228.     requestON[3] = request_TimerWork;                                                // Сообщение запроса на работу где request_TimerWork это время (0x0F = 15 мин)(0x0E = 14) и т.д.
229.     requestON[4] = requestON[0] xor requestON[1] xor requestON[2] xor requestON[3];  // расчитываем КС в четвертый байт(последний)
230.     Serial.println("ATH");                                                           // кладем трубку(прекращаем вызов)
231.     act_call = 0;
232.     ON_Wbst();
233.   }
234. }

235. void ON_Wbst() {
236.   //Serial1.begin(300);
237.   //Serial1.write(0x0);
238.   //Serial1.begin(2400);
239.   Serial1.write(requestON, 5);
240.   countByte_Tx = 5;
241.   delay(400);
242.   data_Rx(1);
243. }

244. void OFF_Wbst() {
245.   byte requestOFF[5] = { 0x34, 0x02, 0x10, 0x26 };  // сообщение на вЫключение Вебасты
246.   Serial1.write(requestOFF, 4);
247.   countByte_Tx = 4;
248.   delay(400);
249.   data_Rx(3);
250. }


Как отредактировать сообщение не разобрался, добавленная нумерация строк в первом посте думаю излишне и не даст использовать код при копировании без редактирования. Вот код для ардуино

Спойлер
#include <SoftwareSerial.h>  // Библиотека програмной реализации обмена по UART-протоколу для ардуино
SoftwareSerial Serial1(5, 6);  // RX, TX 
uint32_t time_call = 0;    // переменная для запоминания времени кода был начат вызов
String _response = "";     // Переменная для хранения ответов модуля
uint8_t countTry = 0;      // переменная хранения количество неудачных попыток ввода кода
uint8_t countByte_Rx = 0;  // переменная хранящая количество принятых байт
uint8_t countByte_Tx = 0;  // переменная хранящая количество переданных байт
bool set_call = 0;         // флаг установки вызова
bool act_call = 0;         // флаг активного вызова
byte recive[15];                        // массив для хранения и обработки приходящих сообщений  от Вебасты
#define sec 10000                       // уставка периуда отпраки сообщения поддержания работы
#define sec_call 20000                  // уставка максимального времени вызова
#define NumberPhone "ATD+79774715411;"  // номер телефона на который будут совершаться звонки
#define PASSWORD_USER 99                // пароль (для евеличения кол-во символов пароля требуется изменить допустимое кол-во введенных
                                        // символов в строке кода:"else if (result.length() <= 3) {" и используемые символы для пароля
                                        // в "if (result.substring(2, 4).toInt() == PASSWORD) {")
// пины для ATtiny841:
/*
#define LED_GREEN PA0         // пин для подключения сетодиода индикатора что МК не завис
#define LED_PIN_1 PA7         // пин для подключения сетодиода индикатора что что команда вкл Вебасты прошла
#define RESET_PIN_SIM800 PA6  // выход/пин для сброса сим800
*/
//  пины для Ардуино:

#define LED_GREEN 12         // пин для подключения сетодиода индикатора что МК не завис
#define LED_PIN_1 13         // пин для подключения сетодиода индикатора что что команда вкл Вебасты прошла
#define RESET_PIN_SIM800 11  // выход/пин для сброса сим800

#define per_proverki_sim800 3000  // период отправки сообщения модему для проверки что он не завис, ожидаем ответ
#define per_indikaci 3000         // период между индикацией  сколько раз модем был перезагружен
#define timeOUT 5000            //  таймаут ожидания ответа от модема
byte requestON[5] = { 0x34, 0x03, 0x21, 0x00, 0x00 };
String result = "";  // Переменная для хранения вводимых данных
uint32_t time_proverki_sim800 = 0;  //переменная для периода отправки сообщения модему для проверки что он не завис
uint32_t time_LED_GREEN = 0;
int count_reset = 0;  // счетчик перезагрузок модема

void setup() {
  pinMode(RESET_PIN_SIM800, OUTPUT);
  digitalWrite(RESET_PIN_SIM800, HIGH);
  pinMode(LED_PIN_1, OUTPUT);  // Настройка пина подключения светодиода на выxод
  pinMode(LED_GREEN, OUTPUT);
  digitalWrite(LED_GREEN, HIGH);
  Serial.begin(9600);
  Serial1.begin(2400);
  Serial.println("Start");
  Serial.setTimeout(300);
  //delay(6000);
  digitalWrite(LED_GREEN, LOW);
  _response = sendATCommand("AT", true);             // Проверка общего статуса
  _response = sendATCommand("AT+DDET=1,0,0", true);  // Включаем DTMF
  Serial.println("END Setup");
}

void loop() {
  if (time_LED_GREEN <= millis()) {
    for (int i = 1; i <= count_reset; i++) {
      digitalWrite(LED_GREEN, HIGH);
      delay(300);
      digitalWrite(LED_GREEN, LOW);
      delay(300);
    }
    time_LED_GREEN = millis() + per_indikaci;
  }
  if (time_proverki_sim800 <= millis()) {
    _response = sendATCommand("AT Proverka", true);  // Проверка общего статуса
    if (_response == 0) {
      count_reset++;
      digitalWrite(RESET_PIN_SIM800, LOW);
      delay(100);
      digitalWrite(RESET_PIN_SIM800, HIGH);
      //delay(6000);  // даем время GSM модулю начать работу
      _response = sendATCommand("AT reset", true);       // Проверка общего статуса
      _response = sendATCommand("AT+DDET=1,0,0", true);  // Включаем DTMF
    }
    time_proverki_sim800 = millis() + per_proverki_sim800;
  }

  if (Serial.available()) {      // Если модем, что-то отправил...
    _response = waitResponse();  // Получаем ответ от модема для анализа
    int index = -1;
    do {                                  // Перебираем построчно каждый пришедший ответ
      index = _response.indexOf("\r\n");  // Получаем идекс переноса строки
      String submsg = "";
      if (index > -1) {                              // Если перенос строки есть, значит
        submsg = _response.substring(0, index);      // Получаем первую строку
        _response = _response.substring(index + 2);  // И убираем её из пачки
      } else {                                       // Если больше переносов нет
        submsg = _response;                          // Последняя строка - это все, что осталось от пачки
        _response = "";                              // Пачку обнуляем
      }
      submsg.trim();                               // Убираем пробельные символы справа и слева
      if (submsg != "") {                          // Если строка значимая (не пустая), то распознаем уже её
        if (submsg.startsWith("+DTMF:")) {         // Если ответ начинается с "+DTMF:" тогда:
          String symbol = submsg.substring(7, 8);  // Выдергиваем символ с 7 позиции длиной 1 (по 8)
          //Serial.println(symbol);
          processingDTMF(symbol);                // Логику выносим для удобства в отдельную функцию
        } else if (submsg.startsWith("RING")) {  // При входящем звонке...
          sendATCommand("ATA", true);            // ...отвечаем (поднимаем трубку)
          result = "";   // очищаем строку от возможных данных
          set_call = 1;  // устанавливаем флаг установки вызова
          countTry = 0;  // При каждом звонке, сбрасываем счетчик попыток
        }
      }
    } while (index > -1);  // Пока индекс переноса строки действителен
  }
  if (set_call == 1) {
    time_call = millis() + sec_call;  // установка максимального времени вызова
    set_call = 0;                     // устанавливаем флаг неактивный вызов*
    act_call = 1;                     // устанавливаем флаг активного вызова
  }
  if ((time_call <= millis()) && (act_call == 1)) {  // если вызов превысил установленное время и был активным
    act_call = 0;
    result = "";
    Serial.println("ATH");  // кладем трубку(прекращаем вызов)
  }
  data_Rx(0);
  if (((recive[7] == 0xA1) && (recive[9] == 0xEE)) || ((recive[8] == 0xC4) && (recive[10] == 0x84))) {
    static uint32_t p_tx_podd = 0;  // переменная для запоминания времени когда было отправлено сообщение поддерж раб Вебасто
    if (p_tx_podd < millis()) {
      memset(recive, 0x00, countByte_Rx);
      podderzhanie();
      p_tx_podd = millis() + sec;
    }
  } else if (((recive[8] == 0xFF) && (recive[9] == 0x7B)) || ((recive[9] == 0xFF) && (recive[10] == 0x7B)) || ((recive[6] == 0x90) && (recive[7] == 0xD1))) {
    digitalWrite(LED_PIN_1, LOW);
    delay(400);
    memset(recive, 0x00, countByte_Rx);
    sendATCommand(NumberPhone, true);  // набираем свой номер телефона
    set_call = 1;  // устанавливаем флаг установки звонка
  }
}

String sendATCommand(String cmd_GSM, bool waiting) {
  //String sendATCommand(String cmd_GSM) {
  String _resp = "";  // Переменная для хранения результата
  Serial.println("1");
  Serial.println(cmd_GSM);  // Отправляем команду модулю
  Serial.println("2");
  if (waiting) {             // Если необходимо дождаться ответа...
    _resp = waitResponse();  // ... ждем, когда будет передан ответ
                             // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать
    //if (_resp.startsWith(cmd_GSM)) {  // Убираем из ответа дублирующуюся команду
    //  _resp = _resp.substring(_resp.indexOf("\r\n", cmd_GSM.length()) + 2);
    //}
  }
  return _resp;  // Возвращаем результат. Пусто, если проблема
}

String waitResponse() {                                     // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                                        // Переменная для хранения результата
  uint32_t _timeout = millis() + timeOUT;                      // Переменная для отслеживания таймаута (10 секунд)
  while (!Serial.available() && (millis() < _timeout)) {};  // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то...  ???????  мне не понятно
  if (Serial.available() > 0) {                             // Если есть, что считывать...
    _resp = Serial.readString();                            // ... считываем и запоминаем
    //Serial.println("1" + _resp);
  }
  //  else {                                              // Если пришел таймаут, то...
  //    FROGI.println("Timeout...");                     // ... оповещаем об этом и...
  //  }
  return _resp;  // ... возвращаем результат. Пусто, если проблема
}

// Отдельная функция для логики DTMF
void processingDTMF(String symbol) {
  if (symbol == "#") {                                      // если введен символ #, то проверяем введенный код
    if (result.substring(2, 4).toInt() == PASSWORD_USER) {  //преобразуем 2 и 3 символ из пришедшей строки в целочисленный тип данных и сверяем с паролем, далее если пароль верный
      byte val_time = result.substring(0, 2).toInt();       // преобразуем 0 и 1 символ из пришедшей строки в целочисленный тип данных
      if ((val_time > 14) && (val_time < 100)) {            // сравниваем больше оно 14  и меньше ли 100, так как это время для работы Вебасты
        setWBSTState(HIGH, val_time);  // отправляем в функцию состояния вебасты флаг на включение и запрошенное время работы
        countTry = 0;                  // Обнуляем счетчик неудачных попыток ввода кода
      } else if (val_time == 0) {      // если введенное значение равно 0, то
        Serial.println("ATH");         // кладем трубку(прекращаем вызов)
        act_call = 0;                  // выключаем флаг активного звонка
        setWBSTState(LOW, 0x00);       // отправляем в функцию состояния вебасты флаг на вЫключение
        countTry = 0;                  // Обнуляем счетчик неудачных попыток ввода кода
      }
    } else {                    // если пароль неверный
      countTry += 1;            // Увеличиваем счетчик неудачных попыток на 1
      if (countTry == 3) {      // если счетчик неуд.попыток равен 3
        Serial.println("ATH");  // кладем трубку(прекращаем вызов)
        act_call = 0;           // выключаем флаг активного звонка
        countTry = 0;           // Обнуляем счетчик неудачных попыток ввода кода
      }
    }
    result = "";  // После каждой решетки сбрасываем вводимую комбинацию
  }
  else if (result.length() <= 6) {  //если количество символов в result <= 6
    result += symbol;               // Все, что приходит, собираем в одну строку
  } else {
    result = "";  // Сбрасываем вводимую комбинацию при вводе большем кол-ве чем кол-во разрешенных символов(это блокировка против роста строки) и при введенной решетки
  }
}

void data_Rx(int o) {  // функция приема сообщений от Вебасты
  if (Serial1.available()) {                  // Если есть, что считывать...
    delay(100);                               // ждем пока все придет
    countByte_Rx = Serial1.available();       // запоминаем сколько байт в буфере
    Serial1.readBytes(recive, countByte_Rx);  // считываем из буфера приема
    byte checksum = 0x00;
    for (uint8_t i = countByte_Tx; i < countByte_Rx - 1; i++) {
      checksum = checksum ^ recive[i];  // расчет чексуммы ксор входных данных
    }
    if (checksum != recive[countByte_Rx - 1]) {  // если расчитанная КС не равно последнему байту сообщения, то данные повреждены и мы их стираем
      memset(recive, 0x00, countByte_Rx);
      switch (o) {
        case 1:
          ON_Wbst();
          break;
        case 2:
          podderzhanie();
          break;
        case 3:
          OFF_Wbst();
          break;
          //default:
          // выполняется, если не выбрана ни одна альтернатива
          // default необязателен
      }
    }
  }
}

void podderzhanie() {
  byte msg_podd[6] = { 0x34, 0x04, 0x44, 0x21, 0x00, 0x55 };  // Сообщение для поддержания работы, без него котел отключится, отправлять не реже 15 секунд
  Serial1.write(msg_podd, 6);
  memset(recive, 0x00, countByte_Rx);
  countByte_Tx = 6;
  delay(400);
  data_Rx(2);
}

void setWBSTState(bool state, byte request_TimerWork) {  // Функция изменения состояния Вебасты (ВКЛ\ВЫКЛ)
  digitalWrite(LED_PIN_1, state);
  if (state == LOW) {
    OFF_Wbst();
  }
  if (state == HIGH) {
    requestON[3] = request_TimerWork;                                                // Сообщение запроса на работу где request_TimerWork это время (0x0F = 15 мин)(0x0E = 14) и т.д.
    requestON[4] = requestON[0] xor requestON[1] xor requestON[2] xor requestON[3];  // расчитываем КС в четвертый байт(последний)
    Serial.println("ATH");                                                           // кладем трубку(прекращаем вызов)
    act_call = 0;
    ON_Wbst();
  }
}

void ON_Wbst() {
  //Serial1.begin(300);
  //Serial1.write(0x0);
  //Serial1.begin(2400);
  Serial1.write(requestON, 5);
  countByte_Tx = 5;
  delay(400);
  data_Rx(1);
}

void OFF_Wbst() {
  byte requestOFF[5] = { 0x34, 0x02, 0x10, 0x26 };  // сообщение на вЫключение Вебасты
  Serial1.write(requestOFF, 4);
  countByte_Tx = 4;
  delay(400);
  data_Rx(3);
}

Принцип работы я не понял, так что то, что бросилось в глаза.

Почему вы сделали буфер на 15 байт, а не 16 ?
Ведь приемный буфер UART размером 16 байт.

Не логичное расположение
217. memset(recive, 0x00, countByte_Rx);
логичнее было бы очистить буфер в функции приема, и не countByte_Rx, а весь.
Хотя я не понял, зачем он вообще очищается. Обработка потом ведется до countByte_Rx.

И к вопросу не относится, но интересно - если вам нужна была четность, то где вы ее используете?

Ну и выбор. Памяти в 4 раза меньше
Я бы посоветовал ATmega328pb взять, но сам с ней дел не имел.

1 лайк
  1. Буфер о котором вы спрашиваете используется для второго порта, который общается с Вебастой, его размер выбрал от болды, с небольшим запасом от размера сообщений которые известны.
  2. Если очищать буфер recive в функции приема, тогда наверное придется создавать дополнительную глобальную переменную или переписывать код что бы функция возвращала то что пришло в порт для анализа данных. Об этом надо подумать.
    Полностью согласен с тем что строка “217. memset(recive, 0x00, countByte_Rx);” лишняя, ее вообще удалю.
    Очищается что бы не было искаженных данных при последующих приемах, так как Вебаста отправляет разное количество байт в посылке. Очищаю столько, байтов сколько пришло из двух соображений: время на очистку меньше и память меньше трется(я понимаю что это время микросекунд да и у памяти ресурс огромен, просто хотелось превратить это в жизнь, может пригодится в других проектах).
    Теперь про то что к вопросу не относится. К физической Вебасте подключал К-лайн адаптер и терминалом отправлял посылки байтов, так убедился в правильности посылок и что Вебаста на них реагирует, включается/выключается, работает установленное время. Для проверки кода в домашних условиях (не бегать же к машине каждый раз как поправил код) Написал код без бита четности для второй ардуино нано которая имитирует Вебасту, в маем случае зажигает светодиод, горит он пока приходят сообщения для поддержания работы и то время которое мы запросили. В теории оставалось только на тиньке включить бит четности на аппаратном порту, но увы).
    Вот этот код:
Спойлер

/*
{0x34, 0x03, 0x21, 0x0f, 0x19};        // Сообщение запроса на вкл Вебасты, третий байт это время на которое включить вебасту в минутах
{0x34, 0x04, 0x44, 0x21, 0x00, 0x55};  // Сообщение для поддержания работы, без него котел отключится, отправлять не реже 15 секунд
{0x34, 0x02, 0x10, 0x26};   // сообщение на вЫключение Вебасты

{0x43, 0x03, 0xA1, 0x0F, 0xEE};  // ответ на сообщение запроса на вкл Вебасты
{0x43, 0x02, 0x90, 0xD1};     // ответ на сообщение вЫключение Вебасты
{0x43, 0x03, 0xC4, 0xFF, 0x7B};   // сообщение о неработающщей вебасте, не горящей, закончившую работу
{0x43, 0x03, 0xC4, 0x00, 0x84};   // ответ на сообщение для поддержания работы
*/
#define led 13
byte recive[20];
int countByte = 0;                                        //  количество принятых байт
byte otvet_requestON[5] = {0x43, 0x03, 0xA1, 0x0F, 0xEE};      // ответ на сообщение запроса на вкл Вебасты
byte otvet_pod[5] = {0x43, 0x03, 0xC4, 0x00, 0x84};      // ответ на сообщение для поддержания работы
byte otvet_requestOFF[4] = {0x43, 0x02, 0x90, 0xD1};                  // ответ на сообщение вЫключение Вебасты
byte requestON[5] = {0x34, 0x03, 0x21, 0x00, 0x00}; // сообщение запроса на вкл Вебасты
byte pod[6] = {0x34, 0x04, 0x44, 0x21, 0x00, 0x55};       // сообщение для поддержания работы
byte requestOFF[4] = {0x34, 0x02, 0x10, 0x26};      // сообщение вЫключение Вебасты
byte otvet_ENDwork[5] = {0x43, 0x03, 0xC4, 0xFF, 0x7B};   // сообщение о неработающщей вебасте, не горящей, закончившую работу
uint32_t timeWork = 0;
uint32_t setTime = 0;
uint32_t TimePod = 0;
#define setTimePod 15000
#define coef_time 6000  // КОЭФФИЦИЕНТ времени работы Вебасты
bool b = 0;
bool p = 0;

void setup() { 
  //Serial.begin(2400, SERIAL_8E1);     // Скорость обмена данными с модемом
  Serial.begin(2400);     // Скорость обмена данными с модемом
  pinMode(led, OUTPUT);
}

void loop() {
  data_Rx();
  if(memcmp(recive, requestON, 3) == 0){
    requestON[3] = recive[3];
    uint32_t k = coef_time;
    setTime = recive[3] * k;
  }
  if(p == 1){
    otvet();
  }
  if(((timeWork <= millis()) || (TimePod <= millis())) && (b == 1)){
    b = 0;
    digitalWrite(led, LOW);
    Serial.write(otvet_ENDwork, 5);
  }
}

void data_Rx(){                                  // функция приема сообщений
    if (Serial.available()) {                    // Если есть, что считывать...
      delay(100);                                // ждем пока все придет
      countByte = Serial.available();            // запоминаем сколько байт в буфере
      Serial.readBytes(recive, countByte);       // считываем из буфера приема
      p = 1;
    }
}

void otvet(){
  
  if(memcmp(recive, requestON, 3) == 0){
    digitalWrite(led, HIGH);
    b = 1;
    timeWork = millis() + setTime;
    TimePod = millis() + setTimePod;
    Serial.write(recive, countByte);           // эхо приема
    //Serial.write(requestON, 5);
    Serial.write(otvet_requestON, 5);
  }
  else if((memcmp(recive, pod, 6) == 0) && (b == 1)){
    TimePod = millis() + setTimePod;
    Serial.write(recive, countByte);           // эхо приема
    //Serial.write(pod, 6);
    Serial.write(otvet_pod, 5);
  }
  else if((memcmp(recive, pod, 6) == 0) && (b == 0)){
    Serial.write(recive, countByte);           // эхо приема
    //Serial.write(pod, 6);
    Serial.write(otvet_ENDwork, 5);
  }
  else if((memcmp(recive, requestOFF, 4) == 0) && (b == 1)){
    digitalWrite(led, LOW);
    b = 0;
    Serial.write(recive, countByte);           // эхо приема
    //Serial.write(requestOFF, 4);
    Serial.write(otvet_requestOFF, 4);
  }
  else if((memcmp(recive, requestOFF, 4) == 0) && (b == 0)){
    Serial.write(recive, countByte);           // эхо приема
    //Serial.write(requestOFF, 4);
    Serial.write(otvet_ENDwork, 5);
  }
  else{
    Serial.write(recive, countByte);           // эхо приема
  }
  memset(recive, 0x00, countByte);
  p = 0;
}


А зачем больше, вроде код помещается во флэш и в ОЗУ? За подсказку про МК спасибо!

А стек ?
P.S.
Простыми словами, нужен ещё достаточный запас свободной памяти.

Тини841 разве вообще поддерживается Ардуиной? Уверены что код соответствует адресам регистров? Может пишет не туда? Компилятор за это не отвечает, ошибок не даст.