/
vint10tov
/
SmartHome
Обзор
Документация
Войти
/
vint10tov
/
SmartHome
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/main.cpp
249 строк
9 KB
vint10tov
13:24/1/12/24
01 дек 2024, 12:24
01 дек 2024, 12:24
d2693b8
Код
Авторство
О чём код?
#include <Arduino.h> #include <microDS3231.h> //https://github.com/GyverLibs/microDS3231?tab=readme-ov-file#usage #include <EEPROM.h> #include <Wire.h> #include "smart_home.hpp" #include "request_from_server.hpp" const int ledPin = 13; // Номер пина, к которому подключен светодиод const long interval = 500; // Интервал мигания в миллисекундах bool ledState = false; // Состояние светодиода unsigned long previousMillis = 0; // Время последнего мигания int blinkCount = 10; // Количество миганий int currentBlink = 0; // Текущий счетчик миганий const uint8_t RELAY_0 = 6; const uint8_t RELAY_1 = 7; const uint8_t RELAY_2 = 8; const uint8_t MINUTES_IN_HOUR = 60; const uint8_t MAX_BUF_in = 11; // Максимальная длина входного массива const uint8_t MAX_BUF_out = 21; // Максимальная длина выходного массива uint8_t dataIn[MAX_BUF_in] = {0}; // Объявляем массив для хранения данных запроса uint8_t dataOut[MAX_BUF_out] = {0}; // Объявляем массив для хранения данных ответа MicroDS3231 rtc; SmartHome smart_home(RELAY_0, RELAY_1, RELAY_2); uint16_t minutes; void clearEEPROM(); bool receiveBytesFromUART(); void pinModeFast(uint8_t pin, uint8_t mode); void digitalWriteFast(uint8_t pin, bool x); void SmartHome_UART(); uint8_t calculate_checksum(const uint8_t *data, uint8_t size); bool verify_checksum(const uint8_t *data, uint8_t size); void blinkError(); void setup() { Serial.begin(9600); //clearEEPROM(); // Затираем EEPROM перед началом работы if (!rtc.begin()) { delay(60000); asm volatile("jmp 0x00"); } // rtc.setTime(BUILD_SEC, BUILD_MIN, BUILD_HOUR, BUILD_DAY, BUILD_MONTH, BUILD_YEAR); if (rtc.lostPower()) { // выполнится при сбросе батарейки rtc.setTime(BUILD_SEC, BUILD_MIN, BUILD_HOUR, BUILD_DAY, BUILD_MONTH, BUILD_YEAR); } //EEPROM.put(20, smart_home); // EEPROM.get(20, smart_home); // smart_home.SET_time(rtc.getTime()); delay(10); minutes = smart_home.GET_time().hour * MINUTES_IN_HOUR + smart_home.GET_time().minute; for (uint8_t i = 0; i < 3; ++i) { pinModeFast(smart_home.GET_pin(i), OUTPUT); digitalWriteFast(smart_home.GET_pin(i), smart_home.GET_status_relay(i)); } } void loop() { if (receiveBytesFromUART()) { // обработка запроса RequestFromServer rfs; if (rfs.deserialize(dataIn, MAX_BUF_in - 1)) { if (rfs.GET_Type() == RequestType::PING) { SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::PIN_ON) { smart_home.SET_on_relay(rfs.GET_relay()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::PIN_ON_MIN) { smart_home.SET_minut_off(rfs.GET_relay(), rfs.GET_mod(), rfs.GET_hour_off() * MINUTES_IN_HOUR + rfs.GET_min_off()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::PIN_OFF) { smart_home.SET_off_relay(rfs.GET_relay()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::MOD_ON) { smart_home.SET_on_mod(rfs.GET_relay(), rfs.GET_mod()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::MOD_OFF) { smart_home.SET_off_mod(rfs.GET_relay(), rfs.GET_mod()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::MOD_T) { smart_home.SET_minut_on(rfs.GET_relay(), rfs.GET_mod(), rfs.GET_hour_on() * MINUTES_IN_HOUR + rfs.GET_min_on()); smart_home.SET_minut_off(rfs.GET_relay(), rfs.GET_mod(), rfs.GET_hour_off() * MINUTES_IN_HOUR + rfs.GET_min_off()); SmartHome_UART(); } else if (rfs.GET_Type() == RequestType::TIME) { rtc.setTime(0, rfs.GET_min_on(), rfs.GET_hour_on(), rfs.GET_day(), rfs.GET_month(), rfs.GET_year() + 2000); smart_home.SET_time(rtc.getTime()); SmartHome_UART(); } } } smart_home.SET_time(rtc.getTime()); delay(10); minutes = smart_home.GET_time().hour * 60 + smart_home.GET_time().minute; if (smart_home.Update(minutes)) { EEPROM.put(20, smart_home); } for (uint8_t z = 0; z < 3; ++z) { digitalWriteFast(smart_home.GET_pin(z), smart_home.GET_status_relay(z)); } } void SmartHome_UART() { smart_home.serialize(dataOut, MAX_BUF_out - 1); dataOut[MAX_BUF_out - 1] = calculate_checksum(dataOut, MAX_BUF_out - 1); Serial.write(dataOut, MAX_BUF_out); // Отправляем данные } void clearEEPROM() { for (uint8_t y = 0; y < EEPROM.length(); y++) { EEPROM.write(y, 0); // Записываем 0 в каждый адрес EEPROM } } bool receiveBytesFromUART() { // получение данных uint8_t byteCount = 0; if (Serial.available() > 0) { while (byteCount < MAX_BUF_in && Serial.available() > 0) { int bytesRead = Serial.readBytes(dataIn + byteCount, MAX_BUF_in - byteCount); byteCount += bytesRead; } if (byteCount == MAX_BUF_in) { if (verify_checksum(dataIn, MAX_BUF_in)) { return true; // Успешно получили и проверили данные } else { blinkError(); } } } return false; // Ошибка } void pinModeFast(uint8_t pin, uint8_t mode) { switch (mode) { case INPUT: if (pin < 8) { bitClear(DDRD, pin); bitClear(PORTD, pin); } else if (pin < 14) { bitClear(DDRB, (pin - 8)); bitClear(PORTB, (pin - 8)); } else if (pin < 20) { bitClear(DDRC, (pin - 14)); // Mode: INPUT bitClear(PORTC, (pin - 14)); // State: LOW } return; case OUTPUT: if (pin < 8) { bitSet(DDRD, pin); bitClear(PORTD, pin); } else if (pin < 14) { bitSet(DDRB, (pin - 8)); bitClear(PORTB, (pin - 8)); } else if (pin < 20) { bitSet(DDRC, (pin - 14)); // Mode: OUTPUT bitClear(PORTC, (pin - 14)); // State: LOW } return; case INPUT_PULLUP: if (pin < 8) { bitClear(DDRD, pin); bitSet(PORTD, pin); } else if (pin < 14) { bitClear(DDRB, (pin - 8)); bitSet(PORTB, (pin - 8)); } else if (pin < 20) { bitClear(DDRC, (pin - 14)); // Mode: OUTPUT bitSet(PORTC, (pin - 14)); // State: HIGH } return; } } void digitalWriteFast(uint8_t pin, bool x) { // раскомментируй, чтобы отключать таймер<br> /*switch (pin) { case 3: bitClear(TCCR2A, COM2B1); break; case 5: bitClear(TCCR0A, COM0B1); break; case 6: bitClear(TCCR0A, COM0A1); break; case 9: bitClear(TCCR1A, COM1A1); break; case 10: bitClear(TCCR1A, COM1B1); break; case 11: bitClear(TCCR2A, COM2A1); // PWM disable break; }*/ if (pin < 8) { bitWrite(PORTD, pin, x); } else if (pin < 14) { bitWrite(PORTB, (pin - 8), x); } else if (pin < 20) { bitWrite(PORTC, (pin - 14), x); // Set pin to HIGH / LOW } } uint8_t calculate_checksum(const uint8_t *data, uint8_t size) { uint8_t checksum = 0; for (size_t i = 0; i < size; ++i) { checksum ^= data[i]; // Используем XOR для контроля } return checksum; } bool verify_checksum(const uint8_t *data, uint8_t size) { if (size < 1) return false; // Если данных недостаточно, контрольная сумма недоступна uint8_t received_checksum = data[size - 1]; // Предполагаем, что последний байт — это контрольная сумма return received_checksum == calculate_checksum(data, size - 1); } // Функция для мигания светодиода void blinkError() { currentBlink = 0; // Сбрасываем счетчик миганий unsigned long currentMillis; // Цикл мигания (воспользуемся millis для ненадо блокирующих задержек) while (currentBlink < blinkCount) { currentMillis = millis(); // Проверяем, пришло ли время для мигания if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // Сохраняем текущее время ledState = !ledState; // Изменяем состояние светодиода digitalWrite(ledPin, ledState ? HIGH : LOW); // Включаем или выключаем светодиод // Увеличиваем счетчик миганий, когда светодиод был выключен (эквивалент обновления) if (ledState == LOW) { currentBlink++; } } } // После завершения мигания, гарантировать, что светодиод выключен digitalWrite(ledPin, LOW); }