Объявление

США начнут предпринимать меры экономического и военного характера, если Россия не прекратит нарушать Договор о ракетах средней и меньшей дальности (ДРСМД)

Решение главы Национального Объединения "Новая Россия - Великая Россия" Rommstaina: http://russianew.ru/viewtopic.php?f=120&t=4039

Часы, будильник, таймер, метеостанция с реле на Arduino

Правила форума
Внимание! Любой спам на нашем форуме запрещён!
Коммерческая реклама сайтов, ссылки, спам запрещены. Так же запрещены ссылки на сайты в профилях новичков.
Бан без предупреждений.

Часы, будильник, таймер, метеостанция с реле на Arduino

Сообщение admin » 22 дек 2016, 23:47

Изображение

Сегодня соберем часы с использованием модуля реального времени. А чтобы усложнить задачу сделаем из них будильник и прикрутим релейный модуль ну, например, для включения света в ванной или чайника. А если ты начинающий техноманьяк , то не лишним будет датчик температуры и влажности. Получится некая метеостанция управляющая чайником или таймер который пригодится если нужно автоматически кормить рыбок, переворачивать яйца в инкубаторе или зажигать ёлку на новый год.

Спецификация набора

CR1225, Элемент питания литиевый (1шт) 3В
Troyka-Temperature Humidity Sensor DHT11, Цифровой датчик температуры и влажности
0.96inch OLED (A), OLED дисплей с разрешением 128х64px, интерфейсы SPI/I2C
Joystick, 3D-джойстик
Пьезодинамик 4кГц 80дБ
Релейный модуль на основе RTD14005 10А/250В (7А/30В)
Часы реального времени на оcнове DS1307
Программируемый контроллер на базе ATmega328 (аналог Arduino Mini)

0.96inch OLED - это встраиваемый двухцветный (желтый/синий) OLED дисплей с интерфейсом I2C/SPI. Разрешение экрана 128х64 пикселей, а угол обзора более 160 градусов.
Размеры платы 29мм х 33 мм.

Arduino Mini — полноценная Arduino-платформа, только маленькая: всего 33×20 мм.

Обратите внимание, что на плате нет собственного USB-порта.
Поэтому для её прошивки понадобится посредник!
Им может быть другой контроллер Arduino

Характеристики Arduino Mini
— Микроконтроллер: ATmega328
— Тактовая частота: 16 МГц
— Флеш-память: 32 КБ (2 КБ используются загрузчиком)
— Оперативная память SRAM: 2 КБ
— Энергонезависимая память EEPROM: 1 КБ
— Рабочее напряжение: 5 В
— Входное напряжение: 5,3–12 В
— Портов ввода-вывода общего назначения: 20
— Портов с поддержкой ШИМ: 6
— Портов, подключённых к АЦП: 8 (4 из них на нераспаянных выводах)
— Разрядность АЦП: 10 бит
— Аппаратные интерфейсы: UART, SPI, I²C (на нераспаянных выводах)
— Максимальный ток одного вывода: 40 мА
— Максимальный ток с пина +5V: 150 мА

Цифровой датчик температуры и влажности DHT11
Данные температуры и влажности датчик отдаёт по одному проводу в виде цифрового сигнала. Это позволяет передавать данные на расстояние до нескольких десятков метров.
В сердце модуля — популярная среди любителей сенсорная сборка DHT11. Он работает по собственному протоколу. На борту модуля — популярная среди любителей сенсорная сборка DHT11.

Характеристики
— Напряжение питания: 3–5 В
— Потребляемый ток при запросе данных: 2,5 мА
— Потребляемый ток в ожидании: 100 мкА
— Диапазон температур: 0–50 °С
— Погрешность температуры: ±2 °С
— Диапазон влажности: 20–90%
— Погрешность влажности: ±5%
— Габариты: 25×25 мм

Joystick - сделает управление нашим устройством быстрым и удобным.
Модуль-джойстик схож с «грибочком» на манипуляторах PlayStation и XBox. Он комбинирует в себе двухосный джойстик и тактовую кнопку. В нейтральном положении аналоговый сигнал соответствует половине напряжения питания. При перемещении джойстика в одну сторону напряжение будет нарастать, а при движении джойстика в другую сторону — падать. Таким образом, можно получать точное положение ручки джойстика и реагировать на угол наклона, а не только на сам факт наклона ручки. Хотя в этом проекте мы используем только факт наклона.

Характеристики
— Напряжение питания: 3–5 В
— Интерфейс по осям X, Y: аналоговый, линейный
— Интерфейс кнопки: цифровой, бинарный
— Габариты: 25×25 мм

