Часы на ардуино своими руками

Programming

Once we connect the module we need to program the Arduino Board to work with the Real Time Clock. However, when it comes to programing a communication between Arduino and an I2C module the code isn’t that small and easy. Luckily, there are already several libraries for the DS3231 RTC which can be found on the internet.

For this tutorial I chose to use the Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com.

So once we download and install the library we can use its first demo example to initially activate the clock of the RTC module. In the setup section of the demo example code we can notice that there are three line that we need to uncomment in order to initially set the day of the week, the time and the data.

// Code from the Demo Example of the DS3231 Library

void setup()
{
  // Setup Serial connection
  Serial.begin(115200);
  // Uncomment the next line if you are using an Arduino Leonardo
  //while (!Serial) {}
  
  // Initialize the rtc object
  rtc.begin();
  
  // The following lines can be uncommented to set the date and time
  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
}

The first line is for setting the day of the week, the second line is for setting the time in hours, minutes and seconds, and the third line is for setting the date in days, months and years.

Once we upload this code we need to comment back the three lines and re-upload the code again.

// Code from the Demo Example of the DS3231 Library

void loop()
{
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.println(rtc.getTimeStr());
  
  // Wait one second before repeating
  delay (1000);
}

If we take a look at the loop section of the code we can see that now using the three custom functions we get the information from the RTC and print them in the Serial Monitor. Here’s how they appear in the Serial Monitor.

Now even if we disconnect the Arduino power and then reconnect it and run the Serial Monitor again we can notice that the time keeps going without being reset.

So now we have our Real Time Clock up and running and we can use in any Arduino Project. As a second example I connected an LCD to the Arduino and printed the time and the date on it.

Here’s the source code of this example:

/*
* Arduino DS3231 Real Time Clock Module Tutorial
*
* Crated by Dejan Nedelkovski,
* www.HowToMechatronics.com
*
* DS3231 Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com.
*
*/
#include <DS3231.h>
#include <LiquidCrystal.h> // includes the LiquidCrystal Library 

DS3231  rtc(SDA, SCL);
LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7) 

void setup() { 
 rtc.begin(); // Initialize the rtc object
 lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } 
}

void loop() { 
 lcd.setCursor(0,0);
 lcd.print("Time:  ");
 lcd.print(rtc.getTimeStr());
 
 lcd.setCursor(0,1);
 lcd.print("Date: ");
 lcd.print(rtc.getDateStr());
 
 delay(1000); 
}

That’s all for this Arduino Tutorial, feel free to ask any question in the comments section below.

Как считывать и рассчитывать время в бинарных часах

Я думаю вы знакомы с бинарными (двоичными) числами, которые включают в себя 0 и 1. Используя эти две цифры, мы можем показывать время, также мы можем конвертировать двоичные числа в десятичные. Используя числа 8 4 2 1 (написанные на нашей печатной плате (см. рисунок) справа), мы можем конвертировать двоичные числа в десятичные.

К примеру, двоичное число 1010 – это десятичное 10. Как это можно определить? Начинаем с самого значимого разряда, он у нас крайний слева в числе 1010 и он равен 1, следовательно нужно умножить 1 на 8. Потом следующий разряд нужно умножить на 4 (он у нас 0, поэтому к сумме ничего не добавляется), затем следующий разряд нужно умножить на 2 (он у нас 1) и крайний справа разряд нужно умножить на 1 и потом все это сложить.

Итого получаем:

А если в расширенном варианте (по всем правилам):

Теперь, если мы увидим следующую картину на наших часах, мы можем легко перевести ее в привычное время.

Как указывалось выше, у нас 6 столбцов и 4 строки светодиодов. Каждые два столбца используются, соответственно, для отображения часов (HH), минут (MM) и секунд (SS). На правой стороне печатной платы мы видим цифры 1, 2, 4 и 8, которые облегчают нам перевод двоичного числа в десятичное.

Теперь рассмотрим как правильно считать время на наших бинарных часах, показанное на предыдущем рисунке. Мы видим, что в первом столбце у нас нет горящих светодиодов, это означает:

В следующем столбце мы видим один горящий светодиод в первой строке, следовательно, в соответствии с цифрами 8 4 2 1 имеем:

То есть число часов (HH), равно 1.

В первом столбце для минут (MM ) мы видим один горящий светодиод в первой строке:

То есть получаем 10 минут потому что этот столбец обозначает десятки минут.

Во втором столбце для минут (MM) мы видим один светодиод, горящий в строке напротив цифры 8, следовательно, имеем:

Таким образом, в сумме мы получили 18 минут.

В первом столбце для секунд (SS) мы видим один горящий светодиод в строке напротив цифры 4, следовательно, получаем:

Во втором столбце для секунд (SS) мы видим два горящих светодиода в строках напротив цифр 4 и 1, следовательно, получаем:

Таким образом, мы получили в сумме 45 секунд.

В итоге мы получили время 01:18:45.

Compact Alarm with Card Reader and RTC

With this alarm, you can tell whenever someone enters your house which can be turned on and off with a card reader and also automatically activated with the RTC!

What do you need?

  • Arduino Uno Rev3 / Seeeduino V4.2 ($6.90)
  • Bread board Clear – 8.2 x 5.3cm
  • LED (Generic)
  • Resistor 221 ohm
  • Grove – Ultrasonic Distance Sensor
  • Grove – Buzzer
  • Grove – RTC
  • RC522 Card Reader

Interested? You can check out the full tutorial by Simonee Adobs on Arduino Project Hub here!

OLED RTC Clock

With an RTC module, you can of course also make your OLED digital clock with the Arduino which shows the date, time and day!

What do you need

  • Arduino Uno Rev3 / Seeeduino V4.2 ($6.90) or Arduino Nano v3 / Seeeduino Nano 
  • Grove – RTC
  • Grove – OLED Display 1.12” V2
  • 2 x Grove – Button
  • 32.768KHz crystal oscillator
  • 2 x 10K ohm resistor
  • 3V coin cell battery

Interested? You can find the full tutorial on Simple Projects!

Задержки

Простейшей с точки зрения использования функцией времени является задержка, их у нас две:

  • delay(time) – “Приостанавливает” выполнение кода на time миллисекунд. Дальше функции delay выполнение кода не идёт, за исключением прерываний. Использовать рекомендуется только в самых крайних или тех случаях, когда delay не влияет на скорость работы устройства. time принимает тип данных unsigned long и может приостановить выполнение на срок от 1 мс до

50 суток (4 294 967 295 миллисекунд) с разрешением в 1 миллисекунду. Работает на системном таймере Timer 0delayMicroseconds(time) – Аналог delay(), приостанавливает выполнение кода на time микросекунд. time принимает тип данных unsigned long и может приостановить выполнение на срок от 4 мкс до

70 минут (4 294 967 295 микросекунд) с разрешением 4 микросекунды. Работает на системном таймере Timer 0

Задержки использовать очень просто:

И вот мы можем делать какое-то действие два раза в секунду. А что делать, если нам нужно выполнять одно действие два раза в секунду, а другое – три? А третье – 10 раз в секунду например. Сразу привыкаем к той мысли, что задержки лучше вообще не использовать в реальном коде. Разве что delayMicroseconds, он бывает нужен для генерации каких-то протоколов связи. Нормальным инструментом для тайм-менеджмента своего кода являются функции, которые считают время со старта МК.

Элементы платы

Микросхема DS1307

Микросхема, занимающаяся подсчетом времени. Связь с микросхемой происходит по протоколу I2C. Её I2C-адрес 0b1101000.

Кварцевый резонатор

Для точной работы часов используется кварцевый резонатор на частоте 32768 Гц. Та же частота используется в кварцевых часах. Такая частота обеспечивает 215 циклов в секунду, что очень удобно для простых двоичных счётчиков

Гнездо для батарейки

Батарейка CR1225 обеспечивает работу часов реального времени при выключенном питании. Без батарейки модуль не может работать, даже если подключено внешнее питание.

Контакты подключения 3-проводных шлейфов

Контакты питания:

  • Земля (G) — чёрный провод. Соедините с пином Arduino.
  • Питание (V) — красный провод. Соедините с пином Arduino.
  • Не используется.

Контакты шины I²C:

  • Сигнальный (D) — Подключите к пину Arduino.
  • Сигнальный (С) — Подключите к пину Arduino.
  • Не используется.

Принципы работы устройства

GPS модуль передает данные в NMEA формате, пример этих данных можно посмотреть на рисунке ниже. NMEA формат состоит из нескольких строк (предложений), из которых нам нужно будет извлечь только время и дату. Эти данные содержатся в строке $GPRMC, которая содержит время, дату, координаты и другую полезную информацию. Длина строки $GPRMC составляет примерно 70 символов. Мы уже рассматривали пример извлечения нужных нам GPS данных из строки $GPGGA в проекте определения местоположения автомобиля, здесь же мы будем извлекать данные из строки $GPRMC.

