На днях один интернет-магазин (ekits.ru) прислал мне микросхему — «часы реального времени» — DS1307N. ( Кстати, магазин весьма симпатичный, если кому интересно.) Раз появилась железка – значит нужно её использовать. Интернет, почему-то разнообразием конструкций на этой микросхеме не блещет, хотя подключение к Arduino – проще не бывает. Одно из немногих законченных устройств, построенное на данной микросхеме – это Часы-ночник на DS1307 , которое было опубликовано на многих сайтах. Из данного проекта была позаимствована библиотека для работы с DS1307. При попытке запустить данную библиотеку, выяснилось, что она не адаптирована для работы с Arduino IDE 1.0. Знаний и желания произвести самостоятельную адаптацию не было, поэтому воспользовался Arduino IDE версии 0023.
Почитав описание на DS1307 решил добавить в библиотеку возможность работы с байтом конфигурации RTC. (Для реализации мигания светодиодом на выходе SQW/OUT с частотой 1 Гц.) Модифицированная библиотека выложена ЗДЕСЬ.
Для работы с кнопками и борьбы с дребезгом контактов была использована библиотека «Bounce». А описание и пример использования подсмотрен сдесь. Схема подключения DS1307 была подсмотрена ЗДЕСЬ. Собранно на макетке буквально за полчаса.
Далее пошли программные эксперименты… Но просто отображать на LCD время стало не интересно. Поэтому решил прикрутить сюда же датчики температуры. Кнопки для управления всем устройством. Бузер, для использования этого устройства в качестве будильника.
Использовал ранее наработанные скетчи, частично взятые из примеров, частично из интернета. Осталось всё это свести в одну кучу.
Электрическая схема получилась следующая:
Конечно, схема включения кнопок весьма расточительна. Можно, например, организовать на резисторах делители напряжения и подключать их кнопками на аналоговый вход, организовав обработчик событий по аналогии Часы-ночник на DS1307.
Один из датчиков температуры был установлен на макетной плате, а второй подключен через трехметровый шлейф, сделанный из Ethernet-кабеля Cat.5. Нумерация датчиков в протоколе 1-Wire привязана к их адресам и не совсем тривиальна. Поэтому порядок опроса датчиков определялся «методом научного тыка». При необходимости можно просто поменять их местами. Ниже приведена схема подключения:
Подробней о подключении датчиков можно почитать там.
Ниже приведен листинг получившегося скетча:
/*Reads the value from a Real Time Clock (RTC) DS1307 and displays it in the serial monitor * *Created by D. Sjunnesson 1scale1.com d.sjunnesson (at) 1scale1.com * *Created with combined information from *http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1180908809 *http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1191209057 * * *Big credit to mattt (please contact me for a more correct name...) from the Arduino forum *which has written the main part of the library which I have modified * */ #include <WProgram.h> #include <Wire.h> #include <DS1307.h> // written by mattt on the Arduino forum and modified by D. Sjunnesson #include <LiquidCrystalRus.h> #include <Bounce.h> #include <OneWire.h> #include <EEPROM.h> /*#define Monday "Monday" #define Tuesday "Tuesday" #define Wednesday "Wednesday" #define Thursday "Thursday" #define Friday "Friday" #define Saturday "Saturday" #define Sunday "Sunday" */ #define Monday "Понедельник" #define Tuesday "Вторник" #define Wednesday "Среда" #define Thursday "Четверг" #define Friday "Пятница" #define Saturday "Суббота" #define Sunday "Воскресенье" #define BUTTON 9 // кнопка на 9 пине #define BUTTON2 10 #define BUTTON3 11 #define BUTTON4 12 OneWire ds(8) ; // on pin 8 LiquidCrystalRus lcd(7, 6, 5, 4, 3, 2); //пины ЛСД Bounce bouncer = Bounce(BUTTON, 400); //создаем экземпляр класса Bounce для вывода Bounce bouncer2 = Bounce(BUTTON2, 50); Bounce bouncer3 = Bounce(BUTTON3, 100); Bounce bouncer4 = Bounce(BUTTON4, 100); byte num = 0 ; byte num_Bounce =0 ; char delitel =':' , delitel2 = '/'; unsigned long previousMillis = 0; unsigned long previousMillis2 = 0; //long previousMillis3 = 0; unsigned long interval = 1000, interval2 = 500, interval3 = 2000; boolean del_print = true; int time_data[8] ;//sec, mins, hr, dow, date, mth, yr, ctrl ; int alarm_hr, alarm_min, alarm_set ; #define OCTAVE_OFFSET 0 #define TONE_PIN 14 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 int notes[] = { 0, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7 }; //char *song = "The Simpsons:d=4,o=5,b=160:c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g,8p,8p,8f#,8f#,8f#,8g,a#.,8c6,8c6,8c6,c6"; char *song = "Indiana:d=4,o=5,b=250:e,8p,8f,8g,8p,1c6,8p.,d,8p,8e,1f,p.,g,8p,8a,8b,8p,1f6,p,a,8p,8b,2c6,2d6,2e6,e,8p,8f,8g,8p,1c6,p,d6,8p,8e6,1f.6,g,8p,8g,e.6,8p,d6,8p,8g,e.6,8p,d6,8p,8g,f.6,8p,e6,8p,8d6,2c6"; //char *song = "Entertainer:d=4,o=5,b=140:8d,8d#,8e,c6,8e,c6,8e,2c.6,8c6,8d6,8d#6,8e6,8c6,8d6,e6,8b,d6,2c6,p,8d,8d#,8e,c6,8e,c6,8e,2c.6,8p,8a,8g,8f#,8a,8c6,e6,8d6,8c6,8a,2d6"; //char *song = "Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f"; //char *song = "Bond:d=4,o=5,b=80:32p,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d#6,16d#6,16c#6,32d#6,32d#6,16d#6,8d#6,16c#6,16c#6,16c#6,16c#6,32e6,32e6,16e6,8e6,16d#6,16d6,16c#6,16c#7,c.7,16g#6,16f#6,g#.6"; //char *song = "MASH:d=8,o=5,b=140:4a,4g,f#,g,p,f#,p,g,p,f#,p,2e.,p,f#,e,4f#,e,f#,p,e,p,4d.,p,f#,4e,d,e,p,d,p,e,p,d,p,2c#.,p,d,c#,4d,c#,d,p,e,p,4f#,p,a,p,4b,a,b,p,a,p,b,p,2a.,4p,a,b,a,4b,a,b,p,2a.,a,4f#,a,b,p,d6,p,4e.6,d6,b,p,a,p,2b"; //char *song = "StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6"; //char *song = "GoodBad:d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#"; //char *song = "TopGun:d=4,o=4,b=31:32p,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,16f,d#,16c#,16g#,16g#,32f#,32f,32f#,32f,16d#,16d#,32c#,32d#,16f,32d#,32f,16f#,32f,32c#,g#"; //char *song = "A-Team:d=8,o=5,b=125:4d#6,a#,2d#6,16p,g#,4a#,4d#.,p,16g,16a#,d#6,a#,f6,2d#6,16p,c#.6,16c6,16a#,g#.,2a#"; //char *song = "Flinstones:d=4,o=5,b=40:32p,16f6,16a#,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,d6,16f6,16a#.,16a#6,32g6,16f6,16a#.,32f6,32f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c6,a#,16a6,16d.6,16a#6,32a6,32a6,32g6,32f#6,32a6,8g6,16g6,16c.6,32a6,32a6,32g6,32g6,32f6,32e6,32g6,8f6,16f6,16a#.,16a#6,32g6,16f6,16a#.,16f6,32d#6,32d6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#,16c.6,32d6,32d#6,32f6,16a#6,16c7,8a#.6"; //char *song = "Jeopardy:d=4,o=6,b=125:c,f,c,f5,c,f,2c,c,f,c,f,a.,8g,8f,8e,8d,8c#,c,f,c,f5,c,f,2c,f.,8d,c,a#5,a5,g5,f5,p,d#,g#,d#,g#5,d#,g#,2d#,d#,g#,d#,g#,c.7,8a#,8g#,8g,8f,8e,d#,g#,d#,g#5,d#,g#,2d#,g#.,8f,d#,c#,c,p,a#5,p,g#.5,d#,g#"; //char *song = "MahnaMahna:d=16,o=6,b=125:c#,c.,b5,8a#.5,8f.,4g#,a#,g.,4d#,8p,c#,c.,b5,8a#.5,8f.,g#.,8a#.,4g,8p,c#,c.,b5,8a#.5,8f.,4g#,f,g.,8d#.,f,g.,8d#.,f,8g,8d#.,f,8g,d#,8c,a#5,8d#.,8d#.,4d#,8d#."; //char *song = "MissionImp:d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d"; //char *song = "KnightRider:d=4,o=5,b=125:16e,16p,16f,16e,16e,16p,16e,16e,16f,16e,16e,16e,16d#,16e,16e,16e,16e,16p,16f,16e,16e,16p,16f,16e,16f,16e,16e,16e,16d#,16e,16e,16e,16d,16p,16e,16d,16d,16p,16e,16d,16e,16d,16d,16d,16c,16d,16d,16d,16d,16p,16e,16d,16d,16p,16e,16d,16e,16d,16d,16d,16c,16d,16d,16d"; #define isdigit(n) (n >= '0' && n <= '9') void get_time() { time_data[0] = RTC.get(DS1307_SEC,true) ; time_data[1] = RTC.get(DS1307_MIN,false) ; time_data[2] = RTC.get(DS1307_HR,false) ; time_data[3] = RTC.get(DS1307_DOW,false) ; time_data[4] = RTC.get(DS1307_DATE,false) ; time_data[5] = RTC.get(DS1307_MTH,false) ; time_data[6] = RTC.get(DS1307_YR,false) ; time_data[7] = RTC.get(DS1307_CTRL,false) ; } int freeRam () { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } void setup() { pinMode(13, OUTPUT); Serial.begin(19200); Serial.print("Free RAM="); Serial.println(freeRam(), DEC); //delay(2000); lcd.begin(16, 2);//экран у меня 16 символов на 2е строки lcd.setCursor(0,0);lcd.print("Время:"); lcd.setCursor(0,1);lcd.print("Дата:"); alarm_hr = int(EEPROM.read(0)); alarm_min = int(EEPROM.read(1)); alarm_set = int(EEPROM.read(2)); Serial.print("Будильник: ");Serial.print(alarm_hr);Serial.print(delitel);Serial.print(alarm_min); if (alarm_set) { Serial.println(" ВКЛ."); } else { Serial.println(" ВЫКЛ."); } /* RTC.stop(); RTC.set(DS1307_CTRL,16); RTC.set(DS1307_SEC,0); //set the seconds RTC.set(DS1307_MIN,39); //set the minutes RTC.set(DS1307_HR,15); //set the hours //RTC.set(DS1307_DOW,4); //set the day of the week RTC.set(DS1307_DATE,11); //set the date RTC.set(DS1307_MTH,3); //set the month RTC.set(DS1307_YR,12); //set the year RTC.start(); */ } void loop() { unsigned long currentMillis = millis (); if (currentMillis - previousMillis > interval) { // интервал отображения времени // сохранить последнее previousMillis = currentMillis; get_time(); s_print_time_data() ; lcd_print_time_data(); // Serial.print("Free RAM="); // Serial.println(freeRam(), DEC); } if (currentMillis - previousMillis2 > interval2) { //интервал отображения разделителя // сохранить последнее previousMillis2 = currentMillis; print_delitel() ; } if (alarm_set) { if ((alarm_hr == time_data[2])&(alarm_min == time_data[1])&(time_data[0] == 0)) { Serial.println("Будильник работает"); lcd.clear(); lcd.setCursor(6,0); lcd.print("ALARM"); play_rtttl(song); //delay(3000); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); } } if (bouncer.update()) { if (bouncer.read()==0) { lcd.clear(); lcd.print("Т.комн."); lcd.setCursor(0, 1); lcd.print("Т.улица"); print_temperature(); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); } } /* if (bouncer4.update()) { if (bouncer4.read()==0) { Serial.println("Нажата кнопка № 4:"); delay(200); } }*/ if (bouncer2.update()) { if (bouncer2.read()==0) { num_Bounce++ ; unsigned long previousMillis3 = millis (); while (millis () - previousMillis3 < interval3) { // previousMillis2 = currentMillis; if (bouncer2.update()) { if (bouncer2.read()==0) num_Bounce++ ; //delay(1000); } } /*Serial.print("Нажата кнопка № 2: "); Serial.print(num_Bounce,DEC); Serial.println(" раза/раз"); num_Bounce = 0 ; delay(500);*/ switch (num_Bounce) { case 1: set_hr(); num_Bounce = 0 ; break; case 2: set_min(); num_Bounce = 0 ; break; case 3: set_alarm_hr(); num_Bounce = 0 ; break; case 4: set_alarm_min() ; num_Bounce = 0 ; default: num_Bounce = 0 ; } //} } } } void set_alarm_min() { lcd.clear(); lcd.print(" Будильник"); lcd.setCursor(0,1);lcd.print("Минуты:"); if (alarm_min<10){ lcd.setCursor(8,1);lcd.print('0');lcd.print(alarm_min); } else { lcd.setCursor(8,1);lcd.print(alarm_min); } if (alarm_set) { lcd.setCursor(12,1) ; lcd.print("ВКЛ."); } else { lcd.setCursor(12,1) ; lcd.print("ВЫКЛ"); } while (1) { if (bouncer3.update()) { if (bouncer3.read()==0) { if (alarm_min++ > 58) alarm_min = 0; if (alarm_min<10){ lcd.setCursor(8,1); lcd.print('0');lcd.print(alarm_min); } else { lcd.setCursor(8,1);lcd.print(alarm_min); } } } if (bouncer2.update()) { //нажали 2-ю кнопку устанавливваем часы и выходим if (bouncer2.read()==0) { EEPROM.write(1,alarm_min); EEPROM.write(2,alarm_set); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; } } if (bouncer4.update()) { if (bouncer4.read()==0) { if (alarm_set) { alarm_set = 0; } else { alarm_set = 1; } if (alarm_set) { lcd.setCursor(12,1) ; lcd.print("ВКЛ."); } else { lcd.setCursor(12,1) ; lcd.print("ВЫКЛ"); } } } } } void set_alarm_hr() { // int temp_hr = int (); lcd.clear(); lcd.print(" Будильник"); lcd.setCursor(0,1);lcd.print("Часы:"); if (alarm_hr<10){ lcd.setCursor(6,1);lcd.print('0');lcd.print(alarm_hr); } else { lcd.setCursor(6,1);lcd.print(alarm_hr); } while (1) { if (bouncer3.update()) { if (bouncer3.read()==0) { if (alarm_hr++ > 22) alarm_hr = 0; if (alarm_hr<10){ lcd.setCursor(6,1); lcd.print('0');lcd.print(alarm_hr); } else { lcd.setCursor(6,1);lcd.print(alarm_hr); } } } if (bouncer2.update()) { //нажали 2-ю кнопку записываем часы в EEPROM и выходим if (bouncer2.read()==0) { EEPROM.write(0,alarm_hr); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; } } if (bouncer4.update()) { if (bouncer4.read()==0) { lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; //выход без изменения } } } } void set_min() { lcd.clear(); lcd.print(" Настройка"); lcd.setCursor(0,1);lcd.print("Минуты:"); if (time_data[1]<10){ lcd.setCursor(8,1);lcd.print('0');lcd.print(time_data[1]); } else { lcd.setCursor(8,1);lcd.print(time_data[1]); } while (1) { if (bouncer3.update()) { if (bouncer3.read()==0) { if (time_data[1]++ > 58) time_data[1] = 0; if (time_data[1]<10){ lcd.setCursor(8,1); lcd.print('0');lcd.print(time_data[1]); } else { lcd.setCursor(8,1);lcd.print(time_data[1]); } } } if (bouncer2.update()) { //нажали 2-ю кнопку устанавливваем часы и выходим if (bouncer2.read()==0) { RTC.stop(); RTC.set(DS1307_CTRL,16); RTC.set(DS1307_SEC,0); //set the seconds RTC.set(DS1307_MIN,time_data[1]); //set the minutes RTC.set(DS1307_HR,time_data[2]); //set the hours //RTC.set(DS1307_DOW,4); //set the day of the week // RTC.set(DS1307_DATE,11); //set the date // RTC.set(DS1307_MTH,3); //set the month // RTC.set(DS1307_YR,12); //set the year RTC.start(); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; } } if (bouncer4.update()) { if (bouncer4.read()==0) { lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; //выход без изменения } } } } void set_hr() { //int hr = time_data[2] ; lcd.clear(); lcd.print(" Настройка"); lcd.setCursor(0,1);lcd.print("Часы:"); if (time_data[2]<10){ lcd.setCursor(6,1);lcd.print('0');lcd.print(time_data[2]); } else { lcd.setCursor(6,1);lcd.print(time_data[2]); } while (1) { if (bouncer3.update()) { if (bouncer3.read()==0) { if (time_data[2]++ > 22) time_data[2] = 0; if (time_data[2]<10){ lcd.setCursor(6,1); lcd.print('0');lcd.print(time_data[2]); } else { lcd.setCursor(6,1);lcd.print(time_data[2]); } } } if (bouncer2.update()) { //нажали 2-ю кнопку устанавливваем часы и выходим if (bouncer2.read()==0) { RTC.stop(); RTC.set(DS1307_CTRL,16); RTC.set(DS1307_SEC,0); //set the seconds RTC.set(DS1307_MIN,time_data[1]); //set the minutes RTC.set(DS1307_HR,time_data[2]); //set the hours //RTC.set(DS1307_DOW,4); //set the day of the week // RTC.set(DS1307_DATE,11); //set the date // RTC.set(DS1307_MTH,3); //set the month // RTC.set(DS1307_YR,12); //set the year RTC.start(); lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; } } if (bouncer4.update()) { if (bouncer4.read()==0) { lcd.clear(); lcd.print("Время:"); lcd.setCursor(0,1); lcd.print("Дата:"); return ; //выход без изменения } } } } void print_temperature() { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; for (byte k = 0; k < 2; k++) { if ( !ds.search(addr)) { Serial.println("No chip DS18x20."); // Serial.println(); ds.reset_search(); //delay(50); break; } switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println("Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end blink(13,750) ; present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); // Serial.print(data[i], HEX); // Serial.print(" "); } int raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // count remain gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms // default is 12 bit resolution, 750 ms conversion time } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); Serial.print(fahrenheit); Serial.println(" Fahrenheit"); if (num == 0) { num = 1; lcd.setCursor(8, 0); lcd.print(" "); lcd.setCursor(8, 0); lcd.print(celsius); lcd.print(" C"); /* lcd.setCursor(8, 1); lcd.print(" "); lcd.setCursor(8, 1); lcd.print(fahrenheit); lcd.print(" F"); */ } else { num = 0; lcd.setCursor(8, 1); lcd.print(" "); lcd.setCursor(8, 1); lcd.print(celsius); lcd.print(" C"); } } delay(3000); ds.reset_search(); } void blink( int Pin , int Delay ) { digitalWrite(Pin, HIGH); // set the LED on delay(Delay/2); // wait for a second digitalWrite(Pin, LOW); // set the LED off delay(Delay/2); // wait for a second } void print_delitel() { if (!del_print) { del_print = true ; lcd.setCursor(9,0);lcd.print(delitel); lcd.setCursor(12,0);lcd.print(delitel); } else { del_print = false ; lcd.setCursor(9,0);lcd.print(' '); //гасим разделитель через 0.5 с lcd.setCursor(12,0);lcd.print(' '); } } void s_print_time_data() { if (time_data[2] < 10) { // часов < 10 Serial.print(0); Serial.print(time_data[2]); } else Serial.print(time_data[2]) ; Serial.print(delitel); if (time_data[1] < 10) { //минут < 10 Serial.print(0); Serial.print(time_data[1]); } else Serial.print(time_data[1]); Serial.print(delitel); if (time_data[0] < 10) { //секунды Serial.print(0); Serial.print(time_data[0]); } else Serial.print(time_data[0]); Serial.print(" "); switch (time_data[3]) { case 1: Serial.print(Monday) ; break ; case 2: Serial.print(Tuesday) ; break ; case 3: Serial.print(Wednesday) ; break ; case 4: Serial.print(Thursday) ; break ; case 5: Serial.print(Friday) ; break ; case 6: Serial.print(Saturday) ; break ; case 7: Serial.print(Sunday) ; break ; } Serial.print(" "); if (time_data[4] < 10) { // числа < 10 Serial.print(0); Serial.print(time_data[4]); } else Serial.print(time_data[4]) ; Serial.print(delitel2); if (time_data[5] < 10) { // месяц < 10 Serial.print(0); Serial.print(time_data[5]); } else Serial.print(time_data[5]) ; Serial.print(delitel2); Serial.print(time_data[6]); //год // Serial.print(" ");Serial.print(RTC.get(DS1307_CTRL,false),BIN); Serial.println(); } void lcd_print_time_data() { // lcd.setCursor(7,0);lcd.print(" "); lcd.setCursor(7,0); if (time_data[2] < 10) { // часов < 10 lcd.print(0); lcd.print(time_data[2]); } else lcd.print(time_data[2]) ; //lcd.print(RTC.get(DS1307_HR,true)); // lcd.setCursor(2+7,0);lcd.print(delitel); lcd.setCursor(3+7,0); if (time_data[1] < 10) { // минут < 10 lcd.print(0); lcd.print(time_data[1]); } else lcd.print(time_data[1]) ; //lcd.print(RTC.get(DS1307_MIN,false)); //lcd.setCursor(5+7,0);lcd.print(delitel); lcd.setCursor(6+7,0); if (time_data[0] < 10) { // минут < 10 lcd.print(0); lcd.print(time_data[0]); } else lcd.print(time_data[0]) ; //lcd.print(RTC.get(DS1307_SEC,false)); lcd.setCursor(0+6,1);lcd.print(" "); lcd.setCursor(0+6,1); if (time_data[4] < 10) { // минут < 10 lcd.print(0); lcd.print(time_data[4]); } else lcd.print(time_data[4]) ; //lcd.print(RTC.get(DS1307_DATE,false)); lcd.setCursor(2+6,1);lcd.print(delitel2); lcd.setCursor(3+6,1); if (time_data[5] < 10) { // минут < 10 lcd.print(0); lcd.print(time_data[5]); } else lcd.print(time_data[5]) ; //lcd.print(RTC.get(DS1307_MTH,false)); lcd.setCursor(5+6,1);lcd.print(delitel2); lcd.setCursor(6+6,1);lcd.print(time_data[6]); } void play_rtttl(char *p) { // Absolutely no error checking in here byte default_dur = 4; byte default_oct = 6; int bpm = 63; int num; long wholenote; long duration; byte note; byte scale; // format: d=N,o=N,b=NNN: // find the start (skip name, etc) while(*p != ':') p++; // ignore name p++; // skip ':' // get default duration if(*p == 'd') { p++; p++; // skip "d=" num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } if(num > 0) default_dur = num; p++; // skip comma } Serial.print("ddur: "); Serial.println(default_dur, 10); // get default octave if(*p == 'o') { p++; p++; // skip "o=" num = *p++ - '0'; if(num >= 3 && num <=7) default_oct = num; p++; // skip comma } Serial.print("doct: "); Serial.println(default_oct, 10); // get BPM if(*p == 'b') { p++; p++; // skip "b=" num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } bpm = num; p++; // skip colon } Serial.print("bpm: "); Serial.println(bpm, 10); // BPM usually expresses the number of quarter notes per minute wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) Serial.print("wn: "); Serial.println(wholenote, 10); // now begin note loop while(*p) { // first, get note duration, if available num = 0; while(isdigit(*p)) { num = (num * 10) + (*p++ - '0'); } if(num) duration = wholenote / num; else duration = wholenote / default_dur; // we will need to check if we are a dotted note after // now get the note note = 0; switch(*p) { case 'c': note = 1; break; case 'd': note = 3; break; case 'e': note = 5; break; case 'f': note = 6; break; case 'g': note = 8; break; case 'a': note = 10; break; case 'b': note = 12; break; case 'p': default: note = 0; } p++; // now, get optional '#' sharp if(*p == '#') { note++; p++; } // now, get optional '.' dotted note if(*p == '.') { duration += duration/2; p++; } // now, get scale if(isdigit(*p)) { scale = *p - '0'; p++; } else { scale = default_oct; } scale += OCTAVE_OFFSET; if(*p == ',') p++; // skip comma for next note (or we may be at the end) // now play the note if(note) { Serial.print("Playing: "); Serial.print(scale, 10); Serial.print(' '); Serial.print(note, 10); Serial.print(" ("); Serial.print(notes[(scale - 4) * 12 + note], 10); Serial.print(") "); Serial.println(duration, 10); tone(TONE_PIN, notes[(scale - 4) * 12 + note]); delay(duration); noTone(TONE_PIN); } else { Serial.print("Pausing: "); Serial.println(duration, 10); delay(duration); } } }
К сожалению, скомпилированный скетч получился больше 16 Кб и при работе использует около 1,5 Кб ОЗУ. Поэтому работать будет на ATMega328.
Как это работает: При включении питания на LCD отображается текущее время. Начальные установки даты и времени были запрограммированы в микросхему RTC в закомментированной части процедуры setup(). Т. к. это не законченное устройство, то для уменьшения скетча установка даты кнопками не реализована. Так же по заверениям разработчиков от одной батарейки емкостью 35 Мач часовая микросхема будет работать больше 10 лет. Т.е. теоретически, корректировать дату в ближайшие 10 лет необходимости не будет )).
Нажав кнопку «Темпер.» получим на LCD показания стационарного и выносного датчиков температуры. Все вышеописанные данные дублируются на терминал. При подключении Arduino к компьютеру, конечно.
При однократном нажатии на кнопку «Режим» можно корректировать «часы», кнопкой «>». При повторном нажатии на кнопку «Режим» скорректированные данные записываются в микросхему часов. При нажатии на кнопку «ESC» происходит выход из режима коррекции часов без изменения данных. При двукратном нажатии на кнопку «Режим» аналогичным образом корректируются минуты. И при записи минут, секунды сбрасываются на 0.
Если нажать три раза на «Режим» устанавливаются часы срабатывания будильника. Если нажать четыре раза – устанавливаются минуты срабатывания будильника, а с помощью кнопки «ESC» производится активация/деактивация будильника.
P.S.
Для отображения русских символов на терминал использовалась программа PUTTY.
Файлы:
Библиотека DS1307
Схема
Код
0 комментариев на «“«Компот» из Arduino, датчиков температуры DS18B20, RTC DS1307, бузера & LCD”»
Спасибо! Чуть подправил грамматику и залил файлы на сервер 🙂
Ок ))