Как оптимизировать код и ускорить работу Arduino?
- Войдите на сайт для отправки комментариев
Втр, 09/06/2020 - 15:12
Всем привет! Имеется скетч, функция которой "Автоматический звонок".
Решил написать все самостоятельно с использованием модуля GPS, RTC, IC2 LCD и силового реле. Звонок не имеет динамики.
Проблема в том, что либо функция loop() работает долго либо где то в говн* коде есть самая вонючая часть, которая работает медленно( Помогите пожалуйста!
P.s Признаюсь! Код реально ужасен...
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <iarduino_RTC.h> #include <SoftwareSerial.h> LiquidCrystal_I2C lcd(0x27, 16, 2); iarduino_RTC time(RTC_DS3231); SoftwareSerial GPS(9, 10); //Переменные для работы с GPS unsigned char buffer[64]; // Буффер int count = 0; // Счетчик для работы с буфером. String GPS_time; // Переменная которая хранит в себе время //когда необходимо получить время с GPS String tmp_data; // Временная переменная полученных данных String tmp_substring; // Переменная для работы со строками полученных из GPS String tmp_full = ""; // Переменная для конкатетации строк из GPS byte gps_hour; byte gps_minute; byte gps_second; // Контакты const PROGMEM byte RELAY_PIN = 8; // Выход для управления РЕЛЕ // Переменные для управления кнопками const PROGMEM byte btn1 = 2; const PROGMEM byte btn2 = 3; const PROGMEM byte btn3 = 4; const PROGMEM byte btn4 = 5; const PROGMEM byte btn5 = 6; byte btn1_clicked = 1; byte btn2_clicked = 1; byte btn3_clicked = 1; byte btn4_clicked = 1; byte btn5_clicked = 1; byte btn_num = 0; // Номер экрана short lcd_num = 0; // Переменная для переключения между экранами //tmp времени byte tmp_t = 0; // Переменная для сохранения изменяемых параметров даты и времени //tmp расписания(Переменные для передачи в функцию РАСПИСАНИЕ для дальнейшей проверки) String shedule_week; // День недели для расписания String shedule_time; // Время для расписания byte shedule_type = 1; // Тип для расписания, которая меняет между 30 минутным //и 45 минутным расписанием bool was_clicked = false; // Нужно чтобы если был выбран 45 минутное //расписание вручную, то во вторник 40 минутное расписание отменяется void setup() { // Инициализация для контактов pinMode(RELAY_PIN, OUTPUT); // Переключаем PIN реле в режим для выхода //Инициализация дисплея lcd.init(); lcd.backlight(); // Включаем подсветку дисплея startArduino(); // Включаем экран приветствия на 1 - секунду lcd.clear(); // Очищаем экран для дальнейшего пользования //Инициализация модулей time.begin(); Wire.begin(); GPS.begin(9600); //Serial.begin(9600); //Отладочное изменение времени time.settime(55, 24, 10, -1, -1, -1, -1); //конфигурация входа контроллера и подключение внутреннего подтягивающего резистора pinMode(btn1, INPUT_PULLUP); pinMode(btn2, INPUT_PULLUP); pinMode(btn3, INPUT_PULLUP); pinMode(btn4, INPUT_PULLUP); pinMode(btn5, INPUT_PULLUP); } void loop() { // Экраны if (lcd_num == 0) { // Экран с таймером tmp_t = 0; if (millis() % 200 == 0) { shedule_time = time.gettime("H:i:s"); // Получение ВРЕМЕНИ GPS_time = shedule_time.substring(0, 5); String date_send = time.gettime("d-m-Y"); // Получение ДАТЫ shedule_week = time.gettime("D"); // Получение ДНЯ недели lcd.setCursor(0, 0); lcd.print(shedule_time); lcd.print(", "); lcd.setCursor(11, 0); lcd.print(shedule_week); lcd.setCursor(0, 1); lcd.print(date_send); lcd.setCursor(12, 1); if (shedule_type == 2 || shedule_week.equals(F("Tue"))) { // Если ТИП для расписания 2(40м) или ДЕНЬ недели ЧТ lcd.setCursor(12, 1); lcd.print(F("40m")); // То выводим оповещение о том,что включени ТИП 40 минутного расписания } if (shedule_type == 1 && (shedule_week.equals(F("Tue")) == false)) { // Если ТИП для расписания 1(45м) и ДЕНЬ недели не ЧТ lcd.setCursor(12, 1); lcd.print(F("45m")); // То выводим оповещение о том, что включен ТИП 45 минутного расписания } if (shedule_type == 3 && (shedule_week.equals(F("Tue")) == false)) { // Если ТИП для расписания 3(35м) и ДЕНЬ недели не ЧТ lcd.setCursor(12, 1); lcd.print(F("35m")); // То выводим оповещение о том, что включен ТИП 35 минутного расписания } if (shedule_type == 4 && (shedule_week.equals(F("Tue")) == false)) { // Если ТИП для расписания 4(30м) и ДЕНЬ недели не ЧТ lcd.setCursor(12, 1); lcd.print(F("30m")); // То выводим оповещение о том, что включен ТИП 30 минутного расписания } } } if (lcd_num == -1) { // Экран выбора 45 минутного расписания lcd.setCursor(0, 0); lcd.print(F("45 minute")); lcd.setCursor(0, 1); lcd.print(F("SEL - choose")); } if (lcd_num == -2) { // Экран выбора 40 минутного расписания lcd.setCursor(0, 0); lcd.print(F("40 minute")); lcd.setCursor(0, 1); lcd.print(F("SEL - choose")); } if (lcd_num == -3) { // Экран выбора 35 минутного расписания lcd.setCursor(0, 0); lcd.print(F("35 minute")); lcd.setCursor(0, 1); lcd.print(F("SEL - choose")); } if (lcd_num == -4) { // Экран выбора 30 минутного расписания lcd.setCursor(0, 0); lcd.print(F("30 minute")); lcd.setCursor(0, 1); lcd.print(F("SEL - choose")); } if (lcd_num == 1) { // Экран изменения ЧАСОВ lcd.setCursor(0, 0); lcd.print(F("Hour edit:")); lcd.setCursor(0, 1); lcd.print(tmp_t); lcd.print(time.gettime(":i:s, D")); } if (lcd_num == 2) { // Экран изменения МИНУТ lcd.setCursor(0, 0); lcd.print(F("Minute edit:")); lcd.setCursor(0, 1); lcd.print(time.gettime("H:")); lcd.print(tmp_t); lcd.print(time.gettime(":s, D")); } if (lcd_num == 3) { // Экран изменения СЕКУНД lcd.setCursor(0, 0); lcd.print(F("Second edit:")); lcd.setCursor(0, 1); lcd.print(time.gettime("H:i:")); lcd.print(tmp_t); lcd.print(time.gettime(", D")); } if (lcd_num == 4) { // Экран изменения дня НЕДЕЛИ lcd.setCursor(0, 0); lcd.print(F("Week edit:")); lcd.setCursor(0, 1); lcd.print(F("NOW:")); lcd.print(time.gettime("D")); lcd.setCursor(9, 1); lcd.print(F("NUM:")); lcd.setCursor(13, 1); lcd.print(tmp_t); } if (lcd_num == 5) { // Изменение ДНЯ lcd.setCursor(0, 0); lcd.print(F("Day edit:")); lcd.setCursor(0, 1); lcd.print(F("NOW:")); lcd.setCursor(5, 1); lcd.print(time.gettime("d")); lcd.setCursor(8, 1); lcd.print(F("NUM:")); lcd.print(tmp_t); } if (lcd_num == 6) { // Изменение МЕСЯЦА lcd.setCursor(0, 0); lcd.print(F("Month edit:")); lcd.setCursor(0, 1); lcd.print(F("NOW:")); lcd.setCursor(5, 1); lcd.print(time.gettime("m")); lcd.setCursor(8, 1); lcd.print(F("NUM:")); lcd.print(tmp_t); } if (lcd_num < -4) { lcd_num = 6; } else if (lcd_num > 6) { lcd_num = -4; } if ((shedule_week.equals(F("Sat")) || shedule_week.equals(F("Sun"))) && GPS_time.equals(F("10:25"))) { if (GPS.available()) { while(GPS.available()) { buffer[count++]=GPS.read(); if(count == 64) break; } tmp_data = buffer, count; tmp_data.replace("\n", "|"); tmp_full = tmp_full + tmp_data; //Serial.println(tmp_full); int index_str = tmp_full.indexOf(F("$GNGGA")); if (index_str != -1) { String time_UTC = tmp_full.substring(index_str+ 7, index_str+13); if (time_UTC == "" || time_UTC.length() < 6) { } else { gps_hour = time_UTC.substring(0, 2).toInt() + 5; gps_minute = time_UTC.substring(2, 4).toInt(); gps_second = time_UTC.substring(4, 6).toInt(); time.settime(gps_second, gps_minute, gps_hour, -1, -1, -1, -1); } } clrBuff(); count = 0; } } // Номера нажатых кнопок if (digitalRead(btn1) == LOW && btn1_clicked == 1) { // Перейти на следующий экран (Кнопка NEXT) btn_num = 0; if (lcd_num == 1) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ ЧАС tmp_t++; if (tmp_t > 24) { tmp_t = 0; } } if (lcd_num == 2) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ МИНУТА tmp_t++; if (tmp_t > 59) { tmp_t = 0; } } if (lcd_num == 3) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ СЕКУНД tmp_t++; if (tmp_t > 59) { tmp_t = 0; } } if (lcd_num == 4) { // ИЗМЕНЕНИЕ ДНЯ НЕДЕЛИ tmp_t++; if (tmp_t > 6) { tmp_t = 0; } } if (lcd_num == 5) { // ИЗМЕНЕНИЕ ДНЯ tmp_t++; if (tmp_t > 31) { tmp_t = 1; } } if (lcd_num == 6) { // ИЗМЕНЕНИЕ МЕСЯЦА tmp_t++; if (tmp_t > 12) { tmp_t = 1; } } } if (digitalRead(btn2) == LOW && btn2_clicked == 1) { // Собитие при нажатии на кнопку BTN2 btn_num = 0; lcd_num++; tmp_t = 0; lcd.clear(); } if (digitalRead(btn3) == LOW && btn3_clicked == 1) { btn_num = 0; if (lcd_num == 1) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ ЧАС tmp_t--; if (tmp_t > 24) { tmp_t = 0; } } if (lcd_num == 2) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ МИНУТА tmp_t--; if (tmp_t > 59) { tmp_t = 0; } } if (lcd_num == 3) { // ИЗМЕНЕНИЕ ЗНАЧЕНИЙ СЕКУНД tmp_t--; if (tmp_t > 59) { tmp_t = 0; } } if (lcd_num == 4) { // ИЗМЕНЕНИЕ ДНЯ НЕДЕЛИ tmp_t--; if (tmp_t < 1) { tmp_t = 1; } } if (lcd_num == 5) { // ИЗМЕНЕНИЕ ДНЯ tmp_t--; if (tmp_t < 1) { tmp_t = 1; } } if (lcd_num == 6) { // ИЗМЕНЕНИЕ МЕСЯЦА tmp_t--; if (tmp_t < 1) { tmp_t = 1; } } } if (digitalRead(btn4) == LOW && btn4_clicked == 1) { btn_num = 0; lcd_num--; tmp_t = 0; lcd.clear(); } if (digitalRead(btn5) == LOW && btn5_clicked == 1) { btn_num = 0; if (lcd_num == 0) { // Внеплановый звонок relaySwitch(); } if (lcd_num == 1) { // Установить часы time.settime(-1,-1,tmp_t,-1,-1,-1,-1); tmp_t = 0; } if (lcd_num == 2) { // Установить минуты time.settime(-1,tmp_t,-1,-1,-1,-1,-1); tmp_t = 0; } if (lcd_num == 3) { // Установить секунды time.settime(tmp_t,-1,-1,-1,-1,-1,-1); tmp_t = 0; } if (lcd_num == 4) { // Установить дня недели time.settime(-1,-1,-1,-1,-1,-1,tmp_t); tmp_t = 0; } if (lcd_num == 5) { // Установить день time.settime(-1,-1,-1,tmp_t,-1,-1,-1); tmp_t = 0; } if (lcd_num == 6) { // Установить месяц time.settime(-1,-1,-1,-1,tmp_t,-1,-1); tmp_t = 0; } if (lcd_num == -1) { // Расписание - 45 минут shedule_type = 1; was_clicked = true; lcd.clear(); lcd_num = 0; } if (lcd_num == -2) { // Расписание - 40 минут shedule_type = 2; lcd.clear(); lcd_num = 0; } if (lcd_num == -3) { // Расписание - 35 минут shedule_type = 3; lcd.clear(); lcd_num = 0; } if (lcd_num == -4) { // Расписание - 30 минут shedule_type = 4; lcd.clear(); lcd_num = 0; } } btn1_clicked = digitalRead(btn1); btn2_clicked = digitalRead(btn2); btn3_clicked = digitalRead(btn3); btn4_clicked = digitalRead(btn4); btn5_clicked = digitalRead(btn5); if (shedule_week.equals(F("Tue")) && shedule_type == 1 && was_clicked == false) { sheduleFunc(); } else { if (shedule_week.equals(F("Sat")) || shedule_week.equals(F("Sun"))) { //Ничего не делаем } else { sheduleFunc(); } } } // Функции void startArduino() { lcd.setCursor(0, 0); lcd.print(F("LCD - ready")); lcd.setCursor(0, 1); lcd.print(F("Arduino UNO")); } void relaySwitch() { //Переключение реле true - вкл, false - выкл //Отладочный код(Для проверки работы всех расписаний) //--------------------------- //Serial.print("Сигнал подан: "); //Serial.print(signal_num); //Serial.println(); //--------------------------- digitalWrite(RELAY_PIN, HIGH); //Serial.print("On"); delay(3000); //Serial.print("Off"); digitalWrite(RELAY_PIN, LOW); shedule_time = time.gettime("H:i:s"); } void clrBuff() { for (int i=0; i<count;i++) { buffer[i]=NULL; } } void sheduleFunc() { // Расписания if (shedule_type == 4) { // Уроки по 30 минут //Звонок на 1 урок if (shedule_time.equals(F("10:25:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:27:00"))) { // Перемена relaySwitch(); } //Звонок на 2 урок if (shedule_time.equals(F("10:29:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:32:00"))) { // Перемена relaySwitch(); } //Звонок на 3 урок if (shedule_time.equals(F("10:35:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:38:00"))) { // Перемена relaySwitch(); } //Звонок на 4 урок if (shedule_time.equals(F("10:41:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:44:00"))) { // Перемена relaySwitch(); } //Звонок на 5 урок if (shedule_time.equals(F("10:47:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:50:00"))) { // Перемена relaySwitch(); } //Звонок на 6 урок if (shedule_time.equals(F("10:53:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:56:00"))) { // Перемена relaySwitch(); } //Звонок на 7 урок if (shedule_time.equals(F("10:59:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:02:00"))) { // Перемена relaySwitch(); } //Звонок на 8 урок if (shedule_time.equals(F("11:05:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:08:00"))) { // Последний звонок дня 15:30:00 relaySwitch(); shedule_type = 0; } } if (shedule_type == 3) { // Уроки по 35 минут //Звонок на 1 урок if (shedule_time.equals(F("10:25:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:27:00"))) { // Перемена relaySwitch(); } //Звонок на 2 урок if (shedule_time.equals(F("10:29:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:32:00"))) { // Перемена relaySwitch(); } //Звонок на 3 урок if (shedule_time.equals(F("10:35:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:38:00"))) { // Перемена relaySwitch(); } //Звонок на 4 урок if (shedule_time.equals(F("10:41:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:44:00"))) { // Перемена relaySwitch(); } //Звонок на 5 урок if (shedule_time.equals(F("10:47:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:50:00"))) { // Перемена relaySwitch(); } //Звонок на 6 урок if (shedule_time.equals(F("10:53:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:56:00"))) { // Перемена relaySwitch(); } //Звонок на 7 урок if (shedule_time.equals(F("10:59:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:02:00"))) { // Перемена relaySwitch(); } //Звонок на 8 урок if (shedule_time.equals(F("11:05:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:08:00"))) { // Последний звонок дня 15:30:00 relaySwitch(); shedule_type = 0; } } if (shedule_type == 2 || shedule_week.equals("Tue")) { // Уроки по 40 минут //Звонок на 1 урок if (shedule_time.equals(F("10:25:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:26:00"))) { // Перемена relaySwitch(); } //Звонок на 2 урок if (shedule_time.equals(F("10:27:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:38:00"))) { // Перемена relaySwitch(); } //Звонок на 3 урок if (shedule_time.equals(F("10:39:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:38:00"))) { // Перемена relaySwitch(); } //Звонок на 4 урок if (shedule_time.equals(F("10:41:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:44:00"))) { // Перемена relaySwitch(); } //Звонок на 5 урок if (shedule_time.equals(F("10:47:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:50:00"))) { // Перемена relaySwitch(); } //Звонок на 6 урок if (shedule_time.equals(F("10:53:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:56:00"))) { // Перемена relaySwitch(); } //Звонок на 7 урок if (shedule_time.equals(F("10:59:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:02:00"))) { // Перемена relaySwitch(); } //Звонок на 8 урок if (shedule_time.equals(F("11:05:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:08:00"))) { // Последний звонок дня 15:30:00 relaySwitch(); shedule_type = 0; } } if (shedule_type == 1) { // Уроки по 45 минут //Звонок на 1 урок if (shedule_time.equals(F("08:00:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("08:45:00"))) { // Перемена relaySwitch(); } //Звонок на 2 урок if (shedule_time.equals(F("08:50:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("09:35:00"))) { // Перемена relaySwitch(); } //Звонок на 3 урок if (shedule_time.equals(F("09:40:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:15:00"))) { // Перемена relaySwitch(); } //Звонок на 4 урок if (shedule_time.equals(F("10:20:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:15:00"))) { // Перемена relaySwitch(); } //Звонок на 5 урок if (shedule_time.equals(F("10:47:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:50:00"))) { // Перемена relaySwitch(); } //Звонок на 6 урок if (shedule_time.equals(F("10:53:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("10:56:00"))) { // Перемена relaySwitch(); } //Звонок на 7 урок if (shedule_time.equals(F("10:59:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:02:00"))) { // Перемена relaySwitch(); } //Звонок на 8 урок if (shedule_time.equals(F("11:05:00"))) { // На урок relaySwitch(); } if (shedule_time.equals(F("11:08:00"))) { // Последний звонок дня 15:30:00 relaySwitch(); } } }
Ах да, проблема в том, что иногда Arduino пропускает 3-5 секунд из за чего она не попадает в расписание.
для начала 90 строку переписать в вид:
xxx - переменная?
иногда Arduino пропускает 3-5 секунд
в 414 строчке
А код и правда ужасен.
Попробуйте хотя бы научится использовать циклы, а не копировать одинаковые блоки программы по 10-20 раз.
и еще, совет - время надо хранить и сравнивать в цифровом формате, а не в виде строчек "10:55:00" - это медленно и неэффективно
Ну я хоть признаю это) Я никогда не работал с Arduino(это мой первый опыт).
Как раз исправляю все в цифровой формат.
иногда Arduino пропускает 3-5 секунд
в 414 строчке
Это длительность звонка...
Её заменить на millis()?
delay(3000) блокирует код на 3 секунды - вот и возникает пауза в отображении секунд .