НЕТ СОСЕД или домофон автомат

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Вообщем я проживаю на первом этаже девятиэтажного дома и все у кого нет ключей от домофона названивают ко мне (почта, электрики, кабельное, соседи и их дети). Т.к. я работаю по сменному графику то иногда перед ночной сменой охото днем подремать, но ... Последней каплей стал один неадыкватный сосед позвонил мне в домофон пол третьего ночи и попросил открыть ему дверь (на что был послан на 3 руские буквы), тут есче ожидал прибавление в симействе, а малышам нужно отдыхать и высыпаться чтоб родителям спокойней жилось.

Так родился этот проект.

Условия были такие - создать недорогое устройство которое по времени включало и отключало домофон и звонок, имело возможность принудительного отключения включения по нажатию кнопки, в связи с всеобщей смартфонизацией иметь возможность управления по блютус в случае установки в неудобном месте, но об этом позже.

Пока проект крутиться на arduino UNO & LCD Keypad shield (на тестировании). Конечно будет перенесен на свою печатку с МК ATmega8 или 168, что найду.

Вот собственно код девайса

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);
long time;//для минутного таймера
byte mode=0;//основной экран
int timer = 0;//текущее время суток в минутах
int timer_off=1350;//время выключения 22.30 в минутах
int timer_on = 480;//время включения 8.00 в минутах
int error=0;//авто корректировка
boolean k=0;//клавиатура вход А0
int k_b[]={639,98,253};//аналоговые кнопки SET + - (LCD Keypad shild
//---------------------для настройки по сериал------------------------------
String myString =  "";
String now_t;
String off_t;
String on_t;
//------------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  pinMode(13,OUTPUT);//реле
  //pinMode(10,OUTPUT);//подсветка дисплея
  digitalWrite(13,LOW);
  //digitalWrite(10,LOW);
  lcd.begin(16, 2);
  time = millis();
  error=millis();
}
void loop(){
  set();
  key();
  lcd.setCursor(12, 0);
  lcd.print(analogRead(0));
  //lcd.setCursor(7, 0);
  //lcd.print(millis()-time);
  if (mode!=3){//если настраиваем время то отсчет не ведем
    tik();
  }

  GUI(mode);//вывод необходимого экрана
  if (timer==timer_on){
    digitalWrite(13,LOW);//включение домофона
  }
  if(timer==timer_off){
    digitalWrite(13,HIGH);//выключение домофона
  }
  if (digitalRead(13)==HIGH){
    analogWrite(10,25);//если реле включено(домофон выключен) убавить яркость подсветки
  }
  else
  {
    analogWrite(10,200);//если реле выключено(домофон включен) прибавить яркость подсветки
  }
}
//-------------------------вывод экранов (меню)-----------------------
void GUI(byte x){
  switch (x){
  case 0://основной экран
    GUI_clock(timer,0,0);
    GUI_clock(timer_off,0,1);
    GUI_clock(timer_on,11,1);
    break;
  case 1://Уставка времени выключения
    GUI_time_off(timer_off);
    break;
  case 2://Уставка времени включения
    GUI_time_on(timer_on);
    break;
  case 3://Установка текущего времени
    GUI_timer_set(timer);
    break;   
  }
}
//------------------------экраны------------------------
void GUI_time_off(int t){
  lcd.setCursor(0, 1);
  lcd.print("Time OFF - ");
  GUI_clock(t,11,1);
} 

void GUI_time_on(int t){
  lcd.setCursor(0, 1);
  lcd.print("Time ON - ");
  GUI_clock(t,10,1);
}

void GUI_timer_set(int t){
  //time = millis();
  lcd.setCursor(0, 1);
  lcd.print("Set Time - ");
  GUI_clock(t,11,1);
}
//--------вывод времени в формате 00:00 в заданых координатах-----------
void GUI_clock(int t,int x,int y){
  lcd.setCursor(x, y);
  byte h=floor(t/60);
  byte m=t-(h*60);
  if (h<10){
    lcd.print("0");
  }
  lcd.print(h);
  lcd.print(":");
  if (m<10){
    lcd.print("0");
  }
  lcd.print(m);
  lcd.print(" ");
}
//----------------опрос клавиш-------------------------------
void key()
{
  int x = analogRead(0);
  if (x>k_b[0]-5 && x<k_b[0]+5){//МЕНЮ
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(0);
  }
  if (x>k_b[1]-5 && x<k_b[1]+5){// +
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(1);
  } 
  if (x>k_b[2]-5 && x<k_b[2]+5){// -
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(2);
  }  
}
//---------------отсчет времени (минут)--------------------
void tik(){
  if (millis()<time){//если переполнился счетчик
    //error=millis();//этот момент пока под ?
    time=0;
  }
  if ((millis()-time)>=60000){//если прошла минута
    timer++;//прибавляем минуту
    if (timer==1440){//если прошли сутки
      timer=0;//сброс часов на ноль
      time=time-4000;//компенсация ухода времени на 4 сек/сутки (опытным путем)
    }
    error=(millis()-time-60000);//расчет погрешности (уход милсек/мин)
    // time = millis();//без учета погрешности
    time = (millis()-error);//учитываем время погрешности
    lcd.setCursor(7, 0);
    lcd.print(error);//вывод погрешности для теста
  }
}
//-----------------работа с кнопками-------------------------
void key_m(int x){
  lcd.clear();
  switch (x){
  case 0://menu
    mode++;
    if (mode>3){
      //error=millis();?
      time = millis();//при установке времени начало отсчета
      mode=0;
    }
    break;
  case 1://кнопка +
    if (mode==0){//при основном экране нажатие + переключает реле принудительно
      digitalWrite(13,!digitalRead(13));
    }
    if (mode==1){//при настр врем откл прибавляем часы
      timer_off=h_p(timer_off);
    }
    if (mode==2){//при настр врем вкл прибавляем часы
      timer_on=h_p(timer_on);
    }   
    if (mode==3){//при настр текущ врем прибавляем часы
      timer=h_p(timer);
    }
    break;
  case 2://кнопка -
    if (mode==1){//при настр врем откл прибавляем минуты
      timer_off=m_p(timer_off);
    }
    if (mode==2){//при настр врем вкл прибавляем минуты
      timer_on=m_p(timer_on);
    }
    if (mode==3){//при настр текущ врем прибавляем минуты
      timer = m_p(timer);
      break;
    }
  }
}
//----------функция приращения минут--------------------
int m_p(int t){
  int result;
  t=t+1;
  if (t>=1440){
    t =0;
  }
  result = t;
  return result;
}
//----------функция приращения часов---------------------
int h_p(int t){
  int result;
  t=t+60;
  if (t>=1440){
    t =0;
  }
  result = t;
  return result;
}
//-------------------функция принятия настроек по сериал-------
//-ждет ввода тек.время(в мин):время выкл(в мин):время вкл(в мин)--
void set(){
  if (Serial.available() ==14) {
    myString = Serial.readString();
    now_t = getValue(myString, ':', 0);
    off_t = getValue(myString, ':', 1);
    on_t = getValue(myString, ':', 2);
    Serial.print("NOW:" + now_t);
    Serial.print(" OFF:" + off_t);
    Serial.print(" ON:" + on_t);
    timer=now_t.toInt();
    timer_off=off_t.toInt();
    timer_on=on_t.toInt();
    //float  xvalue = xval.toInt();
    //Serial.println((xvalue)/100.0);    
  }
}
//--парсер данных с сериал---------------------------------
String getValue(String data, char separator, int index){
  int found = 0;
  int strIndex[] = {
    0, -1              };
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
//---------------------------------------------------------------------

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а как же фото?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

В устройстве не хотел использовать лишние детали типа часов реального времени поэтому отсчет времени предоставлен полностью МК. Много читал на форумах про то как не точно ходят часы построеные на arduino при помощи millis(). Когда я написал первый код они у меня тоже шли мягко сказать неточно (уходили на 1,5 - 2 мин/час). И я начал решать эту проблемму.

Решил я её следующим образом

//---------------отсчет времени (минут)--------------------
void tik(){
  if (millis()<time){//если переполнился счетчик
    //error=millis();//этот момент пока под ?
    time=0;
  }
  if ((millis()-time)>=60000){//если прошла минута
    timer++;//прибавляем минуту
    if (timer==1440){//если прошли сутки
      timer=0;//сброс часов на ноль
      time=time-4000;//компенсация ухода времени на 4 сек/сутки (опытным путем)
    }
    error=(millis()-time-60000);//расчет погрешности (уход милсек/мин)
    // time = millis();//без учета погрешности
    time = (millis()-error);//учитываем время погрешности
    lcd.setCursor(7, 0);
    lcd.print(error);//вывод погрешности для теста
  }
}

Общая ошибка у всех кто пытался так делать в том что они не видят что строка if((millis()-preMillis)>=60000) дает нам не только то что мы прошли интервал и можно совершить какоето действие но и то что мы его перескочили (>=), так вот можно тупо высчитать сколько составил этот перескок error=(millis()-preMillis-60000) в моем случае и далее отнять эту погрешность от накопленного preMillis тем самым не давая часикам убигать.

После добавления этих изменений мои часы за трое суток ушли всего на 12 секунд вперед (4 сек/сутки) которые я скомпенсировал следующим образом. По началу новых суток я от preMillis отнимаю 4000. Если уход таких часиков замерить в течении дней 10 то можно скоректировать по точнее.

Итог за последние 6 суток часы отстали на 1-2 сек. (проверяю по компу после синхронизации времени).

Вот фото. Сверху текущее время рядом переменная error, а внизу время выключения слева и время включения справа.

Всё настраеваеться тремя кнопками SET, UP, DN.

При нажатии на SET по кругу идут установка времени выключения -> установка времени включения-> установка текущего времени и обратно к сновному экрану. Кнопкой UP выставляються часы, кнопкой DN минуты. Если во время отображения основного экрана нажать UP то принудительно состояние домофона поменяеться на противоположное (вкл/выкл).

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну теперь корпус нужен. тут например

http://www.chipdip.ru/catalog-show/plastic-cases/

может такой. надо размеры проверять

http://www.chipdip.ru/product/g1204g/

ATkRnr
Offline
Зарегистрирован: 22.10.2013

yul-i-an пишет:

Вообщем я проживаю на первом этаже девятиэтажного дома и все у кого нет ключей от домофона названивают ко мне (почта, электрики, кабельное, соседи и их дети). Т.к. я работаю по сменному графику то иногда перед ночной сменой охото днем подремать, но ... Последней каплей стал один неадыкватный сосед позвонил мне в домофон пол третьего ночи и попросил открыть ему дверь (на что был послан на 3 руские буквы..........

Сочувствую и понимаю, поскольку тоже живу на первом и тоже самое с соседями и прочими прохожими.

Я просто отключаю звук(пищалку вызов) у домофона. Но сосед у меня не лучше, позвонил в 5 утра, открыть-- реакция была  не хуже твоей(больше вроде не звонит). 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

В APPINVENTOR состряпал приложение для управления девайсом.

Перед использованием необходимо включить блютус. При нажатии кнопки подключить выдет список доступных устройств, выбрать нужное, задать время отключения и включения, нажать кнопку задать. При этом передает в устройство текущее время, время вкл/выкл.

Пока его делал пришла мысль что часы в контроллере и не нужны вовсе. Мое приложение может когда текущее время сравнивается с временем задания передает 0 или 1 и произносит статус. Получается что нам МК нужен только как мост между блютус и реле, а вся программа вертится на смартфоне. И время всегда точное и аккумулятор от потери сетевого питания есть!

А смартфонов старых завалялось уже несколько штук.

Получаеться что для реализаци вполне хватит Тиньки блютус модуля и реле.

Кому интересно можно скачать тут.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

это уже интереснее

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

yul-i-an, всё таки правильнее считать время таймером,  вот типовые часы (шаблон) на 16-битном таймере:

volatile uint8_t minut=0;
volatile uint8_t chas=0;
volatile uint8_t sec=0;

void setup(){
Serial.begin(9600);
TCCR1A=(1<<WGM11); //режим14 FAST PWM 
TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
TIMSK1=(1<<TOIE1); //разрешить прерывание
}

ISR (TIMER1_OVF_vect) { 
sec++ ; //инкремент переменной каждую секунду
if (sec>59){sec=0; minut++; }
if (minut>59){minut=0; chas++; }
if (chas>23){chas=0;}
}

void loop(){
Serial.print(chas);
Serial.write(':');
Serial.print(minut);
Serial.write(':');
Serial.print(sec);
Serial.println();
}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Спасибо за пример. Возможно применю, но пока мои идут точно. в 7 отставали гдето на 1.5 сек. , в 11 уже ровно, к вечеру убегут, а там отнимется 4 сек. Уж неделю как крутяться, всё устраивает.

Есче раз спасибо.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

jeka_tm пишет:

ну теперь корпус нужен. тут например

http://www.chipdip.ru/catalog-show/plastic-cases/

может такой. надо размеры проверять

http://www.chipdip.ru/product/g1204g/

Тут помоему выбор получше.

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

ТС применил совершенно разумный метод коррекции хода программных часов. На мой взгляд, в большинстве случаев это гораздо эффективней (проще и дешевле), чем использоание внешних аппаратных модулей часов. В конце 80-х в СССР выпустили новую линейку наручных часов "Электроника" с общей особенностью - ЦНХ (цифровая настройка хода ). Измерив суточный уход, можно было ввести его компенсацию в диапазоне от минус 6,3 с до плюс 6,3 с дискретностью 0,1 с. На практике удавалось добиться суточного ухода порядка 0,3 с.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Подправил немного приложение под Android

Теперь врямя выводит в формате 00:00:00 и при нажатии кнопки задать рядом с ней отображает что передает по блютус (для тестирования).

Приложение Исходник для appInventor

Немного подправил скетч

#include <LiquidCrystal.h>
#include <string.h>
LiquidCrystal lcd(8,9,4,5,6,7);
long time;//для минутного таймера
byte mode=0;//основной экран
long timer = 0;//текущее время суток в минутах
long timer_off=1350;//время выключения 22.30
long timer_on = 480;//время включения 8.00
long error=0;//корректировка
boolean k=0;//клавиатура вход А0
int k_b[]={
  639,98,253};//аналоговые кнопки SET + -
//---------------------для настройки------------------------------
String myString =  "";
String now_t;
String off_t;
String on_t;
//------------------------------------------------------------------
void setup(){
  Serial.begin(9600);
  pinMode(13,OUTPUT);//реле
  //pinMode(10,OUTPUT);//подсветка дисплея
  digitalWrite(13,LOW);
  //digitalWrite(10,LOW);
  lcd.begin(16, 2);
  time = millis();
  error=millis();
}
void loop(){
  set();
  key();
  //-----для тестирования аналоговых кнопок-------
  //lcd.setCursor(12, 0);
  //lcd.print(analogRead(0));
  if (mode!=3){//если настраиваем время то отсчет не ведем
    tik();
  }

  GUI(mode);//вывод необходимого экрана
  if (timer==timer_on){
    digitalWrite(13,LOW);//включение домофона
  }
  if(timer==timer_off){
    digitalWrite(13,HIGH);//выключение домофона
  }
  if (digitalRead(13)==HIGH){
    analogWrite(10,25);//если реле включено(домофон выключен) убавить яркость подсветки
  }
  else
  {
    analogWrite(10,200);//если реле выключено(домофон включен) прибавить яркость подсветки
  }
}
//-------------------------вывод экранов (меню)-----------------------
void GUI(byte x){
  switch (x){
  case 0://основной экран
    GUI_clock(timer,0,0);
    GUI_clock(timer_off,0,1);
    GUI_clock(timer_on,11,1);
    break;
  case 1://Уставка времени выключения
    GUI_time_off(timer_off);
    break;
  case 2://Уставка времени включения
    GUI_time_on(timer_on);
    break;
  case 3://Установка текущего времени
    GUI_timer_set(timer);
    break;   
  }
}
//------------------------экраны------------------------
void GUI_time_off(int t){
  lcd.setCursor(0, 1);
  lcd.print("Time OFF - ");
  GUI_clock(t,11,1);
} 

void GUI_time_on(int t){
  lcd.setCursor(0, 1);
  lcd.print("Time ON - ");
  GUI_clock(t,10,1);
}

void GUI_timer_set(int t){
  //time = millis();
  lcd.setCursor(0, 1);
  lcd.print("Set Time - ");
  GUI_clock(t,11,1);
}
//--------вывод времени в формате 00:00 в заданых координатах-----------
void GUI_clock(int t,int x,int y){
  lcd.setCursor(x, y);
  byte h=floor(t/60);
  byte m=t-(h*60);
 nz(h);
 /* if (h<10){
    lcd.print("0");
  }*/
  lcd.print(h);
  lcd.print(":");
  nz(m);
  /*if (m<10){
    lcd.print("0");
  }*/
  lcd.print(m);
  lcd.print(" ");
}
//------вывод дополнительного 0 если число < 10-------------
void nz(byte x){
   if (x<10){
    lcd.print("0");
  }
}
//----------------------------------------------------------
//----------------опрос клавиш-------------------------------
void key()
{
  int x = analogRead(0);
  if (x>k_b[0]-5 && x<k_b[0]+5){//МЕНЮ
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(0);
  }
  if (x>k_b[1]-5 && x<k_b[1]+5){// +
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(1);
  } 
  if (x>k_b[2]-5 && x<k_b[2]+5){// -
    while (analogRead(k)<1010){//ждем отпускания кнопки
    } 
    key_m(2);
  }  
}
//---------------отсчет времени (минут)--------------------
void tik(){
  if (millis()<time){//если переполнился счетчик
    //error=millis();//этот момент пока под ?
    time=0;
  }
 long dT =(millis()-time);//разница между накопленым и счетчиком
  if (dT>=60000){//если прошла минута
    timer++;//прибавляем минуту
    if (timer==1440){//если прошли сутки
      timer=0;//сброс времени
      time=time-4000;//компенсация ухода времени на 4 сек/сутки
    }
    error=(dT-60000);//расчет погрешности (уход милсек/мин)
    // time = millis();//без учета погрешности
    time = (millis()-error);//учитываем время погрешности
    lcd.setCursor(7, 0);
    lcd.print(error);//вывод погрешности для теста
  }
}
//-----------------работа с кнопками-------------------------
void key_m(int x){
  lcd.clear();
  switch (x){
  case 0://menu
    mode++;
    if (mode>3){
      //error=millis();?
      time = millis();//при установке времени начало отсчета
      mode=0;
    }
    break;
  case 1://кнопка +
    if (mode==0){//при основном экране нажатие + переключает реле принудительно
      digitalWrite(13,!digitalRead(13));
    }
    if (mode==1){//при настр врем откл прибавляем часы
      timer_off=h_p(timer_off);
    }
    if (mode==2){//при настр врем вкл прибавляем часы
      timer_on=h_p(timer_on);
    }   
    if (mode==3){//при настр текущ врем прибавляем часы
      timer=h_p(timer);
    }
    break;
  case 2://кнопка -
    if (mode==1){//при настр врем откл прибавляем минуты
      timer_off=m_p(timer_off);
    }
    if (mode==2){//при настр врем вкл прибавляем минуты
      timer_on=m_p(timer_on);
    }
    if (mode==3){//при настр текущ врем прибавляем минуты
      timer = m_p(timer);
      break;
    }
  }
}
//----------функция приращения минут--------------------
long m_p(int t){
  long result;
  t=t+1;
  if (t>=1440){
    t =0;
  }
  result = t;
  return result;
}
//----------функция приращения часов---------------------
long h_p(int t){
  long result;
  t=t+60;
  if (t>=1440){
    t =0;
  }
  result = t;
  return result;
}
//-------------------функция принятия настроек по сериал-------
//-ждет ввода тек.время(в мин):время выкл(в мин):время вкл(в мин)--
void set(){
 if (Serial.available() ==14){
    myString = Serial.readString();
    now_t = getValue(myString, ':', 0);
    off_t = getValue(myString, ':', 1);
    on_t = getValue(myString, ':', 2);
    Serial.print(" NOW:" + now_t);
    Serial.print(" OFF:" + off_t);
    Serial.print(" ON:" + on_t);
    timer=now_t.toInt();
    timer_off=off_t.toInt();
    timer_on=on_t.toInt();
      }   
 }
//--парсер данных с сериал---------------------------------
String getValue(String data, char separator, int index){
  int found = 0;
  int strIndex[] = {
    0, -1              };
  int maxIndex = data.length()-1;
  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
      found++;
      strIndex[0] = strIndex[1]+1;
      strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
//---------------------------------------------------------------------
yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Купил рассыпухи (на все детали и текстолит ушло 460р.) дороговато однако (одна тоько ATMega8 - 200р.), разрабатываю плату.

Вот что на данный момент вышло.

обратная сторона

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

я бы увеличил диаметр площадок, а то уж совсем тонкие, и ширину тонких дорожек немного увеличил

к тому же реально сделать односторонним монтажем. смысл усложнять?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

jeka_tm пишет:

я бы увеличил диаметр площадок, а то уж совсем тонкие, и ширину тонких дорожек немного увеличил

к тому же реально сделать односторонним монтажем. смысл усложнять?

Это пока набросок. Разводка будет односторонней, все SMD с тыльной стороны, а выводные детали с лицевой. Кнопочкки наверно придеться врезные поставить, чтоб смотрелись лучше.

Такие примерно

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Спаял девайс.

Ищу корпус.

Скорее всего это будет

распаячная коробка

adrusha
Offline
Зарегистрирован: 02.03.2015
mechaniker
Offline
Зарегистрирован: 21.03.2017

dimax пишет:

yul-i-an, всё таки правильнее считать время таймером,  вот типовые часы (шаблон) на 16-битном таймере:

volatile uint8_t minut=0;
volatile uint8_t chas=0;
volatile uint8_t sec=0;

void setup(){
Serial.begin(9600);
TCCR1A=(1<<WGM11); //режим14 FAST PWM 
TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
ICR1=62499;  // (16000000MHz /div256) -1 = 1 раз в секунду
TIMSK1=(1<<TOIE1); //разрешить прерывание
}

ISR (TIMER1_OVF_vect) { 
sec++ ; //инкремент переменной каждую секунду
if (sec>59){sec=0; minut++; }
if (minut>59){minut=0; chas++; }
if (chas>23){chas=0;}
}

void loop(){
Serial.print(chas);
Serial.write(':');
Serial.print(minut);
Serial.write(':');
Serial.print(sec);
Serial.println();
}

 

большое спасибо за ваш пример!!!!!!!!!!!!!!!!!!!