Электрификация

Справочник домашнего мастера

Термометр из ардуино

Содержание

Урок 19. RTC часы с будильником

В предыдущем уроке 18, мы подключили Trema RTC часы реального времени с Trema кнопками и LCD I2C дисплеем к arduino Uno, написали скетч, для установки времени при помощи кнопок.

Теперь расширим функционал получившихся часов, добавив к ним функцию будильника. А код, который будет выполняться при срабатывании будильника выведем в отдельную функцию «Func_alarm_action()», чтоб Вы смогли легко его найти и изменить. Например, при срабатывании будильника, открывать жалюзи, включать свет или музыку, включить через реле тостер или кофе-машину и т.д.

  • Arduino х 1шт.
  • RTC модуль Trema на базе чипа DS1307 х 1шт.
  • LCD дисплей LCD1602 IIC/I2C(синий) или LCD1602 IIC/I2C(зелёный) х 1шт.
  • Trema Shield х 1шт.
  • Trema-модуль i2C Hub х 1шт.
  • Trema-модуль кнопка c проводами х 3шт.
  • Шлейф «мама-мама»для шины I2С х 2шт.
  • Trema-модуль зуммер х 1шт.
  • Trema-модуль светодиод х 1шт. (белый, синий, красный, оранжевый или зелёный)

Для реализации проекта нам необходимо установить библиотеки:

  • Библиотека iarduino_RTC (для подключения RTC часов реального времени DS1302, DS1307, DS3231)
  • Библиотека LiquidCrystal_I2C_V112 (для подключения дисплеев LCD1602 по шине I2C)

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki — Установка библиотек в Arduino IDE.

Видео:

Схема подключения:

Подключение модулей RTC и LCD, данного урока, осуществляется к аппаратным выводам SDA, и SCL.

RTC модуль Trema на базе чипа DS1307 / LCD дисплей на базе чипа LCD1602 Arduino Uno
GND GND
Vcc +5V
SDA (Serial DAta) A4
SCL (Serial CLock) A5

Подключение кнопок: кнопка «SET» к выводу 2, кнопка «UP» к выводу 3 и копка «DOWN» к выводу 4.

Зуммер подключаем к выводу 5, а светодиод к выводу 13 (дублируя встроенный в arduino).

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

  • В режиме вывода даты/времени/будильника (обычный режим):
    • Кратковременное нажатие на кнопку SET переключает режимы вывода: даты/времени/будильника
    • Удержание кнопки SET переводит часы в режим установки даты/времени/будильника (зависит от того, каким был режим вывода)
    • Кнопки UP и DOWN, в режиме вывода будильника, активируют/деактивируют будильник.
      Если будильник активен, то в правом верхнем углу экрана появляется значок будильника.
  • В режиме установки даты/времени/будильника:
    • Кратковременное нажатие на кнопку SET — переход между устанавливаемыми параметрами (сек, мин, час, дни, мес, год, д.н.)
    • Удержание кнопки SET выводит часы из режима установки
    • Каждое нажатие на кнопку UP увеличивает значение устанавливаемого параметра даты или времени
    • Каждое нажатие на кнопку DOWN уменьшает значение устанавливаемого параметра даты или времени
  • Во время работы сигнализации будильника:
    • Удержание любой кнопки в течении 1 секунды, отключает сигнализацию (без выполнения их действий, в любом режиме)

Код программы:

Работа кнопок, вывод и установка времени, описывались в уроке 18, в этом уроке рассмотрим работу будильника:

  • VAR_alarm_MIN — переменная в которой хранится значение минут, при котором сработает будильник (по умолчанию 0 минут)
  • VAR_alarm_HOUR — переменная в которой хранится значение часов, при котором сработает будильник (по умолчанию 0 часов)
  • VAR_alarm_FLAG1 — флаг разрешения работы будильника, false — не активен, true — активен (по умолчанию true — активен)
  • VAR_alarm_FLAG2 — флаг указывающий на то, что будильник сработал «сигнализация» (по умолчанию false — не сработал)

Последняя переменная которую мы добавили — MAS_alarm_SYM, она содержит изображение символа будильника для вывода на дисплей.

В функции loop, после вывода информации на дисплей, добавляем проверку: не пора ли включить будильник?

void loop(){ if(millis()%1000==0){ // если прошла 1 секунда … … // проверка будильника if(VAR_alarm_FLAG1){ // если будильник включён if(time.seconds==00){ // если в текущем времени 0 секунд if(time.minutes==VAR_alarm_MIN){ // если совпали минуты if(time.Hours==VAR_alarm_HOUR){ // если совпали часы VAR_alarm_FLAG2=true; // устанавливаем флаг разрешающий совершение действий будильника (сигнализация) } } } }else{VAR_alarm_FLAG2=false;} // если будильник выключен, то сбрасываем флаг разрешающий совершение действий будильника (сигнализация) if(VAR_alarm_FLAG2){Func_alarm_action();}// запускаем действия будильника } Func_buttons_control(); // передаём управление кнопкам }

  • если будильник включён (установлен флаг VAR_alarm_FLAG1)
  • если в текущем времени 0 секунд (time.seconds==00)
  • если количество минут текущего времени (time.minutes) равно количеству минут установленных в будильнике (VAR_alarm_MIN)
  • если количество часов текущего времени (time.Hours) равно количеству часов установленных в будильнике (VAR_alarm_HOUR)
    то устанавливаем флаг VAR_alarm_FLAG2 (указывающий на то, что будильник сработал)
  • если установлен флаг VAR_alarm_FLAG2, то запускаем действия будильника (действия описаны в функции Func_alarm_action)
    Так как проверка будильника и запуск функции Func_alarm_action() находится внутри условия if(millis()%1000==0){…}, то действия будильника будут выполняться один раз в секунду.

Теперь всё готово для создания полного кода:

// Подключаем библиотеки: #include <Wire.h> // подключаем библиотеку для работы с шиной I2C #include <LiquidCrystal_I2C.h> // подключаем библиотеку для работы с LCD дисплеем #include <iarduino_RTC.h> // подключаем библиотеку для работы с RTC модулем LiquidCrystal_I2C lcd(0x27,16,2); // объявляем переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) iarduino_RTC time(RTC_DS1307); // объявляем переменную для работы с RTC модулем, указывая название модуля // Объявляем переменные и константы: const uint8_t PIN_button_SET = 2; // указываем номер вывода arduino, к которому подключена кнопка SET const uint8_t PIN_button_UP = 3; // указываем номер вывода arduino, к которому подключена кнопка UP const uint8_t PIN_button_DOWN = 4; // указываем номер вывода arduino, к которому подключена кнопка DOWN const uint8_t PIN_alarm_TONE = 5; // указываем номер вывода arduino, к которому подключён зуммер будильника const uint8_t PIN_alarm_LED = 13; // указываем номер вывода arduino, к которому подключён светодиод uint8_t VAR_mode_SHOW = 1; // режим вывода: 1-время 2-дата 3-время_будильника 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_alarm_FLAG1 = true; // будильник разрешение работы bool VAR_alarm_FLAG2 = false; // будильник совершение действий (сигнализация) byte MAS_alarm_SYM={B00000,B01110,B10101,B10111,B10001,B01110,B00000,B00000}; // символ будильника для отображения на дисплее void setup() { pinMode(PIN_button_SET, INPUT); // устанавливаем режим работы вывода PIN_button_SET, как «вход» pinMode(PIN_button_UP, INPUT); // устанавливаем режим работы вывода PIN_button_UP, как «вход» pinMode(PIN_button_DOWN, INPUT); // устанавливаем режим работы вывода PIN_button_DOWN, как «вход» pinMode(PIN_alarm_TONE, OUTPUT); // устанавливаем режим работы вывода PIN_alarm_TONE, как «выход» pinMode(PIN_alarm_LED, OUTPUT); // устанавливаем режим работы вывода PIN_alarm_LED, как «выход» digitalWrite(PIN_alarm_TONE, LOW); // устанавливаем уровень логического «0» на выводе PIN_alarm_TONE digitalWrite(PIN_alarm_LED, LOW); // устанавливаем уровень логического «0» на выводе PIN_alarm_LED delay(300); // ждем 300мс time.begin(); // инициируем RTC модуль lcd.init(); // инициируем LCD дисплей lcd.backlight(); // включаем подсветку LCD дисплея lcd.createChar(1, MAS_alarm_SYM); // загружаем символ будильника под номером 1 } void loop(){ if(millis()%1000==0){ // если прошла 1 секунда if(VAR_mode_SET==0){ // если дата/время/будильник выводятся, а не устанавливаются lcd.setCursor(0, 0); // устанавливаем курсор в позицию: столбец 0, строка 0 lcd.print(«iArduino.ru»); // выводим текст «iArduino.ru» lcd.setCursor(15, 0); // устанавливаем курсор в позицию: столбец 15, строка 0 lcd.print(VAR_alarm_FLAG1?»\1″:» «); // выводим значёк будильника }else{ // если дата/время/будильник устанавливаются, а не выводятся lcd.setCursor(0, 0); // устанавливаем курсор в позицию: столбец 0, строка 0 if(VAR_mode_SHOW==1){lcd.print(«Set time:» );} if(VAR_mode_SHOW==2){lcd.print(«Set date:» );} if(VAR_mode_SHOW==3){lcd.print(«Set alarm:»);} } if(VAR_mode_SHOW==1){ // если установлен режим вывода времени lcd.setCursor(0, 1); // устанавливаем курсор в позицию: столбец 0, строка 1 lcd.print(time.gettime(«H:i:s»)); // выводим время } if(VAR_mode_SHOW==2){ // если установлен режим вывода даты lcd.setCursor(0, 1); // устанавливаем курсор в позицию: столбец 0, строка 1 lcd.print(time.gettime(«d-m-Y D»)); // выводим дату } if(VAR_mode_SHOW==3){ // если установлен режим вывода будильника lcd.setCursor(0, 1); // устанавливаем курсор в позицию: столбец 0, строка 1 if(VAR_mode_SET==0){lcd.print(«Alarm «);} time.gettime(); // обновляем значение переменной time.seconds, для «мигания» устанавливаемым параметром будильника if(VAR_mode_SET==9&&time.seconds%2){lcd.print(» «);}else{if(VAR_alarm_HOUR<10){lcd.print(«0»);} lcd.print(VAR_alarm_HOUR);} lcd.print(«:»); if(VAR_mode_SET==8&&time.seconds%2){lcd.print(» «);}else{if(VAR_alarm_MIN<10){ lcd.print(«0»);} lcd.print(VAR_alarm_MIN);} } delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс // проверка будильника if(VAR_alarm_FLAG1){ // если будильник включён if(time.seconds==00){ // если в текущем времени 0 секунд if(time.minutes==VAR_alarm_MIN){ // если совпали минуты if(time.Hours==VAR_alarm_HOUR){ // если совпали часы VAR_alarm_FLAG2=true; // устанавливаем флаг разрешающий совершение действий будильника (сигнализация) } } } }else{VAR_alarm_FLAG2=false;} // если будильник выключен, то сбрасываем флаг разрешающий совершение действий будильника (сигнализация) if(VAR_alarm_FLAG2){Func_alarm_action();}// запускаем действия будильника } Func_buttons_control(); // передаём управление кнопкам } // Функция управления кнопками: void Func_buttons_control(){ uint8_t i=0; time.blinktime(VAR_mode_SET); // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0) //Если часы находятся в режиме установки даты/времени if(VAR_mode_SET){ // Если нажата кнопка UP if(digitalRead(PIN_button_UP )){ while(digitalRead(PIN_button_UP)){delay(50);} // ждём пока мы не отпустим кнопку UP if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}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; } } } // Если нажата кнопка DOWN if(digitalRead(PIN_button_DOWN)){ while(digitalRead(PIN_button_DOWN)){delay(50);} // ждём пока мы её не отпустим if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}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; } } } // Если нажата кнопка SET if(digitalRead(PIN_button_SET)){ while(digitalRead(PIN_button_SET)){ // ждём пока мы её не отпустим delay(10); if(i<200){i++;}else{lcd.clear();} // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран } if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{ // если будильник сработал, то выключаем его if(i<200){ // если кнопка SET удерживалась меньше 2 секунд VAR_mode_SET++; // переходим к следующему устанавливаемому параметру if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;} // возвращаемся к первому устанавливаемому параметру if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;} // возвращаемся к первому устанавливаемому параметру if(VAR_mode_SHOW==3 && VAR_mode_SET>9){VAR_mode_SET=8;} // возвращаемся к первому устанавливаемому параметру }else{ // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени VAR_mode_SET=0; // выходим из режима установки даты/времени } } } //Если часы находятся в режиме вывода даты/времени }else{ // Если нажата кнопка UP if(digitalRead(PIN_button_UP )){ while(digitalRead(PIN_button_UP)){delay(50);} // ждём пока мы её не отпустим if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{ // если будильник сработал, то выключаем его if(VAR_mode_SHOW==3){VAR_alarm_FLAG1=VAR_alarm_FLAG1?0:1;} // если установлен режим вывода будильника, то включаем/выключаем будильник } } // Если нажата кнопка DOWN if(digitalRead(PIN_button_DOWN)){ while(digitalRead(PIN_button_DOWN)){delay(50);} // ждём пока мы её не отпустим if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{ // если будильник сработал, то выключаем его if(VAR_mode_SHOW==3){VAR_alarm_FLAG1=VAR_alarm_FLAG1?0:1;} // если установлен режим вывода будильника, то включаем/выключаем будильник } } // Если нажата кнопка SET if(digitalRead(PIN_button_SET)){ while(digitalRead(PIN_button_SET)){delay(10); // ждём пока мы её не отпустим if(i<200){i++;}else{lcd.clear();} // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран } if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{ // если будильник сработал, то выключаем его if(i<200){ // если кнопка SET удерживалась меньше 2 секунд lcd.clear(); // стираем экран VAR_mode_SHOW++; if(VAR_mode_SHOW>3){VAR_mode_SHOW=1;} // меняем режим вывода: дата/время/будильник }else{ // если кнопка SET удерживалась дольше 2 секунд, то требуется перейти в режим установки даты/времени if(VAR_mode_SHOW==1){VAR_mode_SET=1;} // если установлен режим вывода времени, то устанавливаемый параметр — секунды if(VAR_mode_SHOW==2){VAR_mode_SET=4;} // если установлен режим вывода даты, то устанавливаемый параметр — день if(VAR_mode_SHOW==3){VAR_mode_SET=8;} // если установлен режим вывода будильника, то устанавливаемый параметр — минуты_будильника } } } } } // Функция выполняющая действия будильника: void Func_alarm_action(){ digitalWrite(PIN_alarm_LED, HIGH); tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE); delay(100); tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE); delay(100); tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE); digitalWrite(PIN_alarm_LED, LOW); }

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

Действия будильника описаны в функции Func_alarm_action().

В этой функции мы включаем светодиод, далее подаём три коротких звуковых сигнала (с частотой 2000Гц, длительностью и паузой 100мс), после чего выключаем светодиод.

Если Вам необходимо выполнить действие будильника однократно, а не каждую секунду после его срабатывания, то начните выполнение действий со сброса флага VAR_alarm_FLAG2, присвоив ему значение false.

Ссылки:

  • Код программы.
  • Библиотека iarduino_RTC.
  • Библиотека LiquidCrystal_I2C_V112.
  • Wiki — Установка библиотек в Arduino IDE.
  • WiKi — Работа с символьными ЖК дисплеями.
  • Wiki — Часы реального времени, RTC (Trema-модуль).
  • Wiki — Trema Shield.

AVR Урок 19. Собираем часы на микросхеме DS1307 и LCD 1602

Урок 19

Собираем часы на микросхеме DS1307 и LCD 1602

Сегодня, набравшись уже опыта по программирования шины I2С, а также изучив микросхему реального времени DS1307, мы сможем приступить к программированию простейших часов и выводить их показания уже не в компьютер, а в жидкокристаллический дисплей. Я думаю, это будет намного наглядней и красивее, чем просматривать это в терминальной программе на ПК.

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

Будем считать, что модуль с микросхемой у нас уже присоединён к отладочной плате с контроллером Atmega8A, Присоединим к ней также модуль дисплея. Вот упрощённая схема из протеуса (нажмите на картинку для увеличения изображения)

Ясное дело, что ещё здесь будет батарейка для сохранения хода часов при отключении питания, также вообще питание, контрастрость на дисплей. Но, я думаю, это понятно.

А вот так всё будет выглядеть на деле (нажмите на картинку для увеличения изображения)

Дисплей подключен у нас будет подключин также в 4-битном режиме и к тем же ножкам портов, как и в уроке 12.

Проект был создан с именем MyClock1307LCD. Все файлы, кроме главного скопированы туда и впоследствии подключены из проекта урока 17 MyClock1307.

Также к проекту подключены файлы для работы с дисплеем lcd.c и lcd.h. из проекта Test12, где мы работали с шиной USART.

Перейдём в главный модуль MyClock1307LCD.c. Код у нас здесь пока стандартный

#include «main.h»

//—————————————-

int main(void)

{

while(1)

{

}

}

Зайдём в файл lcd.c и исправим там функцию sendchar в sencharlcd во избежания совпадения имен с другими модулями

//—————————————-

void sendcharlcd(unsigned char c)

Также добавим для неё прототип и ещё прототип для функции очистки дисплея в файл lcd.h

void str_lcd (char str1);

void clearlcd(void);

void sendcharlcd(unsigned char c);

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

Функцию инициализации порта возьмём из урока по дисплею

#include «main.h»

//—————————————-

void port_ini(void)

{

PORTD=0x00;

DDRD=0xFF;

}

//—————————————-

Оттуда же возьмём в main() код инициализации порта и дисплея, а заодно его сразу и очистим

int main(void)

{

port_ini(); //Инициализируем порты

LCD_ini(); //Инициализируем дисплей

clearlcd(); //Очистим дисплей

Из главного модуля проекта из урока по часовой микросхемы возьмём инициализацию I2C

port_ini(); //Инициализируем порты

I2C_Init(); //Инициализируем шину I2C

LCD_ini(); //Инициализируем дисплей

Оттуда же возьмём глобальные переменные для хранения показаний регистров

#include «main.h»

//—————————————-

unsigned char sec,min,hour,day,date,month,year;

//—————————————-

Вполне нам может также пригодиться закомментированный код установки времени, вдруг придется устанавливать, так как кнопки мы пока не заводим

clearlcd(); //Очистим дисплей

//Устанавливаем время

// I2C_StartCondition();

// I2C_SendByte(0b11010000);

// I2C_SendByte(0);//Переходим на 0x00

// I2C_SendByte(RTC_ConvertFromBinDec(0)); //секунды

// I2C_SendByte(RTC_ConvertFromBinDec(31)); //минуты

// I2C_SendByte(RTC_ConvertFromBinDec(20)); //часы

// I2C_SendByte(RTC_ConvertFromBinDec(5)); //день недели

// I2C_SendByte(RTC_ConvertFromBinDec(29)); //дата

// I2C_SendByte(RTC_ConvertFromBinDec(1)); //месяц

// I2C_SendByte(RTC_ConvertFromBinDec(16)); //год

// I2C_StopCondition();

while(1)

Также возьмём пока всё полностью и из бесконечного цикла

while(1)

while(1)

{

//Читаем время

I2C_SendByteByADDR(0,0b11010000); //переходим на адрес 0

_delay_ms(300);

I2C_StartCondition(); //Отправим условие START

I2C_SendByte(0b11010001); //отправим в устройство бит чтения

sec = I2C_ReadByte();

min = I2C_ReadByte();

hour = I2C_ReadByte();

day = I2C_ReadByte();

date = I2C_ReadByte();

month = I2C_ReadByte();

year = I2C_ReadLastByte();

I2C_StopCondition(); //Отправим условие STOP

sec = RTC_ConvertFromDec(sec); //Преобразуем в десятичный формат

min = RTC_ConvertFromDec(min); //Преобразуем в десятичный формат

hour = RTC_ConvertFromDec(hour); //Преобразуем в десятичный формат

day = RTC_ConvertFromDec(day); //Преобразуем в десятичный формат

year = RTC_ConvertFromDec(year); //Преобразуем в десятичный формат

month = RTC_ConvertFromDec(month); //Преобразуем в десятичный формат

date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

USART_Transmit(date/10+0x30);//Преобразуем число в код числа

USART_Transmit(date%10+0x30);//Преобразуем число в код числа

USART_Transmit(‘.’);

USART_Transmit(month/10+0x30);//Преобразуем число в код числа

USART_Transmit(month%10+0x30);//Преобразуем число в код числа

USART_Transmit(‘.’);

USART_Transmit(year/10+0x30);//Преобразуем число в код числа

USART_Transmit(year%10+0x30);//Преобразуем число в код числа

USART_Transmit(‘ ‘);

USART_Transmit(‘-‘);

USART_Transmit(day+0x30);//Преобразуем число в код числа

USART_Transmit(‘-‘);

USART_Transmit(‘ ‘);

USART_Transmit(‘ ‘);

USART_Transmit(hour/10+0x30);//Преобразуем число в код числа

USART_Transmit(hour%10+0x30);//Преобразуем число в код числа

USART_Transmit(‘:’);

USART_Transmit(min/10+0x30);//Преобразуем число в код числа

USART_Transmit(min%10+0x30);//Преобразуем число в код числа

USART_Transmit(‘:’);

USART_Transmit(sec/10+0x30);//Преобразуем число в код числа

USART_Transmit(sec%10+0x30);//Преобразуем число в код числа

USART_Transmit(0x0d);//переход в начало строки

USART_Transmit(0x0a);//перевод каретки

}

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

date = RTC_ConvertFromDec(date); //Преобразуем в десятичный формат

setpos(0,0); //Ставим курсор на начало координат

Заменим в коде USART_Transmit на sendcharlcd пока там, где работаем с датой ,не со временем, а также перед показаниями года добавим «20», чтобы год смотрелся посолидней

setpos(0,0); //Ставим курсор на начало координат

sendcharlcd(date/10+0x30);//Преобразуем число в код числа

sendcharlcd(date%10+0x30);//Преобразуем число в код числа

sendcharlcd(‘.’);

sendcharlcd(month/10+0x30);//Преобразуем число в код числа

sendcharlcd(month%10+0x30);//Преобразуем число в код числа

sendcharlcd(‘.’);

sendcharlcd(‘2’);

sendcharlcd(‘0’);

sendcharlcd(year/10+0x30);//Преобразуем число в код числа

sendcharlcd(year%10+0x30);//Преобразуем число в код числа

sendcharlcd(‘ ‘);

sendcharlcd(‘-‘);

sendcharlcd(day+0x30);//Преобразуем число в код числа

sendcharlcd(‘-‘);

Так как мы с показаниями времени не влезем на 1 строку, поэтому переведём перед этим строку, а затем также исправим везде вызов функции на sendcharlcd, также уберём перевод строки и возврат каретки.

setpos(0,1); //Ставим курсор на начало координат

sendcharlcd(hour/10+0x30);//Преобразуем число в код числа

sendcharlcd(hour%10+0x30);//Преобразуем число в код числа

sendcharlcd(‘:’);

sendcharlcd(min/10+0x30);//Преобразуем число в код числа

sendcharlcd(min%10+0x30);//Преобразуем число в код числа

sendcharlcd(‘:’);

sendcharlcd(sec/10+0x30);//Преобразуем число в код числа

sendcharlcd(sec%10+0x30);//Преобразуем число в код числа

Попробуем собрать код и прошить контроллер.

Наши часы отлично ходят!

Барометр-сигнализатор для метеозависимых людей БС-1.

Владимир Макаров.

Введение.

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


Рисунок 1. Внешний вид устройства

Пользователь самостоятельно задает граничные значения – минимальный и максимальный пороги.
В случаях если атмосферное давление превысит максимальный порог или опустится ниже минимального порога, то устройство будет подавать прерывистые звуковые сигналы и световые сигналы «Порог».
После пятикратного повтора звуковых сигналов звук отключается, при этом световой сигнал будет подаваться до возврата значения атмосферного давления в заданные границы.
Пользователь задает величину контролируемого скачка атмосферного давления за устанавливаемый интервал времени.
В случаях если атмосферное давление в заданный интервал времени отклонилось на величину превышающую контролируемый скачок, то устройство будет подавать прерывистые звуковые сигналы и световые сигналы «Скачок».
После пятикратного повтора звуковых сигналов звук отключается, при этом световой сигнал будет подаваться до возврата значения атмосферного давления в условия, когда скачок считается неконтролируемым.
Значения атмосферного давления представлены в устройстве в «мм рт. ст.».

Демонстрационный ролик

Принципиальная схема устройства.

Схема электрическая принципиальная устройства показана на рисунке (Рисунок 2).
Устройство собрано на микроконтроллере ATmega8.
Резистор R1 и конденсатор C3 обеспечивают аппаратный сброс МК при подаче питания.
Конденсаторы C2 и C1 защищают цепи питания от высокочастотных помех и бросков питания.
Значение атмосферного давления поступает от датчика BMP1 (GY68 BMP180).
Управление датчиком давления осуществляется по интерфейсу TWI (I2C).
Входы датчика подтянуты к напряжению питания резисторами R8 и R10.
Для отображения информации используется жидкокристаллический экран Nokia 5110. На экране отображается информация о текущем атмосферном давлении, а также параметры настройки устройства.
Оперативная индикация состояния атмосферного давления осуществляется с использованием светодиодов VD1..3 («Норма», «Порог», «Скачек»).
Звуковая сигнализация осуществляется с помощью усилителя низкой частоты на транзисторах VT1..2 и громкоговорителя SP1. Громкость звучания может быть отрегулирована с помощью переменного резистора R5.
Настройка устройства осуществляется с использованием кнопок SA2(«Установка»), SA3(«+»), SA4(«-«).
При нажатии на кнопку SA5(«Экран») отображается главный экран с текущим значением атмосферного давления.
Внимание! Фьюзы для настройки МК: HIGH=0xD9, LOW=0xE1.


Рисунок 2. Схема электрическая принципиальная

Программное обеспечение.

Программа для МК написана на языке Си в среде AtmelStudio (Version 7.0.1006).
Код программы приведен в Приложении (SignalBarometer.rar Архив проекта Atmel Studio 7 на Си).
В целях снижения энергопотребления устройства применен метод «засыпания» МК в режиме «power-save». При этом потребляемый ток в режиме сна уменьшается до 20мкА.
По расчетам это позволяет использовать две батареи типа АА по 1.5 Вольт в течение 4 месяцев.
Для пробуждения МК из режима «power-save» используется внутренний асинхронный таймер-счетчик №2, который работает постоянно.
Задающий генератор таймера счетчика использует кварцевый резонатор Y1 с частотой резонанса 32768Гц.
Таймер-счетчик №2 настроен так, что каждые 8 секунд происходит его переполнение и вызов прерывания, которое «будит» МК.
МК после пробуждения от таймера-счетчика №2 выясняет не прошло ли 10 минут с предыдущего пробуждения. Если нет, то МК выдает световой сигнал «Норма», «Порог» или «Скачок» в зависимости от условия, сложившегося после предыдущего измерения, и снова засыпает на 8 секунд.
Если с момента предыдущего измерения прошло 10 минут, то МК подает команду датчику давления на проведение измерений, получает ответ от датчика, обрабатывает данные, сравнивая полученное значение с пороговыми значениями или условиями фиксации скачка, выдает световой сигнал «Норма», «Порог» или «Скачок» и звуковой сигнал, если это необходимо. И снова «засыпает» на 8 секунд.
Вторым источником пробуждения МК является внешнее прерывание на входе INT1, которое возникает при нажатии на кнопку «Экран».
МК, пробудившись и выяснив что его «разбудила» кнопка «Экран», включает жидкокристаллический дисплей Nokia 5110 и высвечивает на нем текущее значение атмосферного давления и другую информацию.
Экран будет отображать информацию до момента отпускания кнопки «Экран». После отпускания кнопки «Экран» МК выключает дисплей путем выдачи ему команды «power-down», затем МК «засыпает» сам.
Третьим, и последним, источником пробуждения МК является внешнее прерывание на входе INT0, которое возникает при нажатии на кнопку «Установка».
МК, пробудившись и выяснив что его «разбудила» кнопка «Установка», включает жидкокристаллический дисплей Nokia 5110 и высвечивает на нем параметры настройки устройства.
Повторное нажатие на кнопку «Установка» приводит к перемещению курсора на следующий параметр. Нажатие кнопок «+» и «-» приводит к изменению значения параметра, на котором установлен курсор.
После нажатия кнопки «Установка» на последнем параметре МК выключает дисплей и «засыпает» до очередного пробуждения.

Конструкция устройства.

Устройство выполнено в корпусе распределительной коробки «Tuco 79х79х32, для открытой проводки, цвет белый (65004)»(Рисунок 3).


Рисунок 3. Коробка распределительная Tyco (65004).

Плата выполнена на одностороннем фольгированном стеклотекстолите. Размер платы 72х72мм. Расположение деталей на плате показано на рисунке 4. На плате сверху проложены 9 (!) перемычек. Они выделены разными цветами. Если использовать двухстороннюю печатную плату, то перемычки могут быть преобразованы в дорожки.


Рисунок 4. Плата. Вид сверху.

Разводка печатной платы показана на рисунке 5. Изображение зеркальное.


Рисунок 5. Разводка печатной платы.

Динамик закрепляется на задней стенке корпуса устройства. Компоненты сборки показаны на рисунке 6.


Рисунок 6. Компоненты устройства.

Батареи питания (два элемента типа AA) размещаются в батарейном отсеке в специализированных держателях-кроватках (Рисунок 7).


Рисунок 7. Размещение батареи.

Настройка устройства.

На рисунке 8 показаны органы управления для настройки устройства.
Для входа в режим нажмите кнопку «Установка». На дисплее отобразятся настраиваемые параметры.
Кнопками «+» и «-» установите требуемое значение параметра.
Для перехода к настройке следующего параметра нажмите кнопку «Установка».
Для выхода из режима настройки нажмите несколько раз кнопку «Установка».
Параметры «Верхний <порог>», «Нижний <порог>» «Скачок» задаются в мм рт. ст., «Интервал» измерения скачка задается в часах. .


Рисунок 8. Органы настройки устройства.

Регулировка громкости звукового сигнала осуществляется потенциометром «Громкость». Для регулировки необходимо использовать миниатюрную крестообразную отвертку.
При необходимости может быть установлен потенциометр с выведенной наружу ручкой для удобства регулировки.

Эксплуатация устройства.

После включения устройство готово к работе и сразу производит первое измерение атмосферного давления. При этом экран погашен, а результаты измерения отображаются с помощью светодиодных индикаторов «Норма», «Порог» или «Скачок».
Индикатор, соответствующий результату измерения и анализа, производит пять коротких вспышек каждые 8 секунд.
При переходе от состояния «Норма» в состояния «Порог» или «Скачок» выдается звуковой сигнал. Сигнал звучит на протяжении пяти 8 секундных интервалов, начиная с интервала, следующего за изменением состояния.
Для детальной оценки текущего состояния необходимо нажать и удерживать кнопку «Экран». При этом будет отображаться информация, представленная на рисунке 9:
• текущее атмосферное давление;
• максимальное и минимальное значение давления, измеренного за интервал времени, указанный в настройках;
• величина скачка в мм рт.ст. как разница между величинами, указанными в предыдущем пункте;
• текстовая характеристика результата измерения: НОРМАЛЬНОЕ, ПОРОГ, СКАЧОК.
После нажатия кнопки «Экран» серия звуковых сигналов будет прервана.


Рисунок 9. Органы управления и индикации при эксплуатации устройства.

После отпускания кнопки «Экран» дисплей погаснет, а устройство продолжит работать в штатном режиме, выводя результат измерения и анализа только на светодиодные индикаторы.
Приложение:
SignalBarometer2.dch Схема электрическая в формате DipTrace
SignalBarometer2.dip Печатная плата в формате DipTrace
SignalBarometer.hex Загрузочный файл
SignalBarometer.rar Архив проекта Atmel Studio 7 на Си
Удачи Вам в творчестве и всего наилучшего!
Скачать архив.

Метеостанция на Arduino с беспроводным датчиком температуры

Как-то прогуливаясь по городу увидел новый открывшийся магазин радиоэлектроники. Зайдя в него обнаружил большое количество шилдов для Ардуины т.к. у меня дома была Arduino Uno и Arduino Nano сразу пришла мысль поиграться с передатчиками сигнала на расстоянии. Решил купить самый дешевый передатчик и приемник на 433 МГц:

Передатчик сигнала.

Приемник сигнала.

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

В просторах интернета сказано, что дальность передачи информации на 2Кб/сек может доходить до 150м. Сам не проверял, но в двухкомнатной квартире принимает везде.

Аппаратная часть домашней метеостанции

После нескольких экспериментов решил подключить к Arduino Nano датчик температуры, влажности и передатчик.

Подключение датчика температуры, влажности и передатчика

Датчик температуры DS18D20 подключается к ардуино следующим образом:

1) GND к минусу микроконтроллера.
2) DQ через подтягивающий резистор к земле и к выводу D2 Ардуины
3) Vdd к +5В.

