Делаем реальные часы при помощи чипа arduino ds3231

Functions for reading and writing RTC registers or static RAM (SRAM) for the DS3232

The DS3232RTC.h file defines symbolic names for the timekeeping, alarm, status and control registers. These can be used for the addr argument in the functions below.

writeRTC(byte addr, byte *values, byte nBytes)

Write one or more bytes to RTC memory.

Parameters

addr: First SRAM address to write (byte). The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
values: An array of values to write (*byte)nBytes: Number of bytes to write (byte). Must be between 1 and 31 (Wire library limitation) but is not checked by the library.

I2C status (byte). Returns zero if successful.

//write 1, 2, ..., 8 to the first eight DS3232 SRAM locations
byte buf = {1, 2, 3, 4, 5, 6, 7, 8};
RTC.sramWrite(0x14, buf, 8);

writeRTC(byte addr, byte value)

Write a single byte to RTC memory.

Parameters

addr: SRAM address to write (byte). The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
value: Value to write (byte)

I2C status (byte). Returns zero if successful.

RTC.writeRTC(3, 14);   //write the value 14 to SRAM address 3

readRTC(byte addr, byte *values, byte nBytes)

Read one or more bytes from RTC RAM.

Parameters

addr: First SRAM address to read (byte). The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
values: An array to receive the values read (*byte)nBytes: Number of bytes to read (byte). Must be between 1 and 32 (Wire library limitation) but is not checked by the library.

I2C status (byte). Returns zero if successful.

//read the last eight locations of SRAM into buf
byte buf;
RTC.sramRead(248, buf, 8);
Parameters

addr: SRAM address to read (byte). The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.

DS3231M и DS3231MZ

Это первые RTC с интегрированным задающим генератором типа MEMS (Micro Electronic Mechanical Systems), имеющие температурную компенсацию. Схематика данных RTC представлена на рисунке 3.

Рис. 3. Блок-схема DS3231M

Преимущество данной технологии — кристалл резонатора изготавливается непосредственно на подложке микросхемы. На корпусах микросхем DS3231, DS3232 и DS3234 можно заметить довольно большой участок, свободный от выводов. Именно там находится интегрированный кристалл кварцевого резонатора. Фактически это два отдельных устройства в одном корпусе. Микросхема DS3231M(MZ) является действительно единым целым, что дает ряд преимуществ: меньшие размеры, малый разброс характеристик, пониженное энергопотребление.

Использование технологии MEMS делает возможным применение микросхем в условиях сильной вибрации, при вероятности нанесения устройству «шоковых» ударов. Эти изделия изготавливаются только в индустриальном варианте с температурным режимом работы -40…85°C.

Корпусное исполнение микросхем — в двух вариантах: SO-16 (DS3231M), полностью совместимый по назначению выводов с микросхемой DS3231, что позволяет легко осуществить замену (следует учесть некоторые особенности: в отличие от DS3231 выход сигнала прямоугольной формы у DS3231M жестко задан частотой 32,768 кГц (нет возможности программировать частоту)), и более миниатюрный SOIC-8 150-mil (DS3231MZ).

Заявленная точность RTC DS3231M(MZ) несколько ниже, чем у DS3231, DS3232 и DS3234 — ±5 ppm при -40…85°C (±0,432 сек./день). Фактически же изменение точности от температуры составляет менее ±2 ppm, так как в комплексе температурная компенсация MEMS-генератора более эффективна, поскольку однокристальное исполнение не имеет такого выраженного разброса температур между компонентами, как в случае микросхем со стандартной интеграцией резонатора.

В таблице 1 сравниваются основные характеристики DS3231, DS3232, DS3234, DS3231M(Z)

Таблица 1. Основные характеристики RTC

RTC Точность, (сек./день) Интерфейс Напряжение питания, В Ток потребления, мкА.
(при Vcc 3,3 В)
Память, байт Выход частоты Тип
резонатора
Корпус
DS3231M(Z) ±0,432 I2C от 2,3 до 5,5 менее 200 32,768 кГц MEMS SO-8, SO-16
DS3231 ±0,3 1 Гц; 1,024 кГц; 4,096 кГц; 8,192 кГц; 32,768 кГц Crystal SO-16
DS3232 200 236 SO-20
DS3234 SPI менее 400 256

