В данной статье мы рассмотрим подключение модуля часов реального времени (Real Time Clock Module, RTC) DS1307 к плате Raspberry Pi и создание на их основе будильника. Хотя плата Raspberry Pi имеет встроенные часы и можно было бы создать будильник на их основе, но без подключения к сети Интернет внутренние часы платы сбрасываются после каждой перезагрузки системы, поэтому для создания будильника мы будем использовать внешний модуль учета времени – модуль DS1307. Данный модуль содержит в своем составе батарейку, поэтому он способен хранить точное время даже при отключении питания от схемы. Ранее на нашем сайте мы рассматривали создание подобного будильника на основе платы Arduino и на основе микроконтроллера AVR.
В данном проекте мы также будем использовать ЖК дисплей 16×2 для отображения текущего времени, времени срабатывания будильника и статуса будильника (ON/OFF). После запуска программы на Raspberry Pi мы можем отключить ее от монитора и управлять работой будильника (устанавливать время его срабатывания) с помощью ЖК дисплея 16×2 и пяти кнопок.
Каждый из 17 универсальных контактов ввода/вывода (GPIO) платы Raspberry Pi может выдерживать ток до 15mA. А суммарный ток от всех контактов ввода/вывода не должен превышать 50mA – таким образом, в среднем на каждый контакт будет приходиться ток примерно 3mA. Поэтому дважды проверьте соединения в схеме прежде чем подавать питание на плату Raspberry Pi. Более подробно о контактах ввода/вывода и подключении кнопки к плате Raspberry Pi вы можете прочитать в следующей статье.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- ЖК дисплей 16×2 (купить на AliExpress).
- Резистор 1 кОм – 6 шт. (купить на AliExpress).
- Кнопка – 5 шт.
- Конденсатор – 1000 мкФ (купить на AliExpress).
- Модуль часов реального времени DS1307 (купить на AliExpress).
- Транзистор 2N2222 (купить на AliExpress).
- Зуммер (Buzzer) (купить на AliExpress).
- Источник питания.
- Макетная плата.
- Соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Настройки платы Raspberry Pi для проекта будильника
Прежде чем приступать к написанию программы для платы Raspberry Pi необходимо произвести в ней некоторые настройки и установить библиотеку для работы с модулем часов реального времени. Для этого выполните следующую последовательность шагов.
Шаг 1. Зайдите в меню настроек платы Raspberry Pi и включите в них работу с протоколом I2C как показано на следующем рисунке.
Шаг 2. Создайте новую папку на рабочем столе платы Raspberry Pi и назовите ее “Alarm Clock”.
Шаг 3. Скачайте библиотеку для работы с модулем часов реального времени по следующей ссылке:
https://codeload.github.com/switchdoclabs/RTC_SDL_DS1307/zip/master
Шаг 4. Распакуйте архив со скачанной библиотекой в созданный ранее каталог на рабочем столе (“Alarm Clock”).
Шаг 5. Откройте окно терминала в Raspberry Pi и введите в нем следующую команду:
1 |
sudo apt-get install i2c-tools |
Эта команда устанавливает инструменты протокола I2C, необходимые для работы с RTC (реального времени) модулем. После этого перезагрузите плату Raspberry Pi с помощью команды ‘sudo reboot’.
Шаг 6. Теперь нам нужно проверить адрес I2C RTC модуля. Перед этим подключите модуль RTC в схему, показанную на рисунке ниже. Затем введите в окне терминала команду:
1 2 3 |
sudo i2cdetect -y 0 или sudo i2cdetect -y 1 |
Шаг 7. Если приведенная команда выполнится успешно, то на экране монитора вы увидите следующую картину:
Шаг 8. Если все работает нормально, то вы увидите адрес I2C 0x68 для RTC модуля, запишите это значение.
На этом настройка платы Raspberry Pi для данного проекта будет закончена.
Схема проекта
Схема будильника на Raspberry Pi и RTC модуле DS1307 представлена на следующем рисунке.
Соединения между платой Raspberry Pi и пятью кнопками показаны в следующей таблице.
Объяснение работы проекта
Как уже рассматривалось, RTC модуль имеет собственную батарейку, поэтому он всегда будет хранить точное время даже если питание схемы по каким то причинам будет пропадать.
В программе на Python мы будем считывать значение точного времени с RTC модуля DS1307 и показывать его на экране ЖК дисплея 16×2. На второй строке ЖК дисплея 16×2 мы будем отображать время срабатывания будильника и его статус (ON/ OFF – включен/выключен). Управлять работой будильника мы будем с помощью 5 кнопок, присутствующих в схеме. 2 кнопки будут использоваться для инкрементирования/декрементирования значения часов будильника, 2 кнопки – для инкрементирования/декрементирования значения минут будильника и 1 кнопка для включения/выключения будильника. Более подробно все эти процессы вы можете посмотреть на видео, приведенном в конце статьи.
Программа на Python будет непрерывно сравнивать текущее время с установленным временем будильника и при их совпадении она будет включать зуммер, подключенный к контакту GPIO 22 платы Raspberry Pi через NPN транзистор 2N2222.
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import RPi.GPIO as IO # подключение библиотеки для работы с контактами ввода/вывода import time # подключение библиотеки для работы с задержками import datetime # подключение библиотеки для работы с датой/временем import SDL_DS1307 # подключение библиотеки для работы с модулем часов реального времени h=0 # переменные типа integer для хранения необходимых значений m=0 alarm=0 string_of_characters = 0 ds1307 = SDL_DS1307.SDL_DS1307(1, 0x68) # вводим адрес I2c, который мы ранее записали ds1307.write_now() IO.setwarnings(False) # отключаем показ любых предупреждений IO.setmode (IO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’ # инициализируем GPIO17,27,24,23,18,26,5,6,13,19 в качестве цифровых выходов IO.setup(17,IO.OUT) IO.setup(27,IO.OUT) IO.setup(24,IO.OUT) IO.setup(23,IO.OUT) IO.setup(18,IO.OUT) IO.setup(26,IO.OUT) IO.setup(5,IO.OUT) IO.setup(6,IO.OUT) IO.setup(13,IO.OUT) IO.setup(19,IO.OUT) IO.setup(21,IO.IN) # инициализируем GPIO21 в качестве цифрового входа IO.setup(20,IO.IN) # инициализируем GPIO20 в качестве цифрового входа IO.setup(16,IO.IN) IO.setup(12,IO.IN) IO.setup(25,IO.IN) IO.setup(22,IO.OUT) # инициализируем GPIO22 в качестве цифрового выхода def send_a_command (command): # функция для передачи команды на ЖК дисплей 16х2 pin=command PORT(pin); IO.output(17,0) IO.output(27,1) time.sleep(0.001) IO.output(27,0) pin=0 PORT(pin); def send_a_character (character): # функция для передачи символа на ЖК дисплей 16х2 pin=character PORT(pin); IO.output(17,1) IO.output(27,1) time.sleep(0.001) IO.output(27,0) pin=0 PORT(pin); def PORT(pin): # устанавливаем необходимые значения на контактах D0-D7 чтобы передавать данные ЖК дисплею if(pin&0x01 == 0x01): IO.output(24,1) else: IO.output(24,0) if(pin&0x02 == 0x02): IO.output(23,1) else: IO.output(23,0) if(pin&0x04 == 0x04): IO.output(18,1) else: IO.output(18,0) if(pin&0x08 == 0x08): IO.output(26,1) else: IO.output(26,0) if(pin&0x10 == 0x10): IO.output(5,1) else: IO.output(5,0) if(pin&0x20 == 0x20): IO.output(6,1) else: IO.output(6,0) if(pin&0x40 == 0x40): IO.output(13,1) else: IO.output(13,0) if(pin&0x80 == 0x80): IO.output(19,1) else: IO.output(19,0) def send_a_string(string_of_characters): # функция для передачи строки символов на ЖК дисплей 16х2 string_of_characters = string_of_characters.ljust(16," ") for i in range(16): send_a_character(ord(string_of_characters[i])) # передаем символы последовательно один за другим while 1: send_a_command(0x38); # используем две строки ЖК дисплея send_a_command(0x0E); # включаем курсор на экране дисплея send_a_command(0x01); # очищаем экран time.sleep(0.1) # задержка на 100msec while 1: if (IO.input(21) == 0): if (h<23): # если кнопка 1 нажата и счетчик часов меньше 23, то инкрементируем 'h' на 1 h=h+1 if (IO.input(20) == 0): if (h>0): # если кнопка 2 нажата и счетчик часов больше 0, то декрементируем 'h' на 1 h=h-1 if (IO.input(16) == 0): if (m<59): # если кнопка 3 нажата и счетчик минут меньше 59, то инкрементируем 'm' на 1 m=m+1 if (IO.input(12) == 0): if (m>0): # если кнопка 4 нажата и счетчик минут больше 0, то декрементируем 'm' на 1 m=m-1 if (IO.input(25) == 0): # если кнопка 5 нажата включаем/выключаем будильник if (alarm==0): alarm=1 else: alarm=0 time.sleep(0.1) if (alarm==1): send_a_command(0x80 + 0x40 + 12); send_a_string("ON"); # если будильник включен, то показываем "ON" на 12-й позиции второй строки ЖК дисплея if ((h==ds1307._read_hours())): if ((m==ds1307._read_minutes())): IO.output(22,1) # если будильник включен и текущее время равно времени срабатывания будильника, то включаем зуммер if (alarm==0): send_a_command(0x80 + 0x40 + 12); send_a_string("OFF"); # если будильник выключен, то показываем "OFF" на 12-й позиции второй строки ЖК дисплея IO.output(22,0) # выключаем зуммер send_a_command(0x80 + 0); # перемещаем курсор на 0-ю позицию send_a_string ("Time:%s:%s:%s" % (ds1307._read_hours(),ds1307._read_minutes(),ds1307._read_seconds())); #display RTC hours, minutes, seconds send_a_command(0x80 + 0x40 + 0); # перемещаем курсор на 2-ю строку send_a_string ("Alarm:%s:%s" % (h,m)); # показываем время, на которое установлен будильник time.sleep(0.1) # задержка 100msec |