Более детально почитать о работе датчика можно

Модуль передатчика MX -FS — 03V питается от 5 Вольт, вывод данных (ADATA) подключен к выводу D13.

К Ардуино Уно подключил LCD дисплей и барометр BMP085.

Схема подключение к ардуино уно

Приемник сигнала подключен к выводу D10.

Модуль BMP085 — цифровой датчик атмосферного давления. Датчик позволяет измерять температуру,давление и высоту над уровнем моря. Интерфейс подключения: I2C. Напряжение питания датчика 1.8-3.6 В

Подключается модуль к Arduino также, как и другие I2C устройства:

  • VCC — VCC (3,3 В);
  • GND — GND;
  • SCL — к аналоговому выводу 5;
  • SDA — к аналоговому выводу 4.
  • Очень низкая стоимость
  • Питание и I/O 3-5 В
  • Определение влажности 20-80% с 5% точностью
  • Определение температуры 0-50 град. с 2% точностью
  • Частота опроса не более 1 Гц (не более раза в 1 сек.)
  • Размеры 15.5мм x 12мм x 5.5мм
  • 4 вывода с расстоянием между ножками 0.1″

DHT имеет 4 вывода:

  1. Vcc (3-5V питание)
  2. Data out — Вывод данных
  3. Не используется
  4. Общий

Подключается к D8 Ардуины.

Программная часть домашней метеостанции

Передающий модуль измеряет и передает температуру раз в 10 минут.

Ниже привожу программу:

/* Версия скетча 1.0 Отсылаем температуру каждые 10мин. */ #include #include #include #define ONE_WIRE_BUS 2 //Пин подключения датчика Даллас OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; void setup(void) { //Serial.begin(9600); vw_set_ptt_inverted(true); // Необходимо для DR3100 vw_setup(2000); // Устанавливаем скорость передачи (бит/с) sensors.begin(); if (!sensors.getAddress(insideThermometer, 0)); printAddress(insideThermometer); sensors.setResolution(insideThermometer, 9); } void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); //Serial.print(«Temp C: «); //Serial.println(tempC); //Формирование данных для для отправки int number = tempC; char symbol = ‘c’; //Служебный символ определения что это датчик String strMsg = «z «; strMsg += symbol; strMsg += » «; strMsg += number; strMsg += » «; char msg; strMsg.toCharArray(msg, 255); vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); // Ждем пока передача будет окончена delay(200); } void loop(void) { for (int j=0; j <= 6; j++) { sensors.requestTemperatures(); printTemperature(insideThermometer); delay(600000); } } //Определение адреса void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress < 16); //Serial.print(«0»); //Serial.print(deviceAddress, HEX); } }

Приемное устройство принимает данные, измеряет давление и температуру в помещении и передает на дисплей.

#include #include LiquidCrystal lcd(12, 10, 5, 4, 3, 2); #include dht11 sensor; #define DHT11PIN 8 #include #include BMP085 dps = BMP085(); long Temperature = 0, Pressure = 0, Altitude = 0; void setup() { Serial.begin(9600); vw_set_ptt_inverted(true); // Необходимо для DR3100 vw_setup(2000); // Задаем скорость приема vw_rx_start(); // Начинаем мониторинг эфира lcd.begin(16, 2); Wire.begin(); delay(1000); dps.init(); //lcd.setCursor(14,0); //lcd.write(byte(0)); //lcd.home(); } void loop() { uint8_t buf; // Буфер для сообщения uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера if (vw_get_message(buf, &buflen)) // Если принято сообщение { // Начинаем разбор int i; // Если сообщение адресовано не нам, выходим if (buf != ‘z’) { return; } char command = buf; // Команда находится на индексе 2 // Числовой параметр начинается с индекса 4 i = 4; int number = 0; // Поскольку передача идет посимвольно, то нужно преобразовать набор символов в число while (buf != ‘ ‘) { number *= 10; number += buf — ‘0’; i++; } dps.getPressure(&Pressure); dps.getAltitude(&Altitude); dps.getTemperature(&Temperature); //Serial.print(command); Serial.print(» «); Serial.println(number); lcd.print(«T=»); lcd.setCursor(2,0); lcd.print(number); lcd.setCursor(5,0); lcd.print(«P=»); lcd.print(Pressure/133.3); lcd.print(«mmH»); lcd.setCursor(0,1); lcd.print(«T=»); lcd.print(Temperature*0.1); lcd.print(» H=»); lcd.print(sensor.humidity); lcd.home(); //delay(2000); int chk = sensor.read(DHT11PIN); switch (chk) { case DHTLIB_OK: //Serial.println(«OK»); break; case DHTLIB_ERROR_CHECKSUM: //Serial.println(«Checksum error»); break; case DHTLIB_ERROR_TIMEOUT: //Serial.println(«Time out error»); break; default: //Serial.println(«Unknown error»); break; } } }