Other functions

temperature(void)

Description

Returns the RTC temperature.

Parameters

None.

RTC temperature as degrees Celsius times four. (int)

int t = RTC.temperature();
float celsius = t / 4.0;
float fahrenheit = celsius * 9.0 / 5.0 + 32.0;

squareWave(SQWAVE_FREQS_t freq)

Description

Enables or disables the square wave output.

Parameters

freq: a value from the SQWAVE_FREQS_t enumeration above. (SQWAVE_FREQS_t)

None.

RTC.squareWave(SQWAVE_1_HZ);	//1 Hz square wave
RTC.squareWave(SQWAVE_NONE);	//no square wave
Description

Returns the value of the oscillator stop flag (OSF) bit in the control/status register which indicates that the oscillator is or was stopped, and that the timekeeping data may be invalid. Optionally clears the OSF bit depending on the argument passed. If the argument is omitted, the OSF bit is cleared by default. Calls to and also clear the OSF bit.

Parameters

clearOSF: an optional true or false value to indicate whether the OSF bit should be cleared (reset). If not supplied, a default value of true is used, resetting the OSF bit. (bool)

Примечания

  1. Запасы углей стран мира / Железнова Н. Г., Кузнецов Ю. Я., Матвеев А. К., Череповский В. Ф., М.: Недра, 1983. — С.128
  2. Пригоровский М. М. Ископаемые угли СССР // Наука и жизнь : журнал. — 1935. — Январь (№ 1). — С. 24.
  3. Understanding Energy and Energy, Timothy F. Braun and Lisa M. Glidden 2014
  4. Дрёмов, Алексей Викторович. Обоснование рациональных параметров обеспыливания в комбайновом проходческом забое : диссертация кандидата технических наук : 05.26.01; . — Москва, 2010. — 148 с
  5. Кузьмичёв А. С. ред. «Справочник по борьбе с пылью в горонодобывающей промышленности» М.: Недра, 1982. — 240с.

Новые RTC DS1347

В отличие от вышеописанных, DS1347 (рис. 4) не имеет интегрированного TCXO и использует стандартный внешний кварцевый резонатор (при этом не требует подключения конденсаторов и ограничивающих резисторов).

Рис. 4. Блок-схема DS1347

Микросхема имеет очень низкую стоимость, интерфейс SPI, малое потребление тока, а корпусное исполнение 8-Pin TDFN с размерами 3x3x0,8 мм делают ее одной из самых миниатюрных среди подобных устройств. Про DS1347 можно сказать: «ничего лишнего». У нее отсутствует вход резервного питания, так как микросхема позиционируется для бюджетных решений, критичных к размерам устройства и имеющих батарейный источник питания (например, ручной измерительный инструмент).

Особенности DS1347:

  • счетчик секунд, минут, часов (с признаком АМ/PM), дней, месяцев и лет (с учетом високосных);
  • расширенный диапазон напряжения питания (от +2 до +5,5В);
  • интерфейс SPI 4MHz при питании 5В, 1MHz при 2В;
  • 31 x 8-Bit SRAM для «блокнотных» данных;
  • использование внешнего стандартного часового кварца 32.768кГц;
  • низкое потребление тока в режиме хранения времени (макс. 400 нА при питании 2В);
  • одно- или мультибайтовая передача данных для чтения и записи регистров часов и SRAM;
  • программируемый будильник;
  • не требует внешних нагрузочных конденсаторов и резисторов к кварцевому резонатору;
  • миниатюрный корпус 8-Pin TDFN 3x3x0,8мм;
  • рабочий температурный режим от -40°C до 85°C.

На момент написания данной статьи компании Maxim Integrated Products производит 86 вариантов RTC, что дает широкую возможность выбора под необходимые условия.

Подключение DS3231 к Ардуино

Общение с DS3231 осуществляется по линиям I2C. Схема подключения RTC модуля на DS3231 к Ардуино Уно приведена ниже.

Подключение DS3231 к Ардуино для работы с будильником