Строка $GPRMC, в основном, содержит скорость, время, дату и местоположение:

$GPRMC,123519.000,A, 7791.0381,N, 06727.4434,E,022.4,084.4,230394,003.1,W*6A

$GPRMC,HHMMSS.SSS,A,latitude,N,longitude,E,speed,angle,date,MV,W,CMD

В следующей таблице представлен перевод (описание) данных GPS из строки $GPRMC.

Идентификатор Описание
RMC Recommended Minimum sentence C
HHMMSS.SSS Время в формате: час минута секунда и миллисекунда
A Статус // A=active (активный) and V= void (пустой, недействительный)
Latitude Широта (координата)
N Направление: N=North (север), S=South (юг)
Longitude Долгота (координата)
E Направление: E= East (восток), W=West (запад)
Speed Скорость в узлах (1 узел= 1,87 км в час)
Angle Угол места в градусах
Date Временная отметка (дата в UTC, Universal Time Coordinated — всеобщее скоординированное время)
MV Магнитное возмущение
W Direction of variation E/W (направление изменения E/W)
CMD (*6A) Данные контрольной суммы

В большинстве случаев эта строка ($GPRMC) используется для извлечения данных времени, даты и скорости.

Мы можем извлечь время и дату из строки $GPRMC при помощи подсчета запятых в этой строке. Таким образом, с помощью Arduino мы будем находить в GPS данных строку $GPRMC и сохранять ее в массиве, в котором время (в 24-часовом формате) может быть найдено после одной запятой, а дата – после 9 запятых. Время и дата потом сохраняются в соответствующих строках.

GPS спутники передают время и дату в формате UTC (Universal Time Coordinated — всеобщее скоординированное время), поэтому мы должны конвертировать его в местное время. В нашем проекте мы добавили к этому времени 5:30 чтобы получить время, соответствующее времени в Индии, вы для своего региона можете легко узнать соответствующую поправку.

Схема проекта

Схема часов на Arduino и 4-х разрядном семисегментном индикаторе представлена на следующем рисунке.

В следующей таблице представлены необходимые соединения между модулем часов реального времени и платой Arduino Uno.

DS3231 Arduino Uno
VCC 5V
GND GND
SDA A4
SCL A5

В следующей таблице представлены необходимые соединения между регистром сдвига 74HC595 и платой Arduino Uno.

Регистр сдвига 74HC595 Arduino Uno
11-SH_CP (SRCLK) 6
12-ST_CP (RCLK) 5
14-DS (Data) 4
13-OE(Latch) GND
8-GND GND
10-MR(SRCLR) +5V
16-VCC +5V

В следующей таблице представлены необходимые соединения между регистром сдвига 74HC595, 4-х разрядным семисегментным дисплей и платой Arduino Uno.

4-х разрядный семисегментный дисплей Регистр сдвига 74HC595 Arduino Uno
A Q0
B Q1
C Q2
D Q3
E Q4
F Q5
G Q6
D1 10
D2 11
D3 12
D4 9

Внешний вид собранной конструкции проекта показан на следующем рисунке.

Enumerations

SQWAVE_FREQS_t

Symbolic names used with the squareWave() function (described below).

  • SQWAVE_NONE
  • SQWAVE_1_HZ
  • SQWAVE_1024_HZ
  • SQWAVE_4096_HZ
  • SQWAVE_8192_HZ
  • ALM1_EVERY_SECOND — causes an alarm once per second.
  • ALM1_MATCH_SECONDS — causes an alarm when the seconds match (i.e. once per minute).
  • ALM1_MATCH_MINUTES — causes an alarm when the minutes and seconds match.
  • ALM1_MATCH_HOURS — causes an alarm when the hours and minutes and seconds match.
  • ALM1_MATCH_DATE — causes an alarm when the date of the month and hours and minutes and seconds match.
  • ALM1_MATCH_DAY — causes an alarm when the day of the week and hours and minutes and seconds match.
  • ALM2_EVERY_MINUTE — causes an alarm once per minute.
  • ALM2_MATCH_MINUTES — causes an alarm when the minutes match (i.e. once per hour).
  • ALM2_MATCH_HOURS — causes an alarm when the hours and minutes match.
  • ALM2_MATCH_DATE — causes an alarm when the date of the month and hours and minutes match.
  • ALM2_MATCH_DAY — causes an alarm when the day of the week and hours and minutes match.

