Часы + термометр на Arduino - СамоДельня

Часы + термометр на Arduino

Приветствую всех любителей самоделок! Сегодня хочу рассказать о своём проекте – часы в подарок. У однокурсника в сентябре день рождения, но подарок решил начать готовить пораньше, так как в учебное время этим некогда будет заниматься. Эти часы начинал собирать ещё года так 3-4 назад, но потом забросил их чего-то и недавно наводя порядок в своих закромах наткнулся на них. То есть для меня по сути эти часы нужно доработать, а именно сделать культурный корпус и добавить датчик комнатной температуры, в его роли будет выступать ds18b20. Начинаем!

Для этого нам понадобится:

  1. Светодиодная матрица на MAX7219. 
  2. Плата Arduino Nano (можно и другую, например Pro Mini).
  3. Модуль часов реального времени DS1302. 
  4. Датчик температуры ds18b20 и к нему резистор на 4,7 Ком.
  5. Тонкий провод (в моём случае это МГТФ-0,25). 
  6.  Стойки, винты и гайки к ним.
  7.  Двухсторонний скотч.
  8. Термоклей и клеевой пистолет. 
  9. Ненужный USB провод. 
  10. Два разъёма типа “мама” (необязательно, можно припаять провод без них). 
  11. Три тактовые кнопочки, кусочек макетной платы и 3 SMD резистора по 10 кОм. 
  12. Паяльник, припой, канифоль и т.д. 

1. Прошиваемся

Я постарался максимально понятно написать код с комментариями. Да, он не идеален и его можно упростить, но и так сойдёт. Функция dat работает с датчиком температуры и выводит всю информацию о нём в монитор порта, можно посмотреть. Стоит сразу отметить, что ds18b20 нужно подключать именно к аналоговому входу МК, сначала прицепил на цифровой и долго думал почему ничего не работает.

Сам код: 

//недостающие библиотеки качаем из инета #include <iarduino_RTC.h> // эта библиотека версии 1.3.4 от 09.01.2020 #include <Wire.h> #include <SPI.h> #include <OneWire.h> #include <Adafruit_GFX.h> #include <Max72xxPanel.h> #include <DallasTemperature.h> OneWire  ds(A0); //(пин куда подключён датчик) byte i; //всё для датчика byte present = 0; byte type_s; byte data[9]; byte addr[8]; float celsius, fahrenheit; uint8_t h,m,s; // переменные для хранения времени Max72xxPanel matrix = Max72xxPanel(10, 1, 4); // пин CS, кол-во матриц по вертикали, кол-во матриц по горезонтали iarduino_RTC watch(RTC_DS1302,2,3,4); //rst clk dat модуля часов int spacer = 1; // расстояние между цифрами температуры int width = 5 + spacer; // размер шрифта  void setup(void) { Serial.begin(9600); matrix.setIntensity(1); // Яркость от 0 до 15 matrix.setRotation(matrix.getRotation()+1); // положение матриц  +1 - 90  +2 - 180   +3 - 270 градусов  watch.begin(); // запуск часов watch.settime(0,0,12); // установка текущего времени (сек, мин, час), записывается один раз  pinMode(8, OUTPUT); // настройка пинов для кнопок digitalWrite(8,1); pinMode(7, INPUT); pinMode(6, INPUT); pinMode(5, INPUT); } void dat() { // подключение датчика и вся инфа о нём     if ( !ds.search(addr)) {     Serial.println("No more addresses.");     Serial.println();     ds.reset_search();     delay(10);     return;   }      Serial.print("ROM =");   for( i = 0; i < 8; i++) {     Serial.write(' ');     Serial.print(addr[i], HEX);   }    if (OneWire::crc8(addr, 7) != addr[7]) {       Serial.println("CRC is not valid!");       return;   }   Serial.println();     // the first ROM byte indicates which chip   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      //delay(750);     // maybe 750ms is enough, maybe not   // we might do a ds.depower() here, but the reset will take care of it.      present = ds.reset();   ds.select(addr);       ds.write(0xBE);         // Read Scratchpad    Serial.print("  Data = ");   Serial.print(present, HEX);   Serial.print(" ");   for ( i = 0; i < 9; i++) {           // we need 9 bytes     data[i] = ds.read();     Serial.print(data[i], HEX);     Serial.print(" ");   }   Serial.print(" CRC=");   Serial.print(OneWire::crc8(data, 8), HEX);   Serial.println();    int16_t 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);     // at lower res, the low bits are undefined, so let's zero them     if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms     else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms     else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms    }      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");   //delay(500); }  void loop(void){   dat();    Display();   watch.gettime();   if(millis()%1000==0){ // если прошло 1 секунда    h = watch.Hours;    // Получаем текущие часы     m = watch.minutes;  // Получаем текущие минуты        s = watch.seconds;   // Получаем текущие секунды    delay(2);   }   bool button_setup = digitalRead(7); // считываем состояние кнопок   bool button_plus = digitalRead(6);    bool button_minus = digitalRead(5);       //Проверка нажатий  int regim=1;  int flag=0;    if (regim==1 and button_minus==1){  temp();   }    if(button_setup==1&&flag==0)        {         regim++;           flag=1;                                 if(regim>3) regim=1;                   }              if(button_setup==0&&flag==1) flag=0;         if(regim==1)//настройка часов     {        if(button_plus==1){ //настройка часов          h++;          if(h>23) h=0;           watch.settime(0,m,h);          delay(250);       }     }          if(regim==2)//настройка минут     {        if(button_plus==1){          m++;          if(m>59) m=0;           watch.settime(0,m,h);          delay(250);       }     }       } void temp() { //вывод температуры   String tape = String(celsius, 1)+" ";     for ( int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++ ) {         matrix.fillScreen(LOW);          int letter = i / width;         int x = (matrix.width() - 1) - i % width;         int y = (matrix.height() - 8) / 2;          while ( x + width - spacer >= 0 && letter >= 0 ) {             if ( letter < tape.length() ) {                 matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1);             }             letter--;             x -= width;         }          matrix.write();         delay(50);     } } void Display(){  //вывод времени     matrix.fillScreen(0);     int y = (matrix.height() - 8) / 2; // центрирование по вертикали        if(watch.seconds & 1)  // мигающее двоеточие     {       matrix.drawChar(14, y, (String(":"))[0], HIGH, LOW, 1);     }      else     {       matrix.drawChar(14, y, (String(" "))[0], HIGH, LOW, 1);       }          String hour1 = String (h/10); // преобразовываем числа для вывода     String hour2 = String (h%10);     String min1 = String (m/10);     String min2 = String (m%10);     String sec1 = String (s/10);     String sec2 = String (s%10);     int xh = 2;     int xm = 19;      matrix.drawChar(xh, y, hour1[0], HIGH, LOW, 1);     matrix.drawChar(xh+6, y, hour2[0], HIGH, LOW, 1);     matrix.drawChar(xm, y, min1[0], HIGH, LOW, 1);     matrix.drawChar(xm+6, y, min2[0], HIGH, LOW, 1);       matrix.write(); // Вывод на дисплей }

2. Паяем, собираем

После успешной прошивки переходим к сборке часов. Прикручиваем стойки к матрице по краям для крепления в корпус. Крепим Arduino, модуль часов и кнопки на двухсторонний скотч к обратной стороне платы матрицы, провода на термоклей. Схема: 

Датчик: 

Клавиатура (вид снизу): 

Провод питания можно сделать так. Берём ненужный USB-провод от зарядки и откусываем разъём микро-USB (в моём случае). Теперь зачищаем провода и аккуратно припаиваем разъёмы “мама”. Места спайки изолируем термоусадкой. Соблюдая полярность питания подключаем провод к разъёму ISP для программатора. 

Готово!

3. Корпус

Так как это подарок то корпус должен быть хороший, поэтому открываю программу Компас-3D, моделирую и отправляю для печати чудесной шайтан-машине под названием 3D-принтер. Только под кнопки вручную отверстия надо будет сделать. Вот как это будет выглядеть:

4. Настройка

Настройку немного переработал – осуществляется двумя кнопками + датчик.

При нажатии кнопки 2, увеличиваем час на 1. 

При одновременном нажатии на кнопки 1 и 2, увеличиваем минуты на 1.

При нажатии на кнопку 3 отображаем температуру с датчика в виде бегущей строки. Вот как-то так:

На этом у меня всё, будет интересно узнать ваше мнение об этом проекте. Всем удачных самоделок! 

SitesReady

Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного. - Альберт Эйнштейн

Мы в соцсетях