Если бы нас интересовало только текущее время, то достаточно было бы подключить VCC, GND, SCL и SDA модуля к соответствующим выводам Ардуино. В данном же случае нам нужен ещё вывод INT/SQW. На нём будет генерироваться сигнал запроса прерывания для пробуждения микроконтроллера. Поэтому проще всего подключить его к входу внешнего прерывания, для УНО это D2 и D3. Хотя можно использовать и другие выводы, разрешив на них PCINT.

Кстати, на моём модуле не было вывода INT/SQW. При этом в штыревом разъеме один из выводов был не задействован. Я подпаял его к третьей ножке микросхемы DS3231 (это и есть INT/SQW) и получил нужный мне вывод на штыревом разъеме модуля.

Добавление недостающего вывода INT/SQW на модуле DS3231

Библиотека RTC.h Arduino: описание команд

Для работы с модулями часов Ардуино, в библиотеке реализовано 5 функций:

// запуск модуля

// указать время
— год указывается без учета века, в формате 0-99
— часы указываются в 24-часовом формате, от 0 до 23
— день недели указывается в виде числа от 0-воскресенье, 6-суббота

// получить время
— gettime(«d-m-Y, H:i:s, D»); ответит строкой «12-06-2020, 18:30:05, Fri»
— gettime(«H»); ответит строкой «18»

функцией gettime можно получать различную информацию:

  • s — секунды от 00 до 59 (два знака)
  • i — минуты от 00 до 59 (два знака)
  • h — часы в 12-часовом формате от 01 до 12 (два знака)
  • H — часы в 24-часовом формате от 00 до 23 (два знака)
  • d — день месяца от 01 до 31 (два знака)
  • D — день недели наименование от Mon до Sun (три знака)
  • m — месяц от 01 до 12 (два знака)
  • M — месяц наименование от Jan до Dec (три знака)
  • Y — год от 2000 до 2099 (четыре знака)
  • y — год от 00 до 99 (два знака)

— указывает функции gettime мигать одним из параметров времени

— устанавливает период обращения к модулю в минутах (от 0 до 255)

Constructor

Description

For AVR architecture only (for backwards compatibility with the DS1307RTC library), the DS3232RTC library instantiates a DS3232RTC object named ; the user should not use the constructor for AVR boards. For other architectures, the user’s code must instantiate a DS3232RTC object.

Parameters

initI2C: An optional parameter to control whether the constructor initializes the I2C bus. The default is true (again for backwards compatibility). (bool)

Example
// For non-AVR boards only. Not needed for AVR boards.
DS3232RTC myRTC(false);     // tell constructor not to initialize the I2C bus.

Преимущества подземной проводки

Прокладка кабеля под землёй имеет есть ряд преимуществ перед наземной:

  1. Уменьшение шанса на повреждение сети. При соблюдении всех норм укладки кабель будет сложно передавить или переехать, а также на его состояние не будут влиять погодные условия и деревья. 
  2. Проще определить длину провода. Если выбирается кабель для подземной прокладки, то во время выбора требуется учёт сечения и длины всей линии. Для воздушного кабеля необходимо было бы вычислять вес и силу натяжения, чтобы не было перегрузки. 
  3. Меньшие затраты. Для подключения необходим только устройство принудительного отключения сети, а также небольшие траты на проект. 
  4. Меньше риск возникновения пожара. 
  5. Также уменьшается воздействие электромагнитных волн и грозы. 
  6. Эстетичность. Так как провода находятся под землёй, участок можно использовать по своим предпочтениям. Главное – помнить, где располагается провод, чтобы при посадке деревьев не возникло неприятностей.  


Участок перед закапыванием траншеиИсточник s00.yaplakal.com

Режимы электропитания

Напряжение питания микросхемы может находиться в пределах 2.3…5.5В, имеются две линии питания, для внешнего источника (линия Vcc), а также для батареи (Vbat). Напряжение внешнего источника постоянно отслеживается, при падении ниже порога Vpf=2,5В, происходит переключение на линию батареи. В следующей таблице представлены условия переключения между линиями питания:

Комбинации уровней напряжения Активная линия питания
Vcc < Vpf, Vcc < Vbat Vbat
Vcc < Vpf, Vcc > Vbat Vcc
Vcc > Vpf, Vcc < Vbat Vcc
Vcc > Vpf, Vcc > Vbat Vcc

Точность хода часов поддерживается за счет отслеживания температуры окружающей среды. В микросхеме запускается внутренняя процедура корректировки частоты тактового генератора, величина корректировки определяется по специальному графику зависимости частоты от температуры. Процедура запускается после подачи питания, а затем выполняется каждые 64 секунды.

В целях сохранения заряда, при подключении батареи (подача напряжения на линию Vbat), тактовый генератор не запускается до тех пор, пока напряжение на линии Vcc не превысит пороговое значение Vpf, или не будет передан корректный адрес микросхемы по интерфейсу I2C. Время запуска тактового генератора составляет менее одной секунды. Примерно через 2 секунды после подачи питания (Vcc), или получения адреса по интерфейсу I2C, запускается процедура коррекции частоты. После того как тактовый генератор запустился, он продолжает функционировать до тех пор, пока присутствует напряжение Vcc или Vbat. При первом включении регистры даты и времени сброшены, и имеют следующие значения 01/01/ 00 — 01 — 00/00/00 (день/месяц/год/ — день недели — час/минуты/секунды).

Ток потребления при питании от батареи напряжением 3.63В, составляет 3 мкА, при отсутствии передачи данных по интерфейсу I2C. Максимальный ток потребления может достигать 300 мкА, в случае использования внешнего источника питания напряжением 5.5В, и высокой скорости передачи данных I2C.

Использование DS3231 для пробуждения Ардуино

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

#include <avr/sleep.h>
#include <Wire.h>
#include <DS3231.h>

DS3231 clock;

void alarmFunction() {
  
}

void setup() {
  
  clock.begin();
  clock.enableOutput(false); 
  clock.armAlarm1(false);    
  clock.armAlarm2(false);
  clock.clearAlarm1();       
  clock.clearAlarm2();

  
  clock.setAlarm1(, , , 10, DS3231_MATCH_S); 

  
  pinMode(2, INPUT_PULLUP); 
  attachInterrupt(, alarmFunction, FALLING); 

  pinMode(13, OUTPUT); 
  ADCSRA &= ~(1 << ADEN); 
}

void loop() {
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  noInterrupts();
  sleep_enable();
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  interrupts();
  sleep_cpu();

  
  sleep_disable();
  
  
  if (clock.isAlarm1()) {
    
    clock.clearAlarm1(); 
    
    digitalWrite(13, HIGH);
    delay(2000);
    digitalWrite(13, LOW);
    
  }
}

В данном примере будильник 1 устанавливается на срабатывание в 10 секунд каждой минуты, после чего Ардуино переводится в режим энергосбережения. Доступные для Ардуино (ATmega328P) режимы энергосбережения, а также события, пробуждающие микроконтроллер, я приводил в статье Режимы энергосбережения Ардуино. Проснувшись, не лишним будет проверить флаг будильника, чтобы убедиться, что именно он нас разбудил. Если флаг будильника 1 установлен, то можем выполнять наш код, в данном случае — включение и выключение светодиода.

Будильник не обязательно должен настраиваться единожды, как в приведённых выше скетчах. Его можно менять хоть при каждом срабатывании. Так можно добиться пробуждения Ардуино через определённый интервал времени. Например, чтобы будильник срабатывал каждые 10 минут, его нужно выставлять при каждом пробуждении на текущее время + 10 минут. Это потребует минимальных изменений приведённого выше скетча:

    ...
    
    clock.clearAlarm1(); 
    RTCDateTime dt = clock.getDateTime(); 
    clock.setAlarm1(, , (dt.minute + 10) % 60, dt.second, DS3231_MATCH_M_S); 
    ...

Энергопотребление DS3231

Если мы хотим использовать DS3231 для вывода микроконтроллера из режима энергосбережения, то неплохо бы разобраться с потреблением и самих часов. Обратимся для этого к даташиту. В нём нас интересуют две таблицы Electrical Characteristics. Первая для случая, когда источником питания служит вход VCC, вторая — питание от VBAT, то есть от батарейки. Небольшая выжимка из этих таблиц приведена ниже:

Параметр Обозначение Условия

Максимальное

значение

Питание от Vcc
Active Supply Current  ICCA FSCL = 400МГц VCC = 3.63В 200мкА
VCC = 5.5В 300мкА
Standby Supply Current  ICCS

I2C неактивна,

Вывод 32кГц разрешён,

Меандр (SQW) запрещён

VCC = 3.63В 110мкА
VCC = 5.5В 170мкА
Temperature Conversion Current  ICCSCONV

I2C неактивна,

Вывод 32кГц разрешён,

Меандр (SQW) запрещён

VCC = 3.63В 575мкА
VCC = 5.5В 650мкА
Питание от VBAT
Active Battery Current  IBATA  

FSCL = 400МГц,

Меандр (SQW) запрещён

VBAT = 3.63В 70мкА
VBAT = 5.5В  150мкА
Timekeeping Battery Current   IBATT I2C неактивна,

Вывод 32кГц разрешён,

Меандр (SQW) запрещён

VBAT = 3.63В 3мкА 
VBAT = 5.5В  3.5мкА
Temperature Conversion Current  IBATTC I2C неактивна,

Меандр (SQW) запрещён

VBAT = 3.63В 575мкА
VBAT = 5.5В 650мкА

Active Supply Current — это среднее значение тока, потребляемого микросхемой DS3231 при работающей шине I2C (причем на максимальной частоте — 400кГц), с учётом тока измерения температуры.

Standby Supply Current отражает среднее потребление DS3231 при неактивной шине I2C, разрешённом выводе частоты 32кГц и с запрещённым меандром SQW. Данное значение также включает в себя ток при измерении температуры.

Temperature Conversion Current — ток, потребляемый микросхемой в момент измерения температуры. Измерения выполняются при подаче питания и далее каждые 64 секунды для подстройки частоты генератора. Время измерения температуры (параметр TCONV — Temperature Conversion Time) не превышает 200мс.

Active Battery Current — среднее значение тока, потребляемого DS3231 при питании от VBAT, работающей шине I2C, с учетом тока при измерении температуры.

Timekeeping Battery Current — среднее значение тока, потребляемого DS3231 при питании от VBAT, при неактивной шине I2C, с учетом тока при измерении температуры.

Переключение источника питания с VCC на VBAT происходит при выполнении двух условий: VCC < VPF и VCC < VBAT. VPF — это Power-Fail Voltage, его значение составляет 2.45В .. 2.70В. Переключение на VCC происходит, когда напряжение на данном входе становится больше VBAT.

Из таблицы видно, что потребление DS3231 не превышает 300мкА при работающей шине I2C и VCC = 5.5В. В целом же потребление значительно ниже. Для его оценки я подключил модуль DS3231 к микроконтроллеру ATmega328P без обвязки. Тактирование от внутреннего генератора 8МГц. Питание — литиевый аккумулятор 18650 с напряжением 4.1В. В режиме POWER_DOWN с отключённым АЦП и BOD потребление микроконтроллера и часов составило 93мкА:

Functions for setting and reading the time

get(void)

Description

Reads the current date and time from the RTC and returns it as a time_t value. Returns zero if an I2C error occurs (RTC not present, etc.).

None.

Current date and time (time_t)

Example
time_t myTime;
myTime = RTC.get();

set(time_t t)

Description

Sets the RTC date and time to the given time_t value. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.

t: The date and time to set the RTC to (time_t)

Example
//this example first sets the system time (maintained by the Time library) to
//a hard-coded date and time, and then sets the RTC from the system time.
//the setTime() function is part of the Time library.
setTime(23, 31, 30, 13, 2, 2009);   //set the system time to 23h31m30s on 13Feb2009
RTC.set(now());                     //set the RTC from the system time

read(tmElements_t &tm)

Description

tm: Address of a tmElements_t structure to which the date and time are returned.

I2C status (byte). Returns zero if successful. The date and time read from the RTC are returned to the tm parameter.

Example
tmElements_t tm;
RTC.read(tm);
Serial.print(tm.Hour, DEC);
Serial.print(':');
Serial.print(tm.Minute,DEC);
Serial.print(':');
Serial.println(tm.Second,DEC);
Description

