Гибрид, "походные"часы с будильником иметеостанция.

Katapuf
Offline
Зарегистрирован: 16.05.2018

Здравия хорошим людям.

Выкладываю для тех, кто, так же как и я, недавно влип в эту "среду", среду разработки "Ардуино". Делал для себя, все работает, а то что, что-то, не по феншую, .... это к профессиональным программистам.

Гибрид, часы с будильником, метеостанция.

Задача для нее проработать от 1 до ... ну если повезет, в смысле мне со временем то до 3 недель.

Осенью на охоте, не лишним будет и будильник, и данные о температуре, давлении и влажности.

Компоненты:  

Arduino Pro Mini,  LCD экран 1602,  модуль часов I2C RTC DS1307,  датчик BME280, 4 кнопки, 1 выключатель, пассивный буззер + конденсатор электролит на 1 мкф, модуль зарядки с защитой от переразряда, на TP4056, аккумуляторы 18650, корпус.

Основа скетча, это скетч с сайта Амперка, Урок 19. RTC часы с будильником.

В изначальном виде, на 3 экранах, по очереди можно посмотреть, на 1- текущее время, на 2 - дата, на 3 будильник, листая все это удовольствие кнопкой " SET ".

А теперь мой вариант.

1 экран текущее время и дата.

2 экран температура и влажность.

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

4 экран будильник.

5 экран показания напряжения на аккумуляторе.

6  экран переход к автоматической смене экранов.

То есть после загрузки, экраны сами сменяются по очереди с интервалом 4 секунды.

Это достаточно, чтобы быстро ознакомится с информацией.

Так же по умолчанию подсветка экрана выключена.

Что бы включить есть кнопка " ILLUM "(подсветка).

Кратковременное нажатие включает подсветку на 40 секунд.  Достаточно для отображения всех экранов, два с лишним круга. Потом она сама отключается.

Если удерживать ее 2 и более секунд, включится постоянная подсветка, которую можно выключить кратковременным нажатием на эту же кнопку. Это сделано для удобства настройки часов и будильника. Чтобы подсветка не выключалась в не нужный момент.

Кнопки управления, кроме кнопки " ILLUM "(подсветка),  работают только тогда, когда включена подсветка экрана, а то мало ли кто, ткнет, собьет будильник и "утрянка" пропала.

Так же добавил к будильнику, не большое, но удобное дополнение, это сохранение настроек будильника, в  EEPROM, модуля часов. А то EEPROM есть, а он не используется, тогда его смысл?

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

Включить(завести) или отключить будильник можно на 4 экране, нажав кратковременно кнопки "UP" или "DOWN", которые используются для установки текущего времени и установки времени срабатывания будильника.

Когда будильник выключен, то 3 экрана по очереди, это 1,2 и 3 (смотри в начале описания), когда будильник включен(заведен), отображается 4 экрана, добавляется экран 4 с отображением установленного времени будильника и на 1 и на 4 экране появляются колокольчики.

 Остальные экраны можно увидеть если в ручном режиме с помощью кнопки " SET ", пролистать их. 

На 5 экране отображается реальное напряжение на аккумуляторе, на Pin A(0). С неплохой точностью. За что большая благодарность, вот правда не знаю кто конкретно написал эту функцию(измерение, сравнение, расчет на основе внутренних опорных напряжений ).

По умолчанию эта функция определяет напряжение на "VCC" но мой вариант с "дополнительным" Pin A(0), удобен, когда питание идет от сети и заряжается аккумулятор, можно узнать реальное напряжение аккумулятора, в любой момент.

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

Отключается так же любой кнопкой.

Переход к настройке времени, даты и будильника, выполняется удержанием в течении 2 чекунд кнопки " SET ", на нужном экране.

Перейдя на 6 экран, мы видим  "Smena ekrana AVTOMAT ", то есть, если остаться на этом экране, то начнется автоматическая смена экранов.

Вот вроде бы и все. А забыл, когда срабатывает будильник или сигнал о разряде аккумулятора, кроме звука, еще мигает LED.

Схема подключения , надеюсь понятна из скетча.

Скетч

Библиотеки

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Фото можете выложить результата?

yucan
Offline
Зарегистрирован: 20.04.2015

Скетч - Ничего не найдено...

Katapuf
Offline
Зарегистрирован: 16.05.2018

Вот эта ссылка работает. 

СКЕТЧ

b707
Онлайн
Зарегистрирован: 26.05.2017

Katapuf пишет:

Вот эта ссылка работает. 

СКЕТЧ

лучше прямо в ветку вставьте, нафига вы его в архив закатали, если там всего один файл?

Бегло посмотрел код - повторов много, а так явных ляпов не видно...

Katapuf
Offline
Зарегистрирован: 16.05.2018

b707 пишет:

лучше прямо в ветку вставьте, нафига вы его в архив закатали, если там всего один файл?

