Очередные часики с 7-сигментным индикатором на TM1637 и модулем часов реального времени DS3231, с возможностью установки времени кнопками.
ниже код из видео
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" // http://arduinolab.pw/wp-content/uploads/2016/06/DigitalTube.zip #include <MsTimer2.h> // http://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" // http://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); }
пока всё.