What is an RTC (Real Time Clock), why do we need RTC for Arduino microcontroller?

An RTC (real-time clock) refers to a clock that tracks the current time and can be used to program actions at a specific time.

Arduino and almost all microcontrollers have built-in timers, they can run as long as there is power. However, once the power is turned off (either manually or due to a power failure), all timers will be reset to 0.

It is acceptable to use the internal timer for timing for simple projects if you don’t mind when the timer resets to zero once there is no power. But for projects such as data loggers, clocks, alarms, which requires the timer to run independently of the external power supply, you need to use an RTC.

Almost all RTC are low-current built-in ICs and able to run on a single lithium battery for many years. Currently, RTC based on the DS1307 real-time clock is one of the most popular RTC modules.

Часы без RTC

Для начала мы должны понимать, что такое RTC. Из Википедии:

Часы реального времени (ЧРВ, RTC — англ. Real Time Clock) — электронная схема, предназначенная для учёта хронометрических данных (текущее время, дата, день недели и др.), представляет собой систему из автономного источника питания и учитывающего устройства. Чаще всего часы реального времени встречаются в вычислительных машинах, хотя на самом деле ЧРВ присутствуют практически во всех электронных устройствах, которые должны хранить время.

В итоге в данной версии мы сделаем часы без RTC с индикатором температуры и влажности на Arduino с помощью модуля DHT11. Также мы используем 3 кнопки для установки часов.

Комплектующие

Вам понадобятся эти кусочки для этого проекта:

  • Arduino Uno плата
  • Кнопки 3 шт.
  • Потенциометр
  • Модуль LCD 1602
  • Модуль температуры и влажности DHT11
  • Макетная плата
  • Перемычки

Соедините комплектующие часов как на схеме ниже.

Код

Вы можете скопировать или скачать код часов на Ардуино ниже.

#include <LiquidCrystal.h>
#include <SimpleDHT.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
volatile int sec, minute = 0, hour = 0;
int b_h = 5;
int b_m = 6;
int pinDHT11 = 2;
int b_startstop = 3;
bool startstop = false;

SimpleDHT11 dht11;

void setup() {

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  lcd.setCursor(0, 0);
  lcd.print("Ahmad Ordikhani");
  lcd.setCursor(0, 1);
  lcd.print("Clk without RTC");
  delay(3000);
  lcd.clear();

  pinMode(b_h, INPUT_PULLUP);
  pinMode(b_m, INPUT_PULLUP);
  pinMode(b_startstop, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(3), buttons, FALLING);
}

void loop() {

  //Setting the time will stop the clock to set the time
  while (startstop == false)
  {
    lcd.setCursor(0, 1);
    lcd.print("SET");
    delay(100);
    lcd.setCursor(0, 0);
    lcd.print("Time: ");
    if(hour<10)
    {
    lcd.print("0");
    lcd.print(hour);
    }
    else
    lcd.print(hour);
    
    lcd.print(":");
    if(minute<10)
    {
      lcd.print("0");
    lcd.print(minute);
    }
    else
    lcd.print(minute);
    lcd.print(":");
    if(sec<10)
    {
    lcd.print("0");  
    lcd.print(sec);
    }
    else
    lcd.print(sec);
    lcd.print(" ");

    if (digitalRead(b_h) == LOW)
    {
      hour++;
      if (hour > 23)
        hour = 0;
    }

    if (digitalRead(b_m) == LOW)
    {
      minute++;
      if (minute > 59)
        minute = 0;
    }

  }

  //Start the clock
  while (startstop == true)
  {


    // noInterrupts();
    // read with raw sample data.
    byte temperature = 0;
    byte humidity = 0;
    byte data = {0};
    if (dht11.read(pinDHT11, &temperature, &humidity, data)) {
      lcd.setCursor(0, 1);
      lcd.print("Read DHT11 failed");
      return;
    }
    lcd.setCursor(0, 1);
    lcd.print("Temp:");
    lcd.print((int)temperature);
    //lcd.print("*C");
    lcd.print(" ");
    lcd.print("Hum.:");
    lcd.print((int)humidity);
    lcd.print("%");
    //Serial.print((int)temperature); Serial.print(" *C, ");
    // Serial.print((int)humidity); Serial.println(" %");

    lcd.setCursor(0, 0);
    //sec=millis()/1000;
    delay(1000);
    lcd.print("Time: ");
    if (hour < 10)
    {
      lcd.print("0");
      lcd.print(hour);
    }
    else
    {
      lcd.print(hour);
    }
    lcd.print(":");
    if (minute < 10)
    {
      lcd.print("0");
      lcd.print(minute);
    }
    else
    {
      lcd.print(minute);

    } lcd.print(":");
    if (sec < 10)
    {
      lcd.print("0");
      lcd.print(sec);
    }
    else
    {
      lcd.print(sec);
    }
    lcd.print(" ");
    //lcd.print(startstop);
    sec++;
    if (sec > 59)
    {
      minute++;
      sec = 0;
      //lcd.clear();
    }

    if (minute > 59)
    {
      hour++;
      minute = 0;
      //lcd.clear();
    }
    if (hour > 23)
    {
      hour = 0;
      //lcd.clear();

    }
  }
}

