Navrhněte hodiny s funkcí měření teploty. Implementujte automatické řízení jasu displeje dle okolního osvětlení. Použijte mikrokontrolér Atmel ATSAM3X8E a vhodný obvod hodin reálného času.
Pro projekt byla použita základní deska Arduino DUE s procesorem Atmel AT91SAM3X8E jako periferie byl použit display WC1602A teplotní čidla Dallas DS18B20, fotoodpor VT43N1, Spínací tranzistor IRFZ44NS a obvod reálního času DS3231. Samozřejmostí je nutnost programovacího kabelu s microUSB. Všechny periferie byly propojeny pomocí nepájivého kontaktního pole a propojovacích vodičů. Main deska Arduino DUE je vybaveno zmíněným procesorem Atmel ATSAM3X8E s ARm Cortex-M3. Jedná se o jednoduchý ARM procesor s 54 digitálními piny z nich 12 lze využít pro řízení PWM, 12 jako analogový vstup, až 4 sériové porty, USB-OTG, dvěma DAC převodníky, aj. o taktu 84MHz.
obr.1 Náhled na zapojení všech periferií k procesorové desce
Fotoodpor slouží ke snímání intezity okolního jasu v zapojení jako dělič z napájecího napětí jehož střed je přiveden na analogový vstup procesoru. Tranzostor IRFZ44NS je výkonový spínací prvek pro podsvícení displeje, jehož Gate je řízena signálem PWM z procesoru. LCD display je schopen najednou zobrazit 32 znaků a slouží jako výstupní zařízení celého projektu. Na předchozím obrázku je ještě vidět potenciometr, který nastavuje kontrast displeje. Teplotní čidla Dallas DS18B20 nají výhodu, že lze je uplatnit paralelně s využitím pouze dvou vodičů, zde však je použito standardní tří-vodičové napájení, kde jeden vodič je datový, přivedený na pin procesoru z obou čidel najednou. Obvod reálného času má výhodu využití záložní baterie a proto když odpojíme napájení nemusíme čas znovu nastavovat. Data do procesoru se dostanou pomocí implementované sběrnice IIC na desce RTC.Na následujícím obrázku je vyobrazeno blokové schéma celého zapojení.
obr.2 Blokové schéma zapojení projektu
Pro realizaci projektu bylo využito prostředí eclipse. Za pomocí knihoven pro Arduino a knihoven pro periferie stažené z GitHubu byl vytvořen projekt MPOA v prostředím eclipse ve verzi Kepler c++.
Projekt byl vytvářen po sekcích ,které ospovídali připojení vždy jedné periferie, tedy k CPU desce byl připojen diplej a vyzkoušeno zobrazení jednoduchého text. Dále byla připojena periferie RTC a zobrazeno datum s časem na dipleji. Další fází byly teplotní čidla, fotoodpor a PWM řízení jasu displeje.
V následujícím videu je nahráno kompletní zobrazení displeje s přepínáním zaznamenané maximální a minimální teploty spolu s datumem:
V tutaj části je prezentován zdrojový kód.
//Na displeju zobrazi teplotu, cas a datum #include "MPOA_DUE.h" #include "DallasTemperature.h"//Teplota #include <OneWire.h> //Teplota #include <LiquidCrystal.h> //LCD #include <Wire.h> //RTC //BEZ knihovny DS1307/DS3231!!! // Data wires is plugged into pins: #define ONE_WIRE_BUS 2 //Teplota #define DS3231_I2C_ADDRESS 0x68 //RTC // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); //LCD piny LiquidCrystal lcd(22, 24, 26, 28, 30, 32); float teplota0;//sem se ulozi prectena teplota z Dallasu float teplota0M;//maximum teploty0 float teplota0m;//minimum teploty0 float teplota1;//sem se ulozi prectena teplota z Dallasu float teplota1M;//maximum teploty1 float teplota1m;//minimum teploty1 String teploty;//string na vypis teplot+maxim+minim char LCD_teploty[75];//pomocný char na zobrazení teplot char LCD_Tout[17];//tohle se primo zobrazi na displeji unsigned long previousMillis = 500;//pomocna neblokujici cekani const long interval = 200;//pomocna na nebkokujici cekani byte mov = 0;//posuv int ledPin = 3; // LCD_LED (PWM) connected to digital pin 3 void first_read_sensors() {//první čtení z čidel po zapnutí - do maxima a minima se uloží aktuální teplota sensors.requestTemperatures(); //DALLAS1 teplota1 = sensors.getTempCByIndex(1); //DALLAS0 teplota0 = sensors.getTempCByIndex(0); teplota1M=teplota1; if(-127<teplota1m) teplota1m=teplota1; teplota0M = teplota0; if(-127<teplota0m) teplota0m = teplota0; } void read_sensors() {//kromě prvniho kazde cteni z cidel sensors.requestTemperatures(); //DALLAS1 teplota1 = sensors.getTempCByIndex(1); //DALLAS0 teplota0 = sensors.getTempCByIndex(0); } //RTC byte decToBcd(byte val) {// Convert normal decimal numbers to binary coded decimal return( (val/10*16) + (val%10) ); } byte bcdToDec(byte val) {// Convert binary coded decimal to normal decimal numbers return( (val/16*10) + (val%16) ); } void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { // sets time and date data to DS3231 Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0x00); // set next input to start at the seconds register Wire.write(decToBcd(second)); // set seconds Wire.write(decToBcd(minute)); // set minutes Wire.write(decToBcd(hour)); // set hours Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday) Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31) Wire.write(decToBcd(month)); // set month Wire.write(decToBcd(year)); // set year (0 to 99) Wire.endTransmission(); } void readDS3231time(byte *second,byte *minute,byte *hour,byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year) {//cteni z hodin Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes of data from DS3231 starting from register 00h *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } void set_time() {//nastaveni casu // set the initial time here: // DS3231 seconds, minutes, hours, day, date, month, year setDS3231time(04,57,22,4,26,11,15); } //The setup function is called once at startup of the sketch void setup() { Serial.begin(9600); sensors.begin(); // IC Default 9 bit.Dallas Wire.begin(); //DS3231 lcd.begin(16, 2);//LCD 16*2 //set_time();//Aktivuje nastaveni casu delay(500); first_read_sensors();//pouze první ctení z cidel } // The loop function is called in an endless loop void loop() {/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //RTC-cteni byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // retrieve data from DS3231 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); //Dallsas - cteni if(mov%10==0) { read_sensors();//cteni z čidel } //DALLAS1_max-min_LCD if(teplota1>teplota1M)//Maximalni teplota teplota1M=teplota1; if(teplota1<teplota1m && teplota1 > float(-120))//minimální teplota teplota1m=teplota1; lcd.setCursor(0, 0); lcd.print("i:" + String(teplota1)+ " ");//vypis vnitrni teploty //DALLAS0_max-min_LCD if(teplota0>teplota0M)//Maximalni teplota teplota0M=teplota0; if(teplota0<teplota0m && teplota0 > float(-120))//minimální teplota teplota0m=teplota0; lcd.setCursor(9, 0);//vypis vnejsi teploty lcd.print("o:" + String(teplota0) + " "); //Zobrazeni datumu a min/max hodnot lcd.setCursor(7 ,1);//cursor pro pohybujíci se text teploty=(" " + String(dayOfMonth) + "." + String(month) + "." + String(year) + " iM:" + String(teplota1M) + " im:" + String(teplota1m) + " oM:" + String(teplota0M) + " om:" + String(teplota0m) + " ");//string beziciho textu teploty.toCharArray(LCD_teploty,75); //Neblokujici posouvani textu na displeji unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; strncpy(LCD_Tout, &LCD_teploty[mov], 16);//vykopirovani z dlouhyho stringu na zobrazeni na displey mov = mov+10; if(mov>52){ mov=0; } } lcd.print(LCD_Tout); //Zobrazeni casu lcd.setCursor(0, 1); String min0 = String(0);//prida 0 pred jednosnakova cisla if (int(minute)<10) min0=("0" + String(minute)); else min0 = String(minute); lcd.print(String(hour) + ":" + min0);//vypis casu //Jas Displeje: int inJas = analogRead(A11); int outJas = 255 - inJas/4; if(outJas < 5) outJas = 5; analogWrite(ledPin, outJas); }
Projekt vyl realizován do plné funkce, jak je vide například v předchozím videu. Pro realizaci hodin bylo testování několik obvodů jako je DS1302 a DS1307, ale zde dochází k problému s verzemi knihoven. U Použitého RTC obvodu DS3231 tento problém nebyl. Dále by se dala efektivněji napsat funkce, která přepíná na dipleji maximální, minimální hodnoty a datum. Vývojové prostředí eclipse s pluginy Arduino bylo použito pro jeho vyšší přívětivost oproti standardnímu prostředí Arduino IDE.