Приветствую всех! Так вот, как кто-то говорил, каждый радиолюбитель должен сделать часы, многие делали, а вот кто делал часы, способные говорить? Сейчас быстро это дело поправим! В статье предлагаю рассмотреть не только сами говорящие часы, но и работу с микросхемой RTC PCA/PCF2129 от NXP, которая на данном этапе будет основой часов. Со времен халявы должны быть у всех, а вот информации про нее очень мало.
Схема говорящих часов представляет собой народный микроконтроллер mega8 как сердце конструкции, ЖК дисплей на базе HD44780, линейный стабилизатор питания 7805 и модуль RTC на базе PCA2129, работающий по I2C с микроконтроллером. Для корректной работы I2C в цепях SCL и SDA не забываем про pull-up резисторы.
Динамики на 4 Ом можно использовать без усилителя, громкость будет вполне нормальная для тестирования, но для домашнего использования нужен хоть какой-то минимальный усилитель. Заменив светодиод на ключевой элемент, например транзистор или реле, можно управлять тем же усилителем или просто включать свет, на что фантазии хватит. 7805 можно заменить на любой другой стабилизатор напряжения на 5В. Резисторы все СМД типоразмера 1206, можно заменить на любые другие выводные или другого типоразмера СМД. Номиналы электролитов можно варьировать в широких пределах. Керамические конденсаторы СМД типоразмера 1206, заменить можно на любые другие выводные или других типоразмеров СМД. Диоды 1n4148 или любые аналогичные, а вообще еще лучше заменить на стабилизатор 3,3 В и запитать от него всю схему, не забыв про +5В для ЖК дисплея. Контроллер можно использовать как в DIP корпусе, так и в tqfp. Тактовые кнопки абсолютно любые.
Какие функции выполняет устройство:
- индикация времени на ЖК
- индикация даты и дня недели на ЖК
- индикация будильника на ЖК
- воспроизведение времени при нажатии соответствующей кнопки, причем голоса или треки с временем можно использовать любые, предварительно сконвертировав в Wav формат
- возможность на будильник поставить любой трек, тоже в Wav (обязательное название для трека "alarm.wav")
- меню настроек будильника (время и включенность)
- меню настроек времени
- меню настроек даты
- при воспроизведении загорается светодиод (можно использовать для включения усилителя или чего-то другого)
Ниже будет представлено 2 прошивки - для воспроизведения Wav с частотой 32 КГц и с частотой 44 КГц. Как же правильно конвертировать аудио файлы? Все просто - качаем любой аудио конвертер и задаем параметры 8-bit Mono 44 kHz или 8-bit Mono 32 kHz, далее все в корень флешки. Также ниже архив с голосом Алены из "Балаболки", там же и как пример как правильно обзывать файлы в случае, если будете записывать что-то свое. Из фишек можно отметить то, что если с прошивкой 44 кГц использовать аудио 32 кГц, получится на выходе смешной мультяшный голос, слегка ускоренный, и, если наоборот, то чуть замедленный грубый голос. В общем в этом плане можно поиграться с частотой конвертации, главное не слишком увлекаться.
Что касается управления и настроек. В устройстве 5 кнопок. По логическому порядку:
- S2 - нажимаем и нам воспроизводится текущее время на часах
- S5 - вход в настройки и перебирание настроек
- S4 - управление переменными в настройке (все переменные идут по кругу, при нажатии увеличение на 1, при переполнении переход в минимальное значение, при длительном нажатии +1 идет само или автоматически)
- S1 - при нажатии в любом пункте меню немедленный выход на главную времени и даты, на главной, при звонке будильника нажатие выключает будильник, но тоько по окончании воспроизведения трека (это если любимую пеню поставить)
- S3 - reset, также вырубает будильник сразу
Часы поддерживают флешки от 16 Mb до 8 Gb (до 32 Gb не проверял, но тоже должно)
Фото меню:
Устройство собиралось на макетной плате
Клубок проводов на первый взгляд) Динамик 3ГДШ-4-4 4Ом, макетка mega8, модули 4 кнопки, RTC и карта памяти (просто и со вкусом к адаптеру подпаяны штырьки), конденсатор чуть поболе 220 мк, но разницы нет особо
А вот модуль RTC, главный виновник устройства, разведен с учетом преобразователя уровней, зачем? чуть ниже, там же и печатная плата
По поводу RTC. По данным даташита рабочее напряжение 1,8 - 4,2 В. Соответсвенно и уровни по шине I2C не будут 5 В, поэтому и используется преобразователь уровней PCA9517, работает и без него вроде, но так правильнее, тем более это модуль, который можно будет использовать в любой другой схеме не опасаясь за безопасность, а вообще если просто всю схему запитать от 3,3 В, то убрать можно 100%, но ЖК все рано требует не меньше 5 В по питанию (пожалуй единственный модуль которому в этой схеме нужно 5В).
Плавно переходим к работе PCA/PCF2129. Между прочим, разница между ними только в количестве n.c. ножек и размере корпуса - функционально клоны. На ПП 2 варианта - для работы по I2C и по SPI. Выбираем I2C, т.к. в планах развития заменить на DS1307, вообще в планах много чего, но об этом позже.
Итак, заглядываем в даташит, имеется у нас 28 регистров в этой микросхеме, круто это же столько функций! Время, дата, будильник, прерывания, сторожевой таймер, подстройка частоты кварца, тайм-штамп. Одним из самых главных плюсов является встроенный в саму микросхему кварц и его термокомпенсация, производитель обещает небывалую точность хода! Пожалуй только 2 минуса можно найти, хотя, даже один: размер мне, например, не критичен, но упомянуть стоит (корпус и правда здоровенный относительно той же 1307) и ценник.
Рассмотрим работу с RTC, хотя все то обилие функций нам не понадобится, которое имеется на борту. Для начала берем аппаратные или программные функции I2C или TWI (чтение, запись и прочее).
Определяемся как работать с микросхемой, способ чтения и записи (картинка из даташита):
Между прочим, и в даташитах бывают ошибки, поэтому внимательно, несколько раз попадались не правильные адреса и долго думал почему же не работает.
// дефайны адресов микросхемы #define RTC_adr_write 0b10100010 #define RTC_adr_read 0b10100011
Для записи: посылаем START, адрес записи, потом адрес регистра (если хотим записать время, например, то адрес регистра 03h - это секунды), далее 8 бит информации и STOP.
Для чтения: START, адрес записи, потом адрес регистра и STOP (это для того чтобы установить указатель на нужный для чтения регистр), далее START, адрес чтения и читаем данные, в конце STOP.
По сути нам только и нужно что читать и записывать данные. Скомпануем эти действия в соответствии с выполнением необходимых задач с микросхемой и получаем функции, которые в основной программе только и нужно, что подставлять в нужные места и совершать операции с переменными. В этом и прелесть I2C. Простота.
Вот функции, задействованные в говорящих часах (обычно лучше всего на примерах разобраться):
// функции с часами ======================================================================= // bcd и bin - функции преобразования в двоичную и десятичную форму, информация в регистрах закодирована в BCD формат (Binary Coded Decimal) // инициализация начальных установок void RTC_init(void){ i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x00); // передача адреса памяти (Control) i2c_send_byte(0b00000000); // запись значения Control_1 (по дефолту 00000000) i2c_send_byte(0b00000000); // запись значения Control_2 (по дефолту 00000000) i2c_send_byte(0b00000000); // запись значения Control_3 (по дефолту 00000000) i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x0F); // передача адреса памяти (CLKOUT_ctl - интервал измерения температуры для термостатирования и частота клокаут) i2c_send_byte(0b11000110); // 30 сек интервал измерения и выход на 1 Гц i2c_stop_cond(); // остановка i2c // i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x19); // передача адреса памяти (Aging_offset - подстройка частоты кварца +8 -7 ppm (0-15 в десятичной форме, 0ppm = 8)) i2c_send_byte(0b00001000); // 0 ppm i2c_stop_cond(); // остановка i2c } // установка времени void RTC_set_time(unsigned char hour1,unsigned char min1, unsigned char sec1){ i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x03); // передача адреса памяти - регистры времени 3-5 i2c_send_byte(bin(sec1)); // 0x03 скунды (целесообразно ли задавать еще и секунды?) i2c_send_byte(bin(min1)); // 0x04 минуты i2c_send_byte(bin(hour1)); // 0x05 часы i2c_stop_cond(); // остановка i2c } // получение времени void RTC_get_time(void){ i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x03); // передача адреса памяти - регистры времени 3-5 i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_read); // передача адреса устройства, режим чтения sec = bcd(i2c_get_byte(0)); // чтение секунд, ACK min = bcd(i2c_get_byte(0)); // чтение минут, ACK hour = bcd(i2c_get_byte(1)); // чтение часов, NACK i2c_stop_cond(); // остановка i2c } // установка даты void RTC_set_date(unsigned char day, unsigned char wday, unsigned char month, unsigned char year){ i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x06); // передача адреса памяти - регистры даты 6-9 i2c_send_byte(bin(day)); // 0x06 день месяца i2c_send_byte(bin(wday)); // 0x07 день недели (воскресенье - 0, пн 1, вт 2, ср 3, чт 4, пт 5, сб 6) i2c_send_byte(bin(month)); // 0x08 месяц i2c_send_byte(bin(year)); // 0x09 год i2c_stop_cond(); // остановка i2c } // получение даты void RTC_get_date(void){ i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x06); // передача адреса памяти - регистры даты 6-9 i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_read); // передача адреса устройства, режим чтения day = bcd(i2c_get_byte(0)); // чтение число, ACK wday = bcd(i2c_get_byte(0)); // чтение день недели, ACK month = bcd(i2c_get_byte(0)); // чтение месяц, ACK year = bcd(i2c_get_byte(1)); // чтение год, NACK i2c_stop_cond(); // остановка i2c } // состояние батареи unsigned char RTC_low_bat(void) { // прочитает состояние резервной батареи (возвращаемое значение - bat, 1 - разряжена) char low = 0, bat = 0; i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи (для чтения) i2c_send_byte(0x02); // передача адреса памяти - регистры даты 6-9 i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_read); // передача адреса устройства, режим чтения low = i2c_get_byte(1); // чтение регистра Control_3, NACK интересует только 2й байт BLF (флаг состояния резервной батареи) i2c_stop_cond(); // остановка i2c if((low & (1<<2))) bat = 1; else bat = 0; // если во 2 бите 1, значит разряжена return bat; } // установка будильника void RTC_set_alarm(unsigned char hour, unsigned char min, unsigned char start) { // выставить все необходимое (bit AIE) и (флаг AF) для звонка в control register unsigned char r1 = 0, r2 = 0; if(start == 1){ r1 |= (0<<7) | (bin(min)<<0); r2 |= (0<<7) | (bin(hour)<<0); } else{ r1 |= (1<<7) | (bin(min)<<0); r2 |= (1<<7) | (bin(hour)<<0); } i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи i2c_send_byte(0x0B); // передача адреса памяти - регистры времени будильника 0B-0C (минуты и часы) i2c_send_byte(r1); // 0x0B минуты звонка i2c_send_byte(r2); // 0x0C часы звонка //i2c_send_byte(0b10000000); // 0x0D часы день (месяца) звонка - нам не надо, мы не пользуем - отключено //i2c_send_byte(0b10000000); // 0x0E часы день (недели) звонка - нам не надо, мы не пользуем - отключено i2c_stop_cond(); // остановка i2c } // получить время будильника void RTC_get_alarm_time (void){ char hh5 = 0, mm5 = 0; i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи (для чтения) i2c_send_byte(0x0B); // передача адреса памяти i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_read); // передача адреса устройства, режим чтения mm5 = i2c_get_byte(0); // чтение секунд, ACK hh5 = i2c_get_byte(1); // чтение минут, NACK if((hh5 & (1<<7))) alarm_on = 0; else alarm_on = 1; // alarm_hour = bcd (hh5); alarm_min = bcd (mm5); i2c_stop_cond(); // остановка i2c } // получить состояние будильника (сработал / не сработал сигнал) unsigned char RTC_get_alarm(void) { char alarm = 0, get = 0; i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи (для чтения) i2c_send_byte(0x01); // передача адреса памяти i2c_stop_cond(); // остановка i2c i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_read); // передача адреса устройства, режим чтения alarm = i2c_get_byte(1); // чтение регистра Control_2, NACK интересует только 4й байт AF (флаг состояния будильника) i2c_stop_cond(); // остановка i2c if((alarm & (1<<4))) get = 1; else get = 0; // если в 4 бите 1, значит будильник сработал return get; // для сброса звонка вызываем функцию RTC_alarm_reset // флаг сработки сбрасывается в 0 и ожидается снова время сработки // включается и выключается будильник в функции RTC_set_alarm переменной start } // сбросить будильник(флаг сработки) void RTC_alarm_reset(void) { // сбросит флаг срабатывания будильника AF в Control_2 в нолик i2c_start_cond(); // запуск i2c i2c_send_byte(RTC_adr_write); // передача адреса устройства, режим записи - 0b11010000 (1101000 - slave адрес + 0 бит записи) i2c_send_byte(0x01); // передача адреса памяти (Control) i2c_send_byte(0<<4); // сдвигом записать нолик нодо тут i2c_stop_cond(); // остановка i2c // }
Фактически это почти вся библиотека для работы с этой микросхемой, нужно только запихать это в хидер и си файл.
Думаю, разобраться будет не сложно. Главное, это же что - знания, добытые недюженными усилиями.
Как происходит воспроизведение текущего времени? Все просто. В зависимости от переменных часов и минут выбираются 2 соответствующих файла на флешке и воспроизводятся.
Для воспроизведения wav использовалась библиотека Petit FatFS Chan'a, за что ему большое спасибо.
Сколько я не бился, в протеусе не хочет корректно воспроизводиться wav, но все же прикладываю проект, может кто разберется и расскажет нам почему.
Для программирования МК:
Можно работать с внутренним RC генератором, как во фьюзах на скрине, а можно и от кварца 8МГц, разницы нет, только изменить SUT_CKSEL
Из минусов схемы: только шумок при воспроизведении аудио, на небольшой громкости вообще не заметно, но все же. Вызвано тем, что wav воспроизводится с самого начала файла, а там в начале НЕполезные данные есть, которые также в динамик пихаются, вызвано это ограниченностью памяти mega8, на другом контроллере этот эффект, думаю, будет полностью убран дополнительной функцией в коде.
Чего ожидать в будущем: если эта схема окажется нужной и популярной, планирую заменить RTC на DS1307, добавить термометр (скорее всего LM75 по I2C), контроллер заменить на mega168 или другой с более чем 8 кб памяти, т.к. воспроизведение wav есть очень много, добавить сценарии озвучки, будет не только воспроизводить время и будильник, но и здороваться с хозяином или что-то подобное, озвучивание каких-либо других статусов, добавить усилитель в схему, в меню добавить коррекцию хода часов, убрать коротенький писк в начале воспроизведения аудио.
Список радиоэлементов
Обозначение | Тип | Номинал | Количество | Примечание | Магазин | Мой блокнот |
---|---|---|---|---|---|---|
IC1 | МК AVR 8-бит | ATmega8 | 1 | Поиск в магазине Отрон | ||
IC2 | ИС I2C интерфейса | PCA9517 | 1 | Поиск в магазине Отрон | ||
IC3 | Часы реального времени (RTC) | PCA2129T | 1 | PCF2129 | Поиск в магазине Отрон | |
VR1 | Линейный регулятор | L7805AB | 1 | Поиск в магазине Отрон | ||
VD1...VD3 | Выпрямительный диод | 1N4148 | 3 | Поиск в магазине Отрон | ||
VD4 | Стабилитрон | BZX55C3V3 | 1 | Поиск в магазине Отрон | ||
R1 | Подстроечный резистор | 3296W-1-103LF | 1 | 10к | Поиск в магазине Отрон | |
R3, R4, R5, R7-R11 | Резистор | 10 кОм | 8 | Поиск в магазине Отрон | ||
R2 | Резистор | 270 Ом | 1 | Поиск в магазине Отрон | ||
R6 | Резистор | 220 Ом | 1 | Поиск в магазине Отрон | ||
C1, C4, C5 | Электролитический конденсатор | 220 мкФ | 3 | Поиск в магазине Отрон | ||
C2, C3, C6 | Конденсатор | 0.1 мкФ | 3 | Поиск в магазине Отрон | ||
С7 | Электролитический конденсатор | 10 мкФ | 1 | Поиск в магазине Отрон | ||
S1...S5 | Тактовая кнопка | TC-A109 | 5 | Поиск в магазине Отрон | ||
LED1 | Светодиод | 1 | Поиск в магазине Отрон | |||
HG1 | LCD-дисплей | SC1602 | 1 | на базе HD44780 | Поиск в магазине Отрон | |
Speaker | Динамик | 1 | Поиск в магазине Отрон | |||
Элемент питания | 3 В | 1 | cr2032 | Поиск в магазине Отрон | ||
Карта памяти | microSD | 1 | Поиск в магазине Отрон | |||
Скачать список элементов (PDF)
Прикрепленные файлы:
- proteus.rar (17 Кб)
- RTC PCF2129AT I2C + SPI lay.lay6 (134 Кб)
- v_2 mega8 PCA2129 microSD soft_alarm 32kHZ.hex (22 Кб)
- v_2 mega8 PCA2129 microSD soft_alarm 44kHZ.hex (22 Кб)
- время (балаболка, алена).rar (5995 Кб)
Комментарии (45) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
У меня аналогичная конструкция, но на меге32, ds1338 и ds18b20 - в начале и в конце каждого слова при выводе возникает щелчок. Не знаю как бороться.
[Автор]
Также посоветую попробовать различные программы для записи и конвертации файлов звука - мало ли лишнего мусора добавляют; я озвучивал балаболкой, конвертировал Weeny Free Audio Converter (на каком-то этапе тоже были щелчки, но после множества подбора наиболее качественного аудио, их нет)
[Автор]
Например, что-то типа того:
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]