Часики с 7-сигментным индикатором на TM1637 и часами реального времени DS3231, с возможностью установки времени кнопками.
Ниже несколько версий.
Версия на плате фабричного производства.
Видео:
Код:
/// Код на 24.04.21 #include <Wire.h> #include "TM1637.h" // http://arduinolab.pw/wp-content/uploads/2016/06/DigitalTube.zip /* * В файле TM1637.h нужно подправить табличку и добавить туда "0x63, 0x00" как ниже. static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71, 0x63, 0x00};//0~9,A,b,C,d,E,F */ #define keyP 4 // кнопки #define keySET 3 #define keyM 2 TM1637 tm1637(6, 7); // CLK, DIO ///// ... часы .. #define DS3231_I2C_ADDRESS 0x68 int8_t decToBcd(byte val){ return ( (val/10*16) + (val%10) ); } int8_t bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); } void setDateDs3231(int8_t second, // 0-59 int8_t minute, // 0-59 int8_t hour, // 1-23 int8_t dayOfWeek, // 1-7 int8_t dayOfMonth, // 1-28/29/30/31 int8_t month, // 1-12 int8_t year) // 0-99 { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void getDateDs3231(byte *second, int8_t *minute, int8_t *hour, int8_t *dayOfWeek, int8_t *dayOfMonth, int8_t *month, int8_t *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); *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 setup() { // Serial.begin(9600); Wire.begin(); pinMode(keyP, INPUT_PULLUP); pinMode(keySET, INPUT_PULLUP); pinMode(keyM, INPUT_PULLUP); tm1637.init(); tm1637.set(0); tm1637.point(1); analogReference(INTERNAL); } void loop(){ // читаем время из модуля int8_t second, minute, hour, dayOfWeek, dayOfMonth, month, year; getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); int8_t TimeDisp[4]; // Массив который будем отправлять на дисплей TimeDisp[0] = hour / 10; // Заполняем текущим временем TimeDisp[1] = hour % 10; TimeDisp[2] = minute / 10; TimeDisp[3] = minute % 10; // обработка кнопок /// Установка времени if (!digitalRead(keySET)){ // Если надавили сет delay(200); // антидребезг second = 0; // сбрасываем секунды tm1637.point(1); // включаем ":" do{ /// Крутим цикл! /// часы if (!digitalRead(keyP)){ // если в цикле надавили на "+" hour++; // пребавляем единицу к часу if (hour > 23) hour = 0; // если вылезли за границы присваеваем 0 setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль delay(200); } if (!digitalRead(keyM)){ // если на "-" hour--; // убавляем единицу if (hour < 0) hour = 23; // если вылезли за границы setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль delay(200); } TimeDisp[0] = hour / 10; // в цикле также показываем что получилось TimeDisp[1] = hour % 10; TimeDisp[2] = 17; // 17 это 0xff, выключение TimeDisp[3] = 17; tm1637.display(TimeDisp); // отправляем массив на экран }while(digitalRead(keySET)); // крутимся пока не надавили сет delay(500); // антидребез do{ // снова крутимся, но уже для минут. if (!digitalRead(keyP)){ // также смотрим не нажато ли "+" minute++; // прибавляем минуту if (minute > 59) minute = 0; // проверяем setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); delay(200); } if (!digitalRead(keyM)){ // также смотрим на "-" minute--; if (minute < 0) minute = 59; setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); delay(200); } TimeDisp[0] = 17; TimeDisp[1] = 17; TimeDisp[2] = minute / 10; TimeDisp[3] = minute % 10; tm1637.display(TimeDisp); // отправляем массив на экран }while(digitalRead(keySET)); // крутимся пока не надавили сет delay(200); // задумываемся перед выходом } // таймер на RTC ) static byte oldSec; if (oldSec != second){ // true каждую секунду. oldSec = second; // сохраняем прошедную // мигание точкой static bool point; point = !point; tm1637.point(point); // Устанавливаем яркость LED byte brightness = map(analogRead(A1), 0, 1023, 0, 7); // Читаем вход и мапим, приделы подкорректировать !!! tm1637.set(brightness); // Пишем в дисплей } /// // Отображение температуры // if (second == 15 || second == 16 || second == 17 || !digitalRead(keyP)){ // Отображаем каждые 3 секунды или кнопкой if (!digitalRead(keyP)){ // Отображаем при нажатой кнопки "+" tm1637.point(0); // Выключаем двоеточие /// Получение температуры !!! // int8_t tempC = (analogRead(A0) / 9.31; // Для LM35 и атмеги328 (опорное 1,1) int8_t tempC = (((analogRead(A0) * 2.54) / 1024.0) - 0.5) * 100; // для TMP36 и атмеги8 (опорное 2,56) // int8_t tempC = (((analogRead(A0) * 1.1) / 1024.0) - 0.5) * 100; // для TMP36 и атмеги328 (опорное 1,1) // int8_t tempC = (analogRead(A0)/1024.0)*5.0*1000/10; // для 5 вольт LM35. TimeDisp[0] = tempC / 10; // Заполняем массив TimeDisp[1] = tempC % 10; TimeDisp[2] = 16; // градус (нужно добавить "0x63" в "TubeTab[]" в "TM1637.h") TimeDisp[3] = 12; // C delay(200); } // отправляем массив на экран tm1637.display(TimeDisp); }
Ссылки и файлы:
Проект easyeda: Тут.
Подправленная библиотека: Тут.
Старые, прошлые, версии!!!
позже приведу в порядок и их.
ниже код из видео
update: 04.08.20 \ код и то что написано ниже, основанно на том видео, но не является истенно верным.
Как все подключено:
Было решено отказаться от мигалки двоеточием при помощи аппаратного прерывания, ибо для многих это оказалось слишком сложным техническим решением. Подключать ногу SQW на модуле к ардуино, не нужно. Кнопки и остальная логика работы не изменилась.
Железки на али:
Индикатор на TM1637
Часы DS3231
клон Arduino UNO
Код:
Чтобы всё заработало как нужно, чтобы при компиляции не вываливались ошибоки, необходимо установить библиотеку для работы с индикатором TM1637:
Существуют и другие библиотеки для TM1637, но код написан с использованием DigitalTube от seeedstudio. Работа проверена на версии IDE 1.6.5-r5.
#include <Wire.h> #include "TM1637.h" // http://www.seeedstudio.com/wiki/File:DigitalTube.zip // 7сигментный индикатор #define CLK 6 #define DIO 7 #define brightness 6 // яркость, от 0 до 7 // кнопки #define keyHor 5 #define keyMin 4 #define keyPL 3 TM1637 tm1637(CLK,DIO); #define DS3231_I2C_ADDRESS 0x68 volatile boolean flag; ///// часы .. byte decToBcd(byte val){ return ( (val/10*16) + (val%10) ); } byte bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); } void setDateDs3231(byte second, // 0-59 byte minute, // 0-59 byte hour, // 1-23 byte dayOfWeek, // 1-7 byte dayOfMonth, // 1-28/29/30/31 byte month, // 1-12 byte year) // 0-99 { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); *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 setINT(){ //включает выход SQW, который вроде выключен по умолчанию Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0x0E); Wire.write(0x0); Wire.endTransmission(); } void blink() { digitalWrite(13, !digitalRead(13)); flag = !flag; tm1637.point(flag); } void setup() { // Serial.begin(9600); Wire.begin(); pinMode(13, OUTPUT); pinMode(keyHor, INPUT_PULLUP); pinMode(keyMin, INPUT_PULLUP); pinMode(keyPL, INPUT_PULLUP); tm1637.init(); tm1637.set(brightness); setINT(); attachInterrupt(0, blink, CHANGE); } void loop(){ // читаем время из модуля byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // забиваем массив значениями для отпарвки на экран int8_t TimeDisp[4]; TimeDisp[0] = hour / 10; TimeDisp[1] = hour % 10; TimeDisp[2] = minute / 10; TimeDisp[3] = minute % 10; // обработка кнопок if (!digitalRead(keyHor) && !digitalRead(keyPL)){ // часы second = 0; // сбрасываем секунды hour++; // пребавляем единицу к часам if (hour > 23) hour = 0; // если вылезли за границы присваеваем 0 setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль delay(200); } if (!digitalRead(keyMin) && !digitalRead(keyPL)){ // минуты second = 0; minute++; if (minute > 59) minute = 0; setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); delay(200); } // отправляем массив на экран tm1637.display(TimeDisp); }
Для мигания двоеточием можно использовать таймер и для удобства работы с таймером, библиотеку:
Возможно с ней будут проблемы в новых версиях IDE, но на версии 1.6.5-r5 оно работает.
#include <Wire.h> #include "TM1637.h" // https://arduinolab.pw/wp-content/uploads/2016/06/DigitalTube.zip #include <MsTimer2.h> // https://arduinolab.pw/wp-content/uploads/2016/06/MsTimer2.zip ////// подключение: // 7сигментный индикатор #define CLK 6 #define DIO 7 #define brightness 6 // яркость, от 0 до 7 // кнопки #define keyHor 5 #define keyMin 4 #define keyPL 3 ////// TM1637 tm1637(CLK,DIO); #define DS3231_I2C_ADDRESS 0x68 boolean val; /////... часы .. byte decToBcd(byte val){ return ( (val/10*16) + (val%10) ); } byte bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); } void setDateDs3231(byte second, // 0-59 byte minute, // 0-59 byte hour, // 1-23 byte dayOfWeek, // 1-7 byte dayOfMonth, // 1-28/29/30/31 byte month, // 1-12 byte year) // 0-99 { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); *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 flash() { static boolean output = HIGH; tm1637.point(output); digitalWrite(13, output); output = !output; } void setup() { // Serial.begin(9600); Wire.begin(); pinMode(13, OUTPUT); pinMode(keyHor, INPUT_PULLUP); pinMode(keyMin, INPUT_PULLUP); pinMode(keyPL, INPUT_PULLUP); tm1637.init(); tm1637.set(brightness); MsTimer2::set(500, flash); // 500ms period MsTimer2::start(); } void loop(){ // читаем время из модуля byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // забиваем массив значениями для отпарвки на экран int8_t TimeDisp[4]; TimeDisp[0] = hour / 10; TimeDisp[1] = hour % 10; TimeDisp[2] = minute / 10; TimeDisp[3] = minute % 10; // обработка кнопок if (!digitalRead(keyHor) && !digitalRead(keyPL)){ // часы second = 0; // сбрасываем секунды hour++; // пребавляем единицу к часам if (hour > 23) hour = 0; // если вылезли за границы присваеваем 0 setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль delay(200); } if (!digitalRead(keyMin) && !digitalRead(keyPL)){ // минуты second = 0; minute++; if (minute > 59) minute = 0; setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); delay(200); } // отправляем массив на экран tm1637.display(TimeDisp); }
Версия без мигания двоеточием:
#include <Wire.h> #include "TM1637.h" // https://arduinolab.pw/wp-content/uploads/2016/06/DigitalTube.zip ////// подключение: // 7сигментный индикатор #define CLK 6 #define DIO 7 #define brightness 6 // яркость, от 0 до 7 // кнопки #define keyHor 5 #define keyMin 4 #define keyPL 3 ////// TM1637 tm1637(CLK,DIO); #define DS3231_I2C_ADDRESS 0x68 /////... часы .. byte decToBcd(byte val){ return ( (val/10*16) + (val%10) ); } byte bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); } void setDateDs3231(byte second, // 0-59 byte minute, // 0-59 byte hour, // 1-23 byte dayOfWeek, // 1-7 byte dayOfMonth, // 1-28/29/30/31 byte month, // 1-12 byte year) // 0-99 { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); *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 setup() { // Serial.begin(9600); Wire.begin(); pinMode(13, OUTPUT); pinMode(keyHor, INPUT_PULLUP); pinMode(keyMin, INPUT_PULLUP); pinMode(keyPL, INPUT_PULLUP); tm1637.init(); tm1637.set(brightness); tm1637.point(1); } void loop(){ // читаем время из модуля byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // забиваем массив значениями для отпарвки на экран int8_t TimeDisp[4]; TimeDisp[0] = hour / 10; TimeDisp[1] = hour % 10; TimeDisp[2] = minute / 10; TimeDisp[3] = minute % 10; // обработка кнопок if (!digitalRead(keyHor) && !digitalRead(keyPL)){ // часы second = 0; // сбрасываем секунды hour++; // пребавляем единицу к часам if (hour > 23) hour = 0; // если вылезли за границы присваеваем 0 setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль delay(200); } if (!digitalRead(keyMin) && !digitalRead(keyPL)){ // минуты second = 0; minute++; if (minute > 59) minute = 0; setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); delay(200); } // отправляем массив на экран tm1637.display(TimeDisp); }
пока всё.