Sets the RTC to the date and time given by a tmElements_t structure. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.

Example
tmElements_t tm;
tm.Hour = 23;             //set the tm structure to 23h31m30s on 13Feb2009
tm.Minute = 31;
tm.Second = 30;
tm.Day = 13;
tm.Month = 2;
tm.Year = 2009 - 1970;    //tmElements_t.Year is the offset from 1970
RTC.write(tm);            //set the RTC from the tm structure

Код из видео:

#include <Wire.h>
#include <OLED_I2C.h>

OLED  myOLED(SDA, SCL, 8);

extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];
 
   
 ///// часы ..
byte decToBcd(byte val){
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val){
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(0x68);
   Wire.write(0);
   Wire.write(decToBcd(second));    
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(0x68);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(0x68, 7);

  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f); 
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}
  
///// температура ..
float get3231Temp(){
  byte tMSB, tLSB; 
  float temp3231;

  Wire.beginTransmission(0x68);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(0x68, 2);

  if(Wire.available()) {
    tMSB = Wire.read(); //2's complement int portion
    tLSB = Wire.read(); //fraction portion

    temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  else {
    //oh noes, no data!
  }

  return temp3231;
}


void setup()
{
  Serial.begin(9600);
  myOLED.begin();
  Wire.begin();
 

 /*  // установка часов
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  second = 30;
  minute = 0;
  hour = 14;
  dayOfWeek = 3; // день недели
  dayOfMonth = 1; // день
  month = 4;
  year = 14;

  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
 */
}

void loop(){
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  char week = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
 
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  char time;
  char data;
  
  snprintf(time, sizeof(time),"%02d:%02d:%02d",           
           hour, minute, second);
           
  snprintf(data, sizeof(data), "%02d/%02d/%02d",            
            dayOfMonth, month, year);
  
  myOLED.setFont(SmallFont);
 
  myOLED.print(time, LEFT, 0);
  myOLED.print(data, LEFT, 15);
  myOLED.printNumF(get3231Temp(), 2, LEFT, 30);
  myOLED.print("C", 32, 30);
  myOLED.update();

 delay(1000);
}

////// конец
 

Как подключить DS1302 к Arduino (RTC)

Для этого занятия нам потребуется:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • модуль DS1302, DS1307 или DS3231;
  • LCD монитор 1602 i2c;
  • провода «папа-мама».


DS1307 схема подключения к Ардуино Уно

Модули часов DS1307 и DS3231 подключаются к плате Ардуино через I2C протокол, как LCD дисплей I2C. Контакт SDA подключается к пину A4, контакт SCL к пину A5 Ардуино Уно. При подключении данных модулей к плате Arduino Mega следует использовать порты SDA (20 пин) и SCL (21 пин). При этом в скетче необходимо снять комментарий в строчке с нужным модулем, а строчку с модулем 1302 наоборот закомментировать.

Скетч. Часы реального времени Ардуино DS1307

#include <iarduino_RTC.h>

iarduino_RTC time(RTC_DS1302,6,8,7);  // для модуля DS1302 - RST, CLK, DAT
// iarduino_RTC time(RTC_DS1307);       // для модуля DS1307 с i2C
// iarduino_RTC timeRTC_DS3231);        // для модуля DS3231 с i2C

void setup() {
   delay(300);
   Serial.begin(9600);
   time.begin();
   time.settime(0, 30, 18, 12, 6, 20, 5); // 0  сек, 30 мин, 18 часов, 12, июня, 2020, четверг
}

void loop() {
   // если прошла 1 секунда выводим время
   if (millis() % 1000 == 0) {
      Serial.println(time.gettime("d-m-Y, H:i:s, D"));
      delay(1);
   }
}
  1. для работы с программой необходимо скачать библиотеку iarduino_RTC.h.
  2. с помощью команды можно установить дату и время.


Схема подключения часов реального времени с дисплеем

К сожалению, следующий пример с подключением дисплея 1602 I2C, возможен только с модулем 1302, так как порты SDA(A4) и SCL(A5) на микроконтроллеры Ардуино Уно необходимы для подключения дисплея LCD.

Скетч. Часы на Ардуино с LCD 1602 и DS1302

#include <iarduino_RTC.h>
iarduino_RTC time(RTC_DS1302,6,8,7);  // для модуля DS1302 - RST, CLK, DAT

#include <Wire.h>                             // библиотека для устройств I2C 
#include <LiquidCrystal_I2C.h>       // подключаем библиотеку для дисплея
LiquidCrystal_I2C LCD(0x27,16,2);  // присваиваем имя дисплею

void setup() {
   delay(300);
   LCD.init();            // инициализация LCD дисплея
   LCD.backlight();  // включение подсветки дисплея
   time.begin();
   time.settime(0, 30, 18, 12, 6, 20, 5); // 0  сек, 30 мин, 18 часов, 12, июня, 2020, четверг
}

void loop() {
   // если прошла 1 секунда выводим время на дисплей
   if (millis() % 1000 == 0) {
      LCD.setCursor(0,0);
      LCD.print(time.gettime("d M Y, D"));
      LCD.setCursor(4,1);
      LCD.print(time.gettime("H:i:s"));
      delay(1);
   }
}

Общие сведения

Использовании модуля DS1307 зачастую очень оправдано, например, когда данные считываются редко, интервалом более недели, использовать собственные ресурсы контроллера, неоправданно или невозможно. Обеспечивание бесперебойное питание, например платы Arduino, на длительный срок дорого, даже при использовании батареи.
Благодаря собственной памяти и автономностью, можно регистрировать события, (при автономном питании) например изменение температуры и так далее, данные сохраняются в памяти их можно считать из памяти модуля. Так что модуль DS1307 часто используют, когда контроллерам Arduino необходимо знать точное время, для запуска какого то события и так далее.

Обмен данными с другими устройствами осуществляется по интерфейсу I2C с выводов SCL и SDA. Конденсаторы С1 и С2 необходимы для снижения помех по линию питания. Чтобы обеспечить надлежащего уровня сигналов SCL и SDA установлены резисторы R2 и R3 (подтянуты к питанию). Для проверки работоспособности модуля, на вывод 7 микросхему DS1307Z, подается сигнал SQ, прямоугольной формы с частотой 1 Гц. Элементы R4, R5, R6, VD1 необходимы для подзарядку литиевой батарейки. Так же, на плате предусмотрено посадочное место (U1), для установки датчика температуры DS18B20 (при необходимости можно впаять его), считывать показания, можно с вывода DS, который подтянут к пиатнию, через резистор R1 сопротивлением 3.3 кОм. Принципиальную схему и назначение контактов можно посмотреть на рисунках ниже.

На плате расположено две группы контактов, шагом 2.54 мм, для удобного подключения к макетной плате, буду использовать штырьевые разъемы, их необходимо впаять.

Первая группа контактов:► DS:     вывод DS18B20  (1-wire)► SCL:   линия тактирования (Serial CLock)► SDA:  линия данных (Serial Dфta)► VCC:  «+» питание модуля► GND: «-» питание модуля

Вторая группа контактов:► SQ:    вход 1 МГц► DS:    вывод DS18B20  (1-wire)► SCL:  линия тактирования (Serial CLock)► SDA: линия данных (Serial Dфta)► VCC: «+» питание модуля► GND:«-» питание модуля► BAT: 

Подзарядка батареи
Как описывал ваше модуль может заряжать батарею, реализовано это, с помощью компонентов R4, R5, R6 и диода D1. Но, данная схема имеет недостаток, через резистор R4 и R6 происходит разряд батареи (как подметил пользователь ALEXEY, совсем не большой). Так как модуль потребляем незначительный ток, можно удалить цепь питания, для этого убираем R4, R5, R6 и VD1, вместо R6 поставим перемычку (после удаления компонентов, можно использовать обычную батарейку CR2032).

Пример проекта с i2C модулем часов и дисплеем

Проект представляет собой обычные часы, на индикатор будет выведено точное время, а двоеточие между цифрами будет мигать с интервалом раз в одну секунду. Для реализации проекта потребуются плата Arduino Uno, цифровой индикатор, часы реального времени (в данном случае вышеописанный модуль ds1307), шилд для подключения (в данном случае используется Troyka Shield), батарейка для часов и провода.

В проекте используется простой четырехразрядный индикатор на микросхеме TM1637. Устройство обладает двухпроводным интерфейсом и обеспечивает 8 уровней яркости монитора. Используется только для показа времени в формате часы:минуты. Индикатор прост в использовании и легко подключается. Его выгодно применять для проектов, когда не требуется поминутная или почасовая проверка данных. Для получения более полной информации о времени и дате используются жидкокристаллические мониторы.

Модуль часов подключается к контактам SCL/SDA, которые относятся к шине I2C. Также нужно подключить землю и питание. К Ардуино подключается так же, как описан выше: SDA – A4, SCL – A5, земля с модуля к земле с Ардуино, VCC -5V.

Индикатор подключается просто – выводы с него CLK и DIO подключаются к любым цифровым пинам на плате.

Скетч. Для написания кода используется функция setup, которая позволяет инициализировать часы и индикатор, записать время компиляции. Вывод времени на экран будет выполнен с помощью loop.


#include <Wire.h>

#include "TM1637.h"

#include "DS1307.h" //нужно включить все необходимые библиотеки для работы с часами и дисплеем.

char compileTime[] = __TIME__; //время компиляции.

#define DISPLAY_CLK_PIN 10

#define DISPLAY_DIO_PIN 11 //номера с выходов Ардуино, к которым присоединяется экран;

void setup()

{

display.set();

display.init(); //подключение и настройка экрана.

clock.begin(); //включение часов.

byte hour = getInt(compileTime, 0);

byte minute = getInt(compileTime, 2);

byte second = getInt(compileTime, 4); //получение времени.

clock.fillByHMS(hour, minute, second); //подготовка для записывания в модуль времени.

clock.setTime(); //происходит запись полученной информации во внутреннюю память, начало считывания времени.

}

void loop()

{

int8_t timeDisp; //отображение на каждом из четырех разрядов.

clock.getTime();//запрос на получение времени.

timeDisp = clock.hour / 10;

timeDisp = clock.hour % 10;

timeDisp = clock.minute / 10;

timeDisp = clock.minute % 10; //различные операции для получения десятков, единиц часов, минут и так далее.

display.display(timeDisp); //вывод времени на индикатор

display.point(clock.second % 2 ? POINT_ON : POINT_OFF);//включение и выключение двоеточия через секунду.

}

char getInt(const char* string, int startIndex) {

return int(string - '0') * 10 + int(string) - '0'; //действия для корректной записи времени в двухзначное целое число. В ином случае на экране будет отображена просто пара символов.

}

После этого скетч нужно загрузить и на мониторе будет показано время.

Программу можно немного модернизировать. При отключении питания выше написанный скетч приведет к тому, что после включения на дисплее будет указано время, которое было установлено при компиляции. В функции setup каждый раз будет рассчитываться время, которое прошло с 00:00:00 до начала компиляции. Этот хэш будет сравниваться с тем, что хранятся в EEPROM, которые сохраняются при отключении питания.

Для записи и чтения времени в энергонезависимую память или из нее нужно добавить функции EEPROMWriteInt и EEPROMReadInt. Они нужны для проверки совпадения/несовпадения хэша с хэшем, записанным в EEPROM.

Можно усовершенствовать проект. Если использовать жидкокристаллический монитор, можно сделать проект, который будет отображать дату и время на экране. Подключение всех элементов показано на рисунке.

В результате в коде нужно будет указать новую библиотеку (для жидкокристаллических экранов это LiquidCrystal), и добавить в функцию loop() строки для получения даты.

Алгоритм работы следующий:

  • Подключение всех компонентов;
  • Загрузка скетча;
  • Проверка – на экране монитора должны меняться ежесекундно время и дата. Если на экране указано неправильное время, нужно добавить в скетч функцию RTC.write (tmElements_t tm). Проблемы с неправильно указанным временем связаны с тем, что модуль часов сбрасывает дату и время на 00:00:00 01/01/2000 при выключении.
  • Функция write позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.
Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий