Приветствую всех любителей самоделок! Сегодня хочу рассказать о своём проекте – часы в подарок. У однокурсника в сентябре день рождения, но подарок решил начать готовить пораньше, так как в учебное время этим некогда будет заниматься. Эти часы начинал собирать ещё года так 3-4 назад, но потом забросил их чего-то и недавно наводя порядок в своих закромах наткнулся на них. То есть для меня по сути эти часы нужно доработать, а именно сделать культурный корпус и добавить датчик комнатной температуры, в его роли будет выступать ds18b20. Начинаем!
Для этого нам понадобится:
- Светодиодная матрица на MAX7219.
- Плата Arduino Nano (можно и другую, например Pro Mini).
- Модуль часов реального времени DS1302.
- Датчик температуры ds18b20 и к нему резистор на 4,7 Ком.
- Тонкий провод (в моём случае это МГТФ-0,25).
- Стойки, винты и гайки к ним.
- Двухсторонний скотч.
- Термоклей и клеевой пистолет.
- Ненужный USB провод.
- Два разъёма типа “мама” (необязательно, можно припаять провод без них).
- Три тактовые кнопочки, кусочек макетной платы и 3 SMD резистора по 10 кОм.
- Паяльник, припой, канифоль и т.д.
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 отображаем температуру с датчика в виде бегущей строки. Вот как-то так:
На этом у меня всё, будет интересно узнать ваше мнение об этом проекте. Всем удачных самоделок!