#include <Wire.h>                   // Подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>      // Подключаем библиотеку для работы с LCD дисплеем
#include <iarduino_RTC.h>           // Подключаем библиотеку для работы с RTC модулем
#include <Adafruit_BME280.h>        // Подключаем библиотеку для работы с BME280 модулем
#include <Eeprom24C32_64.h>         // Подключаем библиотеку для работы с внешней EEPROM
#define EEPROM_ADDRESS  0x50        // Указываем адрес внешней EEPROM
static Eeprom24C32_64 eeprom(EEPROM_ADDRESS);
LiquidCrystal_I2C lcd(0x26, 16, 2); // Объявляем  переменную для работы с LCD дисплеем, указываем параметры дисплея                                     (адрес I2C = 0x26, количество столбцов = 16, количество строк = 2) */
iarduino_RTC time(RTC_DS1307);      // Объявляем  переменную для работы с RTC модулем,  указываем название модуля
Adafruit_BME280 bme;                // Подключаем по I2C

const uint8_t Button_SET = 2;       // Pin кнопки SET
const uint8_t Button_UP = 3;        // Pin кнопки UP
const uint8_t Button_DOWN = 4;      // Pin кнопки DOWN
const uint8_t Button_ILLUM = 5;     // Pin кнопки ILLUM
const uint8_t Alarm_TONE = 6;       // Pin зуммера будильника
const uint8_t Alarm_LED = 7;        // Pin светодиода
uint8_t VAR_mode_SHOW = 1;          /* Режим вывода: 1- время и дата, 2 - температура и влажность, 3 - давление и высота,
                                       4 - время_будильника, 5 - аккумулятор, 6 - смена кранов */
uint8_t VAR_mode_SET = 0;           /* Режим установки: 0-нет, 1-сек, 2-мин, 3-час, 4-день, 5-мес, 6-год,
                                       7-день недели(не используется), 8-мин будильника, 9-час будильника */
uint8_t VAR_alarm_MIN = 0;          // Будильник минуты
uint8_t VAR_alarm_HOUR  = 0;        // Будильник часы
bool    VAR_alarm1_Status = true;   // Будильник включен/выключен
bool    VAR_alarm2_Status = false;  // Cигнал будильника
bool    VAR_alarm3_Status = false;  // Cигнал разряда аккумулятора

byte    MAS_alarm_SYM[8] = {B00000, B00100, B01110, B01110, B01110, B01111, B11111, B01000 }; // Символ будильника
byte    MAS_gradus_SYM[8] = {B01110, B01010, B01110, B00000, B00000, B00000, B00000, B00000}; // Символ градуса

unsigned long timing1;                  // Переменная для хранения точки отсчета смены экранов
unsigned long timing2;                  // Переменная для хранения точки отсчета опроса датчика BME280
unsigned long timing3;                  // Переменная для хранения точки отсчета автоматической подсветки
unsigned long timing4;                  // Переменная для хранения точки отсчета переключения на автоматическую смену экранов
unsigned long timing5;                  // Переменная для хранения точки отсчета опроса напряжения на Pin A(0)
unsigned long Vremy_Ekran = 4000;       // Переменная времени смены экранов
unsigned long Vremy_BME280 = 6000;      // Переменная времени опроса датчика BME280
unsigned long Vremy_Avto_Illum = 40000; // Переменная времени автоматической подсветки
unsigned long Vremy_Avto_Ekran = 10000; // Переменная времени переключения на автоматическую смену экранов
unsigned long Vremy_Voltage = 5000;     // Переменная времени опроса напряжения на Pin A(0)

int flag_Ekran = 0;                     // Флаг автоматической смены экранов
int flag_Illum_1 = 0;                   // Флаг постоянной подсветки экрана
int flag_Illum_2 = 0;                   // Флаг временной подсветки экрана
int flag_Arrum = 0;                     // Флаг cигнала разряда аккумулятора
int sec = 0;                            // Переменная для обнавления времени
int Alarm_MIN = 10;                     // Адрес в EEPROM куда записывается и откуда считываются минуты будильника
int Alarm_HOUR = 11;                    // Адрес в EEPROM куда записывается и откуда считываются часы будильника

float Temperatura = 0;                  // Переменная температура
float Vlajnost = 0;                     // Переменная влажность
float Davlenie = 0;                     // Переменная давление
float Vysota = 0;                       // Переменная высота над уровнем моря (врет даже с калибровкой)
float Voltage_Value_Vcc = 0;            // Переменная напряжение в милливольтах, получаемая из фунуции
float Voltage_Vcc = 0;                  // Переменная напряжение напряжения на Vcc, входе питания Ардуино
float Voltage_Value_Pin = 0;            // Переменная данных с аналогового Pin
float Voltage_Pin = 0;                  // Переменная напряжение на аналоговом Pin (до 5 вольт без делителя)

