«Компот» из Arduino, датчиков температуры DS18B20, RTC DS1307, бузера & LCD


На днях один интернет-магазин (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”»

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение