Отследить состояние кнопки

Tails_MP
Tails_MP аватар
Offline
Зарегистрирован: 11.11.2015

Всем привет! Необходимо отследить состояние кнопки. Задача состоит в том что бы сделать включение и выключение диода с кнопки и пульта одновременно, не зависимо друг от друга.

Не работает в том месте когда после операции с пультом (включения или выключения), следующее переключение кнопки не к чему не приводит, и только после второго все корректно. Я понимаю что нужно отслеживать состояние кнопки когда переключаю с пульта, но не понимаю как. Подскажите пожалуйсто гуда ковырять. (новичек).

#include <IRremote.h> // https://github.com/shirriff/Arduino-IRremote

#define RECV_PIN 4 // IR приемник
#define OUT1 9// выхода на мосфеты

const int  buttonPin = 7; // кнопка включения с фиксацией

#define POWER_KEY 0xFF00FF // коды пульта ДУ
#define KEY1 0xFF807F // v-
#define KEY2 0xFF40BF // v+


byte analogData1 = 0; // значения аналогово выхода
uint32_t val; 
int buttonState = 0; //переменная состояния кнопки
int oldButtonState = 0; //переменная старое состояние кнопки
IRrecv irrecv(RECV_PIN);

decode_results results;


void setup()
{
  irrecv.enableIRIn();  //запускаем ик
Serial.begin(9600); //включаем сериал
pinMode(buttonPin, INPUT); //кнопка как вход
}


void loop() {

buttonState = digitalRead(buttonPin);
  if (oldButtonState==LOW && buttonState==HIGH)
   {
     analogWrite(OUT1, 255); // включаем
     analogData1 = 255;
     oldButtonState = buttonState;
   }
  if (oldButtonState==HIGH && buttonState==LOW)//выключили
   {
     analogWrite(OUT1, 0); // выключаем
     analogData1 = 0;
     oldButtonState = buttonState;
   }
   
  ////////////////////////////////////////////////////////////////////////////
  //************************************************************************//
  ////////////////////////////////////////////////////////////////////////////
  if (irrecv.decode(&results)) { // если пришел пакет  
    if (results.value != 0xFFFFFFFF){ // и этот пакет не FF
      val = results.value; // сохраняем правельный пакет в переменную     
    }                 // если пришел FF, соответственно пропускаем.
    
    /// сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
    /// в переменной останется прошлый, правельный, пакет и код выполнится повторно. 
    if (val == KEY1){      
       if (analogData1 != 0)analogData1 -=5; // если шим не равно 0 отнимаем 1 
       analogWrite(OUT1, analogData1);    // устанавливаем значение в выход     
    }    
     if (val == KEY2){ // и это вторая кнопка     
       if (analogData1 < 255) analogData1 +=5; // если шим меньше 255 прибовляем 1 
       analogWrite(OUT1, analogData1);  // устанавливаем значение 
    }
    if (results.value == POWER_KEY) {  
      if (analogData1 != 0){ // если ШИМ неравно 0
        analogWrite(OUT1, 0); // выключаем
        //наверно где то тут нужно отслеживать кнопку
        analogData1 = 0;
       
      }
      else {
        analogWrite(OUT1, 255); // включаем
       //наверно где то тут нужно отслеживать кнопку
        analogData1 = 255;
      }       
     }  
Serial.println(val, HEX); //// ТЕСТЫ!
Serial.println(results.value, HEX); 
Serial.println(analogData1); 
Serial.println();
//Serial.print("положение кнопки ");
//Serial.println(buttonState);


  irrecv.resume(); 
  }
}

  
  

Tails_MP
Tails_MP аватар
Offline
Зарегистрирован: 11.11.2015
#include <IRremote.h>

#define RECV_PIN 4 // IR приемник
#define OUT1 9// выхода на мосфеты

const int  buttonPin = 7; // кнопка включения с фиксацией

#define POWER_KEY 0xFF00FF // коды пульта ДУ
#define KEY1 0xFF807F // v-
#define KEY2 0xFF40BF // v+