void setup()
{
  Serial.begin(9600);                   // Инициируем COM порт
  analogReference(DEFAULT);             // Настройка источника опорного напряжения по умолчанию
  time.begin();                         // Инициируем RTC модуль
  eeprom.initialize();                  // Инициируем EEPROM (в модуле часов)
  bme.begin();                          // Инициируем BME280 модуль
  lcd.begin();                          // Инициируем LCD дисплей
  lcd.noBacklight();                    // Выключаем подсветку LCD дисплея
  lcd.createChar(1, MAS_alarm_SYM);     // Загружаем символ будильника под номером 1
  lcd.createChar(2, MAS_gradus_SYM);    // Загружаем символ градуса под номером 2
  pinMode(Button_SET, INPUT);           // Объявляем Pin входом
  pinMode(Button_UP, INPUT);            // Объявляем Pin входом
  pinMode(Button_DOWN, INPUT);          // Объявляем Pin входом
  pinMode(Button_ILLUM, INPUT);         // Объявляем Pin входом
  pinMode(Alarm_TONE, OUTPUT);          // Объявляем Pin выходом
  pinMode(Alarm_LED, OUTPUT);           // Объявляем Pin выходом
  digitalWrite(Alarm_TONE, LOW);        // Устанавливаем по умолчанию на Pin Alarm_TONE низкий уровень(GND)
  digitalWrite(Alarm_LED, LOW);         // Устанавливаем по умолчанию на Pin Alarm_LED низкий уровень(GND)

  VAR_alarm_MIN = eeprom.readByte(Alarm_MIN);  // Считываем из EEPROM значение минут будильника
  VAR_alarm_HOUR = eeprom.readByte(Alarm_HOUR); // Считываем из EEPROM значение часов будильника
}

void loop()
{
  Func_LCD_ILLUM(); // Инициируем функцию подсветки LCD экрана

  Func_LCD();       // Инициируем функцию LCD экрана

  Func_Voltage();   // Инициируем функцию вольтметра
}