//Start/Stop the clock
void buttons()
{
  lcd.clear();
  startstop = !startstop;
}

На этом пока всё. Мы постарались описать все основные варианты реализации часов на Ардуино.

Скачать популярные библиотеки Arduino IDE на русском

Пользовательские библиотеки создаются разработчиками модулей и плат расширений для Ардуино. Большинство популярных библиотек Ардуино скачать можно на сайте GitHub. Это сервис для совместной разработки IT-проектов, где можно отследить историю изменений исходного кода. Чтобы пройти уроки Ардуино для начинающих, все необходимые для занятий библиотеки Arduino UNO можно скачать здесь:

Список пользовательских библиотек Arduino:

TroykaCurrent — перевод аналоговых значений в Амперы (скачать TroykaCurrent.h)

RotaryEncoder — работа с модулем энкодера (скачать RotaryEncoder.h)

Adafruit NeoPixel — работа с адресной лентой (скачать Adafruit_NeoPixel.h)

Fast LED — работа с адресной лентой ws2812b (скачать FastLED.h)

TroykaMQ — работа с датчиками газа MQ (скачать TroykaMQ.h)

MQ-2 sensor — работа с датчиком газа MQ2 (скачать MQ2.h)

LCD 1602 I2C — библиотека для дисплея 1602 I2C (скачать LiquidCrystal_I2C.h)

LCD 1602 I2C RUS — русификация дисплея 1602 I2C (скачать LCD_1602_RUS.h)

OLED I2C — библиотека для OLED дисплея (русифицированная) (скачать OLED_I2C.h)

SFE_BMP180 — библиотека для датчика давления BMP180 (скачать SFE_BMP180.h)

SD.h — библиотека для работы с sd картой памяти (скачать SD.h)

Alarm functions

The DS3232 and DS3231 have two alarms. Alarm1 can be set to seconds precision; Alarm2 can only be set to minutes precision.

setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate)

Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This function can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). When setting Alarm 2, the seconds value must be supplied but is ignored, recommend using zero. (Alarm 2 has no seconds register.)

alarmType: A value from the ALARM_TYPES_t enumeration, above. (ALARM_TYPES_t)seconds: The seconds value to set the alarm to. (byte)minutes: The minutes value to set the alarm to. (byte)hours: The hours value to set the alarm to. (byte)dayOrDate: The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. (byte)

None.

Example
//Set Alarm1 for 12:34:56 on Sunday
RTC.setAlarm(ALM1_MATCH_DAY, 56, 34, 12, dowSunday);

setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate)

Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This functiuon can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). However, when using this function to set Alarm 1, the seconds value is set to zero. (Alarm 2 has no seconds register.)

alarmType: A value from the ALARM_TYPES_t enumeration, above. (ALARM_TYPES_t)minutes: The minutes value to set the alarm to. (byte)hours: The hours value to set the alarm to. (byte)dayOrDate: The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. (byte)

None.

Example
//Set Alarm2 for 12:34 on the 4th day of the month
RTC.setAlarm(ALM2_MATCH_DATE, 34, 12, 4);

alarmInterrupt(byte alarmNumber, bool alarmEnabled)

Enable or disable an alarm «interrupt». Note that this «interrupt» just causes the RTC’s INT pin to be asserted. To use this signal as an actual interrupt to (for example) a microcontroller, the RTC «interrupt» pin needs to be connected to the microcontroller and the microcontroller application firmware must properly configure the interrupt and also provide for handling it.

alarmNumber: The number of the alarm to enable or disable, ALARM_1 or ALARM_2 (byte)alarmEnabled: true or false (bool)

None.

Example
RTC.alarmInterrupt(ALARM_1, true);      //assert the INT pin when Alarm1 occurs.
RTC.alarmInterrupt(ALARM_2, false);     //disable Alarm2

alarm(byte alarmNumber)

Tests whether an alarm has been triggered. If the alarm was triggered, returns true and resets the alarm flag in the RTC, else returns false.

Value of the alarm flag bit (bool)

Example
if ( RTC.alarm(ALARM_1) ) {		//has Alarm1 triggered?
	//yes, act on the alarm
}
else {
	//no alarm
}

checkAlarm(byte alarmNumber)

Tests whether an alarm has been triggered. If the alarm was triggered, returns true, else returns false. The alarm flag is not reset.

Value of the alarm flag bit (bool)

Example
if ( RTC.checkAlarm(ALARM_1) ) {		//has Alarm1 triggered?
	//yes, act on the alarm
}
else {
	//no alarm
}
Example
if ( RTC.checkAlarm(ALARM_1) ) {		//has Alarm1 triggered?
    //yes, act on the alarm
	RTC.clearAlarm(ALARM_1);           //clear the alarm flag
}
else {
	//no alarm
}

Часы на Ардуино на основе ЖК-дисплея и часов реального времени

Цель первого урока показать, как сделать простые часы на основе Arduino с использованием ЖК-дисплея и часов реального времени.

Комплектующие

Для первого урока этого большого руководства нам понадобятся следующие комплектующие для наших часов на Ардуино:

  • Arduino UNO и Genuino UNO
  • PCF8563 (часы реального времени)
  • Кристалл 32 кГц
  • 10К потенциометры
  • Резистор 10k 1/4w
  • Резистор 220 Ом
  • LCD 16×2
  • Макет с набором проводов

В этом уроке будут использованы ЖК-дисплей и часы реального времени. Если вы хотите знать больше теме взаимодействия Arduino и  ЖК-дисплеев — изучите уроки, которые мы публиковали ранее на нашем сайте.

Схема соединения

Схема очень проста. PCF8563 связывается с Arduino с помощью TWI, и когда данные принимаются, ЖК-дисплей обновляется, показывая новое время.

Установка даты и времени

Чтобы установить дату и время, используйте следующий скетч:

/* Демонстрация установки времени Rtc_Pcf8563. 
 * Установите часы на время затем зациклите время чтения 
 * и выведите дату и время на последовательную консоль.
 *
 * Использовали RBBB с Arduino IDE, распиновка 
 * немного отличается. Поменяйте на свои hw
 * SCK - A5, SDA - A4, INT - D3/INT1
 *
 * После загрузки и запуска скетча используйте последовательный монитор
 * для просмотра часов.
 * 
 * настройка:  смотрите тех. спецификацию Pcf8563.
 *         1x 10 КОм на Pin3 INT
 *         Нет соединений на Pin5 или Pin6 (используем внутренние устройства I2C)
 *         1x 0.1pf на питание
 *         1x 32khz кристал
 *
 */ 
 
#include <Wire.h>
#include <Rtc_Pcf8563.h>
 
//инициализировать часы реального времени
Rtc_Pcf8563 rtc;
 
void setup()
{
  //очистить регистры
  rtc.initClock();
  //установка начального времени.
  //день, неделя, месяц, век(1=1900, 0=2000), year(0-99)
  rtc.setDate(14, 6, 3, 1, 10);
  //часы, минуты, секунды
  rtc.setTime(1, 15, 0);
}
 
void loop()
{
  //обе функции форматирования вызывают внутренний метод getTime(), 
  //поэтому форматированные строки соответствуют текущем времени/дате.
  Serial.print(rtc.formatTime());
  Serial.print("\r\n");
  Serial.print(rtc.formatDate());
  Serial.print("\r\n");
  delay(1000);
} 

Код проекта

Теперь вы сможете использовать свои часы, загрузив этот скетч на Arduino:

#include <Wire.h>
#include <Rtc_Pcf8563.h>
// include the RTC library 
#include <LiquidCrystal.h>

//init the real time clock
Rtc_Pcf8563 rtc;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  lcd.print(" Arduino Clock!");
  while(1500 - millis() > 0);
  pinMode(13, OUTPUT);
}

void loop() {
  lcd.setCursor(0, 0);
  lcd.print("Date: ");
  lcd.print(rtc.formatDate());
  
  lcd.setCursor(0, 1);
  lcd.print("Time: ");
  lcd.print(rtc.formatTime());
}

Общие сведения об OLED дисплеях

OLED означает “Organic Light emitting diode“, что переводится как органический светоизлучающий диод, или, более коротко – органический светодиод. OLED дисплеи для радиолюбителей изготавливаются по той же самой технологии, что и большинство современных телевизоров, но имеют гораздо меньше пикселов по сравнению с ними. Но устройства на их основе (в том числе и с использованием Arduino) смотрятся потрясающе.

В нашем проекте мы будем использовать монохромный 7-пиновый SSD1306 0.96” OLED дисплей. Причина, по которой мы выбрали данный дисплей, заключается в том, что он может работать с тремя разными протоколами связи, трехпроводный SPI (Serial Peripheral Interface — последовательный интерфейс) режим, четырехпроводный SPI режим и режим IIC. В данной статье мы рассмотрим его подключение по четырехпроводному SPI режиму как самому скоростному из приведенных.

Контакты дисплея и выполняемые ими функции описаны в следующей таблице.

Номер контакта Название контакта Альтернативное название контакта Назначение контакта
1 Gnd Ground земля
2 Vdd Vcc, 5V напряжение питания (в диапазоне 3-5 В)
3 SCK D0, SCL, CLK контакт синхронизации (clock pin). Применяется в интерфейсах I2C и SPI
4 SDA D1, MOSI контакт данных. Применяется в интерфейсах I2C и SPI
5 RES RST, RESET контакт сброса модуля. Применяется в интерфейсе SPI
6 DC A0 контакт команд (Data Command pin). Применяется в интерфейсе SPI
7 CS Chip Select (выбор чипа) используется когда несколько устройств взаимодействуют по интерфейсу SPI

Сообществом Arduino разработано достаточно много библиотек для работы с подобными дисплеями. Мы выбрали из них библиотеку Adafruit_SSD1306 как весьма простую и в то же время содержащую достаточно много полезных функций. Но если ваш проект имеет жесткие ограничения по памяти/скорости, то тогда вам лучше использовать библиотеку U8g поскольку она работает быстрее и занимает меньше места в памяти.

Работа схемы

Схема устройства представлена на следующем рисунке.

Как можно видеть, соединения на схеме достаточно простые и перечислены в следующих таблицах:

контакт Arduino контакт датчика температуры и влажности DHT11
Vcc 5V
Gnd Gnd
Nc Nc
Pin 7 Out
контакт Arduino контакт DS3231 RTC
5V Vcc
Gnd Gnd
Pin A5 SCL
Pin A4 SDA
контакт Arduino контакт модуля для чтения SD карт
5V Vcc
Gnd Gnd
Pin 12 MISO
Pin 11 MOSI
Pin 13 SCK
CS CS

Вы можете заменить датчик DHT11 в схеме на любой другой аналогичный, например, LM35. Модуль RTC DS3231 подключается к плате Arduino по протоколу I2C (SCL, SDA), а модуль чтения SD карт – по протоколу SPI (MISO, MOSI, SCK, CS). Контакты 4 и 7 платы Arduino подключаются к контактам CS и Out модуля чтения SD карт и датчика DHT11 соответственно, при желании вы их можете сменить на любые другие контакты. Ранее подключение модуля чтения SD карт к плате Arduino мы рассматривали в проекте аудиоплеера на Arduino.

Battery Backup

The DS3231 incorporates a battery input, and maintains accurate timekeeping when main power to the device is interrupted.

The built-in power-sense circuit continuously monitors the status of VCC to detect power failures and automatically switches to the backup supply. So, you need not worry about power outages, your MCU can still keep track of time.

The bottom side of the board holds a battery holder for 20mm 3V lithium coincells. Any CR2032 battery can fit well.

Assuming a fully charged CR2032 battery with capacity 220mAh is used and chip consumes its minimum 3µA, the battey can keep the RTC running for a minimum of 8 years without an external 5V power supply.

220mAh/3µA = 73333.34 hours = 3055.56 days = 8.37 years