Управление джойстиком

Нажатие влево - вход в меню настроек
изменяемое значение подсвечивается
нажатие вверх - изменение значения
нажатие вправо - переход к следующему значению
при настройки будильника слева появляется значок "а"
нажатие влево - выход из меню с сохранением изменений
время будильника сохраняется в энергонезависимой памяти.
Нажатие вниз - вкл/откл будильника.
Когда сработал будильник
первое нажатие на кнопку - отключение пищалки
второе нажатие на кнопку - отключение реле.

Пьезодинамик

Характеристики
— Номинальная частота: 4 кГц
— Интенсивность: 80 дБ
— Номинальное рабочее напряжение: 5 В
— Габариты: 25,4×25,4 мм

Релейный модуль

Модуль Relay это просто механический рубильник, которым можно управлять при помощи микроконтроллера, такого как Arduino. С помощью реле можно включать и выключать электроприборы, которые подключены к бытовой электросети 220 В. На модуле расположен светодиод, который всегда подскажет — замкнуто реле или нет.
У этого реле есть есть не только нормально разомкнутый (NO) контакт, но и нормально замкнутый (NC). Это удобно.

Характеристики
— Номинальное напряжение питания: 5 В
— Номинальное напряжение сигнала: 3–5 В
— Максимальный ток коммутации: 10 А
— Коммутируемое переменное напряжение (пиковое): 250 В
— Потребляемый ток: 87 мА
— Рабочая температура: −40…+85 °C
— Магнитная система катушки: моностабильная
— Рекомендованная частота переключения: до 1 Гц
— Электрическая износостойкость (NO) контакта: 30×10³ переключений
— Электрическая износостойкость (NC) контакта: 10×10³ переключений
— Габариты: 50,8×25,4 мм

Часы реального времени Модуль RTC - сделан на основе популярного чипа DS1307. Он общается с управляющей электроникой по протоколу I²C / TWI.
Слот предназначен для часовой батарейки размера CR1225 на 3В. Без неё модуль не работает даже с внешним питанием.

Характеристики
Напряжение внешнего питания: 4,5–5,5 В
Напряжение питания батарейки: 2–3,5 В
Потребляемый ток: 500 нА (≈6 месяцев на батарейке)
Выходной интерфейс: I²C
Габариты: 25,4×25,4 мм

Элемент питания

CR1225 – литиевая батарейка

Характеристики
— Напряжение: 3В
— Типоразмер cr1225

Технические параметры нашей конструкции: Индикация Дата, месяц, часы, минуты, температура, влажность
Точность времени, секунд/сутки 2
Диапазон температур 0–50 °С
Погрешность температуры ±2 °С
Диапазон влажности 20–90%
Погрешность влажности ±5%
Максимальный ток коммутации 10 А
Коммутируемое переменное напряжение (пиковое) 250 В
Номинальное напряжение питания 5 В

Электрическая схема
Изображение

Скетч программы

Код: выделить все
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include <PinChangeInt.h>
#include <EEPROM.h>
#include "clock.h"
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <TroykaDHT11.h>
#include <TimerOne.h>
#include <Tone.h>


volatile boolean JoyStickZPressFlag = false;
byte AlarmHour = 7;
byte AlarmMinute = 0;
boolean AlarmFlag;
boolean AlarmSetFlag;
volatile boolean UpdateScreenFlag = false;
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
DHT11 dht(TEMP_SEN_PIN);
Tone Buzzer;