void Func_LCD() //Функция LCD экрана
{
  if (sec != time.seconds)                          // Если прошла секунда, то..
  {
    sec = time.seconds;                             // Каждую секунду...
    time.gettime();                                 // Обновляем время
    Serial.println(time.gettime("H:i:s"));          // Выводим COM порт текущее время (для отладки)
  }
  if (flag_Ekran == 0 && VAR_alarm1_Status == true) // Если флаг экран и равен 0 и будильник включен, то...
  {
    if (millis() - timing1 > Vremy_Ekran)           // Создаем точку отсчета задержки в 4 секунды
    {
      timing1 = millis();                           // Сбрасываем точку отсчета
      lcd.clear();                                  // Очищаем экран
      VAR_mode_SHOW++;                              // Меняем отображение экрана на следующий
      if (VAR_mode_SHOW > 4)                        // Если отобразилось 4 экрана, то..
      {
        VAR_mode_SHOW = 1;                          // Отображаем 1 экран
      }
    }
  }
  if (flag_Ekran == 0 && VAR_alarm1_Status == false) // Если флаг экран равен 0 и будильник выключен, то...
  {
    if (millis() - timing1 > Vremy_Ekran)            // Создаем точку отсчета задержки в 4 секунды
    {
      timing1 = millis();                            // Сбрасываем точку отсчета
      lcd.clear();                                   // Очищаем экран
      VAR_mode_SHOW++;                               // Меняем отображение экрана на следующий
      if (VAR_mode_SHOW > 3)                         // Если отобразилось 3 экрана, то..
      {
        VAR_mode_SHOW = 1;                           // Отображаем 1 экран
      }
    }
  }
  if (millis() - timing2 > Vremy_BME280)             // Создаем точку отсчета задержки в 6 секунды
  {
    timing2 = millis();                              // Сбрасываем точку отсчета
    Temperatura = bme.readTemperature();             // Обновляем переменную температура
    Vlajnost = bme.readHumidity();                   // Обновляем переменную влажность
    Davlenie  = bme.readPressure();                  // Обновляем переменную давление
    Vysota = bme.readAltitude(1031.55);              // Обновляем переменную высота над уровнем моря
  }
  if (VAR_mode_SET == 8 || VAR_mode_SET == 9)        // Если устанавливаются будильник, то...
  {
    lcd.setCursor(3, 0);                             // устанавливаем курсор в позицию: столбец 3, строка 0
    if (VAR_mode_SHOW == 4)                          // Если отображается экран 4, то...
    {
      lcd.print("Alarm set");                        // Выводим на экран установка будильника
    }
  }
  if (VAR_mode_SHOW == 1)                            // Если отображается 1 экран, то...
  {
    if (VAR_mode_SET == 0)                           // Если время, дата, будильник выводятся, а не устанавливаются, то...
    {
      lcd.setCursor(0, 0); lcd.print(VAR_alarm1_Status ? "\1" : " ");  // Выводим на экран значёк будильника, столбец 0, строка 0
      lcd.setCursor(15, 0); lcd.print(VAR_alarm1_Status ? "\1" : " "); // Выводим на экран значёк будильника, столбец 15, строка 0
    }
    lcd.setCursor(4, 0); lcd.print(time.gettime("H:i:s"));             // Выводим на экран время, столбец 4, строка 1
    lcd.setCursor(1, 1); lcd.print(time.gettime("d.m.Y M"));           // Выводим на экран дату, столбец 0, строка 1
  }
  if (VAR_mode_SHOW == 2)                                              // Если отображается экран 2, то...
  {
    time.gettime();                                                    // Обновляем время
    lcd.setCursor(0, 0); lcd.print("Temp");                            // Выводим на экран слово "Temp" (температура), столбец 0 строка 0
    lcd.setCursor(9, 0); lcd.print(Temperatura);                       // Вводим на экран данные с датчика, столбец 9 строка 0
    lcd.setCursor(14, 0); lcd.print("\2");                             // Выводим на экран символ градуса, столбец 14 строка 0
    lcd.setCursor(15, 0); lcd.print("C");                              // Выводим на экран слово "С" c 15 позиции 0 строки
    lcd.setCursor(0, 1); lcd.print("Vlajnost");                        // Выводим слово "Vlajnost" (влажность), столбец 0 строка 1
    lcd.setCursor(9, 1); lcd.print(Vlajnost);                          // Вводим на экран данные с датчика, столбец 9 строка 1
    lcd.setCursor(15, 1); lcd.print("%");                              // Выводим на экран символ "%", столбец 15 строка 1
  }
  if (VAR_mode_SHOW == 3)                                              // Если отображается 3 экран, то...
  {
    time.gettime();                                                    // Обновляем время
    lcd.setCursor(0, 0); lcd.print("Davl");                            // Выводим на экран слово "Davlenie" (давление), столбец 0 строка 0
    lcd.setCursor(7, 0); lcd.print(Davlenie / 133.3, 1);               // Вводим данные с датчика, столбец 7 строка 0
    lcd.setCursor(12, 0); lcd.print("mmrs");                           // Выводим на экран слово "mmrs" (миллиметры ртутного столба), столбец 12 строка 0
    lcd.setCursor(0, 1); lcd.print("Vysota");                          // Выводим на экран слово "Vysota" (высота), столбец 0 строка 1
    lcd.setCursor(7, 1); lcd.print(Vysota, 1);                         // Вводим на экран данные с датчика, столбец 7 строка 1
    lcd.setCursor(13, 1); lcd.print("mum");                            // Выводим на экран слово "mum" (метры над уровнем моря), столбец 13 строка 1
  }
  if (VAR_mode_SHOW == 4)                                              // Если отображается 4 экран, то...
  {
    if (VAR_mode_SET == 0)                                             // Если будильник выводятся, а не устанавливается
    {
      lcd.setCursor(0, 0); lcd.print(VAR_alarm1_Status ? "\1" : " ");  // Выводим на экран значёк будильника, столбец 0, строка 0
      lcd.setCursor(15, 0); lcd.print(VAR_alarm1_Status ? "\1" : " "); // Выводим на экран значёк будильника, столбец 15, строка 0
      lcd.setCursor(5, 0); lcd.print("Alarm");                         // Выводим на экран слово "Alarm" столбец 5, строка 0
    }
    lcd.setCursor(5, 1);                                               // Eстанавливаем курсор в позицию: столбец 5, строка 1
    time.gettime();                                                    // Обновляем значение переменной time.seconds
    if (VAR_mode_SET == 9 && time.seconds % 2)                         // Если настраивается значение "часы" будильника и time.seconds кратное 2, то...
    {
      lcd.print("  ");                                                 /* Выводим на экран "  " (два пробела на месте вывода "часов" будильника,
                                                                          тоесть мигаем настраиваемым параметром)*/
    }
    else
    {
      if (VAR_alarm_HOUR < 10)                                         // Если значение "часов" будильника, меньше 10, то...
      {
        lcd.print("0");                                                // Выводим на экран "0"
      }
      lcd.print(VAR_alarm_HOUR);                                       // Выводим на экран значение "часов" будильника
    }
    lcd.print(":");                                                    // Выводим на экран символ ":"
    if (VAR_mode_SET == 8 && time.seconds % 2)                         // Если настраивается значение "минуты" будильника и time.seconds кратное 2, то...
    {
      lcd.print("  ");                                                 /* Выводим на экран "  " (два пробела на месте вывода "минут" будильника,
                                                                          тоесть мигаем настраиваемым параметром)*/
    }
    else
    {
      if (VAR_alarm_MIN < 10)                                          // Если значение "минут" будильника, меньше 10, то...
      {
        lcd.print("0");                                                // Выводим на экран "0"
      }
      lcd.print(VAR_alarm_MIN);                                        // Выводим на экран значение "часов" будильника
    }
  }
  if (VAR_mode_SHOW == 5)                                              // Если отображается 5 экран, то...
  {
    time.gettime();                                                    // Обновляем время
    lcd.setCursor(2, 0); lcd.print("Akkumulyator");                    // Выводим на экран слово "Akkumulyator"(аккумулятор), столбец 2, строка 0
    lcd.setCursor(3, 1); lcd.print(Voltage_Pin, 3);                    // Выводим на экран данные с датчика, столбец 3 строка 1
    lcd.setCursor(9, 1); lcd.print("Volt");                            // Выводим на экран слово "Volt"(вольт), столбец 9, строка 1
  }
  if (VAR_mode_SHOW == 6)                                              // Если отображается 6 экран, то...
  {
    time.gettime();                                                    // Обновляем время
    lcd.setCursor(2, 0); lcd.print("Smena ekrana");                    // Выводим слово "Smena ekrana" (смена экрана), столбец 2, строка 0
    lcd.setCursor(4, 1); lcd.print("AVTOMAT");                         // Выводим символ "AVTOMAT" (автомат), столбец 4, строка 1

    if (millis() - timing4 > Vremy_Avto_Ekran)                         // Создаем точку отсчета задержки в 10 секунд
    {
      timing4 = millis();                                              // Сбрасываем точку отсчета
      flag_Ekran = 0;                                                  // Обнуляем флаг экран
    }
  }
  delay(1);                                                            // Приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
  //  проверка будильника
  if (VAR_alarm1_Status)                                               // Если будильник включён, то...
  {
    if (time.seconds == 00)                                            // Если в текущем времени секунды равны 0, то...
    {
      if (time.minutes == VAR_alarm_MIN)                               // Если в текущем времени минуты совпали с заданными, то...
      {
        if (time.Hours == VAR_alarm_HOUR)                              // Если в текущем времени часы совпали с заданными, то...
        {
          VAR_alarm2_Status = true;                                    // Состояние флага сигнал будильника становится "правда" (1)
        }
      }
    }
  }
  else
  {
    VAR_alarm2_Status = false;                                         //  Состояние флага сигнал будильника становится "ложь" (0)
  }
  if (VAR_alarm2_Status)                                               // Если состояние флага сигнал будильника становится "правда" (1)
  {
    Func_alarm_action();                                               // Инициируем функцию сигнал будильника
  }
  Func_buttons_control();                                              // Инициируем функцию управления кнопками
}

void Func_buttons_control() // Функция управления кнопками
{
  if (flag_Illum_1 == 1 || flag_Illum_2 == 1) // Если флаг подсветки экрана 1 равен 1 или флаг подсветки экрана 2 равен 1, то...
  {
    uint8_t i = 0;                            // Вводим переменную i
    time.blinktime(VAR_mode_SET);             // Мигаем устанавливаемым параметром

    if (VAR_mode_SET)                         // Если часы находятся в режиме установки даты/времени
    {
      if (digitalRead(Button_UP))             // Если нажата кнопка UP, то...
      {
        while (digitalRead(Button_UP))        // Ждём пока не отпустим кнопку UP
        {
          delay(50);                          // Ждем 50 миллисекунд
        }
        if (VAR_alarm2_Status)                // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;          // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)                // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;          // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                     // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          switch (VAR_mode_SET)               // Инкремент (увеличение) устанавливаемого значения
          {
          /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
          /* мин */ case 2: time.settime(-1, (time.minutes == 59 ? 0 : time.minutes + 1), -1, -1, -1, -1, -1); break;
          /* час */ case 3: time.settime(-1, -1, (time.Hours == 23 ? 0 : time.Hours + 1),     -1, -1, -1, -1); break;
          /* дни */ case 4: time.settime(-1, -1, -1, (time.day == 31 ? 1 : time.day + 1),         -1, -1, -1); break;
          /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month == 12 ? 1 : time.month + 1),     -1, -1); break;
          /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year == 99 ? 0 : time.year + 1),       -1); break;
          /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday == 6 ? 0 : time.weekday + 1) ); break;
          /* м.б.*/ case 8: VAR_alarm_MIN = VAR_alarm_MIN == 59 ? 0 : VAR_alarm_MIN + 1;                      break;
          /* ч.б.*/ case 9: VAR_alarm_HOUR = VAR_alarm_HOUR == 23 ? 0 : VAR_alarm_HOUR + 1;                      break;
          }
        }
      }
      if (digitalRead(Button_DOWN))      // Если нажата кнопка DOWN, то...
      {
        while (digitalRead(Button_DOWN)) // Ждём пока не отпустим кнопку DOWN
        {
          delay(50);                     // Ждем 50 миллисекунд
        }
        if (VAR_alarm2_Status)           // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;     // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)           // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;     // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          switch (VAR_mode_SET)          // Декремент (уменьшение) устанавливаемого значения
          {
          /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
          /* мин */ case 2: time.settime(-1, (time.minutes == 0 ? 59 : time.minutes - 1), -1, -1, -1, -1, -1); break;
          /* час */ case 3: time.settime(-1, -1, (time.Hours == 0 ? 23 : time.Hours - 1),     -1, -1, -1, -1); break;
          /* дни */ case 4: time.settime(-1, -1, -1, (time.day == 1 ? 31 : time.day - 1),         -1, -1, -1); break;
          /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month == 1 ? 12 : time.month - 1),     -1, -1); break;
          /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year == 0 ? 99 : time.year - 1),       -1); break;
          /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday == 0 ? 6 : time.weekday - 1) ); break;
          /* м.б.*/ case 8: VAR_alarm_MIN = VAR_alarm_MIN == 0 ? 59 : VAR_alarm_MIN - 1;                      break;
          /* ч.б.*/ case 9: VAR_alarm_HOUR = VAR_alarm_HOUR == 0 ? 23 : VAR_alarm_HOUR - 1;                      break;
          }
        }
      }
      if (digitalRead(Button_SET))                      // Если нажата кнопка SET, то...
      {
        flag_Ekran = 1;                                 // Флаг смены экрана становится равен 1
        while (digitalRead(Button_SET))                 // Ждём пока не отпустим кнопку SET
        {
          delay(10);                                    // Ждем 10 миллисекунд
          if (i < 200)                                  // Если i меньше 200, то...
          {
            i++;                                        // Переменную i увеличиваем на 1, фиксируем, как долго удерживается кнопка SET
          }
          else                                          // Если дольше 2 секунд, то...
          {
            lcd.clear();                                // Очищаем экран
          }
        }
        if (VAR_alarm2_Status)                          // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;                    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)                          // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;                    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                               // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          if (i < 200)                                  // Если i меньше 200, то кнопка SET удерживалась меньше 2 секунд, то...
          {
            VAR_mode_SET++;                             // Переходим к следующему устанавливаемому параметру
            if (VAR_mode_SHOW == 1 && VAR_mode_SET > 6) // Если отображается 1 экран и устанавливается "год", то...
            {
              VAR_mode_SET = 1;                         // Переходим к устанавливаемому параметру "секунды"
            }
            if (VAR_mode_SHOW == 4 && VAR_mode_SET > 9) // Если отображается 4 экран и устанавливаются "часы" будильника, то...
            {
              VAR_mode_SET = 8;                         // Переходим к устанавливаемому параметру "минуты" будильника
            }
          }
          else                                          // Если кнопка SET удерживалась дольше 2 секунд, то...
          {
            VAR_mode_SET = 0;                           // Выходим из режима установки даты/времени
            eeprom.writeByte(Alarm_MIN, VAR_alarm_MIN); // Сохраняем в EEPROM, данные минут будильника
            delay(50);                                  // Ждем 50 миллисекунд (для успешной записи)
            eeprom.writeByte(Alarm_HOUR, VAR_alarm_HOUR); // Сохраняем в EEPROM, данные часов будильника
            delay(50);                                  // Ждем 50 миллисекунд (для успешной записи)
          }
        }
      }
    }
    else                                                // Если часы находятся в режиме вывода даты/времени
    {
      if (digitalRead(Button_UP))                       // Если нажата кнопка UP, то...
      {
        while (digitalRead(Button_UP))                  // Ждём пока не отпустим кнопку UP
        {
          delay(50);                                    // Ждем 50 миллисекунд
        }
        if (VAR_alarm2_Status)                          // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;                    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)                          // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;                    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                               // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          if (VAR_mode_SHOW == 4)                       // Если отображается 4 экран, то...
          {
            VAR_alarm1_Status = VAR_alarm1_Status ? 0 : 1;  // Включаем или выключаем будильник
          }
        }
      }
      if (digitalRead(Button_DOWN))                     // Если нажата кнопка DOWN, то...
      {
        while (digitalRead(Button_DOWN))                // Ждём пока не отпустим кнопку DOWN
        {
          delay(50);                                    // Ждем 50 миллисекунд
        }
        if (VAR_alarm2_Status)                          // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;                    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)                          // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;                    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                               // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          if (VAR_mode_SHOW == 4)                       // Если отображается 4 экран, то...
          {
            VAR_alarm1_Status = VAR_alarm1_Status ? 0 : 1;  // Включаем или выключаем будильник
          }
        }
      }
      if (digitalRead(Button_SET))                      // Если нажата кнопка SET, то...
      {
        flag_Ekran = 1;                                 // Флаг смены экрана становится равен 1
        while (digitalRead(Button_SET))                 // Ждём пока не отпустим кнопку SET
        {
          delay(10);                                    // Ждем 10 миллисекунд
          if (i < 200)                                  // Если i меньше 200, то...
          {
            i++;                                        // Переменную i увеличиваем на 1, фиксируем, как долго удерживается кнопка SET
          }
          else                                          // Если дольше 2 секунд, то...
          {
            lcd.clear();                                // Очищаем экран
          }
        }
        if (VAR_alarm2_Status)                          // Если включен сигнал будильника, то...
        {
          VAR_alarm2_Status = false;                    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
        }
        if (VAR_alarm3_Status)                          // Если сработал cигнал разряда аккумулятора, то...
        {
          VAR_alarm3_Status = false;                    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
          flag_Arrum = 1;                               // Флаг cигнала разряда аккумулятора становится равен 1
        }
        else
        {
          if (i < 200)                                  // Если i меньше 200, то кнопка SET удерживалась меньше 2 секунд, то...
          {
            lcd.clear();                                // Очищаем экран
            VAR_mode_SHOW++;                            // Меняем отображение экрана на следующий
            if (VAR_mode_SHOW > 6)                      // Если отображался 5 экран, то...
            {
              VAR_mode_SHOW = 1;                        // Отображаем 1 экран
            }
          }
          else                                          // Если кнопка SET удерживалась дольше 2 секунд, то переходим в режим установки даты/времени
          {
            if (VAR_mode_SHOW == 1)                     // Если отображается 1 экран, то...
            {
              VAR_mode_SET = 1;                         // Устанавливаемый параметр - секунды
            }
            if (VAR_mode_SHOW == 4)                     // Если отображается 4 экран, то...
            {
              VAR_mode_SET = 8;                         // Устанавливаемый параметр - минуты будильника
            }
          }
        }
      }
    }
  }
}

void Func_LCD_ILLUM() // Функция подсветки LCD экрана
{
  uint8_t a = 0;                              // Вводим переменную "a"

  if (flag_Illum_1 == 0 && flag_Illum_2 == 0) // Если флаг подсветки LCD экрана 1 равен 0 и флаг подсветки LCD экрана 2 равен 0, то...
  {
    lcd.noBacklight();                        // Выключаем подсветку LCD экрана
  }
  else                                        // Во всех других случаях...
  {
    lcd.backlight();                          // Включаем подсветку LCD дисплея
  }

  if (digitalRead(Button_ILLUM) && (flag_Illum_1 == 0 || flag_Illum_2 == 0)) /*  Если нажата кнопка ILLUM и
                                                                                 флаг подсветки LCD экрана 1 равен 0 или                                                                                 флаг подсветки LCD экрана 2 равен 0, то...*/
  {
    while (digitalRead(Button_ILLUM)) // Ждём когда отпустим кнопку ILLUM
    {
      delay(10);                      // Ждем 10 миллисекунд
      if (a < 200)                    // Если переменная а меньше 200, то...
      {
        a++;                          // Переменную а увеличиваем на 1, фиксируем, как долго удерживается кнопка
      }
      else                            // Если больше 2 секунд, то...
      {
        lcd.clear();                  // Очищаем экран
        flag_Illum_1 = 1;             // Флаг подсветки LCD экрана 1 становится равен 1
      }
      if (VAR_alarm2_Status)          // Если включен сигнал будильника, то...
      {
        VAR_alarm2_Status = false;    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
      }
      if (VAR_alarm3_Status)          // Если сработал cигнал разряда аккумулятора, то...
      {
        VAR_alarm3_Status = false;    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
        flag_Arrum = 1;               // Флаг cигнала разряда аккумулятора становится равен 1
      }

      if (a < 200)                    // Если переменная а меньше 200, кнопка ILLUM удерживалась меньше 2 секунд, то...
      {
        flag_Illum_2 = 1;             // Флаг подсветки LCD экрана 2 становится равен 1
      }
    }
  }
  if (digitalRead(Button_ILLUM))      //Если нажата кнопка ILLUM , то...
  {
    while (digitalRead(Button_ILLUM)) // Ждём когда отпустим кнопку ILLUM
    {
      delay(50);                      // Ждем 10 миллисекунд
      if (VAR_alarm2_Status)          // Если включен сигнал будильника, то...
      {
        VAR_alarm2_Status = false;    // Выключаем его, переводим состояние флага сигнал будильника в "ложь" (0)
      }
      if (VAR_alarm3_Status)          // Если сработал cигнал разряда аккумулятора, то...
      {
        VAR_alarm3_Status = false;    // Выключаем его, переводим состояние флага cигнал разряда аккумулятора в "ложь" (0)
        flag_Arrum = 1;               // Флаг cигнала разряда аккумулятора становится равен 1
      }
      else                            // Или
      {
        flag_Illum_1 = 0;             // Флаг подсветки LCD экрана 1 становится равен 0
        flag_Illum_2 = 0;             // Флаг подсветки LCD экрана 2 становится равен 0
      }
    }
  }

  if (flag_Illum_2 == 1 && flag_Illum_1 == 0) // Если флаг подсветки LCD экрана 1 равен 1 или флаг подсветки LCD экрана 2 равен 0, то...
  {
    if (millis() - timing3 > Vremy_Avto_Illum)// Создаем точку отсчета задержки в 40 секунд
    {
      timing3 = millis();                     // Сбрасываем точку отсчета
      flag_Illum_2 = 0;                       // Флаг подсветки LCD экрана 2 становится равен 0
    }
  }
}

