- Необходими материали:
- Предварителни условия:
- Електрическа схема:
- Програмиране за будилник:
- Симулация:
- Работа на цифров будилник с помощта на PIC16F877A:
Цифровата революция, започнала през 1950 г., променя всички съществуващи механични и аналогови електронни структури в цифрови компютри. Тъй като растежът на цифровата електроника е експоненциален, днес е почти невъзможно човек да се противопостави на използването на каквото и да е електронно оборудване. Започвайки от будилника, който ви събужда, и тостера, който ви сервира закуска, всичко е принос от цифровата електроника. Мислейки за всичко това, наистина е вълнуващо да програмираме наши собствени неща, които биха могли да изпълняват прости, но полезни задачи, като Будилник, който ще изградим в този проект с PIC Microcontroller. Преди това сме изградили будилник с други микроконтролери:
- Будилник Raspberry Pi, използващ RTC модул DS1307
- Цифров часовник с аларма, базиран на Arduino
- Будилник с помощта на микроконтролер ATmega32
Този будилник ще има 16x2 LCD дисплей, който ще показва текущото време и зададеното време. Ще използваме няколко бутона, за да зададем времето за аларма, когато е необходимо. Текущото време ще се следи с помощта на модула DS3231 RTC и ще използваме IIC комуникация, за да получим тези стойности от модула RTC. Вече научихме за RTC модула и как да го свържем с PIC. Затова се препоръчва да прочетете този урок, ние ще пропуснем по-голямата част от информацията, обхваната в този урок.
Необходими материали:
- Дъска за хляб - 2Nos
- PIC16F877A
- 5V източник на захранване - захранващ модул
- 20 MHz кристал
- 33pf кондензатор - 2Nos
- DS3231 RTC модул
- 16 * 2 LCD дисплеен модул
- 10K ПОТ
- 10k и 1K резистор
- Бутони - 5Не
- Звънец
- Свързващи проводници
Предварителни условия:
Този проект изисква да знаете малко основи за микроконтролера PIC и как да го програмирате. За този проект ще използваме GPIO, LCD дисплей и RTC модул. Затова е по-добре да се научите как да използвате тези модули предварително. Следните връзки ще ви помогнат да научите същото
- Писане на първата ви програма с PIC Microcontroller
- Свързване на LCD с PIC
- I2C комуникация чрез PIC
- DS3231 RTC взаимодействие с PIC
Електрическа схема:
Схемата на схемата за този PIC базиран проект за будилник е показана по-долу, която е създадена с помощта на софтуера proteus. The също ще се използва за симулация по-нататък в този проект.
Петте бутони ще действат като вход за настройка на алармата за необходимото време. Така че единият край на всички бутони са свързани към земята, а останалите краища са свързани към PORTB щифт, на тези щифтове ще се използва вътрешен издърпващ резистор, за да се избегнат плаващите щифтове. Звуковият сигнал ще действа като изход и ще ни издава звуков сигнал, когато алармата се задейства и е свързан към щифта PORT S Текущото време винаги се следи от DS3231 RTC модула, от който PIC получава данните през I2C шина, така че SCL и SDA щифтовете на RTC модула са свързани към SCL и SDA щифт на PIC контролера. Към PORTD на PIC е прикрепен LCD дисплей, който се използва за показване на текущото време и зададеното време. Научете повече за използването на DS3231 RTC модул с PIC тук.
Пълната схема може да бъде изградена върху макет. Тъй като има няколко дузини проводници за свързване, така че имайте търпение и се уверете, че връзките са правилни. Моята хардуерна настройка изглеждаше по-долу по следния начин, след като приключих с връзките
Използвал съм модул за макет и адаптер 12V за захранване на модула. Това е моят източник на + 5V захранващо напрежение. Също така трябва да използвам два макета, за да поддържам веригата чиста. Можете също така да спойкате цялата верига на перфектна дъска, ако искате да направите по-здрав проект.
Програмиране за будилник:
Най- пълен PIC програмата за този проект будилник може да се намери в дъното на тази страница. Този проект също изисква три библиотеки за използване на LCD, I2C и RTC с PIC. Пълният код с заглавни файлове може да бъде изтеглен от ZIP файла тук и може да бъде отворен с помощта на MPLABX след извличане. По-нататък по-долу просто обяснявам основния c файл като малки фрагменти. Можете да се върнете към гореспоменатите уроци, ако искате да знаете как работят заглавните файлове.
Преди да влезем в основната програма, трябва да дефинираме щифтовете, които сме използвали с по-смислено име. По този начин ще бъде лесно да ги използвате по време на програмиране. Пиновете, дефинирани в нашата програма, са показани по-долу
// Дефиниране на щифтовете на LCD #define RS RD2 // Нулиране на щифт на LCD #define EN RD3 // Активиране на щифт на LCD #define D4 RD4 // Бит за данни 0 на LCD #define D5 RD5 // Бит за данни 1 на LCD #define D6 RD6 // Бит за данни 2 на LCD #define D7 RD7 // Бит за данни 3 на LCD // Определяне на бутони #define MB RB1 // Средният бутон #define LB RB0 // Ляв бутон #define RB RB2 // Десен бутон # дефинирайте UB RB3 // Горен бутон #define BB RB4 // Бутон отдолу // Определете Buzz #define BUZZ RD1 // Звукът е свързан към RD1
Вътре в основната функция започваме с деклариране на входните и изходните щифтове. В нашия проект PORTB се използва за бутони, което е устройство за въвеждане, така че ние задаваме техните щифтове като входове, а PORTD се използва за LCD и зумер, така че ние задаваме техните щифтове като изход. Също така щифтът никога не трябва да се оставя плаващ в смисъл, I / O щифтовете винаги трябва да бъдат свързани или към земята или към + 5V напрежение. В нашия случай за бутоните щифтовете няма да бъдат свързани към нищо, когато бутонът не е натиснат, затова използваме вътрешен издърпващ резистор, който настройва щифта на Високо, когато не се използва. Това се прави с помощта на контролните регистри, както е показано по-долу
TRISD = 0x00; // Направете щифтове на порт D като изходящи за LCD интерфейс TRISB = 0xFF; // Суичовете се декларират като входни щифтове OPTION_REG = 0b00000000; // Активиране на издърпващия резистор на порт B за превключватели BUZZ = 0; // Завъртане на зумера
Тъй като имаме заглавния файл LCD и I2C, свързан с основната програма, можем да стартираме инициализацията на LCD, като извикаме проста функция. Същото може да се направи и за инициализация на I2C. Тук започваме I2C комуникацията на 100kHz, тъй като RTC модулът работи със 100kHz.
Lcd_Start (); // Инициализиране на LCD модул I2C_Initialize (100); // Инициализиране на I2C Master с 100KHz часовник
Функцията по-долу се използва за задаване на часа и датата на RTC модула, след като времето и датата са зададени, премахнете този ред. Иначе всеки път, когато стартирате програмата, часът и датата ще се задават отново и отново
// Премахнете долния ред, след като времето и датата са зададени за първи път. Set_Time_Date (); // задаване на час и дата на RTC модула
За да покажем, че програмата се стартира, ние показваме малък начален екран, който показва името на проекта и името на уебсайта, както е показано по-долу
// Дайте встъпително съобщение на LCD Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String ("Будилник"); Lcd_Set_Cursor (2,1); Lcd_Print_String ("-Circuit Digest"); __delay_ms (1500);
След това в цикъла while трябва да прочетем текущото време и дата от RTC модула, това може да стане, като просто извикаме функцията по-долу.
Update_Current_Date_Time (); // Прочетете текущата дата и час от модула RTC
Извикването на горната функция ще актуализира променливите sec, min и hour с текущата стойност. За да ги покажем на LCD екрана , трябва да ги разделим на отделни символи, като използваме кода по-долу.
// Разделяме на char за показване на lcd 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 екрана. Текущото време ще се покаже на първия ред, а зададеното време, в което трябва да се задейства алармата, се показва на втория ред. Кодът, който прави същото, е показан по-долу.
// Показване на текущото време на LCD екрана Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("ВРЕМЕ:"); Lcd_Print_Char (час_1 + '0'); Lcd_Print_Char (час_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (мин_1 + '0'); Lcd_Print_Char (мин_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (sec_1 + '0'); Lcd_Print_Char (sec_0 + '0'); // Показване на датата на LCD екрана 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');
Сега сме показали часа и зададеното време на LCD дисплея, за да проверим дали потребителят се опитва да зададе времето за аларма. За да направите това, потребителят трябва да натисне средния бутон, така че ще проверим дали средният бутон е натиснат и превключваме променлива, за да влезем в режим на настройка на алармата. Същият бутон ще бъде натиснат отново, за да потвърди, че стойностите са зададени и в този случай трябва да излезем от режим на настройка на алармата. Затова използваме долния ред код, за да променим състоянието на променливата 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 за множество записи. Този проблем може да бъде решен чрез добавяне на кондензатор през превключвателя или чрез използване на функция за забавяне веднага щом бъде засечено натискането на бутона. Този тип решение се нарича отскачане. Тук използвахме цикъл while, за да задържаме програмата на място, докато бутонът не бъде освободен. Това не е най-доброто решение за отскачане, но за нас ще работи добре.
докато (! 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 IC също е показана на електрическата схема. След като програмата бъде качена, трябва да видите екрана за въвеждане и след това показваното време можете да използвате бутоните, за да зададете времето за аларма. Моята хардуерна настройка при захранване изглежда по-долу.
Когато времето за аларма съвпада с текущото време, зумерът ще започне да издава звуков сигнал, за да алармира потребителя. Цялата работа може да бъде намерена на видеото по-долу. Проектът има множество възможности за надграждане. Модулът RTC може да проследява всяко време и дата, така че можете да изпълнявате планирана задача по всяко време / дата, която се изисква. Можете също да свържете уред за променлив ток като вентилатор или лампа и да планирате да се включва или изключва, когато е необходимо. Все още има много повече неща, които можете да надградите върху този проект, уведомете ме каква идея ви хрумва като надграждане на този проект и ще се радвам да чуем от вас.
Надявам се, че сте разбрали проекта и сте научили нещо полезно от процеса. Ако имате някакви съмнения в този проект, използвайте раздела за коментари, за да ги публикувате или използвайте форумите за техническа помощ.
Пълен PIC код със заглавни файлове можете да намерите тук