P.S. В дальнейшем планирую добавить следующее:
— датчик влажности к передатчику, переработать алгоритм передачи данных
— датчик измерения скорости и направления ветра.
— в приемное устройство добавить другой дисплей.
— приемник и передатчик перевести на отдельный микроконтроллер.

Ниже прилагаю фото того что получилось:

Список радиоэлементов

Обозначение Тип Номинал Количество Примечание Магазин Мой блокнот
Передающая часть.
Плата Arduino Arduino Nano 3.0 1 Поиск в Utsource В блокнот
Датчик температуры DS18B20 1 Поиск в Utsource В блокнот
Резистор 220 Ом 1 Поиск в Utsource В блокнот
Модуль передатчика MX-FS-03V (433 МГц) 1 Поиск в Utsource В блокнот
Радиоприемная часть.
Плата Arduino Arduino Uno 1 Поиск в Utsource В блокнот
Подстроечный резистор 1 Поиск в Utsource В блокнот
Резистор 220 Ом 1 Поиск в Utsource В блокнот
Цифровой датчик атмосферного давления ВМР085 1 Поиск в Utsource В блокнот
Интерфейс подключения барометра 12С 1 Поиск в Utsource В блокнот
LCD-дисплей 1 Поиск в Utsource В блокнот
Радиоприемный модуль 433 МГц 1 Поиск в Utsource В блокнот
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

Погода в доме: беспроводной метеодатчик из Arduino Pro Mini

В прошлом рассказе про то, что можно сделать из Arduino, мне предложили делать погоду и бросать ее в сеть. Не сказать, чтобы это мне это было сильно нужно, но сама идея осталась в голове и это обстоятельство представляло хотя и смутное, но постоянное беспокойство.
Так что я решил попробовать, и закрыть этот вопрос раз и навсегда. Тем более, что тот самый рассказ стал призовым, и позволил мне купить практические все необходимое, чтобы решить задачу.
В некотором смысле это спасибо MySKU и всем, кому понравились игрушки из Arduino.
ЖЕЛЕЗКИ
Arduino Pro Mini
Плата совершенно крошечная. Я даже не ожидал, что настолько. Но при этом на ней — взрослый чип ATmega328, так что по производительности она не уступает той же Uno. Это версия 5В, питается или от 5В стабилизированного по любому пину VCC или же от 5 — 12В по пину RAW (если верить Arduino.cc). По-моему, очень удобно.
Комплект передатчик-приемник ASK/OOK 433 МГц
Это уже проверенные (не в этом магазине, а вообще) простейшие приемники и передатчики с амплитудной модуляцией. У них нет никаких средств коррекции ошибок и контроля передачи, зато они крайне дешевы и без проблем работают с нужными мне устройствами (розетками, выключателями и с самими собой).
Живые фото можно посмотреть в предыдущем тексте про Arduino.
Преобразователь Serial — USB
Очень простой, недорогой и универсальный — есть питание 5В и 3.3В на выбор. Нужен, чтобы загружать код в Arduino Pro Mini, так как у платы нет своего USB. Шлейф, который вы видите на фото, входит в комплект. И хотя ничего необычного в нем нет — обычные четыре провода, все равно приятно.
Датчик влажности и температуры DHT21
Заказывал часы для жены, но DX ошибся с заказом, ошибку признал и вернул стоимость на счет в магазине. Так что вместо часов жене получился датчик температуры мне любимому. Этот датчик выбран за разумную цену (вообще, а не в DX), широкий диапазон измерений и точность до десятых. Кроме того, в отзывах на DX писали, что он полностью совместим с DHT22, для которого есть готовые библиотеки для Arduino.

Пара слов о продавце на eBay С одной стороны, в магазине приятные цены, все выслали достаточно быстро, и почти все пришло в рабочем состоянии.
Исключение — один приемник, который не включился. Возможно, он настроен на другую частоту и поэтому я не увидел сигнала на выходе. С этим буду разбираться позже, но пока факт остается фактом — в текущем состоянии один приемник оказался бесполезен.
Другой минус состоит в том, что бесплатная доставка — без номера для отслеживания. А так как я эти номера все же люблю, то заплатил за него, как и было предложено в письме-подтверждении заказа. При этом продавец предлагает оплатить трек-номер на отдельный эккаунт PayPal.

Итог: сначала мне больше недели номер вообще не давали. Потом, когда я пообещал диспут, выдали с интервалом в день сразу два трек-номера. Один был явно левым, поскольку дата приема посылки по нему была раньше даты заказа.
Другой казался нормальным ровно до импорта в России. Как только появился индекс места назначения стало понятно, что это посылка не моя, а какого-то счастливчика из Обнинска.
Ну а потом уже пришла моя посылка — без каких-либо трек-номеров. Поэтому поводу я еще немного поскандалил с продавцом, и в конечном итоге плату за трек-номер мне вернули.
Впечатления двойственные: с одной стороны, в магазине очень приятные цены. С другой — получается какая-то лотерея.
ФИЗИЧЕСКИЙ УРОВЕНЬ
За громким заголовком суровая правда: дома на боевом дежурстве живет небольшая коробочка с Arduino Uno, подключенная к сети через Ethernet-шилд.
В этой коробочке также есть копия упомянутого выше ASK/OOK приемника для получения сигналов с домашних датчиков (протечки, открытия дверей и т.п.).
Это определило некое подобие клиент-серверной модели для подключения метеодатчика. То есть, метеодатчик на базе Arduino Pro Mini отправляет данные температуры и влажности коробке, а она, в свою очередь, отправляет их в интернет.
Отвечаю на очевидные вопросы )
Q: Почему примитивные приемники, а не, скажем, рекомендованные ранее чудесные nRF24L01, которым не страшны помехи, которые легко объединяются в сеть и вообще идеальны для такого применения?
A: Во-первых, кажется, я просто боюсь, что потрачу слишком много времени на усвоение методики работы с nRF24L01. Во-вторых, у меня (то есть, у Arduino Uno в коробке) заканчивается все — пины, память. А нужно подключить еще несколько устройств: пищалку, датчик движения.
Между тем, в коробке уже есть все, что нужно для получения метеоданных — и приемник, и библиотека RC-Switch, которая вполне подходит не только для управления розетками, но для передачи нескольких символов. Почему бы не воспользоваться уже имеющимися ресурсами?
Q: Почему тогда не Virtual Wire?
A: Ответ, в общем, выше — еще одна библиотека, еще меньше памяти. С практической точки зрения такой радиоканал можно назвать слабым местом системы. Но, если задуматься, вся моя система — сплошное слабое место, так сказать, by design.
Q: почему бы не подключить Arduino Pro Mini к сети напрямую?
A: Дело в том, что для минимального количества проводов я планирую поставить датчик на окно, а рядом нет ни сетевых, ни электрических розеток. Это раз.
И два: Wi-Fi-шилд для Arduino или комбинация из электрической розетки с Ethernet и обычного Ethernet-шилда Arduino стоят совершенно неразумных для решения этой задачи денег.
Q: Почему не меряем атмосферное давление?
A: Потому что датчик сразу не заказал, и в итоге он еще не приехал. А попробовать очень хотелось.
Q: У тебя же есть метеостанция с беспроводным датчиком. Почему не используешь его, а городишь огород на пустом месте?
A: Честно говоря, огород для меня проще, чем писать код для обработки сигнала. Потом, может быть, попробую. А сейчас так гораздо быстрее.
ЛОГИЧЕСКИЙ УРОВЕНЬ
Для логической основы радиоканала я решил воспользоваться возможностями библиотеки RC-Switch. Она предназначена для управления беспроводными розетками, но методика управления позволяет использовать ее и для передачи данных. Медленно, не очень надежно, но — позволяет.
Суть в том, что команда розетки — всего лишь цифровой код. При этом RC-Switch совершенно безразлично, какой именно код передавать. Главное — не больше 24 бит, то есть не больше 16777216.
В итоге мой протокол передачи метеоданных выглядит следующим образом:
Первые три цифры — идентификатор датчика
Четвертая цифра — тип данных (1 — влажность, 0 — температура)
Пятая цифра — знак температуры (1 — отрицательная, 0 — положительная)
Остальные цифры — величина
Например, чтобы передать температуру 23.5С нужно отправить через RC-Switch код 16100235.
Плюсы примитивного «кодирования»: достаточно всего одного действия арифметики, чтобы выделить передаваемую величину. Минусы — один «пакет» для одного значения.
ПРАКТИЧЕСКАЯ РЕАЛИЗАЦИЯ
Arduino Pro Mini поставляется в комплекте с контактными планками. При желании их можно напаять на плату. А при необходимости сделать максимально компактную конструкцию провода можно паять прямо к контактным площадкам платы.
Я выбрал первый вариант — мне так проще, да и плату, если что, легче использовать повторно.
После беглого ознакомления с датчиком температуры и влажности DHT21 выяснилось, что напрямую подключать его к Arduino не очень правильно. Оказывается, правильная схема включает «подтягивающий» резистор 4.7 кОм между плюсом и линией данных. Мне повезло — нужный резистор выкусил из ненужного беспроводного звонка.
Для питания прототипа я воспользовался ненужной «аварийной» зарядкой для мобильного телефона. Это такой цилиндрик: с одной стороны вставляем батарейку AA 1.5В, а с другой получаем 5.9В (без нагрузки). Для страховки я подключил выход зарядки к входу RAW Arduino Pro Mini, чтобы все компоненты (плата и датчик) получали стабилизированные 5В. По крайней мере, из описания платы можно заключить, что RAW принимает от 5В до 12В, при этом на контактах VCC — стабилизированные 5В.
Дальше все просто. Подключаем передатчик, датчик и пишем простой код. В моем случае для кода потребовались три библиотеки: RC-Switch (передача данных), SimpleTimer (отсчет интервалов для передачи) и DHT22 (получение данных с датчика температуры и влажности).
А вот и прототип:
Схема работы: раз в пять минут опрашиваем датчик и попеременно отправляем температуру и влажность. За одну сессию можно передать только один параметр, поэтому «большая сестра» получает их по очереди, а потом скопом отправляет в Open Weather Map. В результате данные в интернете обновляются раз в десять минут.
Почему такой интервал? Потому что, во-первых, каждая сессия — это занятый радиоканал (а у меня есть и другие радиодатчики, требующие внимания) и отнятое процессорное время. Так что это попытка минимизировать издержки.
Во-вторых, я не такой уж и погодный маньяк, чтобы обновлять погоду каждую секунду.
И третье. Интервал в пять минут, по-моему, более-менее рационален с точки зрения энергетики, так как я планирую питать метеодатчик от батареек.
Для записи кода в плату соединяем Arduino Pro Mini с компьютером через преобразователь Serial — USB и не забываем «перекрестить» линии TX/RX, то есть: RX подключаем к TX, и наоборот — TX к RX. Для питания берем пин 5В, потому что эта версия Arduino — 5В.
Секрет: если заливка программы не удается (ошибка типа avrdude: stk500_getsync(): not in sync: resp=0x00), помогает такая процедура:
1) Нажимаем кнопку загрузки программы в среде разработки Arduino
2) Ждем пока загорится красный светодиод на преобразователе Serial — USB
3) Нажимаем кнопку сброса на Arduino Pro Mini
Если не получилось — ждем, пока погаснет красный светодиод на преобразователе и повторяем процедуру.
Со стороны «большой сестры» нужно только добавить несколько фрагментов кода для получения метеоданных из радиоканала и отправки их в интернет. Для примера — готовый код по ссылке в конце текста, который подходит для использования с Arduino Uno как в монопольном режиме, так и в составе вашего кода (если, разумеется, разобрать исходник на нужные части).
Если будете использовать — не забудьте подставить свои IP/MAC, ключ авторизации OpenWeatherMap и координаты метеодатчика.
А вот так метеодатчик выглядит почти в финальной (ну или вообще финальной, если нет ничего более постоянного, чем временное) версии:
НА ДЕРЕВНЮ, ДЕДУШКЕ
Итак, метеоданные получили, передали и приняли. Ок. И что делать с этим счастьем? Мне советовали отправлять его в Openweathermap.org, поскольку дело хорошее и вообще. Я проникся и немного изучил вопрос, хотя такое ощущение, что Openweathermap это совершенно не нужно.
Так что получилось, скорее, не благодаря, а вопреки. Спасибо нашему чуваку, который сделал интернет-метеостанцию и рассказал о ней, Wiki за описание базовой аутентификации HTTP и чудесному сервису hurl.it, который имитирует HTTP-запросы и показывает их тело, что важно для кода. Ах да, еще большое спасибо онлайновым сервисам кодирования Base64.
Иными словами, документация на Openweathemap upload API говорит, что нужна аутентификация HTTP Basic и описывает имена и форматы полей данных, но не дает практических примеров, что нужно таким безмозглым, как я.
Как все получилось.
Сначала я зарегистрировался на Openweathermap.org.
Потом выяснил, что для HTTP Basic нужна строка авторизации, состоящая из имени и пароля, разделенных двоеточием и кодированных Base64. Так что взял логин и пароль, пошел в онлайновый кодер и на выходе получил нужную строчку.
Например, для имени test и пароля test она выглядит так: dGVzdDp0ZXN0
Как результат, строка авторизации Openweathermap выглядит так:
Authorization: Basic dGVzdDp0ZXN0
Берем ее и составляем тестовый запрос в Openweathermap и смотрим тело запроса:
Обратите внимание, что если все правильно, то «тест» отправляет данные в Openweathermap. Я эту проблему решил просто: подставлял актуальную информацию о погоде из своего региона.
Полученный таким образом текст запроса можно запросто использовать в коде Arduino: строчки печатаются в HTTP-клиент.
Плюсы: в целом все довольно просто.
Минусы: у Openweathermap отсутствуют адекватные (с моей точки зрения, разумеется) методы визуализации данных. Доступны только запросы к БД с выдачей результатов для визуализации «на стороне».
КАК ЭТО РАБОТАЕТ
Все просто. Метеодатчик получает температуру и влажность от DHT21, и отправляет их Arduino Uno, подключенной к интернету.
Оттуда данные уходят на Openweathermap (чего добру пропадать?), где их можно посмотреть в онлайне и где они, вероятно, используются для прогноза погоды.
Желающим понаблюдать за местной (Россия, Москва, СВАО, Лианозово) погодой: мой метеодатчик на Openweathermap.org.
А ТЕПЕРЬ О ПРОБЛЕМАХ
Так как руки у меня растут все-таки не совсем из правильного места, то я закономерно наступил на несколько художественным образом разложенных грабель.
Во-первых, несмотря на то, что авторы библиотеки DHT22 заверяли, что они решили проблему с отрицательными температурами, мне это не помогло. При минусе библиотека начала выдавать совершенно нереальные показания, что в обсуждениях обосновывали ошибкой переполнения.
Т.е. вместо -4.5С мне показывали 32763,5. Я не стал переписывать библиотеку (см. выше про руки), а просто стал вычитать полученное значение из 32768 (максимальное значение для заданного типа переменной).
Во-вторых, практически сразу после первого включения метеодатчика выяснилась печальная особенность: на кухонном столе (около 2.5 метров до приемника) он еще работал, а вот на балконе (около 4 метров) — нет. После изучения кода и прочего стало понятно, что проблема, все-таки и не в нем, и не в батарейках.
Подозрение пало на антенны, которые я сделал из простых кусочков провода. Чтение этих ваших интернетов догадки подтвердило: диапазон 433 МГц — довольно коварная в плане распространения волн штука. Поэтому антенну лучше делать хотя бы минимально похожей на антенну, а не изгибать проводочки под причудливыми углами, лишь бы в корпус поместилось.
В итоге я заменил все проводки на штыри из одножильного медного провода (просто купил пару метров (с запасом, да) 2х1.5 электрического кабеля, и распотрошил его на жилы. Длина штырей как и раньше — около 17.3 см, т.е. четверть волны. Все ориентированы вертикально.
Результат — теперь не только метеодатчик работает на балконе, но и другие беспроводные датчики в квартире работают гораздо более уверенно.
Третья очевидная проблема — совершенно зверское потребление энергии. Двух батареек 14500 по 1000 мАч хватает где-то на пару суток. Т.е., по грубым прикидкам метеодатчик кушает около 20 мА. Говорят, что одна из наиболее прожорливых частей — встроенный стабилизатор напряжения, но от него я избавиться как раз и не могу, потому что пока не вижу, как в батарейный отсек на две АА можно разместить автономный источник 5В.
Поэтому рассматриваю две альтернативы. Первая — эксперименты со «спящим» режимом. Вторая — бросить эти девичьи мечты об автономности и запитать уже от электрической сети.
Ну а пока наслаждаюсь тем, что датчик вообще работает 🙂
ССЫЛКИ
Библиотека RC-Switch
Библиотека DHT22
Библиотека SimpleTimer
Сервис для тест HTTP-запросов hurl.it
Сервис кодирования Base64
Код метеодатчика
Код принимающей стороны

На картинке Вы можете увидеть переднюю часть ESP8266 с 8 маркированными контактами. ESP8266 питается от 3.3 В, так что удостоверьтесь, что Вы соединяете контакт Vcc с 3.3-вольтовым контактом на контроллере. Это также означает, что Вы должны будете использовать преобразователь логических уровней или собрать делитель напряжения для последовательного соединения от платы контроллера до ESP8266, чтобы ничего не сжечь. Если Вы не захотите покупать преобразователь логических уровней, тогда, то Вы должны будете собрать делитель напряжения, задействовав два резистора.

Я взял резистор на 220 Ом и резистор на 470 Ом, которые приблизительно дадут 3.3 В. Если приемопередатчик требует 3.3 В, а плата контроллера может работать при таком напряжении, нет никакой потребности делать что-либо с соединением приемопередатчик — контроллер.

Точность датчика составляет только +/-5% влажности и 2°C, так что это не самый точный датчик. Он подходит только для температуры выше нуля. DHT22 более точен и умеет в отрицательные температуры, поэтому, если это важно для Вас, выбирайте его. Оба датчика работают с напряжениями 3.3 — 5В. Сигнальный контакт должен быть подключен через токоограничивающий резистор, номиналом 4.7 кОм.

Схема отображает как соединить провода. Для простоты использования все соединения с 5 В или 3.3 В красные, и все соединения с общим проводом синие. Подключаем провода следующим образом:

С контроллера на приемопередатчик

— RXD | TXD

— TXD | RXD (через делитель напряжения)

— 3.3 В | Vcc, CH_PD, сброс

— GND | GND

С контроллера на датчик температуры/влажности

— 5 В | Vcc

— GND | GND

— D7 | Сигнал (соединение с Vcc через нагрузочный резистор)

Шаг 4: Программирование

Прежде чем использовать код, Вы должны будете загрузить и установить библиотеку DHT от Adafruit. У них есть описание того, как установить, пользоваться их библиотекой и заходить на их хранилище GitHub. Их библиотека имеет разные опции (такие как теплосчетчик — их мы не будем разбирать здесь), но Вы можете самостоятельно выбрать их и использовать, если Вам понадобится!

Бод для ESP8266 установлен в начале .ino файла. Версия ESP8266, которая использовалась в сборке, поддерживает значения 9600 или 115200 бод. Обе из микросхем, которые я заказывал, установлены в 115200 бодов. Но если у вас возникли ошибки, смените бод на 9600 в качестве первого шага в отладке.

Есть несколько мест в коде со значениями в скобках ‘<‘ ‘>’. Это- те места, где Вам нужно будет вставить свои собственные значения, чтобы завершить проект. Это включает имя и пароль для Вашей сети WiFi и ключ для Вашего канала ThingSpeak. Есть код, чтобы использовать красно-зеленый светодиод для отладки и контроля состояния системы, но это не отображено в монтажных схемах. Если Вы хотите знать, верно ли работает работает система, Вы можете добавить пару светодиодов.

Заключительная ремарка, которая может сбить с толку — нельзя загрузить скетч в ардуино, к которому подключен модуль беспроводной связи. Скетч не загрузится, если они будут соединены, так что Вам нужно сначала отсоединить информационный провод — либо с передатчика, либо с контроллера.

Скачать скетч для Arduino IDE —

Шаг 5: Поехали!

Поздравляю! Вы создали свой персональный беспроводной регистратор температуры и влажности! Вы великолепны! Можно оставить его в подвале и контроллировать влажность и температуру посредством проветривания/обогрева. Можно собрать его на печатной плате для удобства монтажа и использования на месте. Я надеюсь, что вам был полезен этот урок и Вы весело провели время! Следующим шагом можно попробовать запрограммировать ESP8266 непосредственно напрямую, в обход контроллера.

Статья перевод с сайта ingenerium.net

Оригинал статьи был на instructables.com (уже лень искать ссылку на саму статью)

Самые простые часы с индикацией на экране LCD1602

С момента приобретения arduino, все никак не было или возможности или времени что-то сделать, начать «изучать» это дело. Но всегда был интерес к любому программированию будь то C, VHDL и прочее.

И вот однажды попал мне в руки экранчик lcd1602, где-то раньше читал, что его под ардуинку собирают. А у меня как раз с распайкой под пины, наверное от какого-нибудь ардуновского набора. Ну и решил, что надо бы его проверить, но проверить его простым включением и выводом текста не слишком интересно. Так и появилась идея написать банально часы и выводить это всё на экранчик.

Наверное стоит обговорить еще тот факт, что это самые простые часы, без кнопок, будильников, погоды и прочего.

После чтения даташитов и изучения информации по подключению экрана к ардуинке получил следующую схему:

При подключении ардуино к usb увидите, что экран загорится синим. На нем должны появится квадратики (экран проинициализирован), если вы их не видите попробуйте покрутить переменный резистор.

Приступим к написанию кода. Логика программы думаю понятна всем, она ровным счетом такая же, как и в любых часах. То есть: Считаем секунды, дошли до 60 — прибавляем минуту, секунды обнуляем, минуты дошли до 60, прибавляем час, обнуляем минуты и секунды.

Вот собственно и сам код программы, с подробнейшими комментариями:

#include <LiquidCrystal.h> //Подключим библиотеку для работы с дисплеем LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // (RS, E, DB4, DB5, DB6, DB7) //Подключение лисплея к пинам ардуино в моем случае УНО int m=9; //минуты int h=13; //часы int s=55; //секунды void setup() { } void loop() { s=s+1; //считаем секунды delay(990); //пауза для отсчета секунд (подбирается эксперементально) if (s==60) //при 60секундах { s=0; //обнуляем секунды m=m+1; //добавляем минуту if(m==60) //при 60 минутах { m=0; // обнуляем минуты h=h+1; //добавляем час } } //Вывод на дисплей //Вывод времени lcd.begin(16, 2); //Задаем размерность экрана формат : кол-во символов в строке на кол-во строк lcd.setCursor(0, 0); //Устанавливаем курсор в начало 1й строки lcd.print(«Time:»); //Выводим надпись «Time:» lcd.setCursor(6, 0); //Устанавливаем курсор в 6й знак, 1й строки lcd.print(h); //Выводим часы lcd.setCursor(8, 0); //Устанавливаем курсор в 8й знак, 1й строки lcd.print(«:»); //Вывод двоеточие lcd.setCursor(9, 0); //Устанавливаем курсор в 8й знак, 1й строки lcd.print(m); //выводим минуты lcd.setCursor(11, 0); //Устанавливаем курсор в 8й знак, 1й строки lcd.print(«:»); // Вывод двоеточие lcd.setCursor(12, 0); //Устанавливаем курсор в 8й знак, 1й строки lcd.print(s); //Выводим секунды }

Всё! Готово, прошиваемся и смотрим что получилось:

Всё, работает. Надеюсь что статья поможет кому-нибудь. Если будет интересно, то напишу следуюущую статью, где сделаем часы + дата. Спасибо за внимание.

Самодельные часы на ардуино с lcd 1602. Пояснения к коду. Способ программирования Arduino для работы с DS1302

При сборке своего металлоискателя у меня на руках оказался LCD дисплей 1602, построенный на контроллера HD44780. Решил не упустить возможность и подключить его к своему китайскому аналогу Arduino UNO.

Вот такой дисплей 1602 будем сегодня подключать к Arduino.

Цифры «1602» говорят о том, что дисплей состоит из 2-х строк, по 16 символов. Это довольно распространённый экран, с применением которого народ конструирует часы, тестеры и прочие гаджеты. Дисплей бывает с зелёной и голубой подсветкой.

К дисплею я припаял гребёнку контактов, что бы можно было легко подключать провода.

Подключать дисплей 1602 к Arduino будем через 4-битный вариант параллельного интерфейса. Существует вариант и 8-битного интерфейса, но при нём задействуется больше проводов, а выигрыша в этом мы не увидим.

Кроме дисплея и Arduino, нам понадобятся провода и переменный резистор на 10кОм. Резистор подойдёт любой марки, лишь бы был необходимого номинала.

Питание на дисплей подаётся через 1-й (VSS) и 2-й (VDD) выводы. К выводам 15 (А) и 16 (K) — подаётся питание на подсветку дисплея. Поскольку для питания и подсветки используется одно напряжение +5В, запитаем их от пинов Arduino «5V» и «GND» . Главное не перепутать полярность, иначе можно спалить электронику дисплея.

3-й вывод (V0) подключаем к ножке переменного резистора, им будем управлять контрастностью дисплея. Резистор можно не использовать, а вывод «V0» подключить к GND . В таком случае контрастность будет максимальной и не будет возможности её плавной регулировки.

5-й вывод (RW) используется для чтения с дисплея либо для записи в него. Поскольку мы будем только писать в дисплей, соединим этот вывод с землёй (GND) .

Моя подключённая Ардуина, осталось соединить её с компьютером через USB и залить скетч.

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

В Arduino IDE выбираем «Файл» — «Образцы» — «LiquidCrystal» — «HelloWorld» .

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

В строке «LiquidCrystal lcd» , в скобках, выставлены цифровые пины, которые задействованы на Arduino. Пины выставляются в такой последовательности: RS, E, DB4, DB5, DB6, DB7 . Если вы задействовали другие цифровые пины, при подключении дисплея, впишите их в нужной последовательности в скобках.

Загружаем скетч в Arduino и вот результат. Вместо «hello, world!» я вписал свой сайт. Строкой ниже, таймер производит отсчёт времени.

LCD дисплей Arduino позволяет визуально отображать данные с датчиков. Расскажем, как правильно подключить LCD монитор к Arduino по I2C и рассмотрим основные команды инициализации и управления LCD 1602. Также рассмотрим различные функции в языке программирования C++, для вывода текстовой информации на дисплее, который часто требуется использовать в проектах на Ардуино.

Видео. Arduino LCD Display I2C 1602

LCD 1602 I2C подключение к Arduino

I2C — последовательная двухпроводная шина для связи интегральных схем внутри электронных приборов, известна, как I²C или IIC (англ. Inter-Integrated Circuit). I²C была разработана фирмой Philips в начале 1980-х годов, как простая 8-битная шина для внутренней связи между схемами в управляющей электронике (например, в компьютерах на материнских платах, в мобильных телефонах и т.д.).

В простой системе I²C может быть несколько ведомых устройств и одно ведущее устройство, которое инициирует передачу данных и синхронизирует сигнал. К линиям SDA (линия данных) и SCL (линия синхронизации) можно подключить несколько ведомых устройств. Часто ведущим устройством является контроллер Ардуино, а ведомыми устройствами: часы реального времени или LCD Display.

Как подключить LCD 1602 к Ардуино по I2C

Жидкокристаллический дисплей 1602 с I2C модулем подключается к плате Ардуино всего 4 проводами — 2 провода данных и 2 провода питания. Подключение дисплея 1602 проводится стандартно для шины I2C: вывод SDA подключается к порту A4, вывод SCL – к порту A5. Питание LCD дисплея осуществляется от порта +5V на Arduino. Смотрите подробнее схему подключения жк монитора 1602 на фото ниже.

Для занятия нам понадобятся следующие детали:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • LCD монитор 1602;
  • 4 провода «папа-мама».

После подключения LCD монитора к Ардуино через I2C вам потребуется установить библиотеку LiquidCrystal_I2C.h для работы с LCD дисплеем по интерфейсу I2C и библиотека Wire.h (имеется в стандартной программе Arduino IDE). Скачать рабочую библиотеку LiquidCrystal_I2C.h для LCD 1602 с модулем I2C можно на странице Библиотеки для Ардуино на нашем сайте по прямой ссылке с Google Drive.

Скетч для дисплея 1602 с I2C

#include // библиотека для управления устройствами по I2C #include // подключаем библиотеку для LCD 1602 LiquidCrystal_I2C lcd(0x27,20,2); // присваиваем имя lcd для дисплея 20х2 void setup () // процедура setup { lcd.init (); // инициализация LCD дисплея lcd.backlight (); // включение подсветки дисплея lcd.setCursor (0,0); // ставим курсор на 1 символ первой строки lcd.print («I LOVE»); // печатаем сообщение на первой строке lcd.setCursor (0,1); // ставим курсор на 1 символ второй строки lcd.print («ARDUINO»); // печатаем сообщение на второй строке } void loop () // процедура loop { /* это многострочный комментарий // изначально процедура void loop() в скетче не используется lcd.noDisplay(); // выключаем подсветку LCD дисплея delay(500); // ставим паузу lcd.display(); // включаем подсветку LCD дисплея delay(500); // ставим паузу */ }

Пояснения к коду:

  1. библиотека LiquidCrystal_I2C.h содержит множество команд для управления LCD дисплея по шине I²C и позволяет значительно упростить скетч;
  2. скетч содержит многострочный комментарий /* … */ , который позволяет закомментировать сразу несколько строк в программе.
  3. перед выводом информации на дисплей, необходимо задать положение курсора командой setCursor(0,1) , где 0 — номер символа в строке, 1 — номер строки.

Во многих проектах Ардуино требуется отслеживать и фиксировать время наступления тех или иных событий. Модуль часов реального времени, оснащенный дополнительной батарей, позволяет хранить текущую дату, не завися от наличия питания на самом устройстве. В этой статье мы поговорим о наиболее часто встречающихся модулях RTC DS1307, DS1302, DS3231, которые можно использовать с платой Arduino.

Модуль часов представляет собой небольшую плату, содержащей, как правило, одну из микросхем DS1307, DS1302, DS3231.Кроме этого, на плате практически можно найти механизм установки батарейки питания. Такие платы часто применяется для учета времени, даты, дня недели и других хронометрических параметров. Модули работают от автономного питания – батареек, аккумуляторов, и продолжают проводить отсчет, даже если на Ардуино отключилось питание. Наиболее распространенными моделями часов являются DS1302, DS1307, DS3231. Они основаны на подключаемом к Arduino модуле RTC (часы реального времени).

Часы ведут отсчет в единицах, которые удобны обычному человеку – минуты, часы, дни недели и другие, в отличие от обычных счетчиков и тактовых генераторов, которые считывают «тики». В Ардуино имеется специальная функция millis(), которая также может считывать различные временные интервалы. Но основным недостатком этой функции является сбрасывание в ноль при включении таймера. С ее помощью можно считать только время, установить дату или день недели невозможно. Для решения этой проблемы и используются модули часов реального времени.

Электронная схема включает в себя микросхему, источник питания, кварцевый резонатор и резисторы. Кварцевый резонатор работает на частоте 32768 Гц, которая является удобной для обычного двоичного счетчика. В схеме DS3231 имеется встроенный кварц и термостабилизация, которые позволяют получить значения высокой точности.

Сравнение популярных модулей RTC DS1302, DS1307, DS3231

В этой таблице мы привели список наиболее популярных модулей и их основные характеристики.

Название Частота Точность Поддерживаемые протоколы
DS1307 1 Гц, 4.096 кГц, 8.192 кГц, 32.768 кГц Зависит от кварца – обычно значение достигает 2,5 секунды в сутки, добиться точности выше 1 секунды в сутки невозможно. Также точность зависит от температуры. I2C
DS1302 32.768 кГц 5 секунд в сутки I2C, SPI
DS3231 Два выхода – первый на 32.768 кГц, второй – программируемый от 1 Гц до 8.192 кГц ±2 ppm при температурах от 0С до 40С.

±3,5 ppm при температурах от -40С до 85С.

Точность измерения температуры – ±3С

I2C

Модуль DS1307

DS1307 – это модуль, который используется для отсчета времени. Он собран на основе микросхемы DS1307ZN, питание поступает от литиевой батарейки для реализации автономной работы в течение длительного промежутка времени. Батарея на плате крепится на обратной стороне. На модуле имеется микросхема AT24C32 – это энергонезависимая память EEPROM на 32 Кбайт. Обе микросхемы связаны между собой шиной I2C. DS1307 обладает низким энергопотреблением и содержит часы и календарь по 2100 год.

Модуль обладает следующими параметрами:

  • Питание – 5В;
  • Диапазон рабочих температур от -40С до 85С;
  • 56 байт памяти;
  • Литиевая батарейка LIR2032;
  • Реализует 12-ти и 24-х часовые режимы;
  • Поддержка интерфейса I2C.

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

Взаимодействие с другими устройствами и обмен с ними информацией производится с помощью интерфейса I2C с контактов SCL и SDA. В схеме установлены резисторы, которые позволяют обеспечивать необходимый уровень сигнала. Также на плате имеется специальное место для крепления датчика температуры DS18B20.Контакты распределены в 2 группы, шаг 2,54 мм. В первой группе контактов находятся следующие выводы:

  • DS – вывод для датчика DS18B20;
  • SCL – линия тактирования;
  • SDA – линия данных;
  • VCC – 5В;

Во второй группе контактов находятся:

  • SQ – 1 МГц;
  • BAT – вход для литиевой батареи.

Для подключения к плате Ардуино нужны сама плата (в данном случае рассматривается Arduino Uno), модуль часов реального времени RTC DS1307, провода и USB кабель.

Чтобы подключить контроллер к Ардуино, используются 4 пина – VCC, земля, SCL, SDA.. VCC с часов подключается к 5В на Ардуино, земля с часов – к земле с Ардуино, SDA – А4, SCL – А5.

Для начала работы с модулем часов нужно установить библиотеки DS1307RTC, TimeLib и Wire. Можно использовать для работы и RTCLib.

Проверка RTC модуля

При запуске первого кода программа будет считывать данные с модуля раз в секунду. Сначала можно посмотреть, как поведет себя программа, если достать из модуля батарейку и заменить на другую, пока плата Ардуино не присоединена к компьютеру. Нужно подождать несколько секунд и вытащить батарею, в итоге часы перезагрузятся. Затем нужно выбрать пример в меню Examples→RTClib→ds1307. Важно правильно поставить скорость передачи на 57600 bps.

При открытии окна серийного монитора должны появиться следующие строки:

Будет показывать время 0:0:0. Это связано с тем, что в часах пропадает питание, и отсчет времени прекратится. По этой причине нельзя вытаскивать батарею во время работы модуля.

Чтобы провести настройку времени на модуле, нужно в скетче найти строку

RTC.adjust(DateTime(__DATE__, __TIME__));

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

Настройка произведена корректно и дополнительно перенастраивать часы реального времени не придется.

Считывание времени. Как только модуль настроен, можно отправлять запросы на получение времени. Для этого используется функция now(), возвращающая объект DateTime, который содержит информацию о времени и дате. Существует ряд библиотек, которые используются для считывания времени. Например, RTC.year() и RTC.hour() – они отдельно получают информацию о годе и часе. При работе с ними может возникнуть проблема: например, запрос на вывод времени будет сделан в 1:19:59. Прежде чем показать время 1:20:00, часы выведут время 1:19:00, то есть, по сути, будет потеряна одна минута. Поэтому эти библиотеки целесообразно использовать в случаях, когда считывание происходит нечасто – раз в несколько дней. Существуют и другие функции для вызова времени, но если нужно уменьшить или избежать погрешностей, лучше использовать now() и из нее уже вытаскивать необходимые показания.

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

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

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

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

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

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

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

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

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

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

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

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

  • Подключение всех компонентов;
  • Проверка – на экране монитора должны меняться ежесекундно время и дата. Если на экране указано неправильное время, нужно добавить в скетч функцию RTC.write (tmElements_t tm). Проблемы с неправильно указанным временем связаны с тем, что модуль часов сбрасывает дату и время на 00:00:00 01/01/2000 при выключении.
  • Функция write позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.

Модули часов используются во многих проектах. Они нужны для систем регистрации данных, при создании таймеров и управляющих устройств, которые работают по заданному расписанию, в бытовых приборах. С помощью широко распространенных и дешевых модулей вы можете создать такие проекты как будильник или регистратор данных с сенсоров, записывая информацию на SD-карту или показывая время на экране дисплея. В этой статье мы рассмотрели типичные сценарии использования и варианты подключения наиболее популярных видов модулей.

С момента приобретения arduino, все никак не было или возможности или времени что-то сделать, начать «изучать» это дело. Но всегда был интерес к любому программированию будь то C, VHDL и прочее.

И вот однажды попал мне в руки экранчик lcd1602, где-то раньше читал, что его под ардуинку собирают. А у меня как раз с распайкой под пины, наверное от какого-нибудь ардуновского набора. Ну и решил, что надо бы его проверить, но проверить его простым включением и выводом текста не слишком интересно. Так и появилась идея написать банально часы и выводить это всё на экранчик.

Наверное стоит обговорить еще тот факт, что это самые простые часы, без кнопок, будильников, погоды и прочего.

После чтения даташитов и изучения информации по подключению экрана к ардуинке получил следующую схему:

При подключении ардуино к usb увидите, что экран загорится синим. На нем должны появится квадратики (экран проинициализирован), если вы их не видите попробуйте покрутить переменный резистор.

Приступим к написанию кода. Логика программы думаю понятна всем, она ровным счетом такая же, как и в любых часах. То есть: Считаем секунды, дошли до 60 — прибавляем минуту, секунды обнуляем, минуты дошли до 60, прибавляем час, обнуляем минуты и секунды.

Вот собственно и сам код программы, с подробнейшими комментариями:

Всё! Готово, прошиваемся и смотрим что получилось:

Всё, работает. Надеюсь что статья поможет кому-нибудь. Если будет интересно, то напишу следуюущую статью, где сделаем часы + дата. Спасибо за внимание.

Проект, который отлично впишется в интерьер вашего DIY угла, комнаты, гаража или офиса, в котором вы собираете роботов и всякие гиковские автоматизированные проекты на Arduino.

На выходе проекта вы получите в пределах одного модуля следующие фичи:

  • Часы!;
  • Отображение даты и времени на LCD экране;
  • Встроенный счетчик времени (для того, чтобы засекать время, затраченное на один проект);
  • Будильник (чтобы напоминать о том, что вы засиделись и пора устроить себе разминку);
  • Отслеживание движения (сберегает заряд аккумулятора, отключая LCD экран, когда вас нет рядом);
  • Отлично впишется в ваш интерьер Arduino-разработчика!

Необходимые материалы для проекта

  • LCD Keypad Shield (LCD шилд с кнопками) для Arduino (в данном случае — от производителя DFRobot)
  • Часы реального времени (RTC) DS1307 (от Adafruit);
  • Закрывающийся бокс (можно найти в радиомагазине или заказать у китайцев);
  • Зуммер (Piezo Buzzer);
  • PIR (Пассивный инфракрасный датчик движения);
  • Проводники мама/мама;
  • Джек 2.1 мм;
  • Переходник для батарейки 9 В 5.5 мм / 2.1 мм;
  • Крона 9 В.

Фото деталей и узлов для проекта

Сборка модуля часов реального времени

Порой модуль часов реального времени (например, от компании Adafruit DS1307), поставляется в виде отдельных компонентов. Сборка не должна вызвать проблем. Тем более, есть отличная инструкция по использованию и сборке модуля часов реального времени . Как правило, батарейка идет в комплектации модуля. Работать от одной батарейки он будет не меньше трех лет.

Коннектор для питания

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

Батарейка (крона) на 9 В просто устанавливается на заднюю часть бокса.

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

Подсоединяем провода ко всем элементам

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

Подключаем все к LCD шилду

После этого добавлен кусок кода из скетча от DFRobot для LCD шилда (включая опцию управления кнопками). Этот скетч можно скачать .

Функции кнопок

На LCD шилде кнопки подписаны (смотрите на фото). Первые пять из шести доступных кнопок (button) были запрограммированы следующим образом:

Кнопка #1 (подписана SELECT) — это кнопка Menu. Эта кнопка отвечает за отображение листаемого списка доступных функций (таймер, установка будильника).

Кнопка #2 (подписана LEFT) — кнопка Select. Служит для выбора функции. Примечание: также используется для инкремента на 10 , когда выбраны часы, минуты и т.п.

Кнопки #3 и 4 (подписаны UP и DOWN) — кнопки Increment и Decrement (инкремент и декремент). Используются для уменьшения и увеличения часов и минут при настройке таймера или будильника. Используются также для переключения между временами суток AM и PM.

Кнопка #5 (подписана RIGHT) — GO! Используется для принятия выбранного значения (например, настроенных минут или часов).

Кнопка #6 (отмечена RST) — Reset, которая перезагружает наш Arduino.

Всем привет!
Я сам еще новичек, совсем зеленый. Поэтому мой пост будет полезен таким же начинающим))
С ардуиной познакомился с месяц назад, заказал деталек — стали приходить — начал потихоньку вникать. Вообще — глобально я хочу собрать бортовой компьютер в авто — для вывода оперативной информации и сброса ошибок. Ну а пока тернеруюь на кошках__)
Решил собрать часы.
Сначала пришел LCD экран 1602 символов, стандартный экран, инстсрукций по подключению в интернете масса.
Подключил-посмотрел, мдя, проводов много(( Запустил на нем простейшие софтовые часы, все ничего, но как только отключаешь питание — продавает и время( А так как кнопок еще нету — то установка происходит через комп по ком порту через Процессинг, вообщем тот еще геморой.
Потом пришел заранее заказанный модуль I2C — символьный LCD. Модуль этот основан на микрухе которая расширяет порты ввода вывода. тоесть по 2м проводам данные входят — а по 8 выводам расходятся на экран. Вещь дюже полезная, на ибээ их полно.
Стало совсем красиво.
Есть некоторая загвоздка. дело в том что в библиотеке с которой работает экран по i2c протоколу — нерабочие примеры((( Это у меня отняло какое-то время для понимания сути процессов))
Кратенько для тех кто купит переходник — в каждом переходнике зашит его адрес, адрес можно узнать с помощью сканера адресов или аналитическим методом. На платке есть перемычки — если ихзапаять, адрес будет 0x20, а если перемычки сводобные — адрес будет 0x27. Адресация нужна для правильной инициализации переходника и работы с LCD экраном.
Сразу понятно будет не все, но после суток-двух копания в инете, прийдет понимание.
Вообщем суть такая, по двум проводам можно подключить любое количество экранов! Главное чтобы у каждого был свой адрес, а менять адрес можно если менть перемычки на переходничке i2c lcd. Если экранчик один, то можно выяснить аэрес перебором или найти сканер и посмотреть все доступные адреса по протоколу i2c. Адрес зависит от типа переходника, про типы подробно вот тут
У меня оказался Третий вариант как по ссылке. Разобравшись что куда, выяснил что адрес у него 0x27, эта цифра нужна для обращения к экрану.
А теперь важное.
Есть 2 рабочих варианта (может даже больше)
Перая библиотека с примерами качается по ссылке
Сама библиотка https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
Примеры брать не из библиотки а из блога выше.
Второй вариант,
Мой пример работает на этой библиотеке. Она старее, но мне показалось достаточной использовать ее.
Обе эти библиотеки НЕ СОВМЕСТИМЫ!
Так что ставим второй вариант, если не заработает — ставим первый и переписываем пример под свою библиотеку, благо там не много.
Я честно уже не помню почему выбрал второй вариант и где взял примеры, главное, что все работает))
//
После настройки экрана по двум проводам, пришли RTC модуль — часы реального времени на микрухе 1307. Общаются они по тем же 2м проводам, то есть портов на ардуине не занимают вообще.
Рабочую библиотеку нашел не сразу, заработала вот эта https://github.com/adafruit/RTClib
Примеры в ней хорошие, рабочие, все сразу стало понятно. Адрес в часах зашит жестко (я не понял как его менять)
Теперь при отключении питания, часы не сбрасываются)))
//
Итак, особенностью часов является отображение 3х чисел в виде столбиков, секундыи минуты слева -направо, часы — наоборот справа-налево.
Используется 8 собственных символов, которые создают индикацию. Сначала сдеал 9 — начали скакать символы, смотрел — думал — оказалось что максимальное количество собственных символов — 8. Поэтому в качестве полного закрашенного квадрата используется системный знак по коду, а процентное заполнение — нарисовано в массиве битами.
Я думаю что в коде все понятно.
Функция Map — «растягивает» отображаемый промежуток в 24 часа на то количество клеток, которое нужно. так же и с минутами и секундами, но там растягивается другой диапазон.
Сначала делал без мапа — не смог найти функцию округления, коэффициенты были целыми числами — и растягивался диапазон всегда то больше — то меньше чем нужно. А мап меня спас))
В остальном все довольно просто, не забываем стирать квадраты, когда цикл часов начинается занова.

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib #include <Wire.h> #include «RTClib.h» #include <LiquidCrystal_I2C.h> RTC_DS1307 rtc; LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display int progbar=0; byte p20 = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, }; byte p40 = { B11000, B11000, B11000, B11000, B11000, B11000, B11000, }; byte p60 = { B11100, B11100, B11100, B11100, B11100, B11100, B11100, }; byte p80 = { B11110, B11110, B11110, B11110, B11110, B11110, B11110, }; byte p100 = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, }; byte ip20 = { B00001, B00001, B00001, B00001, B00001, B00001, B00001, }; byte ip40 = { B00011, B00011, B00011, B00011, B00011, B00011, B00011, }; byte ip60 = { B00111, B00111, B00111, B00111, B00111, B00111, B00111, }; byte ip80 = { B01111, B01111, B01111, B01111, B01111, B01111, B01111, }; void setup () { Serial.begin(57600); Wire.begin(); rtc.begin(); lcd.init(); // initialize the lcd lcd.backlight(); lcd.home(); //Make progress characters lcd.createChar(0, p20); lcd.createChar(1, p40); lcd.createChar(2, p60); lcd.createChar(3, p80); // lcd.createChar(4, p100); lcd.createChar(4, ip20); lcd.createChar(5, ip40); lcd.createChar(6, ip60); lcd.createChar(7, ip80); lcd.clear(); if (! rtc.isrunning()) { Serial.println(«RTC is NOT running!»); // following line sets the RTC to the date & time this sketch was compiled // rtc.adjust(DateTime(__DATE__, __TIME__)); } } void loop () { digitalClockDisplay(); delay(200); } void digitalClockDisplay(){ // digital clock display of the time DateTime now = rtc.now(); lcd.setCursor(5, 0); printDigits(now.hour()); // печатает часы //рисуем прогресс бар часов progbar=map(now.hour(),0,24,0,25); //стираем бар если час =0 if(now.hour()<1 ){ lcd.setCursor(0,0); lcd.print(» «); } // отрисовка бара часа в обратном направлении //сначала рисуем квадраты for (int i = 0; i<(progbar/5); i++) { lcd.setCursor(4-i, 0); lcd.write(B11111111); } //отрисовываем деления в поле символа, lcd.setCursor(4-progbar/5, 0); if(progbar%5<4){ lcd.write(progbar%5+4); } else{ lcd.write(B11111111); } //нарисовали часы и шкалу часов //рисуем бегающие двоеточие, привязано к секундам, вывод слева или справа двоеточие зависит от четности секунд lcd.setCursor(7, 0); if (now.second()%10%2==0){ lcd.print(«: «); } else { lcd.print(» :»); } //нарисовали двоеточие //рисуем минуты lcd.setCursor(9, 0); printDigits(now.minute()); //стираем бар минут если минуты=0 if(now.minute()<1 ){ lcd.setCursor(11,0); lcd.print(» «); } //рисуем бар минут //тут уже отрисовка происходит в прямом направлении progbar=map(now.minute(),0,60,0,25); for (int i = 0; i<(progbar/5); i++) { lcd.setCursor(i+11, 0); lcd.write(B11111111); } lcd.setCursor(progbar/5+11, 0); if(progbar%5<4){ lcd.write(progbar%5); } else{ lcd.write(B11111111); } //нарисовали минуты //рисуем бар минут //самый длинный бар в самом низу lcd.setCursor(7, 1); printDigits(now.second()); if(now.second()<1 ){ lcd.setCursor(0,1); lcd.print(» «); lcd.setCursor(9,1); lcd.print(» «); } progbar=map(now.second(),0,60,0,80); for (int i = 0; i<(progbar/5); i++) { lcd.setCursor(i, 1); lcd.write(B11111111); } lcd.setCursor(progbar/5, 1); if(progbar%5<4){ lcd.write(progbar%5); } else{ lcd.write(B11111111); } lcd.setCursor(7, 1); printDigits(now.second()); } void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 if(digits < 10){ lcd.print(‘0’); } lcd.print(digits); }
Ссылка на видео

Во многих проектах Ардуино требуется отслеживать и фиксировать время наступления тех или иных событий. Модуль часов реального времени, оснащенный дополнительной батарей, позволяет хранить текущую дату, не завися от наличия питания на самом устройстве. В этой статье мы поговорим о наиболее часто встречающихся модулях RTC DS1307, DS1302, DS3231, которые можно использовать с платой Arduino.

Модули часов реального времени в проектах Arduino

Модуль часов представляет собой небольшую плату, содержащей, как правило, одну из микросхем DS1307, DS1302, DS3231.Кроме этого, на плате практически можно найти механизм установки батарейки питания. Такие платы часто применяется для учета времени, даты, дня недели и других хронометрических параметров. Модули работают от автономного питания – батареек, аккумуляторов, и продолжают проводить отсчет, даже если на Ардуино отключилось питание. Наиболее распространенными моделями часов являются DS1302, DS1307, DS3231. Они основаны на подключаемом к Arduino модуле RTC (часы реального времени).

Часы ведут отсчет в единицах, которые удобны обычному человеку – минуты, часы, дни недели и другие, в отличие от обычных счетчиков и тактовых генераторов, которые считывают «тики». В Ардуино имеется специальная функция millis(), которая также может считывать различные временные интервалы. Но основным недостатком этой функции является сбрасывание в ноль при включении таймера. С ее помощью можно считать только время, установить дату или день недели невозможно. Для решения этой проблемы и используются модули часов реального времени.

Электронная схема включает в себя микросхему, источник питания, кварцевый резонатор и резисторы. Кварцевый резонатор работает на частоте 32768 Гц, которая является удобной для обычного двоичного счетчика. В схеме DS3231 имеется встроенный кварц и термостабилизация, которые позволяют получить значения высокой точности.

Пример проекта с 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 позволяет получить дату и время с компьютера, после чего на экране будут указаны верные параметры.

Модули часов используются во многих проектах. Они нужны для систем регистрации данных, при создании таймеров и управляющих устройств, которые работают по заданному расписанию, в бытовых приборах. С помощью широко распространенных и дешевых модулей вы можете создать такие проекты как будильник или регистратор данных с сенсоров, записывая информацию на SD-карту или показывая время на экране дисплея. В этой статье мы рассмотрели типичные сценарии использования и варианты подключения наиболее популярных видов модулей.

Часы реального времени DS3231

  • Обзор
  • Технические характеристики
  • Назначение контактов
  • Подключение к Arduino
  • Пример использования
  • Часто задаваемые вопросы

Обзор часов реального времени DS3231

Если вы создаете устройство, которому нужно знать точное время, вам пригодится модуль часов реального времени RTC (Real Time Clock). Данные модули отсчитывают точное время и могут сохранять его даже при отключении основного питания при использовании резервного питания (батарейка CR2032 или литий-ионный аккумулятор LIR2032-3,6 В), которого хватит на несколько лет.

Еще совсем недавно основным модулем RTC в среде Ардуинщиков являлся модуль на микросхеме DS1307. В этом модуле использовался внешний кварцевый генератор частотой 32кГц, при изменении температуры менялась частота кварца, что приводило к погрешности в подсчете времени.

Новые модули RTC (рис. 1) построены на микросхеме DS3231, внутрь которой установлен кварцевый генератор и датчик температуры, который компенсирует изменения температуры, поэтому время отсчитывается более точно. Погрешность составляет ±2 минуты за год.

Рисунок 1.

Технические характеристики

  • календарь до 2100 года

  • погрешность : +/- 4ppm

  • два будильника

  • выход стабильной частоты : 1-32768 Гц

  • напряжение питания : 2,7 — 5,3 В

  • напряжение батарейки : 2,3 — 5,3 В

  • ток потребления : 250 мкA

  • ток потребления от батарейки : 3 мкA

  • порог переключения на батарейку : 2,6 В

  • интерфейс : I2C

  • размеры : 40х22 мм

Назначение контактов

Модуль имеет 6 выводов:

  • GND – общий

  • VCC – питание 2,7 — 5,3 В

  • SDA – вход/выход данных интерфейса I2C

  • SCL – синхронизация интерфейса I2C

  • SQW – прерывание от будильников или выход импульсов 1-8192 Гц

  • 32K – выход импульсов 32768 Гц

Подключение к плате Arduino

Модуль DS3231 подключается к плате Arduino по интерфейсу I2C, используются выводы SDA и SCL. Схема подключения показана на рис. 2.

Рисунок 2.

Для программирования будем использовать библиотеки DS1307 и Time. Скетч получения данных с DS3231 и вывода в последовательный порт показан в листинге 1.

Листинг 1

#include <Wire.h>

#include <DS1307RTC.h>

#include <Time.h>

tmElements_t datetime;

void setup() {

Serial.begin(9600);

}

void loop() {

// получение данных из ds3231

if (RTC.read(dt)) {

print2(datetime.Hour, «:»);

print2(datetime.Minute, «:»);

print2(datetime.Second, » «);

print2(datetime.Day, «/»);

print2(datetime.Month, «/»);

print2(tmYearToCalendar(datetime.Year) ,»»);

Serial.println();

}

else {

Serial.println(«error»);

delay(5000);

}

delay(1000);

}

void print2(int nn,String str) {

if (nn >= 0 && nn < 10)

{ Serial.print(«0»);}

Serial.print(nn);

Serial.print(str);

}

Открываем монитор последовательного порта (рис. 3).

Рисунок 3.

Результат работы – правильный отсчет, но неверное значение времени и даты. При отсутствии питания значение времени в микросхеме DS3231 сбрасывается на 00:00:00 01/01/2000.

Добавим функционал скетчу – установка времени отправкой строки вида «dd/mm/ YYYY hh:mm:ss» в последовательный порт.

Листинг 2

#include <DS1307RTC.h>

#include <Time.h>

#include <Wire.h>

String inSer = «»;

boolean strFull = false;

tmElements_t datetime;

void setup() {

Serial.begin(9600);

}

void loop() {

// пришли данные по serial

if (strFull) {

datetime.Hour=(int(inSer)-48)*10+(int(inSer)-48);

datetime.Minute=(int(inSer)-48)*10+(int(inSer)-48);

datetime.Second=(int(inSer)-48)*10+(int(inSer)-48);

datetime.Day=(int(inSer)-48)*10+(int(inSer)-48);

datetime.Month=(int(inSer)-48)*10+(int(inSer)-48);

datetime.Year=CalendarYrToTm((int(inSer)-48)*1000+(int(inSer)-48)*100+(int(inSer)-48)*10+(int(inSer)-48));

RTC.write(datetime); // записать данные в DS3231

// очистить строку

inSer = «»;

strFull = false;

}

// получение данных из ds3231

if (RTC.read(datetime)) {

print2(datetime.Hour, «:»);

print2(datetime.Minute, «:»);

print2(datetime.Second, » «);

print2(datetime.Day, «/»);

print2(datetime.Month, «/»);

print2(tmYearToCalendar(datetime.Year) ,»»);

Serial.println();

}

else {

Serial.print(«error»);

delay(5000);

}

delay(1000);

}

void print2(int nn,String str) {

if (nn >= 0 && nn < 10)

{ Serial.print(«0»);}

Serial.print(nn);

Serial.print(str);

}

void serialEvent() {

while (Serial.available()) {

// получить очередной байт:

char c = (char)Serial.read();

// добавить в строку

inSer += c;

// /n — конец передачи

if (c == ‘\n’)

{ strFull = true;}

}

}

После загрузки скетча на плату Arduino, открываем монитор последовательного порта и отправляем в Arduino строку «dd/mm/ YYYY hh:mm:ss» для установки текущей даты и точного времени (рис. 4,5).

Рисунок 4,5.

Теперь DS3231 будет отсчитывать точное время. И если установлена батарейка, время не собъется после отключения питания.

Пример использования

Создадим проект часов с выводом данных на 4-х разрядный семисегментный дисплей на базе драйвера TM1637.

Нам потребуются следующие компоненты:

  • Плата Arduino Uno – 1

  • Плата прототипирования – 1

  • Модуль DS3231 – 1

  • 4digit display на базе TM1637 – 1

  • Провода

Схема соединения элементов показана на рис. 6.

Рисунок 6.

Для программирования вывода данных на 4-х разрядный семисегментный дисплей на базе драйвера TM1637 установим в Arduino IDE библиотеку TM1637. Каждые 5 секунд меняем на дисплее отображение:

  • текущее время;

  • день и месяц.

При отображении показаний текущего времени каждые 0.5 секунды мигаем разделителем типа «двоеточие» между вторым и третьим разрядом. Содержимое скетча показано в листинге 3.

Листинг 3

#include <DS1307RTC.h>

#include <Time.h>

#include <Wire.h>

#include «TM1637.h»

#define CLK 3

#define DIO 2

TM1637 4dig_display(CLK,DIO);

// для данных времени

int8_t ListTime={0,0,0,0};

// для данных dd/mm

int8_t ListDay={0,0,0,0};

// разделитель

boolean point=true;

// для смены время / день-месяц

unsigned long millist=0;

tmElements_t datetime;

void setup() {

Serial.begin(9600); // запустить последовательный порт

// запуск дисплея

4dig_display.init();

// яркость дисплея

tm1637.set(7);

}

void loop() {

// получение времени

if (RTC.read(datetime)) {

ListTime= datetime.Hour/10;

ListTime= datetime.Hour%10;

ListTime= datetime.Minute/10;

ListTime= datetime.Minute%10;

ListDay= datetime.Day/10;

ListDay= datetime.Day%10;

ListDay= datetime.Month/10;

ListDay= datetime.Month%10;

}

else {

// ошибка

4dig_display.display(0,ListDay);

4dig_display.display(1,ListDay);

4dig_display.display(2,ListDay);

4dig_display.display(3,ListDay);

4dig_display.point(false);

}

if(millis()-millist>=10000) {

millist=millis();

}

else if(millis()-millist>=5000) {

// вывод день — месяц

4dig_display.display(0,ListDay);

4dig_display.display(1,ListDay);

4dig_display.display(2,ListDay);

4dig_display.display(3,ListDay);

4dig_display.point(false);

}

else {

// вывод времени

4dig_display.display(0,ListTime);

4dig_display.display(1,ListTime);

4dig_display.display(2,ListTime);

4dig_display.display(3,ListTime);

4dig_display.point(point);

}

delay(500);

// поменять индикацию точек

point=!point;

}

Загружаем скетч на плату Arduino и проверяем работу часов.

Рисунок 7,8.

Часто задаваемые вопросы

1. Отсутствует получение данных времени с модуля DS3231.

  • Проверьте правильность подключения модуля DS3231 к плате Arduino.

2. Данные, получаемые с модуля DS3231, неверные.

  • Установите правильную дату и время, загрузив код из листинга 2 и отправив из последовательного порт правильные данные.

3. При отключении питания сбивается время и дата.

  • Установите резервное питание модуля (батарейка CR2032 или литий-ионный аккумулятор LIR2032-3,6 В).

  • Проверьте напряжение резервного питания (должно быть не менее 2,3 В).

Обзор часов реального времени DS1307 (RTC)

DS1307 это небольшой модуль, предназначенный для подсчета времени. Собранный на базе микросхемы DS1307ZN с реализацией питания от литиевой батарейки (LIR2032), что позволяет работать автономно в течение длительного времени. Также на модуле, установлена энергонезависимая память EEPROM объемом 32 Кбайт (AT24C32). Микросхема AT24C32 и DS1307ZN связаны обшей шиной интерфейсом I2C.

Технические параметры

► Напряжение питания: 5В
► Рабочая температура: – 40℃ … + 85℃
► Память: 56 байт (энергонезависимая)
► Батарейка: LIR2032 (автоматическое определение источника питания)
► Интерфейса: I2C
► Габариты: 28мм х 25мм х 8 мм

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

Использовании модуля 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 мм, для удобного подключения к макетной плате, буду использовать штырьевые разъемы, их необходимо впаять.

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

Подключение DS1307 к Arduino

Необходимые детали:
► Arduino UNO R3 x 1 шт.
► Провод DuPont, 2,54 мм, 20 см x 1 шт.
► Кабель USB 2.0 A-B x 1 шт.
► Часы реального времени RTC DS1307 x 1 шт.

Подключение:
Для подключения часы реального времени DS1307, необходимо впаять впаять штыревые разъемы в первую группу контактов. Далее, подключаем провода SCL (DS1307) к выводу 4 (Arduino UNO) и SDA (DS1307) к выводу 5 (Arduino UNO), осталось подключить питания VCC к +5V и GND к GND. Кстати, в различных платах Arduino вывода интерфейса I2C отличаются, назначение каждого можно посмотреть ниже.

Установка времени DS1307
Первым делом, необходимо скачать и установить библиотеку «DS1307RTC» и «TimeLib» в среду разработки IDE Arduino, далее необходимо настроить время, открываем пример из библиотеки DS1307RTC «Файл» —> «Примеры» —> «DS1307RTC» —> «SetTime» или копируем код снизу.

Загружаем данную скетч в контроллер Arduino (время берется с ОС), открываем «Мониторинг порта»

Программа
В библиотеке есть еще один пример, открыть его можно DS1307RTC «Файл» —> «Примеры» —> «DS1307RTC» —> «ReadTest»

Загружаем данную код в контроллер Arduino, открываем «Мониторинг порта»

Ссылки
Библиотека libraries-DS1307RTC
Библиотека libraries-TimeLib

Купить на Aliexpress
Контроллер Arduino UNO R3
Провода DuPont, 2,54 мм, 20 см
Часы реального времени RTC DS1307

Купить в Самаре и области
Купить контроллер Arduino UNO R3 в г. Самаре
Купить провода DuPont, 2,54 мм, 20 см в г. Самаре
Купить часы реального времени RTC DS1307 в г. Самаре

admin

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Наверх