- Необхідні матеріали:
- Передумови:
- Кругова діаграма:
- Програмування для будильника:
- Моделювання:
- Працює цифровий будильник за допомогою PIC16F877A:
Цифрова революція, розпочата в 1950 році, змінює всі існуючі механічні та аналогові електронні структури на цифрові комп'ютери. Оскільки зростання цифрової електроніки було експоненціальним, сьогодні людині практично неможливо протистояти використанню будь-якого електронного обладнання. Починаючи від будильника, який вас прокидає, і тостера, який подає сніданок, все - внесок цифрової електроніки. Думаючи про все це, дуже цікаво програмувати наші власні речі, які могли б виконувати прості, але корисні завдання, такі як Будильник, який ми збираємось створити в цьому проекті за допомогою мікроконтролера PIC. Раніше ми побудували будильник з іншими мікроконтролерами:
- Будильник Raspberry Pi за допомогою модуля RTC DS1307
- Цифровий годинник на базі Arduino з сигналізацією
- Будильник за допомогою мікроконтролера ATmega32
Цей будильник матиме РК-дисплей 16x2, який відображатиме поточний час та встановлений час. Ми будемо використовувати кілька кнопок для встановлення часу будильника, коли це буде потрібно. Поточний час буде відстежуватися за допомогою модуля RTC DS3231, і ми будемо використовувати зв'язок IIC, щоб отримати ці значення з модуля RTC. Ми вже дізналися про модуль RTC та про те, як взаємодіяти з PIC. Тому рекомендується прочитати цей підручник, ми пропустимо більшу частину інформації, викладеної в цьому підручнику.
Необхідні матеріали:
- Хлібна дошка - 2Ні
- PIC16F877A
- Джерело живлення 5 В - модуль живлення
- Кристал 20 МГц
- Конденсатор 33pf - 2Ні
- Модуль RTC DS3231
- Модуль РК-дисплея 16 * 2
- 10K POT
- Резистор 10k та 1K
- Кнопки - 5Ні
- Зумер
- Підключення проводів
Передумови:
Цей проект вимагає, щоб ви знали трохи основних відомостей про мікроконтролер PIC та як його запрограмувати. Для цього проекту ми будемо використовувати GPIO, РК-дисплей та модуль RTC. Тому краще заздалегідь навчитися користуватися цими модулями. Наступні посилання допоможуть вам вивчити те саме
- Написання вашої першої програми за допомогою мікроконтролера PIC
- Зв'язок РК з PIC
- Зв'язок I2C за допомогою PIC
- DS3231 RTC взаємодіє з PIC
Кругова діаграма:
Схема для цього проекту будильника на основі PIC наведена нижче, яка була створена за допомогою програмного забезпечення proteus. Також буде використано для моделювання далі в цьому проекті.
П'ять кнопок будуть виконувати роль входу для встановлення сигналу тривоги на необхідний час. Отже, один кінець усіх кнопок підключений до землі, а інші кінці - до штиря PORTB, на цих штифтах буде використовуватися внутрішній підтягуючий резистор, щоб уникнути плаваючих штифтів. Звуковий сигнал буде діяти як вихідний сигнал і подаватиме звуковий сигнал, коли спрацьовує будильник і підключений до виводу PORT S. Поточний час завжди відслідковується модулем RTC DS3231, з якого ПІК отримує дані через шину I2C, тому висновки SCL та SDA модуля RTC підключені до виводу SCL та SDA контролера PIC. РК-дисплей приєднаний до PORTD PIC, який використовується для відображення поточного часу та встановленого часу. Дізнайтеся більше про використання модуля DS3231 RTC з PIC тут.
Повна схема може бути побудована на макеті. Оскільки є кілька десятків проводів для підключення, то просто запасіться терпінням і переконайтеся, що підключення правильні. Моє апаратне налаштування виглядало приблизно так нижче, як тільки я закінчив із підключеннями
Я використовував модуль макетної плати та адаптер 12 В для живлення модуля. Це моє джерело напруги живлення + 5 В. Крім того, я повинен використовувати дві макетні плати, щоб підтримувати чистоту ланцюга. Ви також можете припаяти всю схему до перф-дошки, якщо хочете зробити більш надійний проект.
Програмування для будильника:
Повна програма ПОС для цього проекту Clock Alarm можна знайти в нижній частині цієї сторінки. Цей проект також потребує трьох бібліотек для використання LCD, I2C та RTC з PIC. Повний код із файлами заголовків можна завантажити з ZIP-файлу тут і відкрити за допомогою MPLABX після вилучення. Далі нижче я просто пояснюю основний файл c як невеликі фрагменти. Ви можете повернутися до вищезазначених підручників, якщо хочете знати, як працюють файли заголовків.
Перш ніж потрапити в основну програму, ми повинні визначити шпильки, які ми використовували з більш значущою назвою. Таким чином буде легко використовувати їх під час програмування. Шпильки, визначені в нашій програмі, показані нижче
// Визначити штифти РК-дисплея #define RS RD2 // Скинути штифт РК-дисплея #define EN RD3 // Увімкнути штифт РК-дисплея #define D4 RD4 // Біт даних 0 РК-дисплея #define D5 RD5 // Біт даних 1 РК-дисплея #define D6 RD6 // Біт даних 2 РК # визначити D7 RD7 // Біт даних 3 РК // Визначити кнопки # визначити MB RB1 // Середня кнопка # визначити LB RB0 // Ліва кнопка # визначити RB RB2 // Права кнопка # визначити UB RB3 // Верхня кнопка #define BB RB4 // Нижня кнопка // Визначити Buzz #define BUZZ RD1 // Звуковий сигнал підключений до RD1
Всередині основної функції ми починаємо з декларування вхідних та вихідних штифтів. У нашому проекті PORTB використовується для кнопок, що є пристроєм введення, тому ми встановлюємо їх висновки як входи, а PORTD використовується для РК-дисплея та зумера, тому ми встановлюємо їх висновки як вихід. Крім того, штифт ніколи не повинен залишатися плаваючим, значення штифтів вводу-виводу завжди повинні бути підключені до заземлення або до напруги + 5 В. У нашому випадку для натискання кнопок штифти не будуть підключатися ні до чого, коли кнопка не натиснута, тому ми використовуємо внутрішній підтягуючий резистор, який встановлює штифт на Високий, коли він не використовується. Це робиться за допомогою регістрів управління, як показано нижче
TRISD = 0x00; // Зробити штифти порту D як вихідні для РК-інтерфейсу TRISB = 0xFF; // Комутатори оголошуються як вхідні штифти OPTION_REG = 0b00000000; // Увімкнути підтягуваний резистор на порту B для комутаторів BUZZ = 0; // Поворот зумера
Оскільки у нас є файл заголовка РК-дисплея та I2C, пов'язаний з основною програмою, ми можемо розпочати ініціалізацію РК-дисплея, викликавши просту функцію. Те саме можна зробити і для ініціалізації I2C. Тут ми починаємо зв'язок I2C на частоті 100 кГц, оскільки модуль RTC працює на частоті 100 кГц.
Lcd_Start (); // Ініціалізація РК-модуля I2C_Initialize (100); // Ініціалізація I2C Master з тактовою частотою 100 кГц
Наведена нижче функція використовується для встановлення часу та дати на модулі RTC, після встановлення часу та дати видаліть цей рядок. В іншому випадку кожного разу, коли ви запускаєте програму, час і дата встановлюватимуться знову і знову
// Видаляємо нижче лінії раз час і дата буде встановлена в перший раз. Set_Time_Date (); // встановити час і дату в модулі RTC
Щоб вказати, що програма запускається, ми відображаємо невеликий вступний екран, який відображає назву проекту та назву веб-сайту, як показано нижче
// Даємо вступне повідомлення на РК-дисплеї Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String ("Будильник"); Lcd_Set_Cursor (2,1); Lcd_Print_String ("-Cesture Digest"); __delay_ms (1500);
Далі всередині в той час циклу, ми повинні прочитати поточний час і дату з модуля RTC, це може бути зроблено просто виклик нижче функції.
Update_Current_Date_Time (); // Зчитування поточної дати та часу з модуля RTC
Виклик вищевказаної функції оновить змінні сек, хв і годину з поточним значенням. Для того, щоб відобразити їх на РК-екрані, ми повинні розділити їх на окремі символи, використовуючи наведений нижче код.
// Розділіть на char для відображення на рідкокристалічному дисплеї char sec_0 = sec% 10; char sec_1 = (sec / 10); char min_0 = min% 10; char min_1 = min / 10; char година_0 = година% 10; char година_1 = година / 10;
Далі ми оновлюємо значення на РК-екрані. Поточний час відображатиметься в першому рядку, а встановлений час, у який повинен спрацьовувати будильник, відображається у другому рядку. Код, який робить те саме, показано нижче.
// Відображення поточного часу на РК-екрані Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("TIME:"); Lcd_Print_Char (година_1 + '0'); Lcd_Print_Char (година_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (min_1 + '0'); Lcd_Print_Char (min_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (sec_1 + '0'); Lcd_Print_Char (sec_0 + '0'); // Відображення дати на РК-екрані Lcd_Set_Cursor (2, 1); Lcd_Print_String ("Будильник:"); Lcd_Print_Char (alarm_val + '0'); Lcd_Print_Char (alarm_val + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (alarm_val + '0 '); Lcd_Print_Char (alarm_val + '0');
Тепер ми відобразили час і встановили час на РК-дисплеї, щоб перевірити, чи намагається користувач встановити час будильника. Для цього користувач повинен натиснути середню кнопку, тому ми перевіримо, чи натиснута середня кнопка, і перемкнемо змінну для переходу в режим встановленого будильника. Цю ж кнопку буде натиснуто ще раз, щоб підтвердити, що значення встановлені, і в цьому випадку ми повинні вийти з режиму встановлення сигналізації. Отже, ми використовуємо нижченаведений рядок коду, щоб змінити статус змінної set_alarm .
// Використовуйте середню кнопку, щоб перевірити, чи потрібно встановлювати будильник , якщо (MB == 0 && set_alarm == 0) {// Якщо натиснута середня кнопка і будильник не ввімкнено, поки (! MB); // Зачекайте, поки кнопка не буде відпущена set_alarm = 1; // починаємо встановлювати значення сигналу тривоги } if (MB == 0 && set_alarm == 1) {// Якщо натиснута середня кнопка і сигнал тривоги не вимкнено, поки (! MB); // Зачекайте, поки кнопка не буде відпущена set_alarm = 0; // зупинити встановлення значення будильника }
Якщо користувач натиснув середню кнопку, це означає, що він намагається встановити час будильника. У цьому випадку програма переходить у режим встановлення сигналізації за допомогою наведеного вище коду. Якщо користувач натискає ліву або праву кнопку всередині режиму встановленого будильника, це означає, що ми повинні рухати курсор вліво або вправо. Для цього ми просто збільшуємо зменшення значення позиції, в яку повинен бути розміщений курсор
if (LB == 0) {// Якщо натиснута ліва кнопка, поки (! LB); // Зачекайте, поки кнопка не буде відпущена pos--; // Потім перемістіть курсор вліво } if (RB == 0) {// Якщо натиснута права кнопка, поки (! RB); // Зачекайте, поки кнопка не буде відпущена pos ++; // Переміщення курсору вправо }
При використанні кнопки з мікроконтролером або мікропроцесором існує одна загальна проблема, яку потрібно вирішити. Ця проблема називається підскакуванням перемикача. Тобто при натисканні кнопки це може подавати шумові імпульси на MCU / MPU, що може підробляти MCU для декількох записів. Цю проблему можна вирішити шляхом додавання конденсатора через комутатор або за допомогою функції затримки, як тільки виявляється натискання кнопки. Цей тип розв’язку називається відскоком. Тут ми використовували той час як цикл, щоб тримати програму на місці, поки кнопка НЕ буде відпущена. Це не найкраще рішення для відмови, але для нас воно буде спрацьовувати чудово.
в той час як (! RB);
Подібно до лівої та правої кнопки, ми також маємо верхню та нижню кнопки, які можна використовувати для збільшення або зменшення значення часу будильника. Код, щоб зробити те ж саме, показано нижче. Зверніть увагу, що кожен символ встановленого часу тривоги адресується значенням індексу масиву. Це було те, що ми можемо легко отримати необхідний символ, значення якого слід змінити.
if (UB == 0) {// Якщо натиснути верхню кнопку, поки (! UB); // Зачекайте, поки кнопка не буде відпущена alarm_val ++; // Збільште це конкретне значення символу } if (BB == 0) {// Якщо натиснута нижня кнопка, коли (! UB); // Зачекайте, поки кнопка не буде відпущена alarm_val--; // Зменшити саме це значення символу }
Після встановлення часу будильника користувач знову натисне середню кнопку. Тоді ми можемо почати порівнювати поточний час із заданим часом. Порівняння, перевіряючи, чи кожен окремий символ поточного часу дорівнює символу встановленого часу. Якщо значення рівні, тоді ми запускаємо сигнал тривоги, встановлюючи змінну trigger_alarm, інакше ми просто порівнюємо, поки воно не стане рівним.
// ЯКЩО встановлений сигнал тривоги Перевірте, чи дорівнює встановлене значення поточному значенню, якщо (set_alarm == 0 && alarm_val == hour_1 && alarm_val == hour_0 && alarm_val == min_1 && alarm_val == min_0) trigger_alarm = 1; // Увімкнути тригер, якщо значення збігається
Якщо будильник встановлений, ми повинні подати звуковий сигнал, щоб попередити користувача про тривогу. Це можна зробити, просто перемикаючи зуммер із регулярним інтервалом, як показано нижче.
if (trigger_alarm) {// Якщо спрацьовує сигнал тривоги // Звуковий сигнал BUZZ = 1; __delay_ms (500); BUZZ = 0; __delay_ms (500); }
Моделювання:
Цю програму також можна змоделювати за допомогою програмного забезпечення proteus. Просто повторно створіть схему, показану вище, і завантажте шістнадцятковий файл у PIC. Шістнадцятковий код для цього проекту можна знайти у ZIP-файлі, на який посилається тут. Знімок екрану, зроблений під час моделювання, показаний нижче
Моделювання стає дуже корисним, коли ви намагаєтесь додати до проекту нові функції. Ви також можете використовувати модуль налагоджувача I2C, щоб перевірити, які дані надходять і виходять через шину I2C. Ви можете спробувати натиснути кнопки, а також встановити час будильника. Коли встановлений час дорівнює поточному часу, тоді зумер буде високим.
Працює цифровий будильник за допомогою PIC16F877A:
Побудуйте схему на макетній панелі, отримайте код за посиланням для завантаження та скомпілюйте його за допомогою компілятора MplabX та XC8. Якщо ви завантажили код із наведеного тут ZIP-файлу, тоді у вас не повинно виникнути проблем із його компіляцією, оскільки заголовкові файли вже вкладені.
Після компіляції завантажте програму на апаратне забезпечення за допомогою програміста PicKit3. З'єднання для підключення програміста pickit до мікросхеми PIC також показано на схемі. Після завантаження програми ви побачите вступний екран, а потім, що відображається час, ви можете за допомогою кнопок встановити час будильника. Моє апаратне налаштування при живленні виглядає так нижче.
Коли час будильника збігається з поточним часом, зумер почне подавати звуковий сигнал, щоб застерегти користувача. Повну роботу можна знайти на відео нижче. Проект має безліч варіантів, на яких можна продовжувати. Модуль RTC може відстежувати будь-який час і дату, тому ви можете виконувати заплановане завдання в будь-який час / потрібну дату. Ви також можете підключити прилад змінного струму, такий як вентилятор або світло, і запланувати його вмикання або вимикання, коли це потрібно. Ви ще можете набагато більше використати цей проект, дайте мені знати, яка ідея спадає вам на думку як оновлення цього проекту, і я буду радий почути від вас.
Сподіваюся, ви зрозуміли проект і навчились із цього процесу щось корисне. Якщо у вас є якісь сумніви щодо цього проекту, використовуйте розділ коментарів, щоб розмістити їх, або скористайтесь форумами для отримання технічної допомоги.
Повний код PIC із файлами заголовків можна знайти тут