byte analogData1 = 0; // значения аналогово выхода
uint32_t val; 
int buttonState = 0; //переменная состояния кнопки
int oldButtonState = 0; //переменная старое состояние кнопки
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
  irrecv.enableIRIn();  //запускаем ик
Serial.begin(9600); //включаем сериал
pinMode(buttonPin, INPUT); //кнопка как вход
}


void loop() {

buttonState = digitalRead(buttonPin);
  if (oldButtonState==LOW && buttonState==HIGH)
   {
     analogWrite(OUT1, 255); // включаем
     analogData1 = 255;
     oldButtonState = buttonState;
   }
  if (oldButtonState==HIGH && buttonState==LOW)//выключили
   {
     analogWrite(OUT1, 0); // выключаем
     analogData1 = 0;
     oldButtonState = buttonState;
   }
  if (irrecv.decode(&results)) { // если пришел пакет  
    if (results.value != 0xFFFFFFFF){ // и этот пакет не FF
      val = results.value; // сохраняем правельный пакет в переменную     
    }                 // если пришел FF, соответственно пропускаем.
    
    /// сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
    /// в переменной останется прошлый, правельный, пакет и код выполнится повторно. 
    if (val == KEY1){      
       if (analogData1 != 0)analogData1 -=5; // если шим не равно 0 отнимаем 1 
       analogWrite(OUT1, analogData1);    // устанавливаем значение в выход     
    }    
     if (val == KEY2){ // и это вторая кнопка     
       if (analogData1 < 255) analogData1 +=5; // если шим меньше 255 прибовляем 1 
       analogWrite(OUT1, analogData1);  // устанавливаем значение 
    }
    if (results.value == POWER_KEY) {  
      if (analogData1 != 0){ // если ШИМ неравно 0
        analogWrite(OUT1, 0); // выключаем
        //наверно где то тут нужно отслеживать кнопку
        analogData1 = 0;
       
      }
      else {
        analogWrite(OUT1, 255); // включаем
       //наверно где то тут нужно отслеживать кнопку
        analogData1 = 255;
      }       
     }  
Serial.println(val, HEX); //// ТЕСТЫ!
Serial.println(results.value, HEX); 
Serial.println(analogData1); 
Serial.println();
//Serial.print("положение кнопки ");
//Serial.println(buttonState);


  irrecv.resume(); 
  }
}

  
  

 

UserDead
UserDead аватар
Offline
Зарегистрирован: 29.11.2015

Мне наверное стоило прочесть код более внимательно. Но я пока что обойдусь советом. 

Как насчет конструкции где есть общая переменная и обработкик контроллирующий состояние переменной кнопки. И изменяет состояние светодиода если было изменение опираясь на предыдущее значение.

Тоесть три куска кода:

1- обработчик контроллирует состояние переменной скажем keyvar

2 - обработчик кнопки на устройстве. при нажатии меняет состояние на keyvar

3 - обработчик приема данных с пульта и так же вносит изменение в keyvar

суть проста. 2 и 3 обработчики не работают с командой вывода сигнала на светодиод. этм занимается первый обработчик который просто контроллирует переменную и делает выводы стоит что-то менять или нет.

okta
Offline
Зарегистрирован: 10.01.2015

Если вы хотите, что бы работало по такому алгоритму:

1. Включили кнопкой (кнопка, как я понимаю, например замкнула контакт и зафиксировалась в этом положении)  ->  2. Выключили с пульта  -> 3. Включили кнопкой (кнопка разомкнула котакт и зафиксировалась в этом положении)

Т.е. у кнопки нет фиксированных положений вот так она вкл, а вот так выкл, то вместо строк 30-41 нужно что-то такое:

  if (oldButtonState!=buttonState) 
    { 
      if(analogData1>0){
        analogWrite(OUT1, 0); // выключаем 
        analogData1 = 0;
      }else{
        analogWrite(OUT1, 255); // включаем 
        analogData1 = 255;
      }
      oldButtonState = buttonState; 
    } 

 

Tails_MP
Tails_MP аватар
Offline
Зарегистрирован: 11.11.2015

Я уж отчаялся, думал не ответят. Спасибо Вам добрые дяденьки программисты! Домой приду сразу попробую. 

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

