Как оптимизировать код и ускорить работу 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 строку переписать в вид:
if ((millis() - xxx) >= 200 ) { xxx = millis(); //тут что то делаем }xxx - переменная?
иногда Arduino пропускает 3-5 секунд
в 414 строчке
А код и правда ужасен.
Попробуйте хотя бы научится использовать циклы, а не копировать одинаковые блоки программы по 10-20 раз.
и еще, совет - время надо хранить и сравнивать в цифровом формате, а не в виде строчек "10:55:00" - это медленно и неэффективно
Ну я хоть признаю это) Я никогда не работал с Arduino(это мой первый опыт).
Как раз исправляю все в цифровой формат.
иногда Arduino пропускает 3-5 секунд
в 414 строчке
Это длительность звонка...
Её заменить на millis()?
delay(3000) блокирует код на 3 секунды - вот и возникает пауза в отображении секунд .