void Func_Voltage() // Функция вольтметра
{
  if (millis() - timing5 > Vremy_Voltage)                 // Создаем точку отсчета задержки в 2,5 секунды
  {
    timing5 = millis();                                   // Сбрасываем точку отсчета

    Voltage_Value_Vcc = Read_Voltage_Vcc();               /* Присуаиваем переменной значение получаемое из функции
                                                             в милливольтах и изменяем тип данных на float
                                                             (переменная с плпвающей точкой)*/

    Voltage_Vcc = Voltage_Value_Vcc / 1000;               // Присваиваем переменной значение в вольтах
    Voltage_Value_Pin = float (analogRead(A0));           // Присуаиваем переменной значение получаемое с аналогового Pin
    Voltage_Pin = Voltage_Value_Pin * Voltage_Vcc / 1024; /* Присваиваем переменной значение в вольтах
                                                             (в вычисление подставляем значение Voltage_Vcc, полученные
                                                              с помощью функции "long readVcc())"  */
    if (Voltage_Pin <= 3 && flag_Arrum == 0)              // Если напряжение на Pin А0 меньше или равно 3, то...
    {
      VAR_alarm3_Status = true;                           // Флаг сигнал разряда аккумулятора переводим в состояние "правда" (1)
    }
    else                                                  // В других случаях...
    {
      VAR_alarm3_Status = false;                          // Сигнал разряда аккумулятора переводим в состояние "ложь" (0)
    }
    if (VAR_alarm3_Status == true)                        // Если флаг сигнал разряда аккумулятора  в состоянии "правда" (1), то...
    {
      Func_Akkumulytor_tone();                            // Инициируем функцию сигнал разряда аккумулятора
    }
    if (Voltage_Pin > 3)                                  // Если напряжение на Pin А0 больше 3, то...
    {
      flag_Arrum = 0;                                     // Обнуляем Флаг cигнала разряда аккумулятора
    }
    /* 
        // Для отладки
     	Serial.println("Напряжение на Vcc Ардуино:  ");
        Serial.println(Voltage_Vcc, 3);
        Serial.println("Напряжение на Pin A0:  ");
        Serial.println(Voltage_Pin, 3);
        Serial.println("");
    */
  }
}