okta
Offline
Зарегистрирован: 10.01.2015

Ну тогда однозначно, тот код что я привел в предыдущем посте решит вопрос.

Tails_MP
Tails_MP аватар
Offline
Зарегистрирован: 11.11.2015

Господи!!! Это прекрасно!!! Оно работает!!! Спасибо громадное!!! Я несколько недель этого добивался. Спасибо Вам!!! 11 строчек кода, как нужно мало для счастья)))

 

Вот так теперь выглядит полный вариант.

/*
ЧТО ХОТЕЛОСЬ БЫ ДОБАВИТЬ
1) Настройка часов тремя кнопками. SET, +, -.
2) Настройка часов тремя кнопками с пульта. (дублируют SET, +, -)
3) Запись в EEPROM шесть кнопок от любого пульта. (SET, +(clock), -(clock), Power ON/OFF, +(яркость), -(яркость)) (Программирование на лету))
---на этом проект считался бы полностью завершенным..... наверное.....---
*/

/////////////////////////////////////////////////
///*КОД ЛАМПЫ*//////////////////////////////////
///////////////////////////////////////////////
#include <IRremote.h>
#define RECV_PIN 4 // IR приемник
#define OUT1 9// выхода на мосфеты
const int  buttonPin = 3; // кнопка включения с фиксацией
#define POWER_KEY 0xFF30CF // коды пульта ДУ
#define KEY1 0xFFA857 // v-
#define KEY2 0xFF28D7 // v+
byte analogData1 = 0; // значения аналогово выхода
uint32_t val; 
int buttonState = 0; //переменная состояния кнопки
int oldButtonState = 0; //переменная старое состояние кнопки
IRrecv irrecv(RECV_PIN);
decode_results results;

/////////////////////////////////////////////////
///*КОД ЧАСОВ*//////////////////////////////////
///////////////////////////////////////////////
#include "Wire.h"
//#include <DS3231.h>
#define DS3231_ADDRESS 0x68
int latchPin = 11;
//Pin connected to SH_CP of 74HC595
int clockPin = 13;
////Pin connected to DS of 74HC595
int dataPin = 12;

void setup()
{
/////////////////////////////////////////////////
///*КОД ЛАМПЫ*//////////////////////////////////
///////////////////////////////////////////////
  irrecv.enableIRIn();  //запускаем ик
Serial.begin(9600); //включаем сериал
pinMode(buttonPin, INPUT); //кнопка как вход

/////////////////////////////////////////////////
///*КОД ЧАСОВ*//////////////////////////////////
///////////////////////////////////////////////
Wire.begin();
// setDateTime(); // Первый раз запустит для установки текущего времени, второй раз запускаем "закоментированно"
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}


void loop() {
/////////////////////////////////////////////////
///*КОД ЛАМПЫ*//////////////////////////////////
///////////////////////////////////////////////
buttonState = digitalRead(buttonPin);
 if (oldButtonState!=buttonState)
    {if(analogData1>0)
      {analogWrite(OUT1, 0);
        analogData1 = 0;}
      else{
        analogWrite(OUT1, 255);
        analogData1 = 255;}
      oldButtonState = buttonState;}
  if (irrecv.decode(&results)) { // если пришел пакет  
    if (results.value != 0xFFFFFFFF){ // и этот пакет не FF
      val = results.value; // сохраняем правильный пакет в переменную     
    }                 // если пришел FF, соответственно пропускаем.    
    /// сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
    /// в переменной останется прошлый, правильный, пакет и код выполнится повторно. 
    if (val == KEY1){      
       if (analogData1 != 0)analogData1 -=5; // если шим не равно 0 отнимаем 1 
       analogWrite(OUT1, analogData1);    // устанавливаем значение в выход     
    }    
     if (val == KEY2){ // и это вторая кнопка     
       if (analogData1 < 255) analogData1 +=5; // если шим меньше 255 прибавляем 1 
       analogWrite(OUT1, analogData1);  // устанавливаем значение 
    }
    if (results.value == POWER_KEY) {  
      if (analogData1 != 0){ // если ШИМ неравно 0
        analogWrite(OUT1, 0); // выключаем
        //наверно где то тут нужно отслеживать кнопку
        analogData1 = 0;
      }
      else {
        analogWrite(OUT1, 255); // включаем
       //наверно где то тут нужно отслеживать кнопку
        analogData1 = 255;
      }       
     }  
Serial.println(val, HEX); //// ТЕСТЫ!
Serial.println(results.value, HEX); 
Serial.println(analogData1); 
Serial.println();
//Serial.print("положение кнопки ");
//Serial.println(buttonState);
irrecv.resume(); 
  }
/////////////////////////////////////////////////
///*КОД ЧАСОВ*//////////////////////////////////
///////////////////////////////////////////////
printDate();
//delay(1000);
}
void setDateTime(){
byte second = 0; //0-59
byte minute = 05; //0-59
byte hour = 18; //0-23
byte dow = 2; //1-7
byte day = 8; //1-31
byte month = 11; //1-12
byte year = 11; //0-99
byte getTemp = 0;
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(0); //stop Oscillator
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(day)); //число
Wire.write(decToBcd(dow)); //день недели
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(decToBcd(getTemp));
Wire.write(0); //start 
Wire.endTransmission();
}
byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
void printDate(){
// Reset the register pointer
Wire.beginTransmission(DS3231_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESS, 7);
int second = bcdToDec(Wire.read());
int minute = bcdToDec(Wire.read());
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
int dow = bcdToDec(Wire.read()); //0-6 -> sunday — Saturday
int day = bcdToDec(Wire.read());
int month = bcdToDec(Wire.read());
int year = bcdToDec(Wire.read());
int getTemp = bcdToDec(Wire.read());

//if (hour>12) hour=hour-12;
digitalWrite(latchPin, 0);
//count up on GREEN LEDs
//shiftOut(dataPin, clockPin,MSBFIRST, second);
shiftOut(dataPin, clockPin,MSBFIRST, minute); 
//count down on RED LEDs
shiftOut(dataPin, clockPin,MSBFIRST, hour);
//return the latch pin high to signal chip that it 
//no longer needs to listen for information
digitalWrite(latchPin, 1);
}

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

1. Тут местные критики сразу бы тебя распинали, как меня в свое время, за использование "if", которое при выполнении одного из условий, все равно проверяет все остальные, которые заведомо не выполнятся. Посоветовали применить конструкцию "swith-case", с которой я потом намучался досыта, но оставил чисто в целях расширеня кругозора.

2. Лично я на своём опыте убедился, что "irrecv.resume(); " надо ставть сразу после считывания "results.value" в переменную, что бы подготовить ее для следующего значения. Проверено - работает более стабильно.

Logik
Offline
Зарегистрирован: 05.08.2014

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

Про "swith-case" зря вы так, эта штука очень удобна и проста для старта, намного наглядней кучи ифов.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Logik пишет:

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

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

Logik пишет:
Про "switсh-case" зря вы так, эта штука очень удобна и проста для старта, намного наглядней кучи ифов.
А вот это как раз из области личных предпочтений. Лично мне удобнее было бы всё проверять "if"-ами, но народ высказался в пользу "switсh-case" и я, в тот момент, стал ломать об него руки и ноги чисто с целью расширения кругозора, а вовсе не с точки зрения оптимизации, хотя на ус-таки намотал и этот момент.

Однако же не могу упустить момент пожаловаться на "switсh-case", который добавил мне головняка на днях...

Что бы не забредать в дебри - в двух словах:

Есть скетч-часы, время выставляется кнопками с пульта, кнопки прописаны в "#define", где им присваиваются совершенно отвольные значения, которые потом нигде не фигурируют и главное в каждом "#define"-е - только название самой кнопки. (Тут у меня закрадываются некоторые сомнения насчет этих названий: зачем им присваивать какие-то числа, по которым потом все равно не выполняются никакие проверки и эта величина нигде не используется? Неужели это нормально: объявить константу только ради самого имени? Возможно я чего-то недопонял или невнимательно изучил алгоритм, но по "CTRL+F" всё что я нашёл, это только "return btn_..." или "case btn_..." и ни слова о его значении). Так вот если одной из этих констант присвоить значение "ноль", то ваш любимый "switсh-case" обязательно считает что это событие уже настало! Но стоило мне убрать "0" из этой константы, как всё стало на свои места.

Ну и где тут, скажите, удобство и простота? Я чуть не тронулся, пока не убрал этот ноль из списка "#define"! И причем - совершенно случайно...

Tails_MP
Tails_MP аватар
Offline
Зарегистрирован: 11.11.2015
#include <TimeHelpers.h> //подключаем библиотеки
#include <class_BUTTON.h>
#include <DS3231.h>
#include <IRremote.h>

#define DS3231_ADDRESS 0x68
#define BLINK_INTERVAL 500
#define PRINT_INTERVAL _SEC_(1)
#define SERIAL_SPEED 9600
#define RECV_PIN 4 // IR приемник
#define OUT1 9// выхода на мосфеты
const int  buttonPin = 3; // кнопка включения с фиксацией
#define POWER_KEY 0xFF30CF // коды пульта ДУ
#define KEY1 0xFFA857 // v-
#define KEY2 0xFF28D7 // v+
byte analogData1 = 0; // значения аналогово выхода
uint32_t val; 
int buttonState = 0; //переменная состояния кнопки
int oldButtonState = 0; //переменная старое состояние кнопки
IRrecv irrecv(RECV_PIN);
decode_results results;

DS3231 rtc(SDA, SCL);
Time RTC_Time;

byte mon, date;  //переменные даты
byte second, minute, hour;   //переменные времени
byte decToBcd (byte val){return((val/10*16)+(val%10));}
byte bcdToDec(byte val){return ((val/16*10)+(val%16));}

int regim=1;   //режим отображения и установки

int flagRead=0;   //переменные для блинка

int h=0;   //переменные хранения часов и минут
int m=0;

int mo=0;   //переменные хранения месяца и числа
int da=0;

int latchPin = 11; //порты для вывода на регистры
int clockPin = 13;
int dataPin = 12;

