Кухонные часы-таймер

Нет ответов
PRC
Offline
Зарегистрирован: 03.02.2019

Сделал часы на кухню, с таймером. Время и день недели показывают постоянно (я вообще не понимаю зачем нужны часы в которых время показывается секунд 20 в минуту))). Шрифт часов можно выбрать из 3 вариантов. Могут пищать каждый час, длительность писка 200мс, т.ч. отключение на ночь не делал. Во второй строке или число и месяц или день недели и температура или выдержка таймера. Данные меняются каждые 10 секунд, время таймера показывается постоянно пока не отработает выдержку, температура берется с DS3231. В режиме таймера можно задать задержку до 999 минут. Все собрано из готовых блоков с али: 6 индикаторов на MAX7219, модуль для распбери DS3231 (он небольшой и стоит в окне внизу корпуса), пленочная клавиатура и пассивный бипер. Подключение расписано в самом скетче. Корпус печал сам, модели есть тут - https://3dtoday.ru/3d-models/for-home/kitchen/chasy_taymer_na_kukhnyu/

/*
 * Connect:
 * MAX7219:
 * Pin 11 - DIN
 * Pin 13 - CLK
 * Pin 10 - CS
 * Matrix:
 * 0 2 4
 * 1 3 5
 * Add library 'LedControl' on IDE
 *
 * I2C MAX3231:
 * pin A5 - SCL
 * pin A4 - SDA
 *
 * Keypad:
 * Pin 2,3,4,5,A0,A1,A2,A3
 *
 * Biper:
 * Pin 7 and VCC
 *
 * Управление:
 * 'A' - Set time/timer (Установка времени/таймера)
 * 'B' - Set mode 'Time/Timer' (Переключение режима "Часы/Таймер")
 * 'C' - Start/Stop timer, stop timer sound (Запуск/Остановка таймера, Выключение звука таймера)
 * 'D' - Enable/Disable ring every hour (Включение/Выключение сигнала каждый час)
 * '*' - Change time font (Смена шрифта часов)
 * '#' - Change screen light (Изменение яркости экрана)
*/  
#include "LedControl.h"
#include <Wire.h>
#include <avr/wdt.h>

#define DS3231    0x68
#define MAX_LIGHT 5    // Maximum==16
const unsigned char PinBiper=7;
const unsigned char PinOut[] ={A0, A1, A2, A3}; // пины выхода клавиатуры
const unsigned char PinIn[] ={2, 3, 4, 5}; // пины входа клавиатуры
const char key_value[4][4]={
{'A', 'B', 'C', 'D'},
{'3', '6', '9', '#'},
{'2', '5', '8', '0'},
{'1', '4', '7', '*'}};
LedControl lc=LedControl(11,13,10,6); 
// Дни недели -       П  Н  В  Т  С  Р  Ч  Т  П  Т  С  Б  В  С
const unsigned char days[]={16,17,18,19,20,21,04,19,16,19,20,06,18,20};   
unsigned char scr_level=1;              // Яркость экрана. Настройка сохраняется в DS3231 по аресу 0x09
unsigned char buffer[24][2];            // Буфер экрана
unsigned char mode=0;                   // Режим: 0 - Дата, 1 - День недели/температура, 2 - Таймер, 3 - Установка времени
unsigned char ds[0x12];                 // Буфер DS3231
unsigned char sound_en=0;               // Сигнал каждый час. Настройка сохраняется в DS3231 по адресу 0x0C
unsigned int timer_min=0;               // Время таймера
unsigned char timer_sec=0;
unsigned char timer_mode=0;             // Режим таймера
unsigned char font=0;                   // Шрифт часов 0-2
// Символы 7x4
const unsigned char DigBig1[] PROGMEM ={
0x3E,0x41,0x41,0x3E,// 0
0x00,0x42,0x7F,0x40,// 1
0x62,0x51,0x49,0x66,// 2
0x22,0x49,0x49,0x36,// 3
0x18,0x14,0x12,0x7F,// 4
0x2F,0x49,0x49,0x33,// 5
0x3E,0x49,0x49,0x32,// 6
0x03,0x79,0x05,0x03,// 7
0x36,0x49,0x49,0x36,// 8
0x26,0x49,0x49,0x3E,// 9
0x0,0x24,0x12,0x0,  // Точка 1
0x0,0x12,0x24,0x0,  // Точка 2
0,0,0,0};           // Space
const unsigned char DigBig2[] PROGMEM ={
0x7F,0x63,0x63,0x7F,// 0
0x42,0x7F,0x7F,0x40,// 1
0x7B,0x7B,0x6F,0x6F,// 2
0x6B,0x6B,0x7F,0x7F,// 3
0x1F,0x18,0x18,0x7F,// 4
0x6F,0x6B,0x7B,0x7B,// 5
0x7F,0x6B,0x6B,0x7B,// 6
0x03,0x7B,0x7F,0x07,// 7
0x7F,0x6B,0x6B,0x7F,// 8
0x6F,0x6B,0x6B,0x7F,// 9
0x0,0x24,0x12,0x0,  // Точка 1
0x0,0x12,0x24,0x0,  // Точка 2
0,0,0,0};           // Space
const unsigned char DigBig3[] PROGMEM ={
0x7F,0x41,0x41,0x7F,// 0
0x00,0x42,0x7F,0x40,// 1
0x79,0x49,0x49,0x4F,// 2
0x49,0x49,0x49,0x7F,// 3
0x0F,0x08,0x08,0x7F,// 4
0x4F,0x49,0x49,0x79,// 5
0x7F,0x49,0x49,0x79,// 6
0x01,0x01,0x7D,0x03,// 7
0x7F,0x49,0x49,0x7F,// 8
0x4F,0x49,0x49,0x7F,// 9
0x0,0x24,0x12,0x0,  // Точка 1
0x0,0x12,0x24,0x0,  // Точка 2
0,0,0,0};           // Space
// Символы 5x3
const unsigned char DigSmall[] PROGMEM ={
0x1F,0x11,0x1F,   // 0
0x12,0x1F,0x10,   // 1
0x1D,0x15,0x17,   // 2
0x15,0x15,0x1F,   // 3
7,4,0x1F,         // 4
0x17,0x15,0x1D,   // 5
0x1F,0x15,0x1D,   // 6
1,0x1D,3,         // 7
0x1F,0x15,0x1F,   // 8
0x17,0x15,0x1F,   // 9
0,0x10,0,         // Точка      10
0,0x0A,0,         // Двоеточие  11
0x0A,0x04,0x0A,   // Сигнал     12
0x0E,4,0,         // Play       13
6,6,0,            // Stop       14
0,0,0,            // Space      15
// Дни недели
0x1F,1,0x1F,      // П          16
0x1F,0x04,0x1F,   // H          17
0x1F,0x15,0x1B,   // B          18
0x01,0x1F,0x01,   // T          19
0x1F,0x11,0x1B,   // C          20
0x1F,0x05,0x07    // P          21
};
//***********************************************************************************************
void setup() {
  //Serial.begin(9600);
  // Клавиатура
  for(unsigned char i=0;i<4;i++) {pinMode(PinOut[i], OUTPUT);digitalWrite(PinOut[i],HIGH);}
  for(unsigned char i=0;i<4;i++) {pinMode(PinIn[i], INPUT);digitalWrite(PinIn[i],HIGH);}
  // I2C
  Wire.begin();
  Wire.setClock(400000);
  Read_I2C(DS3231,0,0x12,ds);
  // Перезапуск DS3231
  if(ds[0x0E] & 0x80)
  {
    ds[0]=ds[1]=ds[2]=0;ds[3]=2;ds[4]=ds[5]=1;ds[6]=0x19;
    for(unsigned int i=7;i<0x0E;i++)ds[i]=0;
    ds[0x0E]=0x20;
    Write_I2C(DS3231,0,15,ds);
  } 
  sound_en=ds[0x0C];
  scr_level=ds[9];
  // Матричный экран
  for(unsigned char address=0;address<6;address++) {lc.shutdown(address,false); lc.setIntensity(address,scr_level); lc.clearDisplay(address);}
  for(unsigned char i=0;i<24;i++) {buffer[i][0]=buffer[i][1]=0;}
  // Biper
  pinMode(PinBiper, OUTPUT);digitalWrite(PinBiper,HIGH);
  tone(PinBiper,1000,200);
  // WDT
  wdt_reset();wdt_enable(WDTO_4S);
}
//***************************************************************************************
//* Запись символа 5x3 в буфер
//* adr - позиция Х (0..23)
//* line - линия Y (0...1)
void WriteSmallChar(unsigned char adr, unsigned char line, unsigned char data)
{
  unsigned char tmp=data*3;
  buffer[adr++][line] |=pgm_read_byte_near(DigSmall+tmp++)<<3;
  buffer[adr++][line] |=pgm_read_byte_near(DigSmall+tmp++)<<3;
  buffer[adr][line] |=pgm_read_byte_near(DigSmall+tmp)<<3;
}
//***************************************************************************************
//* Запись символа 7x4 в буфер
void WriteBigChar (unsigned char adr, unsigned char line, unsigned char data)
{
  unsigned char tmp=data*4;
  const unsigned char *ad=&DigBig1[tmp];
  if(font==1) ad=&DigBig2[tmp];
  if(font==2) ad=&DigBig3[tmp];
  buffer[adr++][line]=pgm_read_byte_near(ad++);
  buffer[adr++][line]=pgm_read_byte_near(ad++);
  buffer[adr++][line]=pgm_read_byte_near(ad++);
  buffer[adr++][line]=pgm_read_byte_near(ad);
}
//***************************************************************************************
//* Вывод буфера на экран
void WriteDisplay()
{
  unsigned char z=0;
  for(char i=0;i<8;i++) lc.setRow(0,i,buffer[z++][0]);
  for(char i=0;i<8;i++) lc.setRow(2,i,buffer[z++][0]);
  for(char i=0;i<8;i++) lc.setRow(4,i,buffer[z++][0]);
  z=0;
  for(char i=0;i<8;i++) lc.setRow(1,i,buffer[z++][1]);
  for(char i=0;i<8;i++) lc.setRow(3,i,buffer[z++][1]);
  for(char i=0;i<8;i++) lc.setRow(5,i,buffer[z++][1]);
}
//***********************************************************************************************
// Опрос клавиатуры
char Keypad()
{
  char key=0;
  for (int i = 0; i < 4; i++)
  {
    digitalWrite(PinOut[i], LOW);
    for (int j = 0; j < 4; j++) if (digitalRead(PinIn[j]) == LOW) key=key_value[i][j];
    digitalWrite(PinOut[i], HIGH);
  }
  return key;
}
//***************************************************************************************
//* Чтение регистров I2C
void Read_I2C(unsigned char device, unsigned char adr, unsigned char count,unsigned char *data)
{
  unsigned char i=0;
  // Установить адрес
  Wire.beginTransmission(device);
  Wire.write(adr);
  Wire.endTransmission();
  // Считать данные
  Wire.beginTransmission(0x68);
  Wire.requestFrom(device, count);
  while(Wire.available()){data[i++] = Wire.read();}
  Wire.endTransmission();
}
//***************************************************************************************
//* Запись регистров I2C
void Write_I2C (unsigned char device, unsigned char adr, unsigned char count,unsigned char *data)
{
  Wire.beginTransmission(device);
  Wire.write(adr);
  for(unsigned char i=0;i<count;i++) Wire.write(data[i]);
  Wire.endTransmission();
}
//***********************************************************************************************
// Очистка нижней части экрана и вывод дня недели
void ClearDate()
{
  unsigned char tmp;
  buffer[0][1]=buffer[1][1]=buffer[22][1]=buffer[23][1]=0;
  tmp=2;
  for(unsigned char i=0;i<7;i++) {buffer[tmp++][1]=2;buffer[tmp++][1]=2;buffer[tmp++][1]=0;}
  tmp=(ds[3]-1)*3+2;
  buffer[tmp++][1]=3;buffer[tmp][1]=3;
}
//***********************************************************************************************
// Вывод таймера
void WriteTimer()
{
    unsigned char tmp;
    ClearDate();
    if(timer_mode==0) WriteSmallChar(0,1,14);   // Таймер остановлен
    if(timer_mode==2) WriteSmallChar(0,1,13);   // Таймер работает
    tmp=timer_min%100;
    WriteSmallChar(3,1,timer_min/100);
    WriteSmallChar(7,1,tmp/10);
    WriteSmallChar(11,1,tmp%10);
    WriteSmallChar(14,1,11);
    WriteSmallChar(17,1,timer_sec/10);
    WriteSmallChar(21,1,timer_sec%10);
}
//***********************************************************************************************
// Вывод даты
void WriteData()
{
    ClearDate();
   if(sound_en==1) WriteSmallChar(0,1,12); // Символ сигнала каждый час
    WriteSmallChar(4,1,ds[4]>>4);
    WriteSmallChar(8,1,ds[4] & 0xF);
    WriteSmallChar(11,1,10);
    WriteSmallChar(14,1,ds[5]>>4);
    WriteSmallChar(18,1,ds[5] & 0xF);
}
//***********************************************************************************************
// Вывод дня недели и температуры
void WriteTemp()
{
    unsigned char tmp=(ds[3]-1)*2;
    ClearDate();
    if(sound_en==1) WriteSmallChar(0,1,12); // Символ сигнала каждый час
    WriteSmallChar(4,1,days[tmp++]);
    WriteSmallChar(8,1,days[tmp]);    
    WriteSmallChar(15,1,ds[0x11]/10);
    WriteSmallChar(19,1,ds[0x11]%10);  
    buffer[23][1]=0x10;
}
//***********************************************************************************************
// Ввод цифры часов или минут
unsigned char EnterBigDigit( unsigned char adr, unsigned char v_min, unsigned char v_max, unsigned char value)
{
  unsigned char tmp=0,key;
  unsigned char flash=0;
  while(1)
  {
    // Ожидание отпускания кнопки 'A'
    if(tmp==0 && Keypad()==0) tmp=1;
    // Ожидание ввода цифры и подтверждения 'A'
    if(tmp==1)
    {
      key=Keypad();
      if(key>v_min && key<v_max) {value=key-'0';tmp=2;}
    }
    // Ожидание отпускания кнопки
    if(tmp==2 && Keypad()==0) tmp=3;
    if(tmp==3)
    {
      WriteBigChar(adr,0,value);
      WriteDisplay();
      return value;
    }
    if(flash) WriteBigChar(adr,0,value);
    else WriteBigChar(adr,0,12);
    flash=!flash;
    WriteDisplay();
    wdt_reset();
    delay(200);
  }
}
//***********************************************************************************************
// Ввод цифры числа, месяца или года
unsigned char EnterSmallDigit( unsigned char adr, unsigned char v_min, unsigned char v_max, unsigned char value)
{
  unsigned char tmp=0,key;
  unsigned char t1=buffer[adr][1] & 3,t2=buffer[adr+1][1] & 3,t3=buffer[adr+2][1] & 3;
  unsigned char flash=0;
  while(1)
  {
    // Ожидание отпускания кнопки 'A'
    if(tmp==0 && Keypad()==0) tmp=1;
    // Ожидание ввода цифры и подтверждения 'A'
    if(tmp==1)
    {
      key=Keypad();
      if(key>v_min && key<v_max) {value=key-'0';tmp=2;}
    }
    // Ожидание отпускания кнопки
    if(tmp==2 && Keypad()==0) tmp=3;
    if(tmp==3)
    {
      buffer[adr][1] =t1; buffer[adr+1][1] =t2; buffer[adr+2][1] =t3;
      WriteSmallChar(adr,1,value);
      WriteDisplay();
      return value;
    }
    if(flash) WriteSmallChar(adr,1,value);
    else {buffer[adr][1] =t1; buffer[adr+1][1] =t2; buffer[adr+2][1] =t3;}
    flash=!flash;
    WriteDisplay();
    wdt_reset();
    delay(200);
  }
}
//******************************************************************************
// День недели по дате: 1 — понедельник, 2 — вторник и так далее.
unsigned char Calc_Day(unsigned char day, unsigned char month, unsigned int year)
{
  unsigned int t1, t2;
  unsigned char m[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
  t1 = year - 2001;
  t2 = m[month-1];
  if ( ((year & 0x0003) == 0) && (((month-1) >> 1) != 0) ) t2++;
  return (((t1 + (t1 >> 2) + t2 + (day-1)) % 7)+1);
}
//***********************************************************************************************
// Установка времени
void SetupTime()
{
  unsigned char tmp,tmp1;
  unsigned char hour=ds[2],minute=ds[1],date=ds[4],month=ds[5],year=ds[6];
  unsigned char days_of_month[]={0,0x31,0x28,0x31,0x30,0x31,0x30,0x31,0x31,0x30,0x31,0x30,0x31};
  // Ввод десятков часов
  tmp=EnterBigDigit(1,'0'-1,'3',hour>>4);
  // Ввод единиц часов
  if(tmp==2)
  {
    // Для 20++ часов - максимум 3
    if((hour & 0xF)>3) hour=0x20;
    tmp1=EnterBigDigit(6,'0'-1,'4',hour & 0xF);
  }
  else tmp1=EnterBigDigit(6,'0'-1,'9'+1,hour & 0xF);
  hour=(tmp<<4) | tmp1;
  // Ввод минут
  tmp=EnterBigDigit(14,'0'-1,'6',minute>>4);
  tmp1=EnterBigDigit(19,'0'-1,'9'+1,minute & 0xF);
  minute=(tmp<<4) | tmp1;
  // Вывод года
  ClearDate();
  WriteSmallChar(7,1,2);
  WriteSmallChar(11,1,0);    
  WriteSmallChar(15,1,year>>4);
  WriteSmallChar(19,1,year & 0xF);
  WriteDisplay();
  // Ввод года
  tmp=EnterSmallDigit(15,'0'-1,'9'+1,year>>4);
  tmp1=EnterSmallDigit(19,'0'-1,'9'+1,year & 0xF);
  year=(tmp<<4) | tmp1;
  // Вывод числа и месяца
  WriteData();
  // Ввод месяца
  tmp=EnterSmallDigit(14,'0'-1,'2',month>>4);
  if(tmp==1)
  {
    if((month & 0xF)>2) month=0x10;
    tmp1=EnterSmallDigit(18,'0'-1,'3',month & 0xF);
  }
  else tmp1=EnterSmallDigit(18,'0'-1,'9'+1,month & 0xF);
  month=(tmp<<4) | tmp1;  
  // Ввод даты
  if( (year%4)==0)days_of_month[2]=0x29;
  tmp1=(month>>4)*10+(month & 0xF);
  if((date>>4)>(days_of_month[tmp1]>>4)) tmp=EnterSmallDigit(4,'0'-1,(days_of_month[tmp1]>>4)+0x31,days_of_month[tmp1]>>4);
  else tmp=EnterSmallDigit(4,'0'-1,(days_of_month[tmp1]>>4)+0x31,date>>4);
  if(tmp==(days_of_month[tmp1]>>4))
  {
    // Для числа 3++ (в феврале 2++) максимальное значение == 0/1 (для февраля 28/29)
    date=tmp<<4;
    tmp1=EnterSmallDigit(8,'0'-1,((days_of_month[tmp1] & 0xF)+0x31),date & 0xF);
  }
  else
  {
    // Нулевой даты не бывает
    if(!tmp) tmp1=EnterSmallDigit(8,'1'-1,'9'+1,date & 0xF);
    else tmp1=EnterSmallDigit(8,'0'-1,'9'+1,date & 0xF);
  }
  date=(tmp<<4) | tmp1;   
  ds[0]=0;ds[1]=minute,ds[2]=hour,ds[4]=date,ds[5]=month,ds[6]=year;
  ds[3]=Calc_Day((date>>4)*10+(date & 0xF),(month>>4)*10+(month & 0xF),2000+(year>>4)*10+(year & 0xF));
  Write_I2C(DS3231,0,7,&ds[0]);
}
//***********************************************************************************************
void loop() {
  unsigned char tmp;
  static unsigned char old_sec=0xFF;
  static unsigned char delay_10=10;     // Задержка до смены режима "Дата/Температура"
  static unsigned int adr=0;            // Позиция редактируемого символа таймера
  static unsigned char flash=0;         // Мигание разряда
  static unsigned char next_digit=0;    // Ожидание отпускания клавиши
  static unsigned char sec_upd=0;       // Прошла 1 секунда
  static unsigned int old_timer=0;      // Последнее введеное значение таймера
  static unsigned int timer_sound=0;    // Задержка выключения звука таймера
  Read_I2C(DS3231,0,0x12,ds);
  // Вывод времени
  if(ds[2]>>4) WriteBigChar(1,0,ds[2]>>4);
  else WriteBigChar(1,0,12);
  WriteBigChar(6,0,ds[2] & 0xF);
  if(ds[0] & 1) WriteBigChar(10,0,10);
  else WriteBigChar(10,0,11);
  WriteBigChar(14,0,ds[1]>>4);
  WriteBigChar(19,0,ds[1] & 0xF);
  // Прошла секунда
  if(ds[0]!=old_sec)
  {
    old_sec=ds[0];
    wdt_reset();
    if(!timer_sound) digitalWrite(PinBiper,HIGH);    // Отключение бипера
    else
    {
      timer_sound--;
      // Возврат в режим часов
      if(!timer_sound) mode=0;
    }
    sec_upd=1;
    // Сигнал каждый час
    if(sound_en && !ds[0] && !ds[1] && !timer_sound) tone(PinBiper,1000,200);
    // Смена режимов каждые десять секунд
    // В режиме таймера и установки времени режимы не меняются
    if(mode<2) {delay_10--; if(!delay_10) {delay_10=10; mode++;if(mode==2) mode =0; }}
  }
  // Режимы таймера:
  // 0 == Остановлен
  // 1 == Установка значений
  // 2 == Работает
  
  // Опрос клавиатуры
  tmp=Keypad();
  if(tmp==0) next_digit=0;  
  if(tmp=='A')
  {
    if(mode<2) { mode=3; WriteData(); SetupTime(); mode=0; }        // Установка времени
    if(mode==2 && !timer_mode)                                      // Установка таймера
    {
      timer_mode=1;
      timer_min=timer_sec=adr=0;
      if(timer_sound) {timer_sound=0; noTone(PinBiper);}
    }
  }
  // Смена шрифта часов
  if(tmp=='*' && !next_digit)
  {
    next_digit=1;
    font++;if(font==3)font=0;
  }
  // Изменение яркости экрана
  if(tmp=='#' && !next_digit)
  {
    scr_level++;if(scr_level==MAX_LIGHT) scr_level=0;
    for(unsigned char address=0;address<6;address++) lc.setIntensity(address,scr_level);
    ds[0]=scr_level; Write_I2C(DS3231,0x09,1,&ds[0]);
    next_digit=1;
  }
  // Таймер
  if(tmp=='B' && !next_digit)
  {
    if(mode<2){mode=2;timer_mode=0;timer_min=old_timer;timer_sec=0;WriteTimer();}     // Вход в режим таймера
    else { mode=0;timer_mode=0; WriteData(); }                                        // Выход из режима таймера
    next_digit=1;
  }
  // Установка времени таймера
  if(mode==2 && timer_mode==1)
  {
    // Ввод значения
    if(tmp>0 && tmp<('9'+1) && !next_digit)
    {
      if(!adr) {timer_min=(tmp-0x30)*100;adr++;}
      else if(adr==1) {timer_min+=(tmp-0x30)*10;adr++;}
      // После ввода последней цифры переход таймера в режим "Стоп"
      else if(adr==2) {timer_min+=(tmp-0x30); old_timer=timer_min;timer_mode=0;adr++;}
      next_digit=1;
    }
    // Мигание разряда
    ClearDate();WriteTimer();
    if(adr==0 && flash) {buffer[3][1] &=3;buffer[4][1] &=3;buffer[5][1] &=3;}
    if(adr==1 && flash) {buffer[7][1] &=3;buffer[8][1] &=3;buffer[9][1] &=3;}
    if(adr==2 && flash) {buffer[11][1] &=3;buffer[12][1] &=3;buffer[13][1] &=3;}
    flash=!flash;
  }
  // Выключение звука таймера
  if((tmp=='B' || tmp=='C') && timer_sound) {timer_sound=0; noTone(PinBiper);}
  // Включение/Выключение таймера. Нельзя запустить таймер при нулевом счетчике
  if(tmp=='C' && (timer_mode==0 || timer_mode==2) && (timer_min!=0 || timer_sec!=0) && !next_digit)
  {
    if(timer_mode==2) timer_mode=0;
    else timer_mode=2;
    next_digit=1;
    WriteTimer();
  }
  // Счет таймера
  if(mode==2 && timer_mode==2)
  {
    if(sec_upd)
    {
      sec_upd=0;
      // Уменьшение секунд таймера
      if(timer_sec || timer_min) timer_sec--;
      // Время кончилось
      if(!timer_min && !timer_sec)
      {
        timer_mode=0;
        tone(PinBiper,1500,30000);
        timer_sound=31;
      }
      // Уменьшение минут таймера
      else {if(timer_sec==0xFF) {timer_sec=59;timer_min--;}}
      WriteTimer();
    }
  }
  // Сигнал каждый час вкл/выкл
  if(tmp=='D' && mode<2 && !next_digit) {ds[0]=sound_en=!sound_en; Write_I2C(DS3231,0x0C,1,&ds[0]);next_digit=1; }
  if(mode==0) WriteData();                          // Вывод даты
  if(mode==1) WriteTemp();                          // Вывод дня недели и температуры
  WriteDisplay();
  delay(200);
}