void setup()
{
  digitalWrite(JOYSTICK_Z_PIN, HIGH);
  PCintPort::attachInterrupt(JOYSTICK_Z_PIN, &JOYSTICK_Z_PIN_ISR, FALLING);

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  //pinMode(BUZZER_PIN, OUTPUT);
  //digitalWrite(BUZZER_PIN, LOW);
  Buzzer.begin(BUZZER_PIN);

  AlarmHour = EEPROM.read(ALARM_HOUR_ADR);
  if (AlarmHour > 23)
    AlarmHour = 7;

  AlarmMinute = EEPROM.read(ALARM_MINT_ADR);
  if (AlarmMinute > 59)
    AlarmMinute = 0;

  AlarmFlag = EEPROM.read(ALARM_FLAG_ADR);
  if (AlarmFlag > 1)
    AlarmFlag = ALARM_FLAG_DEFAULT;
   

  Wire.begin();
  tmElements_t CurTime;
  RTC.read(CurTime);
 
  dht.begin();
 
  display.begin(SSD1306_SWITCHCAPVCC);
  UpdateScreenFlag = true;

  //период обновления экрана по прерыванию таймера
  Timer1.initialize(8000000);
  Timer1.attachInterrupt(TimerOne_ISR);
}
//---------------------------------
void loop()
{   
  static tmElements_t CurrentTime;

  if (UpdateScreenFlag) //если обновление экрана
  {
    RTC.read(CurrentTime); //чтение времени с RTC
    display.clearDisplay(); //очистка дисплея
    UpdateTime(&CurrentTime); //обновление времени
    UpdateDate(&CurrentTime); //обновление даты
    UpdateTemp(); //обновление показаний температуры и влажности
    if (AlarmFlag) //если включен будильник
    {//отображение символа "а"
      display.setTextSize(ALARM_SIZE);
      display.setCursor(ALARM_HOR_POS, ALARM_VER_POS);
      display.print("a");
    }
   
    display.display(); //отображение на дисплее обновленной информации

    if (AlarmFlag) //если включен будильник
      CheckAlarm(&CurrentTime); //проверка времени

    UpdateScreenFlag = false; //стирание флага обновления экрана
  }

  switch(ScanJoyStick()) //проверка нажатия джойстивка
  {
    case JOYSTICK_LEFT_: //если влево
      ChangeSettings(); //меню настроек
    break;

    case JOYSTICK_DOWN_: //если вниз
      ChangeAlarmState(&CurrentTime); //вкл/откл будильник
    break;

    default:
    break;
  }
   
  if ((JoyStickZPressFlag) && (digitalRead(RELAY_PIN))) //если нажата кнопка джойстика
  {
    delay(100);
    if (!digitalRead(JOYSTICK_Z_PIN))
    {
      static byte JoyStickZPressCnt = 0;
     
      if (JoyStickZPressCnt == 0) //если первое нажатие
      {
        //digitalWrite(BUZZER_PIN, LOW);
        Buzzer.stop(); //выключение пищалки
        JoyStickZPressCnt++;
      }
      else if (JoyStickZPressCnt == 1) //если второе нажатие
      {
        digitalWrite(RELAY_PIN, LOW); //выключение реле
        JoyStickZPressCnt = 0;
      }
     
      JoyStickZPressFlag = false; //стирание флага нажатия кнопки джойстика
    }
  }
}
//---------------------------------
void UpdateTime(tmElements_t* TimeVal)
{
  display.setTextColor(WHITE); //установка неинверсного отображения
  display.setTextSize(TIME_SIZE); //установка размера текста
  display.setCursor(HOUR_HOR_POS, HOUR_VER_POS); //установка курсора
  //вывод времени
  if (TimeVal->Hour < 10)
    display.print("0");
  display.print(TimeVal->Hour);
  display.print(":");

  if (TimeVal->Minute < 10)
    display.print("0");
  display.print(TimeVal->Minute);
}
//---------------------------------
void UpdateDate(tmElements_t* TimeVal)
{
  display.setTextColor(WHITE);
  display.setTextSize(TEMP_SIZE);
  display.setCursor(DATE_HOR_POS, DATE_VER_POS);
 //вывод даты
  if (TimeVal->Day < 10)
    display.print("0");
  display.print(TimeVal->Day);
  display.print("/");

  if (TimeVal->Month < 10)
    display.print("0");
  display.print(TimeVal->Month);
}
//---------------------------------
void UpdateTemp()
{
  display.setTextColor(WHITE);
  display.setTextSize(TEMP_SIZE);
  display.setCursor(TEMP_HOR_POS, TEMP_VER_POS);
 
  if (dht.read() == DHT_OK) //если чтение данных без ошибок
  { //вывод температуры и влажности
    display.print("t ");
    display.print(dht.getTemperatureC());
    display.print("C");
    display.print("  h ");
    display.print(dht.getHumidity());
    display.print("%");
  }

  else //иначе
  { //вывод надписи "Chip & Dip"
    display.print("Chip & Dip");
  }
}
//---------------------------------
void CheckAlarm(tmElements_t* TimeVal)
{ //если будильник не включен и совпадение времени будильника с текущим временем
  if ((!AlarmSetFlag) && (TimeVal->Hour == AlarmHour) && (TimeVal->Minute == AlarmMinute))
  {
    digitalWrite(RELAY_PIN, HIGH); //включение реле
    //digitalWrite(BUZZER_PIN, HIGH);
    Buzzer.play(NOTE_A3); //включение пищалки
    AlarmSetFlag = true; //установка флага включения будильника
  }
  //иначе
  else if ((AlarmSetFlag) && ((TimeVal->Hour != AlarmHour) || (TimeVal->Minute != AlarmMinute)))
    AlarmSetFlag = false; //стирание флага включения будильника
}
//---------------------------------
void ChangeSettings()
{
    tmElements_t tm;
    RTC.read(tm);
   
    byte TimeParts[6] = {tm.Hour, tm.Minute, AlarmHour, AlarmMinute, tm.Day, tm.Month};
    byte TimeMAXVals[6] = {23, 59, 23, 59, 31, 12};
    byte CurTimePart = 0;
    boolean ExitSetUp = false;

    //отображение начального экрана настроек:
    //значение часов отображается инверсно
    display.clearDisplay();
    UpdateTemp();
    UpdateDate(&tm);
    display.setTextSize(TIME_SIZE);
    display.setCursor(HOUR_HOR_POS, HOUR_VER_POS);
    display.setTextColor(BLACK, WHITE); //инверсное отображение

    if (TimeParts[0] < 10)
      display.print("0");
    display.print(TimeParts[0]);

    display.setTextColor(WHITE);
    display.print(":");

    if (TimeParts[1] < 10)
      display.print("0");
    display.print(TimeParts[1]);
   
    display.display();

    delay(500);

    //цикл меню настроек
    while (!ExitSetUp)
    {
      delay(150);
     
      switch(ScanJoyStick()) //проверка нажатия джойстивка
      {
        case JOYSTICK_UP_: //если вверх
        { //изменение значения на один
          TimeParts[CurTimePart]++;
          if (TimeParts[CurTimePart] > TimeMAXVals[CurTimePart])
          {
            TimeParts[CurTimePart] = 0;

            if (CurTimePart > 3)
              TimeParts[CurTimePart] = 1;
          }
        }
        break;

        case JOYSTICK_RIGHT_: //если вправо
        { //переход к следующему значению
          CurTimePart++;
          if (CurTimePart > 5)
            CurTimePart = 0;
        }
        break;
       
        case JOYSTICK_LEFT_: //если влево
          ExitSetUp = true; //выход из меню
        break;
      }
      //отображение на экране
      //изменяемое значение отображается инверсно
      //при настройке будильника отображается символ "а"
      //изменяемое значение определяет переменная CurTimePart:
      //CurTimePart = 0 - часы времени
      //CurTimePart = 1 - минуты времени
      //CurTimePart = 2 - часы будильника
      //CurTimePart = 3 - минуты будильника
      //CurTimePart = 4 - день
      //CurTimePart = 5 - месяц, см. определение массива TimeParts[]
      display.clearDisplay();
     
      if (CurTimePart <= 3)
      {
        UpdateTemp();
        display.setCursor(DATE_HOR_POS, DATE_VER_POS);
        if (TimeParts[4] < 10)
            display.print("0");
        display.print(TimeParts[4]);
        display.print("/");
        if (TimeParts[5] < 10)
          display.print("0");
        display.print(TimeParts[5]);
        display.setTextSize(TIME_SIZE);
        display.setCursor(HOUR_HOR_POS, HOUR_VER_POS);
     
        if ((CurTimePart%2) == 0)
        {
          display.setTextColor(BLACK, WHITE); //инверсное отображение
          if (TimeParts[CurTimePart] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart]);

          display.setTextColor(WHITE);
          display.print(":");

          if (TimeParts[CurTimePart + 1] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart + 1]);
        }

        else
        {
          if (TimeParts[CurTimePart - 1] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart - 1]);
          display.print(":");
          display.setTextColor(BLACK, WHITE); //инверсное отображение
          if (TimeParts[CurTimePart] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart]);
        }
      }

      else
      {
        display.setTextColor(WHITE);
        display.setTextSize(TIME_SIZE);
        display.setCursor(HOUR_HOR_POS, HOUR_VER_POS);
        if (TimeParts[2] < 10)
          display.print("0");
        display.print(TimeParts[2]);
        display.print(":");
        if (TimeParts[3] < 10)
          display.print("0");
        display.print(TimeParts[3]);
        UpdateTemp();

        display.setCursor(DATE_HOR_POS, DATE_VER_POS);

        if (CurTimePart == 4)
        {
          display.setTextColor(BLACK, WHITE); //инверсное отображение
          if (TimeParts[CurTimePart] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart]);

          display.setTextColor(WHITE);
          display.print("/");
          if (TimeParts[CurTimePart + 1] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart + 1]);
        }

        else
        {
          if (TimeParts[CurTimePart - 1] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart - 1]);
          display.print("/");
          display.setTextColor(BLACK, WHITE); //инверсное отображение
          if (TimeParts[CurTimePart] < 10)
            display.print("0");
          display.print(TimeParts[CurTimePart]);
        }
      }

      if (CurTimePart > 1)
      {
        display.setTextColor(WHITE);
        display.setTextSize(ALARM_SIZE);
        display.setCursor(ALARM_HOR_POS, ALARM_VER_POS);
        display.print("a");
      }

      display.display();
    }

    //будильник
    AlarmHour = TimeParts[2];
    AlarmMinute = TimeParts[3];
    //запись в память
    EEPROM.write(ALARM_HOUR_ADR, AlarmHour);
    EEPROM.write(ALARM_MINT_ADR, AlarmMinute);
   
    //установка времени в RTC
    tm.Second = 0;   
    tm.Minute = TimeParts[1];
    tm.Hour = TimeParts[0];
    tm.Day = TimeParts[4];
    tm.Month = TimeParts[5];
    tm.Year = 16;
    RTC.write(tm);

  UpdateScreenFlag = true; //установка флага обновления экрана
  delay(500);
}
//---------------------------------
void ChangeAlarmState(tmElements_t* TimeVal)
{
  display.clearDisplay();
 
  if (!AlarmFlag) //если будильник выключен
  {
    AlarmFlag = true; //установка флага включения будильника
    //отображение символа "а"
    display.setTextSize(ALARM_SIZE);
    display.setCursor(ALARM_HOR_POS, ALARM_VER_POS);
    display.print("a");
  }

  else //иначе
  {
    AlarmFlag = false; //стирание флага включения будильника
  }

  EEPROM.write(ALARM_FLAG_ADR, AlarmFlag); //запись состояния будильника в память

  UpdateTemp();
  UpdateDate(TimeVal);
  UpdateTime(TimeVal);
  display.display();

  delay(500);
}
//---------------------------------
byte ScanJoyStick()
{
  byte Direction = JOYSTICK_RELEASED;
  unsigned int X_Val = analogRead(JOYSTICK_X_PIN);
  unsigned int Y_Val = analogRead(JOYSTICK_Y_PIN);
 
  if ((Y_Val >= 900) && (X_Val >= 400))
  {
    Direction = JOYSTICK_UP_;
  }
  else if ((Y_Val <= 400) && (X_Val >= 400))
  {
    Direction = JOYSTICK_DOWN_;
  }
  else if ((Y_Val >= 400) && (X_Val >= 900))
   {
    Direction = JOYSTICK_RIGHT_;
   }
  else if ((Y_Val >= 400) && (X_Val <= 400))
  {
    Direction = JOYSTICK_LEFT_;
  }
 
  return Direction;
}
//---------------------------------
void JOYSTICK_Z_PIN_ISR()
{
  JoyStickZPressFlag = true; //установка флага нажатия кнопки джойстика
}
//---------------------------------
void TimerOne_ISR()
{
  UpdateScreenFlag = true; //установка флага обновления экрана
}


Техническая документация:

Relay Module http://lib.chipdip.ru/165/DOC001165590.pdf
Arduino Mini http://lib.chipdip.ru/176/DOC001176746.pdf
Часы реального времени http://lib.chipdip.ru/423/DOC001423693.pdf
dht11 http://lib.chipdip.ru/426/DOC001426894.pdf
Joystick -Подключение и настройка http://lib.chipdip.ru/484/DOC001484478.pdf
0.96inch-OLED-UserManual http://lib.chipdip.ru/490/DOC001490735.pdf

Библиотеки:

TroykaDHT11-master http://lib.chipdip.ru/495/DOC001495147.zip
Adafruit_SSD1306-master http://lib.chipdip.ru/495/DOC001495440.zip
Adafruit-GFX-Library-master http://lib.chipdip.ru/495/DOC001495442.zip
Arduino-Library-Tone http://lib.chipdip.ru/495/DOC001495443.zip
DS1307RTC http://lib.chipdip.ru/495/DOC001495444.zip
PinChangeInt http://lib.chipdip.ru/495/DOC001495445.zip
Time http://lib.chipdip.ru/495/DOC001495446.zip
TimerOne-r11 http://lib.chipdip.ru/495/DOC001495447.zip
clock http://lib.chipdip.ru/546/DOC001546960.zip

Описание проекта:
http://www.chipdip.ru/product0/9000318627/
admin
Администратор
 
Сообщений: 79
Зарегистрирован: 27 ноя 2016, 18:21
ТегиЧасы, будильник, таймер, метеостанция с реле на Arduino

Вернуться в Для новичков. Азы.

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron
/