BUTTON Set(5);   // объявляем объект класса BUTTON кнопку с именем Set, подключенную к пину 5.
BUTTON Up(6);    // объявляем объект класса BUTTON кнопку с именем Up, подключенную к пину 6.
BUTTON Down(7);  // объявляем объект класса BUTTON кнопку с именем Down, подключенную к пину 7.

   void setup(){
  irrecv.enableIRIn();  //запускаем ик
  Serial.begin(SERIAL_SPEED); //включаем сериал
  pinMode(buttonPin, INPUT); //кнопка как вход
  rtc.begin();
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

   void read_RTC(){   //чтение данных с RTC
      RTC_Time = rtc.getTime();
      mon = RTC_Time.mon;
      date = RTC_Time.date;
      hour = RTC_Time.hour;
      minute = RTC_Time.min;
      second = RTC_Time.sec;
   }

   void print_RTC(){   //показ времени
      read_RTC();
      read_Button();
      DO_EVERY(PRINT_INTERVAL,{
      Serial.print("regim - ");
     // Serial.println(regim);
      Serial.println(rtc.getTimeStr());
      });
      
      if(Set.retention){
         h=hour;   //присваиваем переменной значение часов
         m=minute;   //присваиваем переменной значение минут
        set_RTC();}   //переходим в режим установки
        
       if(Up.retention){
        mo=mon;
        da=date;
        set_Data();}
        
       if(Up.click_up){data();}
       
       if(Down.click_up){temp();}
       
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin,MSBFIRST, second);
      shiftOut(dataPin, clockPin,MSBFIRST, minute);
      shiftOut(dataPin, clockPin,MSBFIRST, hour);
      digitalWrite(latchPin, HIGH);
   }

   void read_Button(){   //чтение состояния кнопок
    Set.read();
    Up.read();
    Down.read();
   }



   void set_RTC(){   //установка RTC
      DO_EVERY(PRINT_INTERVAL,{
      Serial.println("set_RTC");
      });
      regim=2;


   while(regim==2){
    read_Button();
    DO_EVERY(PRINT_INTERVAL,{
    Serial.print("regim - ");
    //Serial.println(regim);
    Serial.print("часов - ");
    Serial.println(h);
    });
    blink_H(flagRead * 200);   //вызываем блинк ртс
    if (Up.click_down) {h++;   //увеличиваем часы
    if(h > 23)  {h = 0;}}      //если больше 23 переходим к 0
    if (Down.click_down) {h--;  //уменьшаем часы
    if(h < 0)  {h = 23;}}     //если меньше 0 переходим к 23

      if(Set.click_down){ //если нажать сет
      regim++;}   //прибавляем режим
      
    if(Set.retention){rec_RTC();} //удерживаем Set 3 сек. сохраняем время и выходим из режима установки

    if(Set.timer){Serial.println("Set не трогал 30 сек");}
    }

   while(regim==3){
    read_Button();
    DO_EVERY(PRINT_INTERVAL,{
    Serial.print("regim - ");
    //Serial.println(regim);
    Serial.print("минут - ");
    Serial.println(m);
    });
    blink_M(flagRead * 200);
    if (Up.click_down) {
      m++;
    if(m > 59)  {m = 0;}}
    if (Down.click_down) {
      m--;
    if(m < 0)  {m = 59;}}

    if(Set.click_down){
       regim--;
       set_RTC();
      }

    if(Set.retention){rec_RTC();}
    }

      
}   

   void rec_RTC(){   //запись данных в RTC
    rtc.setTime(h, m, 0);
    regim=1;
   }

   void blink_H(unsigned long interval){   //мигаем переменной часов в установке
    static unsigned long prevTime=0;
    if(millis() - prevTime > interval){
    static boolean flag = 0;
    prevTime = millis();
    flag =! flag;
    if(flag){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, second);
    shiftOut(dataPin, clockPin,MSBFIRST, m);
    shiftOut(dataPin, clockPin,MSBFIRST, h);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
    else{
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, second);
    shiftOut(dataPin, clockPin,MSBFIRST, m);
    shiftOut(dataPin, clockPin,MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
     }
    }
   }
  
   void blink_M(unsigned long interval){   //мигаем переменной минут в установке
    static unsigned long prevTime=0;
    if(millis() - prevTime > interval){
    static boolean flag = 0;
    prevTime = millis();
    flag =! flag;
    if(flag){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, second);
    shiftOut(dataPin, clockPin,MSBFIRST, m);
    shiftOut(dataPin, clockPin,MSBFIRST, h);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
    else{
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, second);
    shiftOut(dataPin, clockPin,MSBFIRST, 0);
    shiftOut(dataPin, clockPin,MSBFIRST, h);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
   }
  }




   void set_Data(){   //установка Даты
      DO_EVERY(PRINT_INTERVAL,{
      Serial.println("set_Data");
      });
      regim=2;


   while(regim==2){
    read_Button();
    DO_EVERY(PRINT_INTERVAL,{
    Serial.print("regim - ");
    //Serial.println(regim);
    Serial.print("месяц - ");
    Serial.println(mo);
    });
    blink_MO(flagRead * 200);   //вызываем блинк ртс
    if (Up.click_down) {mo++;   //увеличиваем часы
    if(mo > 12)  {mo = 1;}}      //если больше 23 переходим к 0
    if (Down.click_down) {mo--;  //уменьшаем часы
    if(mo < 1)  {mo = 12;}}     //если меньше 0 переходим к 23

      if(Set.click_down){ //если нажать сет
      regim++;}   //прибавляем режим
      
    if(Set.retention){rec_Data();} //удерживаем Set 3 сек. сохраняем время и выходим из режима установки

    if(Set.timer){Serial.println("Set не трогал 30 сек");}
    }

   while(regim==3){
    read_Button();
    DO_EVERY(PRINT_INTERVAL,{
    Serial.print("regim - ");
    //Serial.println(regim);
    Serial.print("число - ");
    Serial.println(da);
    });
    blink_DA(flagRead * 200);
    if (Up.click_down) {
      da++;
    if(da > 31)  {da = 1;}}
    if (Down.click_down) {
      da--;
    if(da < 1)  {da = 31;}}

    if(Set.click_down){
       regim--;
       set_Data();
      }

    if(Set.retention){rec_Data();}
    }
      
}

   void rec_Data(){   //запись данных в RTC
    rtc.setDate(da, mo, 2016);
    regim=1;
   }

    void blink_MO(unsigned long interval){   //мигаем переменной месяца в установке
    static unsigned long prevTime=0;
    if(millis() - prevTime > interval){
    static boolean flag = 0;
    prevTime = millis();
    flag =! flag;
    if(flag){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, da);
    shiftOut(dataPin, clockPin,MSBFIRST, mo);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;}
    
    else{
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, da);
    shiftOut(dataPin, clockPin,MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
   }
  }

    void blink_DA(unsigned long interval){   //мигаем переменной числа в установке
    static unsigned long prevTime=0;
    if(millis() - prevTime > interval){
    static boolean flagDA = 0;
    prevTime = millis();
    flagDA =! flagDA;
    if(flagDA){
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, da);
    shiftOut(dataPin, clockPin,MSBFIRST, mo);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
    else{
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin,MSBFIRST, 0);
    shiftOut(dataPin, clockPin,MSBFIRST, mo);
    digitalWrite(latchPin, HIGH);
    flagRead = 1;
    }
   }
  }



   void temp(){    //показ температуры
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin,MSBFIRST, 0);
        shiftOut(dataPin, clockPin,MSBFIRST, rtc.getTemp());
        shiftOut(dataPin, clockPin,MSBFIRST, 0);
        digitalWrite(latchPin, HIGH);
        Serial.println("Temp");
        Serial.println(rtc.getTemp());
        delay(2000);
        print_RTC();
   }

   void data(){     //показ даты (месяц. число.)
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin,MSBFIRST, 0);
        shiftOut(dataPin, clockPin,MSBFIRST, rtc.getTime().date);
        shiftOut(dataPin, clockPin,MSBFIRST, rtc.getTime().mon);
        digitalWrite(latchPin, HIGH);
        Serial.print("Data ");
        Serial.print(rtc.getTime().date);
        Serial.print(" - ");
        Serial.print(rtc.getTime().mon);
        Serial.print(" - ");
        Serial.println(rtc.getTime().year);
        delay(2000);
        print_RTC();
   }


   void lampa(){     //управление лампой
  buttonState = digitalRead(buttonPin);
 if (oldButtonState!=buttonState)
    {if(analogData1>0)
      {analogWrite(OUT1, 0);
        analogData1 = 0;}
      else{
        analogWrite(OUT1, 255);
        analogData1 = 255;}
      oldButtonState = buttonState;}
  if (irrecv.decode(&results)) { // если пришел пакет  
    if (results.value != 0xFFFFFFFF){ // и этот пакет не FF
      val = results.value; // сохраняем правельный пакет в переменную     
    }                 // если пришел FF, соответственно пропускаем.    
    /// сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
    /// в переменной останется прошлый, правельный, пакет и код выполнится повторно. 
    if (val == KEY1){      
       if (analogData1 != 0)analogData1 -=5; // если шим не равно 0 отнимаем 1 
       analogWrite(OUT1, analogData1);    // устанавливаем значение в выход     
    }    
     if (val == KEY2){ // и это вторая кнопка     
       if (analogData1 < 255) analogData1 +=5; // если шим меньше 255 прибовляем 1 
       analogWrite(OUT1, analogData1);  // устанавливаем значение 
    }
    if (results.value == POWER_KEY) {  
      if (analogData1 != 0){ // если ШИМ неравно 0
        analogWrite(OUT1, 0); // выключаем
        //наверно где то тут нужно отслеживать кнопку
        analogData1 = 0;
      }
      else {
        analogWrite(OUT1, 255); // включаем
       //наверно где то тут нужно отслеживать кнопку
        analogData1 = 255;
      }       
     }  
Serial.println(val, HEX); //// ТЕСТЫ!
Serial.println(results.value, HEX); 
Serial.println(analogData1); 
Serial.println();
//Serial.print("положение кнопки ");
//Serial.println(buttonState);
irrecv.resume(); 
   }
  }


   void loop() {

   if(regim==1){print_RTC();}
   lampa();
   
  }