void Func_alarm_action() // Функция сигнал будильника
{

  flag_Illum_2 = 1;                                                   /* Флаг подсветки LCD экрана 2 становится равен 0
                                                                        (пока проигрывается сигнал будильника, экран буден включен)*/
  digitalWrite(Alarm_LED, HIGH);                                      // Включаем LED
  tone(Alarm_TONE, 2780); delay(100); noTone(Alarm_TONE); delay(100); // Проигрываем сигнал будильника
  tone(Alarm_TONE, 2780); delay(100); noTone(Alarm_TONE); delay(100); // Проигрываем сигнал будильника
  tone(Alarm_TONE, 2780); delay(100); noTone(Alarm_TONE);             // Проигрываем сигнал будильника
  digitalWrite(Alarm_LED, LOW);                                       // Выключаем LED
}

void Func_Akkumulytor_tone() // Функция сигнал разряда аккумулятора
{

  flag_Illum_2 = 1;                                                   /* Флаг подсветки LCD экрана 2 становится равен 0
                                                                        (пока проигрывается сигнал разряда аккумулятора,экран буден включен)*/
  digitalWrite(Alarm_LED, HIGH);                                      // Включаем LED
  tone(Alarm_TONE, 2780); delay(100); noTone(Alarm_TONE); delay(100); // Проигрываем сигнал
  tone(Alarm_TONE, 2000); delay(100); noTone(Alarm_TONE); delay(100); // Проигрываем сигнал
  tone(Alarm_TONE, 2900); delay(100); noTone(Alarm_TONE);             // Проигрываем сигнал
  digitalWrite(Alarm_LED, LOW);                                       // Выключаем LED
}

long Read_Voltage_Vcc() // Функция расчета и определения напряжения на Vcc Arduino
{
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

  delay(75); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both

  long result = (high << 8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

 

 

Katapuf
Offline
Зарегистрирован: 16.05.2018

Здравия. "b707". Выложил код на "станицу". Если не трудно, указать где повторы.