Gроект для аквариума (акваконтроллер для led, temp, time, co2)

Thorn
Offline
Зарегистрирован: 07.11.2014

Ну вот я и затупил. Таймер обрабатывает вкл\выкл ВСЕ 3 канала реле ОТЛИЧНО, часики идут. А вот диммирование никак. Я вставил в результат функции:

if((isLght1 == 1) && (lghtStat1 == 0)) {   //если свет еще не включен и выставлен флаг необходимости включить
       lghtStat1 = 1;
       digitalWrite(OUT1, LOW);       //собственно, включаем подавая высокий уровень на вывод
      if (tDimm < millis()) {
      periodManualDimm = 500; dimmUp();        //Интервал УВЕЛИЧЕНИЯ диммирования
       }
        lcd.setCursor(1, 3);
        lcd.print(!digitalRead(OUT1));

самую НУЖНУЮ функцию dimmUp(); - а она нехочет диммировать. Тупо включает реле, значение диммирования = 1 и все, далее нерастёт. Может я нетак прописал выполнение? Скорее всего да. Выручайте ...

Thorn
Offline
Зарегистрирован: 07.11.2014

Здрасти форумане. Жаль последний мой пост остался без вашего ответа :(, ушло дня три пока победил.

Наконец-то приехали вчера  часики RTC на ds3231. Подключал стандартно (по sda, scl, vcc, gnd). Заменил свои ПРОГРАМНЫЕ часики (которые кстати за 12 часов отставали на 16 минут !!!! :) ну это несильно мешало им обслуживать релюшки и прочее. Та к вот, уход сверхточных часов на ds3231 у меня сейас составляет ровно 10 сек за 12 часов. Код использовал для работы с ними такой:

//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104
byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];
byte tMSB, tLSB;
float temp3231;
long tmIntv = 1000;               //Интервал для обновления времени на экране каждую секунду
long prvMlsTm = 0;                //Предыдущее показание миллисекунд для обновления показания часов
long prvMlsLght = 0;              //Предыдущее показание проверки временного интервала

void setup() {
  Wire.begin();
    Wire.beginTransmission(DS3231_I2C_ADDRESS);  // 104 is DS3231 device address
    Wire.write(0x0E); //                         //set control register to output square wave on pin 3 at 1Hz
    Wire.write(B00000000);
    Wire.write(B10001000);
    Wire.endTransmission();
}

//=========== Обработка RTC часов
void timeRtc(){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);     //104 is DS3231 device address
  Wire.write(0x00);                               //Start at register 0
  Wire.endTransmission();                         //Send request to receive data starting at register 0
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);        //Request seven bytes

  if(Wire.available()) { 
    seconds = Wire.read();       //Get seconds
    minutes = Wire.read();       //Get minutes
    hours   = Wire.read();       //Get hours
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read();       //Get month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  
  switch (day) {
    case 1:
      strcpy(weekDay, "Sun");
      break;
    case 2:
      strcpy(weekDay, "Mon");
      break;
    case 3:
      strcpy(weekDay, "Tue");
      break;
    case 4:
      strcpy(weekDay, "Wed");
      break;
    case 5:
      strcpy(weekDay, "Thu");
      break;
    case 6:
      strcpy(weekDay, "Fri");
      break;
    case 7:
      strcpy(weekDay, "Sat");
      break;
  }
    unsigned long currentMillis = millis();
      if(currentMillis - prvMlsTm > tmIntv) {  //Проверяем интервал для обновления часов
    prvMlsTm = currentMillis;                  //Вызываем ф-цию вывода времени на экран
  lcd.setCursor(0, 0); 
 /*
 lcd.print(month); 
 lcd.print("/"); 
 if (month==1){lcd.print ("Jan");} 
 if (month==2){lcd.print ("Feb");} 
 if (month==3){lcd.print ("Mar");} 
 if (month==4){lcd.print ("Apr");} 
 if (month==5){lcd.print ("May");} 
 if (month==6){lcd.print ("Jun");} 
 if (month==7){lcd.print ("Jul");} 
 if (month==8){lcd.print ("Aug");} 
 if (month==9){lcd.print ("Sep");} 
 if (month==10){lcd.print ("Oct");} 
 if (month==11){lcd.print ("Nov");} 
 if (month==12){lcd.print ("Dec");} 
 lcd.print("/"); 
 lcd.print(year+2000); 
 if (weekDay==0){lcd.print ("Sun.");} 
 if (weekDay==1){lcd.print ("Mon.");} 
 if (weekDay==2){lcd.print ("Tue.");} 
 if (weekDay==3){lcd.print ("Wed.");} 
 if (weekDay==4){lcd.print ("Thu.");} 
 if (weekDay==5){lcd.print ("Fri.");} 
 if (weekDay==6){lcd.print ("Sat.");} 
 */
 if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);} 
 lcd.print(":"); 
 if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);} 
 lcd.print(":"); 
 if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);}
}
/*
   counter=!counter;
   if (counter==false){
   seconds ++;  //Переменная секунда + 1

     lcd.setCursor(2,0);
     lcd.print(":");                  //Выводим символ ":" между часами и минутами
     lcd.setCursor(5,0);
     lcd.print(":");                  //Выводим символ ":" между минутами и секундами
   } else {
     lcd.setCursor(2,0);
     lcd.print(" ");                  //Мигание ":"
     lcd.setCursor(5,0);
     lcd.print(" ");                  //Мигание ":"
   }  
*/ 
}
///=========== Обработка RTC температуры 
void tempRtc() {
   unsigned long currentMillis = millis();
      if(currentMillis - prvMlsTemp > tempIntv){     //Проверяем интервал для обновления температуры
    prvMlsTemp = currentMillis;
  lcd.setCursor(15, 1);
  lcd.print(get3231Temp());
    }
  }
  float get3231Temp() {                //temp registers (11h-12h) get updated automatically every 64s
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if(Wire.available()) {
    tMSB = Wire.read();                 //2's complement int portion
    tLSB = Wire.read();                 //fraction portion
    temp3231 = (tMSB & B01111111);      //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  return temp3231;
}

void loop(){
    timeRtc();
    tempRtc();
}

В коде я пока оставил кусок для работы с датой , таймер вобщем то работает во все дни одинаково но вдруг захочу изменить расписание по дням. Кстати ругается в таком виде на строку if (weekDay==1){lcd.print ("Mon.");}  вот так "ISO C++ forbids comparison between pointer and integer" - я так понял что нетак задан вывод на lcd

Господа, ОЧЕНЬ прошу подсказать что делать с коррекцией хода сверточных часов - у всех не более 15 сек в месяц (если верить ГУГЛУ) и с weekDay - как описать правильный вывод. Спасибо.

Кстати весь свой проект я позже выложу в фото тут и на аквафоруме, пока вот так:

 

bwn
Offline
Зарегистрирован: 25.08.2014

С прошедшими, я чет загулял. Вы не пробовали чисто со стандартным скетчем RTC без коррекций и посмотреть за сутки?

Thorn
Offline
Зарегистрирован: 07.11.2014

Thorn пишет:

Кстати весь свой проект я позже выложу в фото тут и на аквафоруме, пока вот так:

Чтото затупил с вложением, вот:

Почти готовая компоновка

и вот:

На банке, &quot;антенка&quot; Ir

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

С прошедшими, я чет загулял. Вы не пробовали чисто со стандартным скетчем RTC без коррекций и посмотреть за сутки?

Согласится немогу, праздники были весьма кстати и плодотворными, однако с наступающим Вас Старым Новым Годом!

Библотеку нашёл самую свежую для ds3231 оттуда и брал пример:

// DS3231_Serial_Easy (C)2014 Henning Karlsen
// web: http://electronics.henningkarlsen.com/
//
// A quick demo of how to use my DS3231-library to 
// quickly send time and date information over a serial link
//
// To use the hardware I2C (TWI) interface of the Arduino you must connect
// the pins as follows:
//
// Arduino Uno/2009:
// ----------------------
// DS3231:  SDA pin   -> Arduino Analog 4 or the dedicated SDA pin
//          SCL pin   -> Arduino Analog 5 or the dedicated SCL pin
//
// Arduino Leonardo:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 2 or the dedicated SDA pin
//          SCL pin   -> Arduino Digital 3 or the dedicated SCL pin
//
// Arduino Mega:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA pin
//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL pin
//
// Arduino Due:
// ----------------------
// DS3231:  SDA pin   -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin
//          SCL pin   -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin
//
// The internal pull-up resistors will be activated when using the 
// hardware I2C interfaces.
//
// You can connect the DS3231 to any available pin but if you use any
// other than what is described above the library will fall back to
// a software-based, TWI-like protocol which will require exclusive access 
// to the pins used, and you will also have to use appropriate, external
// pull-up resistors on the data and clock signals.
//

#include <DS3231.h>

// Init the DS3231 using the hardware interface
DS3231  rtc(SDA, SCL);

void setup()
{
  // Setup Serial connection
  Serial.begin(9600);
  // Uncomment the next line if you are using an Arduino Leonardo
  //while (!Serial) {}
  
  // Initialize the rtc object
  rtc.begin();
  
  // The following lines can be uncommented to set the date and time
  //rtc.setDOW(WEDNESDAY);     // Set Day-of-Week to SUNDAY
  //rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
  //rtc.setDate(1, 1, 2014);   // Set the date to January 1st, 2014
}

void loop()
{
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.println(rtc.getTimeStr());
  
  // Wait one second before repeating :)
  delay (1000);
}

Но с ней непробовал мониторить, мне как попался код БЕЗ использования #include <DS3231.h> я сразу за него и зацепился. Кстати стандарный код что я указал выше:  Размер скетча в двоичном коде: 7 312 байт (из 258 048 байт максимум)

А тот что я нашёл у нас на форуме

вот: 

#include <Wire.h>

#define DS3231_I2C_ADDRESS 104

byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];

byte tMSB, tLSB;
float temp3231;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  //set control register to output square wave on pin 3 at 1Hz
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(0x0E); // 
  Wire.write(B00000000);
  Wire.write(B10001000);
  Wire.endTransmission();
  //RTC.adjust(DateTime(__DATE__, __TIME__));
}

void loop() {
  
  watchConsole();
  
  
  get3231Date();
  
  Serial.print(weekDay); Serial.print(", "); Serial.print(month, DEC); Serial.print("/"); Serial.print(date, DEC); Serial.print("/"); Serial.print(year, DEC); Serial.print(" - ");
  Serial.print(hours, DEC); Serial.print(":"); Serial.print(minutes, DEC); Serial.print(":"); Serial.print(seconds, DEC);
  
  Serial.print("   Temperature: "); Serial.print(get3231Temp());Serial.print("; ");Serial.println(get3231Register(0x0F));

  delay(1000);
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

void watchConsole()
{
  if (Serial.available()) {      // Look for char in serial queue and process if found
    if (Serial.read() == 84) {      //If command = "T" Set Date
      set3231Date();
      get3231Date();
      Serial.println(" ");
    }
  }
}
  
void set3231Date()
{ 
//T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
//T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
//Example: 02-Feb-09 @ 19:57:11 for the 3rd day of the week -> T1157193020209
//Example: 01-Jan-15 @ 17:12:45 for the 6rd day of the week -> T451217610015

  seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
  minutes = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hours   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  day     = (byte) (Serial.read() - 48);
  date    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.write(decToBcd(seconds));
  Wire.write(decToBcd(minutes));
  Wire.write(decToBcd(hours));
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

byte get3231Register(byte regNo) {
  // send request to receive data starting at register regNo
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(regNo); // start at register regNo
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 1); // request one byte
  if(Wire.available()) return  Wire.read();
}

void set3231Register(byte regNo, byte value) { 
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(regNo);
  Wire.write(value);
  Wire.endTransmission();
}

void get3231Date()
{
  // send request to receive data starting at register 0
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(0x00); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes

  if(Wire.available()) { 
    seconds = Wire.read(); // get seconds
    minutes = Wire.read(); // get minutes
    hours   = Wire.read();   // get hours
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read(); //temp month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  else {
    //oh noes, no data!
  }
  
  switch (day) {
    case 1:
      strcpy(weekDay, "Sun");
      break;
    case 2:
      strcpy(weekDay, "Mon");
      break;
    case 3:
      strcpy(weekDay, "Tue");
      break;
    case 4:
      strcpy(weekDay, "Wed");
      break;
    case 5:
      strcpy(weekDay, "Thu");
      break;
    case 6:
      strcpy(weekDay, "Fri");
      break;
    case 7:
      strcpy(weekDay, "Sat");
      break;
  }
}

float get3231Temp()
{
  //temp registers (11h-12h) get updated automatically every 64s
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  
  if(Wire.available()) {
    tMSB = Wire.read(); //2's complement int portion
    tLSB = Wire.read(); //fraction portion
    
    temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  else {
    //oh noes, no data!
  }
    
  return temp3231;
}

 и решил его поюзать:  Размер скетча в двоичном коде: 9 624 байт (из 258 048 байт максимум) 

и это с температурой, настройками, таймерами его.

Thorn
Offline
Зарегистрирован: 07.11.2014

Кстати а как мне полностью "обрезать" термокоррекцию в моём коде? Я же вынес измерение температуры и времени по ds3231 в разные функции. И да. Я имел ввиду уход за 12 часов это: ВЫКЛЮЧЕНИЕ ардуино и внешнего питания с RTC модуля и включение всего этого хозяйства через 12 часо. И тут опачки сравниваю со временем на PC (его я синхронизировал с NTP на момент установки времени в RTC) в обоих случаях, тоесть время на PC принимаем за эталон (NTP я делал даже принудительно!) и вот... разница в 10сек вперед на RTC. Я-бы понял если бы эти 12 часов ардуинка выводила показания, вобщем делала свои расчёты и выполняла цикл но нет.

bwn
Offline
Зарегистрирован: 25.08.2014

Thorn пишет:

Кстати а как мне полностью "обрезать" термокоррекцию в моём коде? Я же вынес измерение температуры и времени по ds3231 в разные функции. И да. Я имел ввиду уход за 12 часов это: ВЫКЛЮЧЕНИЕ ардуино и внешнего питания с RTC модуля и включение всего этого хозяйства через 12 часо. И тут опачки сравниваю со временем на PC (его я синхронизировал с NTP на момент установки времени в RTC) в обоих случаях, тоесть время на PC принимаем за эталон (NTP я делал даже принудительно!) и вот... разница в 10сек вперед на RTC. Я-бы понял если бы эти 12 часов ардуинка выводила показания, вобщем делала свои расчёты и выполняла цикл но нет.

Мдя, тогда мою задумку не подтверждает. Люди их хвалили, а получается с DS1307 никакой разницы(((.

А термокоррекция в каком из кодов?

Thorn
Offline
Зарегистрирован: 07.11.2014

Чуток упростил код до:

#define DS3231_I2C_ADDRESS 104 
byte seconds, minutes, hours, day, date, month, year;

void setup() {
  Wire.begin();
}

void timeRtc(){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);       //104 is DS3231 device address
  Wire.write(0x00);                                 //Start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);          //Request seven bytes
      if(Wire.available()) { 
    seconds = Wire.read();                           //Get second
    minutes = Wire.read();                           //Get minute
    hours   = Wire.read();                           //Get hour
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read();                          //Get month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111));  //Convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111));      //Convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111));     //Convert BCD to decimal  1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111));   //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  lcd.setCursor(0, 0);
 if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);} 
 lcd.print(":"); 
 if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);} 
 lcd.print(":"); 
 if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);} 
} 

void loop(){
    timeRtc();
}

Как видно я выкинул из setup ВСЁ. и получения показаний перенс в саму функцию timeRtc()

Я так понимаю ранее в setup() я вызывал ВСЮ шину адресную для ds3231 где и таймеры и температура и прочее а теперь токма адрес времени (даты).

Также победил вывод корректно даты дня недели.

Пока за 2,5 часа мониторинга :)) убеганий и наоборот нету. 

Господа, мне осталось лиш чуть чуть до МЕНЮ :) и НАСТРОЕК  этого в EPROM. Небудьте безучастны! Сколько курил форум - вашими советами можно иногда запускать спутники, без шуток.

Thorn
Offline
Зарегистрирован: 07.11.2014

А может "севший" элемент питания для RTC быть проблеммой "убегания"? Счас измерил его - 2,96В Свеженького нет. воткнул чтоб ыло, выходит менее 3,3В

Thorn
Offline
Зарегистрирован: 07.11.2014

Гм, сейчас что то было. Итак замерил я напряжение, вставил назад, подозрительно замигал Led Power на модуле RTC, пошевелил провода (в ардуинку тупо воткнуты, в монтажную - не в рабочуу на аквариуме) и что выдумаете помойму gnd плохо сидел и в какойт омомент херак и часики на 00-00-00 посбросили всё. Проверил и Serial и в скетче - пусто, пришлось заново время устанавливать. Так вот - немог ли какой плохой контак, или мой кот пока ардуинка лежала ночью тихо спала выдать такую оказию?

Вобщем пока много переменных и нельзя уверенно заявитть - что у меня неточный "модуль"

bwn
Offline
Зарегистрирован: 25.08.2014

Thorn пишет:

Гм, сейчас что то было. Итак замерил я напряжение, вставил назад, подозрительно замигал Led Power на модуле RTC, пошевелил провода (в ардуинку тупо воткнуты, в монтажную - не в рабочуу на аквариуме) и что выдумаете помойму gnd плохо сидел и в какойт омомент херак и часики на 00-00-00 посбросили всё. Проверил и Serial и в скетче - пусто, пришлось заново время устанавливать. Так вот - немог ли какой плохой контак, или мой кот пока ардуинка лежала ночью тихо спала выдать такую оказию?

Вобщем пока много переменных и нельзя уверенно заявитть - что у меня неточный "модуль"

По идее все эти бяки могут бытьтолько при подключенном питании (не резерв). Если батарею шевельнуть, опять вылетят на ноль, но не 10 секунд???. Напряжение если это не аккумулятор правильное.

bwn
Offline
Зарегистрирован: 25.08.2014

А вы напряжение меряли - вынимали батарею? Если да, то должна была сбросить. Основное питание не есть замена резерву, по крайней мере на 1307.

bwn
Offline
Зарегистрирован: 25.08.2014

Thorn пишет:

Кстати а как мне полностью "обрезать" термокоррекцию в моём коде? Я же вынес измерение температуры и времени по ds3231 в разные функции. И да. Я имел ввиду уход за 12 часов это: ВЫКЛЮЧЕНИЕ ардуино и внешнего питания с RTC модуля и включение всего этого хозяйства через 12 часо. И тут опачки сравниваю со временем на PC (его я синхронизировал с NTP на момент установки времени в RTC) в обоих случаях, тоесть время на PC принимаем за эталон (NTP я делал даже принудительно!) и вот... разница в 10сек вперед на RTC. Я-бы понял если бы эти 12 часов ардуинка выводила показания, вобщем делала свои расчёты и выполняла цикл но нет.

В коде 2, 105пост, это не термокоррекция, а скорее температура самой мелкосхемы. Думаю можно просто выкинуть этот кусок и обращения к этой функции.

А время потом сверяли с компьютером или новым NTP?

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

А время потом сверяли с компьютером или новым NTP?

Время сверял с PC который предварительно был "вручную" обновлён по серверу NTP. Вобщем проблемма за сегодня ушла, нет даже долей секунды (на глаз :) конечное) опережения или отставания. Мне кажется это проблеммы с "ОЧЕНЬ" хреновм контактом, все протсо воткнуто прямо в штырьки ли разъёмики ардуинки, ну вобщем по три провода в vcc и по 4в один gnd? что то вышло что то отошло. может sda с scl повели себя как то в момент "недоконтакта" однако прецендент был. 

 несмотря на это я распаивал сам модуль RTC сегодня с подключенной батареей и настроенным временем. Выпаля родные 6 штырьков и с обратной стороны припаял к монтажной плате моего блока управления аквариумом. При этом все завелось сразу. 

На сегодня есть немного проблемм, некоторые весьма.  Первая суточный таймер, с одним расписанием всё пучком, скопипастил его и настроил на "вечернее" время и всё зациклилось. Начинается диммированиеdimmUp доходит до 255 и тут-же начинается снижение dimmDown. Пришлось на врмея оставить одно расисание. Вот кусок для него:

//=====Timer*
//    long lghtIntv = 60000;            //Интервал для проверки включения/выключения освещения аквариума, 1 минута
byte lcdStat = 0;                //Флаг подсветки Lcd если включена, то в 1
byte lghtStat = 0;               //Флаг освещения, Реле Dimm, если включена, то в 1
byte co2Stat = 0;                //Флаг Co2, Реле, если включена, то в 1
byte upLghtTime1 = 07;            //Флаг включаения, Реле Dimm, в 5 утра
byte downLghtTime1 = 12;          //Флаг выключаения, Реле Dimm, в 10 вечера
byte upLghtTime2 = 19;            //Флаг включаения, Реле Dimm, в 5 утра
byte downLghtTime2 = 22;          //Флаг выключаения, Реле Dimm, в 10 вечера
byte upCo2Time = 08;            //Флаг включаения, Реле Co2, в 7 утра
byte downCo2Time = 23;          //Флаг выключаения, Реле Co2, в 17 вечера
byte upLsdTime = 6;             //время включения подсветки LCD
byte downLsdTime = 23;          //время выключения подсветки LCD
byte isNight = 0;                //Если включаем на ночь, т.е. начальное время больше конечного
byte prevSec = 0;                //Предыдущее показание секунд для перезапуска если остановились
byte isLcdt = 0;                 //Флаг для обработки необходимости включить подсветку Lcd
byte isLght = 0;                 //Флаг для обработки необходимости включить реле освещения на 1 канале
byte isCo2t = 0;                 //Флаг для обработки необходимости включить реле Co2

//=========== Обработка Таймеров
/void timer(){                            //Включаем/выключаем освещение аквариума и СО2
//========== Таймер №1  
      if (upLghtTime1 > downLghtTime1){  //Если ночное время
    isNight = 1;
    }
    if (isNight == 0){                   //Если день
    if (hours >= upLghtTime1 && hours < downLghtTime1){           //Проверяем интервал
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
    }
  } else {                               //Если ночь
      if(hours - upLghtTime1 >= 0){        //Если больше или равно верхнему значению, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
      if(hours < downLghtTime1){           //Если меньше нижнего значения, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isLght == 1) && (lghtStat == 0)){   //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm){             //Ограничение верхнего значения диммирования, (0-255)
    lghtStat = 1;
  }
  } else {
      if(isLght == 0 && lghtStat == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){                  //Ограничение нижнего значения диммирования, (0-255)
    lghtStat = 0;
    }
  }
  }
//========== Таймер №2  
      if (upLghtTime2 > downLghtTime2){  //Если ночное время
    isNight = 1;
    }
    if (isNight == 0){                   //Если день
    if (hours >= upLghtTime2 && hours < downLghtTime2){           //Проверяем интервал
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
    }
  } else {                               //Если ночь
      if(hours - upLghtTime2 >= 0){        //Если больше или равно верхнему значению, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
      if(hours < downLghtTime2){           //Если меньше нижнего значения, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isLght == 1) && (lghtStat == 0)){   //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm){             //Ограничение верхнего значения диммирования, (0-255)
    lghtStat = 1;
  }
  } else {
      if(isLght == 0 && lghtStat == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){                  //Ограничение нижнего значения диммирования, (0-255)
    lghtStat = 0;
    }
  }
  }  

Теперь непонятное явление с аналоговым выходом analogData2. Вот кусочек кода:

void dimmDown(){
      if (analogData2 > 0) {
    analogData2 --;  //Начало снижения диммирования 
    analogData1 --;
    analogWrite(OUT4,analogData2);
    analogWrite(OUT5,analogData1); 
      if (analogData2 == downR3){                  //Выключаем Третье реле при downR3
    digitalWrite(OUT3,HIGH);
  }
      if (analogData2 == downR2){                  //Выключаем Втором реле при downR2
    digitalWrite(OUT2,HIGH); 
  }
      if (analogData2 == 0){                       //Выключаем реле диммера (по окончании диммирования)
    digitalWrite(OUT0,HIGH);
    digitalWrite(OUT1,HIGH);
    digitalWrite(OUT2,HIGH);
    digitalWrite(OUT3,HIGH);
  }
  tDimm=millis() + pManDimmDown;                    //Устанавливаем время следующего шага
  }
}

так вот при достижении (analogData2 == 0) и выключении всех реле (обесточивании 12в части) происходит вспышка равная (analogData2 == 255) Почему так? 

Ну и третье, больше техническое, реле что включают Led нагреваются до 45-50градусов (даже на ввремя вывел на них запасной ds18b20 хотя там токи не более7-8А а по даташиту релюшки аж 10А и драйвера на pt5115 (примерное 25 штук из 30) воют, несильно но напряжно и воют начиная с 1 и до 255, при максимуме - тишина, толи в них проблема толи в PWM арудуинки .

Вобщем так. Подскажите какое ваше мнение?

bwn
Offline
Зарегистрирован: 25.08.2014

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

Раньше эта вспышка была? Она происходит в момент сработки реле?

А вот с релюшками я думаю проблема и сильная (если только напряжение питания не попутали). Не должны они так грется. Кстати проверьте без нагрузки.

Драйвера  имеют трансформатор и он поет с частотой PWM. Здесь вряд ли чего сделаете.

bwn
Offline
Зарегистрирован: 25.08.2014

По второму коду, в строках 7 и 10 я бы поставил меньше или равно, 16, 17 вообще бы убрал. А так по программе вроде не должно мигать.

А что у нас в это время делают OUT4 и OUT5 ?

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

Раньше эта вспышка была? Она происходит в момент сработки реле?

Ранее была но непридавал значения, все происходило пока "нас нет" :) а тут праздники и все уже не на модели со светиками в 40мА а с серьёзными токами и вот. Мне кажется нужно снимать напряжение с реле пока analogData2 не менее 1. Тоесть выключаем реле при минимимнимальном освещении, в любом случае есть порожки от 0 до 7-9 гдето кстати.

bwn пишет:

А вот с релюшками я думаю проблема и сильная (если только напряжение питания не попутали). Не должны они так грется. Кстати проверьте без нагрузки.

Греются именно сильноТОКОВЫЕ OUT1,2,3 на которых ток до 7-9А (греются не катушки трансформаторов а видимо сами лепестки механические, кстати дорожки на платах которыми они управляют в нагрузке толщиной не более 0,25мм при ширине в 2,5мм - это для тока в 10А заявленных явно перебор. Вобщем либо делить нагрузку есчо в половину либо более силовые реле.

bwn пишет:

Драйвера  имеют трансформатор и он поет с частотой PWM. Здесь вряд ли чего сделаете.

Да поют именно дрсселя в цепи, хорошо что у меня диммируется всего 10 из 30 (чесно хватило бы и 5-ти для мягкого света) но снова переделывать СИЛОВУЮ часть где провода в 6квадратов!!! ну вы поняли.

bwn
Offline
Зарегистрирован: 25.08.2014

Получается какой то переходной процесс в момент отключения. Здесь уже только вы сами сможете поэкспериментировать.

Ну как вариант, контакторы после реле. Шилды я думаю все из той же оперы.

По ШИМу можно попробовать поменять частоту на более комфортную, но там вопрос как себя поведут драйверы. На дуине стандартный ШИМ - 490Гц

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

По второму коду, в строках 7 и 10 я бы поставил меньше или равно, 16, 17 вообще бы убрал. А так по программе вроде не должно мигать.

А что у нас в это время делают OUT4 и OUT5 ?

ООО тут у меня ИЗУМИТЕЛЬНАЯ темка получилась. Так как я питаю всё LED диоды с током в 22-24А и напряжением 12В, саму ардуинку, дисплей и прочие мелочи 5В. И ту я думаю - а зачем мне нужен вообще стартовый таймер (которым я включаю ИБП от ПК) у него же есть +5VSB с током до 2А которые есть даже если незамкнута (черно-зелёная) цепь и вото оно, я добавляю ещё одно реле, которое и замыкает цепь запуска ИБП оно всегда срабатывает первым и выключается последним, и на сегодня у меня есть и 5В и 3,3В (на случай какого датчика с низким напряжением без стабилизатора) и 12В.

А вот OUT4, 5 - это АНАЛОГОВЫЕ выходы analogData1 и 2. Просто разделил 10 светиков по 5+5 и на каждый по димимрованию, оно синхронное просто вдруг тока ардуинки будет недостаточно диммировать сразу 10 штук (диммирую напрямую без всяких транзисторов и ключей с подтяжками) даташит pt4115 это ПОЗВОЛЯЕТ!!!

OUT6,7 пока мирно спят они для вентиляторов радиатора LED и воды в банке. Зимой неактуально сильно.Вода после перехода с Т5 негреется абсолютно и равна +24,5....25,5град. а радиаторы светиков невыше 48град

bwn
Offline
Зарегистрирован: 25.08.2014

Просто в том куске кода неявно, что analogData1 и 2 равны друг другу. Я и подумал, что может там что то колбасит.

А если просто подать на драйвер analogData1=0; и разомкнуть цепь его питания выключателем, что будет?

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

А если просто подать на драйвер analogData1=0; и разомкнуть цепь питания выключателем, что будет?

А вот таким способом я и искал "гудящие" драйвера, включил одну линию в 10 светиков и установив на analogData2 ==1 присоединял поочереди, они мгновенно гасли (почти в ноль, на самом деле шажок есть) и слышался гул дросселя, так я и нашёл 7 более-менее тихих и 3 приемлемо тихих. При этом если подать analogData2 ==0 то ледик просто гас полностью и без звука, разъединял цепь и он снова загорался. Что то мне кажется или во времени срабатывания реле или в объявлении пинов. Аналоговые выходы я объявил так:

#define OUT4 5                      //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6                      //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)

void setup() {
analogWrite(OUT4,analogData2);                      //Инициация выхода 1/2 диммера
analogWrite(OUT5,analogData1);                      //Инициация выхода 1/2 диммера
}

Можетсделать задержку какую после analogData1, 2 ==0

типа как в считывании показаний с Dallasa: tzad=millis() + 750;

пробовал - всерано реле срабатывает синхронно с analogData - видимо коряво описал задержку

bwn
Offline
Зарегистрирован: 25.08.2014

Так вспышка при этом была или нет?

Thorn
Offline
Зарегистрирован: 07.11.2014

Нет тото и оно, она есть когда или "ручное" диммирование - удержанием кнопки с пульта или"автоматическое" по dimmerDown - они вобщем то одинаковы за исключением что в ручном нет периода снижения (с 255 до 0) там сколько держиш столько и снижает. Но при аналоге ==0 и digitalOUT1,2,3 HIGH (оноже выкл) происходит вспышка - очень быстрая и рыбок ненапрягает, да и меня тоже если это програмно а вот когда я вручную включаю и диммирую свет для создания атмосферы вечером то напрягает.

bwn
Offline
Зарегистрирован: 25.08.2014

Попробуйте 114 пост, второй кусок, между строками 6 и 7 вставить Serial.println(analogData2,DEC); и помониторить, что там происходит в цикле. Интересует последнее значение.

Thorn
Offline
Зарегистрирован: 07.11.2014

bwn пишет:

Попробуйте 114 пост, второй кусок, между строками 6 и 7 вставить Serial.println(analogData2,DEC); и помониторить, что там происходит в цикле. Интересует последнее значение.

Логичнее вставить между 13 и 14 строками когда analog==0 и выключаются реле. В лбом случае мой serial.print выдавал мне значения от byte maxDimm = 255; (максимального значнеия диммирования -1) тоесть от 254 и вниз до 0

Думаю пока оставим это, попробую вечером выставить в коде так:

if (analogData2 == 1){      //Выключаем реле диммера (по окончании диммирования)
digitalWrite(OUT0,HIGH);
digitalWrite(OUT1,HIGH);
digitalWrite(OUT2,HIGH);
digitalWrite(OUT3,HIGH);
}

А помогите мне для начала с настройками в меню времени включения и выключения, вот в самом простом виде пока с записье в EPROM и раз уж об этом заговорили как мне задавать и ЧАСЫ и МИНУТЫ при запуске таймеров. Счас могу использовать что то одно:(.

Вот кусочек кода для таймера. пока с одним расписанием, потом скопипастю и сделаю второе:

//Это оъявление переменных
//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104 
byte seconds, minutes, hours, day, date, month, year;
long tmIntv = 1000;               //Интервал для обновления времени на экране каждую секунду
long prvMlsTm = 0;                //Предыдущее показание миллисекунд для обновления показания часов
long prvMlsLght = 0;              //Предыдущее показание проверки временного интервала
//=====Timer*
//    long lghtIntv = 60000;            //Интервал для проверки включения/выключения освещения аквариума, 1 минута
byte lcdStat = 0;                //Флаг подсветки Lcd если включена, то в 1
byte lghtStat = 0;               //Флаг освещения, Реле Dimm, если включена, то в 1
byte co2Stat = 0;                //Флаг Co2, Реле, если включена, то в 1
byte upLghtTime1 = 7;            //Флаг включаения, Реле Dimm, в 7 утра
byte downLghtTime1 = 12;          //Флаг выключаения, Реле Dimm, в 12 дня
byte upLghtTime2 = 19;            //Флаг включаения, Реле Dimm, в 19 вечера
byte downLghtTime2 = 22;          //Флаг выключаения, Реле Dimm, в 22 вечера
byte upCo2Time = 10;            //Флаг включаения, Реле Co2, в 10 утра
byte downCo2Time = 22;          //Флаг выключаения, Реле Co2, в 22 вечера
byte upLsdTime = 6;             //время включения подсветки LCD
byte downLsdTime = 23;          //время выключения подсветки LCD
byte isNight = 0;                //Если включаем на ночь, т.е. начальное время больше конечного
byte prevSec = 0;                //Предыдущее показание секунд для перезапуска если остановились
byte isLcdt = 0;                 //Флаг для обработки необходимости включить подсветку Lcd
byte isLght = 0;                 //Флаг для обработки необходимости включить реле освещения на 1 канале
byte isCo2t = 0;                 //Флаг для обработки необходимости включить реле Co2

//И собственно функция таймера
void timer(){                            //Включаем/выключаем освещение аквариума и СО2
//========== Таймер №1  
      if (upLghtTime1 > downLghtTime1){  //Если ночное время
    isNight = 1;
    }
    if (isNight == 0){                   //Если день
    if (hours >= upLghtTime1 && hours < downLghtTime1){           //Проверяем интервал
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
    }
  } else {                               //Если ночь
      if(hours - upLghtTime1 >= 0){        //Если больше или равно верхнему значению, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
      if(hours < downLghtTime1){           //Если меньше нижнего значения, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isLght == 1) && (lghtStat == 0)){   //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm){             //Ограничение верхнего значения диммирования, (0-255)
    lghtStat = 1;
  }
  } else {
      if(isLght == 0 && lghtStat == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){                  //Ограничение нижнего значения диммирования, (0-255)
    lghtStat = 0;
    }
  }
  }
//========== Таймер №2  
      if (upLghtTime2 > downLghtTime2){  //Если ночное время
    isNight = 1;
    }
    if (isNight == 0){                   //Если день
    if (hours >= upLghtTime2 && hours < downLghtTime2){           //Проверяем интервал
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
    }
  } else {                               //Если ночь
      if(hours - upLghtTime2 >= 0){        //Если больше или равно верхнему значению, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
      if(hours < downLghtTime2){           //Если меньше нижнего значения, то необходимо включить свет
    isLght = 1;                          //Если необходимо включить свет
  } else {
    isLght = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isLght == 1) && (lghtStat == 0)){   //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm){             //Ограничение верхнего значения диммирования, (0-255)
    lghtStat = 1;
  }
  } else {
      if(isLght == 0 && lghtStat == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){                  //Ограничение нижнего значения диммирования, (0-255)
    lghtStat = 0;
    }
  }
  }  
 
//========== Реле CO2   

      if (lcdLghtOn > lcdLghtOff){        //Если ночное время
    isNight = 1;
  }
      if (isNight == 0){                   //Если день
      if (hours >= upCo2Time && hours < downCo2Time){           //Проверяем интервал
    isCo2t = 1;                          //Если необходимо включить подачу CO2
  } else {
    isCo2t = 0;
    }
  } else {                              //Если ночь
      if(hours - upCo2Time >= 0){        //Если больше или равно верхнему значению, то необходимо включить подачу СО2
    isCo2t = 1;                         //Если необходимо включить подачу CO2
  } else {
      if(hours < downCo2Time){           //Если меньше нижнего значения, то необходимо включить подачу CO2
    isCo2t = 1;                         //Если необходимо включить подачу CO2
  } else {
    isCo2t = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isCo2t == 1) && (co2Stat == 0)){    //Если нет подачи CO2 и выставлен флаг необходимости включить
    digitalWrite(OUT6, LOW);                  //Включаем подавая НИЗКИЙ уровень на вывод (инверсно)
    co2Stat = 1;
  } else {
      if(isCo2t == 0 && co2Stat == 1){
    digitalWrite(OUT6, HIGH);                 //Выключаем подавая ВЫСОКИЙ уровень на вывод (инверсно)
    co2Stat = 0;
    }
  }
//========== Включение\отключение Lcd подсветки
      if (upLsdTime > downLsdTime){  //Если ночное время
    isNight = 1;
  }
      if (isNight == 0){                   //Если день
      if (hours >= upLsdTime && hours < downLsdTime){           //Проверяем интервал
    isLcdt = 1;                          //Если необходимо включить свет
  } else {
    isLcdt = 0;
    }
  } else {                               //Если ночь
      if(hours - upLsdTime >= 0){        //Если больше или равно верхнему значению, то необходимо включить свет
    isLcdt = 1;                          //Если необходимо включить свет
  } else {
      if(hours < downLsdTime){           //Если меньше нижнего значения, то необходимо включить свет
    isLcdt = 1;                          //Если необходимо включить свет
  } else {
    isLcdt = 0;
      }
    }
  }                                      //Закончился цикл выбора: день или ночь?
      if((isLcdt == 1) && (lcdStat == 0)){   //Если свет еще не включен и выставлен флаг необходимости включить
    lcd.backlight();
    lcdStat = 1;
  } else {
      if(isLcdt == 0 && lcdStat == 1){
    lcd.noBacklight();
    lcdStat = 0;
    }
  }
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Вот и у меня подозрения, что analogData успевает принять -1, оно же 255. Поэтому и мониторить предлагаю сразу за изменением.

По часам, наверно так if (часы==23&минуты==15) {flag=1;}  if (flag==1) {включить} на выключение аналогично. Только надо продумать систему записи-хранения этих значений и передачи в функцию. Возможно массив на включение и массив на выключение + циклы перебора-сравнения. Как у вас, неудобно, а если еще минуты прибавятся, так вовсе заблудишься.

Thorn
Offline
Зарегистрирован: 07.11.2014

Блин блин блин. Сейчас уже на банке проверил. Вывел analogData в Serial и что вы думаете? А ничего при любом значении будь-то

analogData2 == 1, двум и луюому значению при выполеннии условия

if (analogData2 == 1( 2,3,4,5,6 - вобщем при любом :) )     {       //Выключаем реле диммера (по окончании диммирования)
digitalWrite(OUT0,HIGH);
digitalWrite(OUT1,HIGH);
digitalWrite(OUT2,HIGH);
digitalWrite(OUT3,HIGH);

при выключении реле на digitalWrite(OUT1,HIGH); (остальные уже к тому времени выключены но обрабатываются на всякий случай) так вот происходит ВСПЫШКА, так-что наша математика и ардуинка тут непричём. Дело в КОММУТАЦИИ и в частности в реле. Вот была-бы возможность заменить к примеру на твёрдотельное.

В любом случае при ВКЛЮЧЕНИИ всё мягко будь то analogData2 == 0 или 1, а вот при выключении... Буду думать.

Кстати победил я свой код таймера на два и более расписаний на одном OUT. Нужно было задать:

byte lghtStat = 0; //Флаг освещения, Реле Dimm, если включена, то в 1 первого таймера
byte lghtStat2 = 0; //Флаг освещения, Реле Dimm, если включена, то в 1 второго таймера

byte upLghtTime1 = 7; //Флаг включаения, Реле Dimm, в 7 утра
byte downLghtTime1 = 11; //Флаг выключаения, Реле Dimm, в 11 утра
byte upLghtTime2 = 19; //Флаг включаения, Реле Dimm, в 19 вечера
byte downLghtTime2 = 23; //Флаг выключаения, Реле Dimm, в 23 вечера

byte isLght = 0; //Флаг для обработки необходимости включить реле освещения на 1 канале 1-го таймера
byte isLght2 = 0; //Флаг для обработки необходимости включить реле освещения на 1 канале 2-го таймера

ну и код таймера остаётся неизменным за исключением правки флагов.

ПО часам что вы показали как я тоже так думал однако как задать их прощще в примере выше может типа 

byte upLghtTime1 = 7*hours+15*minutes;

однако он хоть и неругается но неработает. Правильно ли я делаю в таймере при этом:

if (hours + minutes >= upLghtTime2 && hours + minutes < downLghtTime2){ //Проверяем интервал
isLght2 = 1;

Поправьте пожалста.

bwn
Offline
Зарегистрирован: 25.08.2014

Тогда перед полным отключением реле, попробуйте тупой delay() c разными значениями. Ведь говорите если просто тумблером при 0 диммера вспышки нет. Что то здесь неправильно.

С часами час+минута и подобные варианты не катят, 7час 15мин = 15час 7мин.  Массив мне кажется более оптимален. 0 -час вкл. 1-мин вкл. 3-час выкл. 4-мин.выкл и далее двухмерный на требуемое количество. 00 00 - запретное число. С ними потом и меню будет легче кодить.

А с условиями я и сам регулярно путаюсь. Просто начинаю мониторить получаемые значения в if-ах. Если они верные, значит в знаках напутал и наоборот.

Причем комбинации >= в них не пойдут, только по == на флаг. Иначе при ручных изменениях девайс вас начнет поправлять.

На худой конец с реле http://arduino.ru/forum/apparatnye-voprosy/pitanie-pravila там еще в самом конце интересную ссылку давали, пока не изучил.

 

Thorn
Offline
Зарегистрирован: 07.11.2014

Доброго дня форумчанам и "bwn" - отдельный привет.

Много курил форум и инет. Много сломал копий о самый простой "таймер" с расписанием, наверное с неделю. Пока непришёл к выводу что надо работать не с часаи и минутами а с одним общим выражением часов+минут. Можно было просто сравнивать часы и >= минуты но тогда при отключениях электричества или если время вкл к примеру 7 часов а выключения 5 часов таймер НЕВКЛЮЧАЛСЯ - непонимал что надо работать чуть менее суток. Вобщем бамбука выкурил пока ненаваял что то. 

Потом приехал модуль BMP-180 - такая классная штука, и давление измеряет и темпиратуру с шагом 0,5 град и высоту над уровнем МИРОВОГО ОКЕАНА :) даже. бобщем приблуда классная. Присоединил к акваконтроллеру.

Потом приехала блютусина HC-06 та что пассивная, один минус при заливке скетча приходится выдёргивать или использовать переназначение портов TX и RX и стороннюю библитотеку. Поигрался, даже в appInventore xn ото налепил для вкл\выкл и диммирования (оказалось и пульта хватает) лучьшебы выводить показания на смарт параметров или задавать их а ардуинку.

На сегодня меню в разработке ниже выложу пример того что получилось. Далее два расписания на свет  сдиммированием, одно на СО2 и на подсветку LCD. Термореле для воды и радиаторов. Время вкл\выкл для таймера беру из EPROM, туда пока их завожу тупо записью потмо комментирую и снова заливаю скетч уже без записи (чтоб незабивать ограниченные ресурсы). Хочется потмо из меню записывать и время и границы температур для термореле.

Вот скетчик, полностью рабочий уже в течении полных 3 недель почти с многократным отключением по питанию:

#include <EEPROM.h>
#include <Wire.h>                     //Подключаем библиотеку для использования однопроводного интерфейса                                     
#include <LiquidCrystal_I2C.h>        //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h>                  //Подключаем библиотеку для температурного датчика DS18B20
#include <BMP085.h>                   //Подключаем библиотеку для маленького барометра
#include <IRremote.h>                 //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4);     //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0;                  //Переменная включения подсветки LCD 

//=====IR-light*
#define RECV_PIN 3                 //Вход IR-приемника и кнопки пульта
#define POWER_KEY 0x20DF4EB1       //red_power-OFF_ATX_ON/OFF
#define KEY1 0x20DF8E71            //green_relay1_ON/OFF
#define KEY2 0x20DFC639            //yellow_relay2_ON/OFF
#define KEY3 0x20DF8679            //blue_relay3_ON/OFF
#define KEY4 0x20DF0DF2            //play_up_dimmer-UP_relay1
#define KEY5 0x20DF5DA2            //pause_down_dimmer-DOWN_relay1
#define KEY6 0x20DFF10E            //<<-left_down_dimmer-DOWN_relay1_manual
#define KEY7 0x20DF718E            //>>-right_up_dimmer-UP_relay1_manual
#define KEY8 0x20DFDA25            //exit_ON\OFF_LCD
#define KEY9 0x20DF8D72            //stop_dimmer-DOWN_relay0,1,2,3_OFF

//=====IR-menu*
#define KEY10 0xACE7C23F           //setting
#define KEY11 0x20DF14EB           //back
#define KEY12 0x20DFE01F           //<-left
#define KEY13 0x20DF609F           //<-right
#define KEY14 0x20DF02FD           //^-up
#define KEY15 0x20DF827D           //$-down
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;

//=====BT*
char incomingByte;                  //Ввходящие данные BT (Bluetooth модуля)

//=====IR_Dimmer*
byte analogData1, analogData2 = 0;  //Переменная выходов диммирования (из двух половинок :))
byte maxDimm = 255;                 //Переменная определяет МАКСИМАЛЬНОЕ значение диммирования
byte upR2 = 200;                    //Переменная включения 2 свето-релейного канала
byte upR3 = 240;                    //Переменная включения 3 свето-релейного канала
byte downR2 = 195;                  //Переменная выключения 2 свето-релейного канала
byte downR3 = 235;                  //Переменная выключения 3 свето-релейного канала
int pManDimmUp = 1000;              //Период увеличения яркости 
int pManDimmDown = 500;             //Период уменьшения яркости
byte flagDimm = 0;                  //Флаг для обработки "НЕОБРАТИМОГО" выключения stop_Key9
long tDimm = millis();              //Переменная задержки auto_key_dimmer
long prvMlsOut = 0;                 //Предыдущее показание обновления показания OUT
long outIntv = 100;                 //Интервал для обновления OUT

//=====TermoRelay*
const int RelayChn1 = 4;            //Используем цифровой ПОРТ 4 для ПЕРВОГО канала термо-реле (вода) 
const int RelayChn2 = A1;           //Используем цифровой ПОРТ A1 для ВТОРОГО канала термо-реле (радиатор)

//=====Led_Relay*
#define OUT1 7                      //Используем цифровой ПОРТ 7 для 1 свето-релейного канала Dimm
#define OUT2 8                      //Используем цифровой ПОРТ 8 для 2 свето-релейного канала
#define OUT3 9                      //Используем цифровой ПОРТ 9 для 3 свето-релейного канала

//=====Other_Relay*
#define OUT0 10                     //Используем цифровой ПОРТ 10 для ATX (включение ATX (зелёный + черный))
//#define OUT6 11                   //Используем цифровой ПОРТ 11 для CO2
//#define OUT7 12                   //Используем цифровой ПОРТ 12 для другое

//=====Dimmer_Out*
#define OUT4 5                      //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6                      //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)

//=====VoltMeter*
int voltInput = A7;                 //Используем аналоговый вход A7 для измерения напряжения
float vout = 0.0;
float vin = 0.0;
float R1 = 21700.0;                 //Resistance of R1 (22K) - see text!
float R2 = 12770.0;                 //Resistance of R2 (12K) - see text!
int value = 0;
long prvMlsVo = 0;                  //Предыдущее показание обновления показания вольтметра
long voIntv = 5000;                 //Интервал для обновления напряжения

//=====Pressure*
BMP085 dps = BMP085();              // Digital Pressure Sensor 
long Temperature = 0, Pressure = 0, Altitude = 0;
unsigned long time1=0;
long prvMlsBar = 0;                 //Предыдущее показание обновления показания барометра
long barIntv = 5000;                //Интервал для обновления барометра

//=====TermoSensor*
int TSensorPin = 2;                 //Определяем порт шины OneWire (IC) для температурного датчика DS18B20                               
OneWire ds(TSensorPin);             //Создаем объект для работы с термометром
long tzad = millis();               //Переменная задержки (пока для ds18b20, ds.write)
byte flagDallas=0;                  //Флаг для обработки показаний с датчиков Dallas
byte data[12];
byte addr1[8] = {0x28, 0xC5, 0x3B, 0x5C, 0x06, 0x00, 0x00, 0x85};     //адрес датчика DS18B20_Вода в аквариуме
byte addr2[8] = {0x28, 0x86, 0x48, 0xEA, 0x05, 0x00, 0x00, 0xF6};     //адрес датчика DS18B20_Радиатор (2-ой канал, центр)
byte addr3[8] = {0x28, 0xF2, 0x29, 0xEB, 0x05, 0x00, 0x00, 0xE1};     //адрес датчика DS18B20_Блок реле
unsigned int raw;                    //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
float temp1, temp2, temp3;           //Температура аквариума \ радиаторов Led \ блока реле
float t1 = 24.5;                     //Переменная предела срабатывания реле RelayChn1
float t2 = 47.5;                     //Переменная предела срабатывания реле RelayChn2
float t3 = 49.5;                     //Переменная предела срабатывания реле RelayChn3
float tGistrsis = 0.5;               //Гистерезис температур (по 0,25 в каждую сторону)
long prvMlsTemp = 0;                 //Предыдущее показание обновления температур
long tempIntv = 7000;                //Интервал для обновления температур

//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104 
byte seconds, minutes, hours, day, date, month, year;
long tmIntv = 1000;               //Интервал для обновления времени на экране каждую секунду
long razdIntv = 3000;             //Интервал для обновления ":" на экране каждые 3 секунды
long prvMlsTm = 0;                //Предыдущее показание миллисекунд для обновления показания часов
long prvMlsRazd = 0;              //Предыдущее показание миллисекунд для обновления ":"
long prvMlsLght = 0;              //Предыдущее показание проверки временного интервала

//=====Timer*
//    long lghtIntv = 60000;            //Интервал для проверки включения/выключения освещения аквариума, 1 минута
byte lcdStat = 0;                //Флаг подсветки Lcd если включена, то в 1
byte lghtStat1 = 0;              //Флаг освещения, Реле Dimm, если включена, то в 1 в первом таймере
byte lghtStat2 = 0;              //Флаг освещения, Реле Dimm, если включена, то в 1 во втором таймере
byte co2Stat = 0;                //Флаг Co2, Реле, если включена, то в 1
byte isLcdt = 0;                 //Флаг для обработки необходимости включить подсветку Lcd
byte isLght1 = 0;                //Флаг для обработки необходимости включить реле освещения на 1 канале в первом таймере
byte isLght2 = 0;                //Флаг для обработки необходимости включить реле освещения на 1 канале во втором таймере
byte isCo2t = 0;                 //Флаг для обработки необходимости включить реле Co2
byte isNight = 0;                //Если включаем на ночь, т.е. начальное время больше конечного

//=====Byte_Symbol*
byte equ[8] =                    //Символ "=" но КОРОТКИЙ :)
{
  B00000,
  B00000,
  B01110,
  B00000,
  B01110,
  B00000,
  B00000,
}; 

//=====Eeprom*
int hrOn_r1e;                  //переменные для хранения данных о вкл. выкл. реле1 после считывания с EEPROM
int mnOn_r1e;
int hrOff_r1e;
int mnOff_r1e;
int hrOn_r2e;                 //переменные для хранения данных о вкл. выкл. реле2 после считывания с EEPROM
int mnOn_r2e;
int hrOff_r2e;
int mnOff_r2e;
int hrOn_r3e;                 //переменные для хранения данных о вкл. выкл. реле3 CO2 после считывания с EEPROM
int mnOn_r3e;
int hrOff_r3e;
int mnOff_r3e;
int hrOn_lcde;                //переменные для хранения данных о вкл. выкл. Lcd после считывания с EEPROM
int mnOn_lcde;
int hrOff_lcde;
int mnOff_lcde;


void setup() {
  Wire.begin();
  Serial.begin(9600);
      irrecv.enableIRIn();                            //Включаем IR-сенсор
      dps.init(MODE_STANDARD, 25000, true);           // 250 meters, true = using meter units  
//    pinMode(RelayChn1,OUTPUT);                      //пределяем выход 1-термореле охлаждения воды аквариума 
//    pinMode(RelayChn2,OUTPUT);                      //пределяем выход 2-термореле охлаждения радиаторов Led
//  digitalWrite(RelayChn1,HIGH);                     //Определяем инверсный выход в HIGH охлаждения воды аквариума
//  digitalWrite(RelayChn2,HIGH);                     //Определяем инверсный выход в HIGH охлаждения радиаторов Led
     pinMode(OUT0,OUTPUT);                            //Определяем инверсные выходы реле ATX 
     pinMode(OUT1,OUTPUT);                            //Определяем инверсные выходы реле 1 канала Led
     pinMode(OUT2,OUTPUT);                            //Определяем инверсные выходы реле 2 канала Led
     pinMode(OUT3,OUTPUT);                            //Определяем инверсные выходы реле 3 канала Led
 //    pinMode(OUT6,OUTPUT);
 //    pinMode(OUT7,OUTPUT);
  digitalWrite(OUT0,HIGH);                            //Определяем инверсный выход в HIGH реле ATX
  digitalWrite(OUT1,HIGH);                            //Определяем инверсный выход в HIGH реле 1 канала Led
  digitalWrite(OUT2,HIGH);                            //Определяем инверсный выход в HIGH реле 2 канала Led
  digitalWrite(OUT3,HIGH);                            //Определяем инверсный выход в HIGH реле 3 канала Led
//  digitalWrite(OUT6,HIGH);
//  digitalWrite(OUT7,HIGH);
  analogWrite(OUT4,analogData2);                      //Инициация выхода 1/2 диммера
  analogWrite(OUT5,analogData1);                      //Инициация выхода 1/2 диммера
    pinMode(voltInput,INPUT);                         //Определяем вход вольтметра
      lcd.init();                                     //Инициализируем дисплейчик
      lcd.setBacklight(1);  
      lcd.clear();                                    //Очищаем на всякий случай дисплейчик
      lcd.setCursor(2, 0);
      lcd.print("Aqua  Controller");                  //Выводим версию и прочее
      lcd.setCursor(2, 1);
      lcd.print("      v1.1      ");
      lcd.setCursor(1, 3);
      lcd.print("_2501_eprom_newBat");
  delay(2000);
      lcd.clear();                                    //Очистка дисплея и вывод статичной информации
      lcd.setCursor(16, 1);
      lcd.print("pw\1");
       lcd.setCursor(0, 1);
      lcd.print("bar\1");
      lcd.setCursor(0, 2);
      lcd.print("a\1");
      lcd.setCursor(7, 2);
      lcd.print("b\1");
      lcd.setCursor(14, 2);
      lcd.print("c\1");
      lcd.setCursor(0, 3);
      lcd.print("~");
      lcd.setCursor(2, 3);
      lcd.print(":");
      lcd.setCursor(4, 3);
      lcd.print(":");
      lcd.setCursor(7, 3);
      lcd.print("v\1");
      lcd.setCursor(15, 3);
      lcd.print("%\1");
      lcd.createChar(1, equ);                          //Создаем символ под номером 1
/*
EEPROM.write(1,  6);
EEPROM.write(2,  55);
EEPROM.write(3,  12);
EEPROM.write(4,  10);
EEPROM.write(5,  18);
EEPROM.write(6,  45);
EEPROM.write(7,  22);
EEPROM.write(8,  55);
EEPROM.write(9,  6);
EEPROM.write(10,  45);
EEPROM.write(11,  23);
EEPROM.write(12,  00);
*/      
}
//====================================================
//=========== Обработка даных вкл. откл. с EEPROM
//====================================================
void eEPROMread() {
    hrOn_r1e = EEPROM.read(1);
    mnOn_r1e = EEPROM.read(2);
    hrOff_r1e = EEPROM.read(3); 
    mnOff_r1e = EEPROM.read(4);
    hrOn_r2e = EEPROM.read(5);
    mnOn_r2e = EEPROM.read(6);
    hrOff_r2e = EEPROM.read(7); 
    mnOff_r2e = EEPROM.read(8);
    hrOn_r3e = EEPROM.read(9);
    mnOn_r3e = EEPROM.read(10);
    hrOff_r3e = EEPROM.read(11); 
    mnOff_r3e = EEPROM.read(12);
    hrOn_lcde = EEPROM.read(13);   
    mnOn_lcde = EEPROM.read(14);
    hrOff_lcde = EEPROM.read(15); 
    mnOff_lcde = EEPROM.read(16);
}
//====================================================
//========== Обработка IR-кнопок, ручное управление реле и диммером
//====================================================
void ir_manual_key(){
  if (irrecv.decode(&results)){      //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
    if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
      val = results.value;            //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)    
  }                                   //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
//====================================================
//========== Отключение LCD с кнопки
//====================================================
  if (results.value == KEY8){
    lcd.setBacklight(currentLight);
    currentLight = !currentLight;
 }
//====================================================
//========== Увеличение яркости (удержание кнопки)
//====================================================
      if (val == KEY7){      
      if (analogData1, analogData2 < 255) analogData1 ++, analogData2 ++;   //Начало увеличения диммирования
         analogWrite(OUT4, analogData2);
         analogWrite(OUT5, analogData1);
           if (analogData1, analogData2 > 0){        //Включаем реле ATX и диммера на первом шаге (начало диммирования)
         digitalWrite(OUT0,LOW);                     //Включаем реле ATX
         digitalWrite(OUT1,LOW);
    }
  }
//====================================================
//========== Уменьшение яркости (удержание кнопки)
//====================================================
        if (val == KEY6){      
       if (analogData1, analogData2 != 0) analogData1 --, analogData2 --;  //Начало снижения диммирования 
       analogWrite(OUT4, analogData2);
       analogWrite(OUT5, analogData1);
       if (analogData1, analogData2 == 0){           //Выключаем реле диммера (по окончании диммирования)
          digitalWrite(OUT1,HIGH);
          digitalWrite(OUT2,HIGH);
          digitalWrite(OUT3,HIGH);
          digitalWrite(OUT0,HIGH);                   //Выключаем реле ATX
    }
  }
//====================================================
//========== Обработка ATX, НЕдиммируемых реле
//====================================================
     if (results.value == POWER_KEY) digitalWrite(OUT0, !digitalRead(OUT0));      //Power_KEY, ON/OFF_KEY, включение ATX
   else if (results.value == POWER_KEY) digitalWrite(OUT0, !digitalRead(OUT0));
 //    if (results.value == KEY1) digitalWrite(OUT1, !digitalRead(OUT1));
 //  digitalWrite(OUT0,LOW);
 //    if (results.value == KEY1) digitalWrite(OUT1, !digitalRead(OUT1));
 //  digitalWrite(OUT0,HIGH);
     if (results.value == KEY2 && !digitalRead(OUT1) !=0 && analogData2 >= 1) digitalWrite(OUT2, !digitalRead(OUT2));
   else if (results.value == KEY2 && !digitalRead(OUT1) !=0 && analogData2 != 0) digitalWrite(OUT2, digitalRead(OUT2));
     if (results.value == KEY3 && digitalRead(OUT1) ==0 && analogData2 >= 1) digitalWrite(OUT3, !digitalRead(OUT3));
   else if (results.value == KEY3 && digitalRead(OUT1) ==0 && analogData2 != 0) digitalWrite(OUT3, digitalRead(OUT3));
  irrecv.resume(); 
  }
    lcd.setCursor(17, 3);                    //Вывод состояния аналогового выхода диммирования
    lcd.print(analogData2);
    lcd.setCursor(18, 3);
    lcd.print("  ");
    lcd.setCursor(17, 3);
    lcd.print(analogData2);
      lcd.setCursor(19, 1);                  //Вывод состояния ATX (Power ON\OFF)
      lcd.print(!digitalRead(OUT0));
      lcd.setCursor(1, 3);                   //Вывод состояния выходов реле освещения
      lcd.print(!digitalRead(OUT1));
      lcd.setCursor(3, 3);
      lcd.print(!digitalRead(OUT2));
      lcd.setCursor(5, 3);
      lcd.print(!digitalRead(OUT3));
} 
//====================================================
//========== Увеличение яркости (одно нажатие)
//====================================================
void dimmUp(){
      if (analogData2 < maxDimm){              //Ограничение верхнего значения диммирования, (0-255)
    analogData2 ++;                            //Начало подъёма диммирования
    analogData1 ++;
    analogWrite(OUT4,analogData2);             //Пишем в порт
    analogWrite(OUT5,analogData1);
      if (analogData2 > 0){                    //Включаем реле ATX и диммера на первом шаге (начало диммирования)
    digitalWrite(OUT0,LOW);
    digitalWrite(OUT1,LOW);
   }
      if (analogData2 == upR2){                //Включаем Второе реле при upR2
    digitalWrite(OUT2,LOW);
   }    
      if (analogData2 == upR3){                //Включаем Третье реле при upR3
    digitalWrite(OUT3,LOW);
  }
  tDimm=millis() + pManDimmUp;                  //Устанавливаем время следующего шага
  }
}
//====================================================
//========== Уменьшение яркости (одно нажатие)
//====================================================
void dimmDown(){
      if (analogData2 > 0) {
    analogData2 --;  //Начало снижения диммирования 
    analogData1 --;
    analogWrite(OUT4,analogData2);
    analogWrite(OUT5,analogData1);
//Serial.println(analogData2,DEC);
//Serial.println(analogData1,DEC); 
      if (analogData2 == downR3){                  //Выключаем Третье реле при downR3
    digitalWrite(OUT3,HIGH);
  }
      if (analogData2 == downR2){                  //Выключаем Втором реле при downR2
    digitalWrite(OUT2,HIGH); 
  }
      if (analogData2 == 0){                       //Выключаем реле диммера (по окончании диммирования)
    digitalWrite(OUT0,HIGH);
    digitalWrite(OUT1,HIGH);
    digitalWrite(OUT2,HIGH);
    digitalWrite(OUT3,HIGH);
  }
  tDimm=millis() + pManDimmDown;                    //Устанавливаем время следующего шага
  }
}
//====================================================
//========== Обработка нажатия (одно нажатие)
//====================================================
void auto_key_dimmer(){                        //Считываем значение кнопки. 
      if (val == KEY4 & flagDimm == 0){        //Если нажата кнопка УВЕЛИЧЕНИЯ диммирования
      if (tDimm < millis()) {                  //И не дана команда на полное выключение
  pManDimmUp; dimmUp();                        //Интервал УВЕЛИЧЕНИЯ диммирования
    } 
  }
      if (val == KEY5 & flagDimm == 0){          //Здесь аналогично увеличению яркости
      if (tDimm < millis()) {
  pManDimmDown; dimmDown();                      //Интервал Снижения диммирования
    }
  }
      if (val == KEY9 & analogData2 != 0){       //Stop_and_Dimmer_DOWN. Если диммер включен, устанавливаем флаг
    flagDimm=1;
  }
      if (flagDimm == 1){                        //Если флаг установлен, продолжаем уменьшение яркости
      if (analogData2 == 0){                     //Яркость на 0, флаг сбросили.
    flagDimm = 0;
    digitalWrite(OUT1,HIGH);
    digitalWrite(OUT2,HIGH);
    digitalWrite(OUT3,HIGH);
    digitalWrite(OUT0,HIGH);
    }
      if (tDimm < millis()){                     //Последовательно уменьшаем яркость, кнопки заблокированы
  pManDimmDown = 300; dimmDown();                //Интервал СНИЖЕНИЯ диммирования (по KEY9_stop)
    } 
  }
}
//====================================================
//========== Считывание напряжения
//====================================================
void voltM(){
  value = analogRead(voltInput);               //Read the value at analog input
  vout = (value * 5.0) / 1024.0;               //See text
    vin = vout / (R2/(R1+R2)); 
      if (vin<0.09) {
    vin=0.0;                                   //Statement to quash undesired reading
    }
    unsigned long currentMillis = millis();
      if(currentMillis - prvMlsVo > voIntv){   //Проверяем интервал для обновления напряжения
    prvMlsVo = currentMillis;
  lcd.setCursor(9, 3);
  lcd.print(vin);
  } 
}
//====================================================
//========== Считывание Давления
//====================================================
void bar() {
  if (((millis() - time1)/1000.0) >= 1.0) {     
     dps.calcTrueTemperature();
     time1 = millis(); }
//  dps.getTemperature(&Temperature); 
  dps.getPressure(&Pressure);
//  dps.getAltitude(&Altitude);
      unsigned long currentMillis = millis();
      if(currentMillis - prvMlsBar > barIntv){   //Проверяем интервал для обновления 
   prvMlsBar = currentMillis;
  lcd.setCursor(5, 1);
  lcd.print(Pressure/133.3,1);                //Выводим на экранчик показания атм.давления в мм.
//  lcd.print(Altitude*0.01,1);                 //Выводим на экранчик показания высоты над уровнем моря в м.
//  lcd.print(Temperature*0.1);                 //Выводим на экранчик показания температуры в град.
  } 
}
//====================================================
//=========== Считывание температур
//====================================================
void dallas(){
  ds.reset();
  ds.write(0xCC);                             //Команда инициации  
  ds.write(0x44);                             //Start conversion, with parasite power on at the end
    tzad=millis() + 750; flagDallas=1;
  }
  float DS18B20(byte *adres){
//  flagDallas=0;
  ds.reset();
  ds.select(adres);
  ds.write(0xBE);                             //Read Scratchpad
//  float celsius =  (float)raw / 16.0;
//  return celsius;
    for (byte i = 0; i < 9; i ++) data[i] = ds.read();     //We need 9 bytes
    int raw = (data[1] << 8) | data[0];                    // Переводим в температуру   
//    if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];  
//      return raw / 16.0;
    float celsius =  (float)raw / 16.0;
    return celsius;
}
//====================================================
//=========== Обработка Термо-Реле
//====================================================
void tempRelay(){
    temp1 = DS18B20(addr1);
    temp2 = DS18B20(addr2);
    temp3 = DS18B20(addr3);
      if (temp1 > t1-tGistrsis/2){
    digitalWrite(RelayChn1,LOW);                 //Термо-реле 1-включается
//        lcd.setCursor(8, 2);
//        lcd.print("*");
  }     
      else if (temp1 < t1+tGistrsis/2){
    digitalWrite(RelayChn1,HIGH);                //Термо-реле 1-выключается
//        lcd.setCursor(8, 2);
//        lcd.print("-");
  } 
      if (temp2 > t2-tGistrsis/2){
    digitalWrite(RelayChn2,LOW);                 //Термо-реле 2-включается
//        lcd.setCursor(18, 2);
//        lcd.print("*");
  }     
      else if (temp2 < t2+tGistrsis/2){
    digitalWrite(RelayChn2,HIGH);                //Термо-реле 2-выключается
//        lcd.setCursor(18, 2);
//        lcd.print("-");
  } 
    unsigned long currentMillis = millis();
      if(currentMillis - prvMlsTemp > tempIntv){     //Проверяем интервал для обновления температуры
    prvMlsTemp = currentMillis;
  lcd.setCursor(2, 2);                               //Вывод значений температур на LCD                     
  lcd.print((temp1),1);
  lcd.setCursor(9, 2);                          
  lcd.print((temp2),1);  
  lcd.setCursor(16, 2);                          
  lcd.print((temp3),1);
  }  
} 
//====================================================
//=========== Обработка RTC часов
//====================================================
void timeRtc(){
  Wire.beginTransmission(DS3231_I2C_ADDRESS);       //104 is DS3231 device address
  Wire.write(0x00);                                 //Start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);          //Request seven bytes
      if(Wire.available()) { 
    seconds = Wire.read();                           //Get second
    minutes = Wire.read();                           //Get minute
    hours   = Wire.read();                           //Get hour
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read();                          //Get month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111));  //Convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111));      //Convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111));     //Convert BCD to decimal  1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111));   //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  unsigned long currentMillis = millis();
     if(currentMillis - prvMlsTm > tmIntv) {   //Проверяем интервал для обновления часов
    prvMlsTm = currentMillis;                  //Вызываем ф-цию вывода времени на экран
  lcd.setCursor(0, 0);
      if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);} 
  lcd.print(":"); 
      if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);} 
  lcd.print(":"); 
      if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);} 
      if(currentMillis - prvMlsRazd > razdIntv) {  //Проверяем интервал для обновления ":"
    prvMlsRazd = currentMillis;
    lcd.setCursor(2, 0);
    lcd.print(" ");
    lcd.setCursor(5, 0);
    lcd.print(" ");
    lcd.setCursor(8, 0);
    lcd.print(" ");
      if (date<10) {lcd.print(0);lcd.print(date);} else {lcd.print(date);} 
 lcd.print("/");
 if (month==1){lcd.print ("Jan");} 
 if (month==2){lcd.print ("Feb");} 
 if (month==3){lcd.print ("Mar");} 
 if (month==4){lcd.print ("Apr");} 
 if (month==5){lcd.print ("May");} 
 if (month==6){lcd.print ("Jun");} 
 if (month==7){lcd.print ("Jul");} 
 if (month==8){lcd.print ("Aug");} 
 if (month==9){lcd.print ("Sep");} 
 if (month==10){lcd.print ("Oct");} 
 if (month==11){lcd.print ("Nov");} 
 if (month==12){lcd.print ("Dec");} 
 lcd.print("/"); 
 lcd.print(year+2000); 
    lcd.setCursor(12, 1);
 if (day==1){lcd.print ("Sun");} 
 if (day==2){lcd.print ("Mon");} 
 if (day==3){lcd.print ("Tue");} 
 if (day==4){lcd.print ("Wed");} 
 if (day==5){lcd.print ("Thu");} 
 if (day==6){lcd.print ("Fri");} 
 if (day==7){lcd.print ("Sat");}
    }
  }
}

/*
//====================================================
//=========== Обработка RTC температуры 
//====================================================
void tempRtc() {
   unsigned long currentMillis = millis();
      if(currentMillis - prvMlsTemp > tempIntv){     //Проверяем интервал для обновления температуры
    prvMlsTemp = currentMillis;
  lcd.setCursor(15, 1);
  lcd.print(get3231Temp());
    }
  }
  float get3231Temp() {                //temp registers (11h-12h) get updated automatically every 64s
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if(Wire.available()) {
    tMSB = Wire.read();                 //2's complement int portion
    tLSB = Wire.read();                 //fraction portion
    temp3231 = (tMSB & B01111111);      //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  return temp3231;
}
*/
//====================================================
//=========== Обработка Таймеров
//====================================================
void timer(){                            //Включаем/выключаем освещение аквариума и СО2
//========== Перевод часов и минут к ПОЛНЫМ минутам и объявление переменных внутри 
  int fullMinutes = hours * 60 + minutes;                       //Переводим часы + минуты к полным минутам
  int fullMinutesOn1 = hrOn_r1e * 60 + mnOn_r1e;                //Переводим часы + минуты включения 1 реле к полным минутам
  int fullMinutesOff1 = hrOff_r1e * 60 + mnOff_r1e;             //Переводим часы + минуты выключения 1 реле к полным минутам
  int fullMinutesOn2 = hrOn_r2e * 60 + mnOn_r2e;                //Переводим часы + минуты выключения 2 реле к полным минутам
  int fullMinutesOff2 = hrOff_r2e * 60 + mnOff_r2e;             //Переводим часы + минуты выключения 2 реле к полным минутам
  int fullMinutesLcdOn1 = hrOn_lcde * 60 + mnOn_lcde;                //Переводим часы + минуты выключения 2 реле к полным минутам
  int fullMinutesLcdOff1 = hrOff_lcde * 60 + mnOff_lcde;             //Переводим часы + минуты выключения 2 реле к полным минутам
//========== Таймер №1  
      if (fullMinutesOn1 > fullMinutesOff1) {isNight = 1;}      //Если ночное время
    if (isNight == 0) {                          //Если день
    if (fullMinutes >= fullMinutesOn1 && fullMinutes < fullMinutesOff1) {isLght1 = 1;}        //Проверяем интервал
   else {isLght1 = 0;}                           //Если необходимо включить свет
  } else {                                       //Если ночь
      if(fullMinutes - fullMinutesOn1 >= 0) {isLght1 = 1;}        //Если больше или равно верхнему значению, то необходимо включить свет
   else {                                        //Если необходимо включить свет
      if(fullMinutes < fullMinutesOff1) {isLght1 = 1;}            //Если меньше нижнего значения, то необходимо включить свет
   else {isLght1 = 0;}                           //Если необходимо включить свет
    }
  }  
    if((isLght1 == 1) && (lghtStat1 == 0)){      //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm) {lghtStat1 = 1;}
  } else {
      if(isLght1 == 0 && lghtStat1 == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){lghtStat1 = 0;}
  }
}
//========== Таймер №2
      if (fullMinutesOn2 > fullMinutesOff2) {isNight = 1;}        //Если ночное время
    if (isNight == 0) {                          //Если день
    if (fullMinutes >= fullMinutesOn2 && fullMinutes < fullMinutesOff2) {isLght2 = 1;}        //Проверяем интервал
   else {isLght2 = 0;}                           //Если необходимо включить свет
  } else {                                       //Если ночь
      if(fullMinutes - fullMinutesOn2 >= 0) {isLght2 = 1;}        //Если больше или равно верхнему значению, то необходимо включить свет
   else {                                        //Если необходимо включить свет
      if(fullMinutes < fullMinutesOff2) {isLght2 = 1;}            //Если меньше нижнего значения, то необходимо включить свет
   else {isLght2 = 0;}                           //Если необходимо включить свет
    }
  }  
    if((isLght2 == 1) && (lghtStat2 == 0)){      //Если свет еще не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm) {lghtStat2 = 1;}
  } else {
      if(isLght2 == 0 && lghtStat2 == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){lghtStat2 = 0;}
  }
}
/*
//========== Таймер СО2  
      if (fullMinutesOn3 > fullMinutesOff3) {isNight = 1;}        //Если ночное время
    if (isNight == 0) {                          //Если день
    if (fullMinutes >= fullMinutesOn3 && fullMinutes < fullMinutesOff3) {isLght3 = 1;}        //Проверяем интервал
   else {isLght3 = 0;}                           //Если необходимо включить C02
  } else {                                       //Если ночь
      if(fullMinutes - fullMinutesOn3 >= 0) {isLght3 = 1;}        //Если больше или равно верхнему значению, то необходимо включить Co2
   else {                                        //Если необходимо включить Co2
      if(fullMinutes < fullMinutesOff3) {isLght3 = 1;}            //Если меньше нижнего значения, то необходимо включить Cj2
   else {isLght3 = 0;}                           //Если необходимо включить Co2
    }
  }  
    if((isLght3 == 1) && (lghtStat3 == 0)){      //Если Со2 не включен и выставлен флаг необходимости включить
    pManDimmUp; dimmUp();
      if (analogData2 == maxDimm) {lghtStat3 = 1;}
  } else {
      if(isLght3 == 0 && lghtStat3 == 1){
    pManDimmDown; dimmDown();
      if (analogData2 == 0){lghtStat3 = 0;}
  }
}
*/
//========== Таймер Lcd-подсветки  
      if (fullMinutesLcdOn1 > fullMinutesLcdOff1) {isNight = 1;}        //Если ночное время
    if (isNight == 0) {                          //Если день
    if (fullMinutes >= fullMinutesLcdOn1 && fullMinutes < fullMinutesLcdOff1) {isLcdt = 1;}        //Проверяем интервал
   else {isLcdt = 0;}                           //Если необходимо включить подсветку Lcd
  } else {                                       //Если ночь
      if(fullMinutes - fullMinutesLcdOn1 >= 0) {isLcdt = 1;}        //Если больше или равно верхнему значению, то необходимо включить подсветку Lcd
   else {                                        //Если необходимо включить подсветку Lcd
      if(fullMinutes < fullMinutesLcdOff1) {isLcdt = 1;}            //Если меньше нижнего значения, то необходимо включить подсветку Lcd
   else {isLcdt = 0;}                           //Если необходимо включить подсветку Lcd
    }
  }  
    if((isLcdt == 1) && (lcdStat == 0)){        //Если подсветка Lcd еще не включена и выставлен флаг необходимости включить
    lcd.backlight(); lcdStat = 1;
  } else {
      if(isLcdt == 0 && lcdStat == 1){
    lcd.noBacklight(); lcdStat = 0;
  }
}
}
//====================================================
//=========== Обработка Bluetooth
//====================================================
void bluetooth() {
      if (Serial.available() > 0) {   
  int i = Serial.read()-48;
    if (i == 0) digitalWrite(OUT0, !digitalRead(OUT0));
    if (i == 1) currentLight = !currentLight;
    if (i == 2 && !digitalRead(OUT1) !=0 && analogData2 >= 1) digitalWrite(OUT2, !digitalRead(OUT2));
  else if (!digitalRead(OUT1) !=0 && analogData2 != 0) digitalWrite(OUT2, digitalRead(OUT2));
    if (i == 3 && digitalRead(OUT1) ==0 && analogData2 >= 1) digitalWrite(OUT3, !digitalRead(OUT3));
  else if (digitalRead(OUT1) ==0 && analogData2 != 0) digitalWrite(OUT3, digitalRead(OUT3));
//    if (i == 6) {
//     pManDimmUp; dimmUp();
//      if (analogData2 == maxDimm){             //Ограничение верхнего значения диммирования, (0-255)
//    lghtStat = 1;
//      }
//   }
//   if(i == 5) {pManDimmDown; dimmDown();
//      if (analogData2 == 0){                  //Ограничение нижнего значения диммирования, (0-255)
//    lghtStat = 0;
//    }
//  }
  }
}

void loop(){
    eEPROMread();
    timeRtc();
    timer();
    ir_manual_key();
    auto_key_dimmer();
    dallas(); //flagDallas==0;
    tempRelay();
//    tempRtc();
    voltM();
    bar();
    bluetooth();
}

И да если помните писал чт одескать часики ds3231 отставали прочее. Всё дело было в батарейке. Она стояла почти никакая и однажды при откл. электроэнергии на пару минут заметил что отставать стали.поменял и всё пучком, за прошедшие две недели сек в секунду никуда неубегают. Для сравнения тестовые на 1307 в неделю до 15 сек отстают.

Вот скетчик ДЕМО-меню, пишу его на другом дисплейчике мааалюсеньком потмоу отличаются координаты и библиотеки:

#include <EEPROM.h>
#include <Wire.h>                     //Подключаем библиотеку для использования однопроводного интерфейса                                     
#include <OneWire.h>                  //Подключаем библиотеку для температурного датчика DS18B20
#include <IRremote.h>                 //Подключаем библиотеку для IR сенсора

 //=====Tft*
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define sclk 52
#define mosi 51
#define cs   4
#define dc   2
#define rst  3  // you can also connect this to the Arduino reset
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);

//=====Rtc_Clock*
#define DS1307_I2C_ADDRESS 0x68
byte seconds, minutes, hours, day, date, month, year;
long tmIntv = 1000;               //Интервал для обновления времени на экране каждую секунду
//long razdIntv = 500;              //Интервал для обновления ":" на экране каждые 2 секунды
long prvMlsTm = 0;                //Предыдущее показание миллисекунд для обновления показания часов
//long prvMlsRazd = 0;              //Предыдущее показание миллисекунд для обновления ":"
//long prvMlsLght = 0;              //Предыдущее показание проверки временного интервала

//=====Menu* 
int m=0; //переменная для экранов меню
int p1=0; // переменная для примера 1
int p2=0; // -//- 2
int p3=0; // -//- 3

#define RECV_PIN 11               //Вход IR-приемника и кнопки пульта
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;

#define KEY10 0x41BE30CF           //кнопка Setup вход в меню настроек параметров
#define KEY2 0x41BEC03F            //кнопка enter принятие установок и запись их
#define KEY1 0x41BED02F            //кнопка Up меню
#define KEY3 0x41BE609F            //кнопка Down возврата 
#define KEY6 0x41BE40BF            //уменьшение значения Left
#define KEY7 0x41BEB04F            //увеличение значения Right

byte ledPin = 7;          //Светодиод
byte ledPin1 = 9;         //Светодиод

void setup() {
  Wire.begin();
  irrecv.enableIRIn();                  //Включаем IR-сенсор
  tft.initR(INITR_BLACKTAB);   
  tft.fillScreen(ST7735_BLACK);         // Clear screen

  pinMode(ledPin, OUTPUT);
  pinMode(ledPin1, OUTPUT);
  digitalWrite(ledPin, HIGH);
  digitalWrite(ledPin1, HIGH);
}

//====================================================
//=========== Обработка RTC часов
//====================================================
void timeRtc(){
  Wire.beginTransmission(DS1307_I2C_ADDRESS);       //104 is DS3231 device address
  Wire.write(0x00);                                 //Start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);          //Request seven bytes
      if(Wire.available()) { 
    seconds = Wire.read();                           //Get second
    minutes = Wire.read();                           //Get minute
    hours   = Wire.read();                           //Get hour
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read();                          //Get month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111));  //Convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111));      //Convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111));     //Convert BCD to decimal  1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111));   //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  if (m == 0) {
   tft.setCursor(15,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(2);
if (hours<10) {tft.print(0);tft.print(hours);} else {tft.print(hours);} 
  tft.print(":"); 
      if (minutes<10) {tft.print(0);tft.print(minutes);} else {tft.print(minutes);} 
  tft.print(":"); 
      if (seconds<10) {tft.print(0);tft.print(seconds);} else {tft.print(seconds);}
  tft.setCursor(15,25);
     tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
     tft.setTextSize(1); 
      if (date<10) {tft.print(0);tft.print(date);} else {tft.print(date);} 
 tft.print("/");
 if (month==1){tft.print ("Jan");} 
 if (month==2){tft.print ("Feb");} 
 if (month==3){tft.print ("Mar");} 
 if (month==4){tft.print ("Apr");} 
 if (month==5){tft.print ("May");} 
 if (month==6){tft.print ("Jun");} 
 if (month==7){tft.print ("Jul");} 
 if (month==8){tft.print ("Aug");} 
 if (month==9){tft.print ("Sep");} 
 if (month==10){tft.print ("Oct");} 
 if (month==11){tft.print ("Nov");} 
 if (month==12){tft.print ("Dec");} 
 tft.print("/"); 
 tft.print(year+2000); 
 if (day==1){tft.print (" Sun.");} 
 if (day==2){tft.print (" Mon.");} 
 if (day==3){tft.print (" Tue.");} 
 if (day==4){tft.print (" Wed.");} 
 if (day==5){tft.print (" Thu.");} 
 if (day==6){tft.print (" Fri.");} 
 if (day==7){tft.print (" Sat.");} 
}
}
void menu() {
  if (irrecv.decode(&results)){       //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
    if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
      val = results.value;            //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)    
  }                                   //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
  
  //Обработка нажатия кнопки меню
  if (results.value == KEY10){
  m=0;
//  delay (100);
  tft.fillScreen(ST7735_BLACK); } // Clear screen
  if (results.value == KEY1) {
  m++;                              //увеличиваем переменную уровня меню
  if (m>4) {                        //если уровень больше 3
  m=0; }// то вернуться к началу
//  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
}
  
  //Обработка нажатия кнопки назад
  if (results.value == KEY3) {
  m--;
  if (m<0) {
  m=4; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
}
  
  //Обработка нажатия для р1 +
    if (results.value == KEY7 && m==2) {//если находимся на экране с переменной р1
  p1++;//то при нажатии кнопки + увеличиваем переменную р1 на единицу
  if (p1>10) {//если переменная достигла придела в 10 едениц
  p1=0; }//то возвращаем ее к 0
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
}
  //+ для р2
    if (results.value == KEY7 && m==3) {
  p2++;
  if (p2>1) {
  p2=0; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
  digitalWrite(ledPin1, p2);
}
    //+ для р3
    if (results.value == KEY7 && m==4) {
  p3++;
  if (p3>1) {
  p3=0; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
//  if (results.value == KEY2)
  digitalWrite(ledPin, p3);
}
  //сдесь код для уменьшения значений
  //аналогичен коду увеличения
  
  //Обработка нажатия для р1 -
    if (results.value == KEY6 && m==2) {//если находимся на экране с переменной р1
  p1--;//то при нажатии кнопки + увеличиваем переменную р1 на единицу
  if (p1>10) {//если переменная достигла придела в 10 едениц
  p1=0; }//то возвращаем ее к 0
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
}
  //- для р2
    if (results.value == KEY6 && m==3){
  p2--;
  if (p2>1){
  p2=0; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
  digitalWrite(ledPin1, p2);
}
    //- для р3
    if (results.value == KEY6 && m==4){
  p3--;
  if (p3>1) {
  p3=0; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
  digitalWrite(ledPin, p3);
}  

//****************************************************  
    //вывод меню
  if (m==0) {
  tft.setCursor(120, 160);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_BLUE);
  tft.print("_");
  tft.setCursor(120, 160);
  tft.print(" ");
  
  } else if (m==1) {
  tft.setCursor(10, 130);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
  tft.print("Main Menu");
  tft.setCursor(5, 25);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("P1=");
  tft.print(p1);
  tft.print(" Led=");
  tft.print(p2);
  tft.print("  Led1=");
  tft.print(p3);
  
  } else if (m==2) {
  tft.setCursor(0, 0);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Menu-2");
  tft.setCursor(5, 25);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Parametr-1");
  tft.setCursor(5, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("P1 = ");
  tft.print(p1);
  
  } else if (m==3) {
  tft.setCursor(0, 0);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Menu-3");
  tft.setCursor(5, 25);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Led Control");
  tft.setCursor(5, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Led = ");
  tft.print(p2);
  
  } else if (m==4) {
  tft.setCursor(0, 0);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Menu-4");  
  tft.setCursor(5, 25);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Led1 Control");
  tft.setCursor(5, 45);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Led1 = ");
  tft.print(p3);
  }
irrecv.resume(); 
  }
}

void loop() {
  timeRtc();
  menu();
}

Первое чт ов меню хочу сделать принятие значения и запись его в Eprom после нажатия кнопки setup а то счас тупо записывается (сохраняется после выбора). Ну и кажестя что какоето оно громозкое это меню. Хотя надо то пару экранов на одном таймеры на другом температуры.

bwn
Offline
Зарегистрирован: 25.08.2014

Что можно сказать, труд великий. В первом коде, так понимаю от задержки опроса отказались намеренно? Функция dallas() у вас считывает старые значения. Она должна быть разбита на две (начало и вторая которая начинается с float DS18B20 в нее мы должны зайти по истечении tzad.

Вольтметр последняя цифра не скачет постоянно?

Не очень понял, с какой целью считываете значения из EEPROM в переменные. Они там уже есть, так и работать с ними напрямую.

Thorn
Offline
Зарегистрирован: 07.11.2014

Нет, ненамерянно, просто пока немогу правильно флагами описать когда измерять - поставить флаг-сделаь задержку-вывести на экранчик -поставить флаг. Получается пока неправильно (да и мне несильно важна точность сиюминутного замера) позже опишу правильно с millis или тупо воткну delay небольшой.

Последняя скачет но это сознательно, есть некая динамика а работе (как и мигание ":" в часах между минутами и часами.

Почему ЕПРОМ - так как значения будут определяться из меню то туда же (в адреса) и записываться будут. У вас в скетче также все но более хитро как то. По чесноку - ВАШ код САМЫЙ мудрёный, я из него НИЧЕГО несмог для себя приспособить (хотел меню взять), у вас там все через массивы, через [ ] - тоетсь то чего я вообще непользовал нигде у себя в коде.

Так вот. Счас нжно первую m=1 переменную меню использовать как настроку времени час и минут для включения первого реле, а также вообще использование расписания (кстати надо в код добавить флаги - будет ли выполняться расписание_1 или только расписание_2, кстати это надо мне сейчас реализовать чтобы в меню добавить испоьзование этого флага.

Меню m=0 думаю оставить как начальное, вывод для ВСЕХ имеющихся счас показаний, ну тоетсь то что на сейчас выводится согласно скетча. А далее я по аналогии сделаю меню для других расписаний и термореле. Вот.

Кстати работа с дисплейчиком на модуле st7735s 128 X 160 в 1,8 дюйма НАМНОГО сложнее, код весит БОЛЬШЕ чуток, и ОЧЕНЬ медленный если выводить на него сразу всё т очто я вывожу на I2C то ОЧЕНЬ медленный (я так понял он програмно работает с графикой а не аппаратно, как сенсорные и прочее).

Но на него можно столько былобы вывести сразу всего, и бойтись парой менюшек - влезет всё :) с расстояния в 40-50 см глазу есчо терпимо а дальше шрифт в 1 единичку уже неразличим.

Thorn
Offline
Зарегистрирован: 07.11.2014

Вот что у меня сейча в меню (для простого понимания пробую). Стрелками вверх\вниз перехожу по 4 экранам в меню .В каждом представлен один параметр, который могу менять стреклами вправо\влево. Как только выбрал значение параметра он спустя delay тут-дже и применяется. Я в последствии хочу записывать этот параметр в ЕПРОМ а значит чтоб он незаписывал тупо - все что листается пропускаем, нужное ПРИМЕНЯЕТСЯ по нажатию KEY10 она же setup прописана. Как? пробовал всякими if-ами ничего невыходит, ничего. Как только это реализую буду пробовать на один экран меню вывести ДВА параметра (к примеру не только часы но и минуты, опятьже как перейти от часов к минутам без KEY10 пока тоже несмогу, а так выбрал параметр часов на экране, нажал (вправо\влево), нажал setup применил значение и как без следующей кнопки перейти к параметру минуты? вот тут я пока затупил. Ну да ладно можно былобы и много экранов меню для для каждого параметра, нестрашно, полистал дошёл-выбрал. Подскажите как приклеить setup сюда к примеру:



//Обработка нажатия для р1 +
    if (results.value == KEY7 && m==2) {//если находимся на экране с переменной р1
  p1++;//то при нажатии кнопки + увеличиваем переменную р1 на единицу
  if (p1>10) {//если переменная достигла придела в 10 едениц
  p1=0; }//то возвращаем ее к 0
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
}
  //+ для р2
    if (results.value == KEY7 && m==3) {
  p2++;
  if (p2>1) {
  p2=0; }
  delay (100);
  tft.fillScreen(ST7735_BLACK); // Clear screen
  digitalWrite(ledPin1, p2);
}

где m=3 это третий экраничк меню. А p2 - собсвенно сам параметр (LOW или HIGH) в моем случае. 

bwn
Offline
Зарегистрирован: 25.08.2014

По алгоритму, я делал так:

Считываем изменяемое значение из Епром в служебную переменную, печатаем, изменяем его, печатаем, если устраивает нажимаем "Ок".

По нажатию "Ок", проверяем значение в Епром, если отличается записываем, если одинаковые - уходим. Основной код работает со значениями из Епром.

Если после изменения ни одна клавиша 20сек не нажата, уходим на предыдущий экран и так пока не выйдем из меню. Пока вы находитесь в меню основной цикл стоит. Циклы меню у меня закольцованы, выход по времени или по "Ок"

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

 

Thorn
Offline
Зарегистрирован: 07.11.2014

Алгоритм ваш то что надо. А вот как это будет выглядеть в моем коде? Эт оя какбы недвусмысленно намекаю.... ПО поводу автовыхода согласен полнсотью, так как правильно, вдру при ползании по меню уснул лил забылся и всё  все горит свтеит или наоборот. У вас в коде кстати заметил одно важное, в нем прописаны значения "по умолчанию" которые - это я и хотел также применить, оказывается у вас есчо и сравнение было - про это недодумался. Очень прошу - опишите кодом мой кусочек а далее я уже сам остальные по аналогии и да, "выходим" я так понял это отдальная кнопка или можно setup сделать многоступенчато, а то сейчас она меня выводит в основной экран. 

bwn
Offline
Зарегистрирован: 25.08.2014

Попробую, только не сегодня, затемпературил. А выход, да, по "Setup-у"

Thorn
Offline
Зарегистрирован: 07.11.2014

Вот вашу кусочек с кнопочками:

 

ledBlink();
keyKod=analogRead(0); //Считываем значение кнопки
delay(zadTime[0]);
if (key1==1&&keyKod>400) { continue; } //Если не изменялось - возврат
if (key1==0&&keyKod<400) { continue; } //Если не изменялось - возврат
if (key1==0&&keyKod>400) { key1=1; } //Изменение статуса состояния
if (key1==1&&keyKod<400) { key1=0; } //Изменение статуса состояния

Я так понял функция { continue; } это и есть возврат ежели ненажимоалось ничево, и неменялось. Время ожидания я так понял это delay(zadTime[0]); - опять массив :( стояло бы значения понял а [0] это значение в массиве, а какой размер его и в каком месте . Вобщем темный лес.

Вобщем без помощи как приделать setup для принятия значения и перехода к след параметру в окне меню я на месте стою - как тогда с диммированием и програмными часами, пока флаг недодумался применить. 

bwn
Offline
Зарегистрирован: 25.08.2014

Массив заполнен значениями в самом начале, "Блок инициализации переменных". Эти if-ы делал, чтобы автоматом не изменялось. Одно нажатие - одно изменение. Сontinue; -  возврат на бесконечный цикл "while". Выход произойдет или по истечении времени или по "break" после изменения значений.

zadTime[0] - это антидребезг, а время нахождения в условии цикла while.

bwn
Offline
Зарегистрирован: 25.08.2014

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

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>

#define DS1307_I2C_ADDRESS 0x68

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

const byte outPin = 13; // выход управления нагрузки

byte setMinClockOn; // 
byte setHorClockOn;
byte setMinClockOff; // 
byte setHorClockOff;

byte key(){ //// для кнопок ЛСДшилда
  int val = analogRead(0);
    if (val < 50) return 5;
    else if (val < 150) return 3;
    else if (val < 350) return 4;
    else if (val < 500) return 2;
    else if (val < 800) return 1;
    else return 0;  
}

/////////// часы ..
byte decToBcd(byte val){
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val){
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(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(DS1307_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 getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_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 setClock(){ // установка часов
  byte pos = 1;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; 
    getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
    lcd.clear();
    lcd.blink();

   while(key() != 1){ // крутим   цикл   
    byte KEY = key(); // читаем состояние кнопок
      delay(200);
    lcd.setCursor(1, 1);
    lcd.print("set to save");
    lcd.setCursor(0, 0);     // выводим инфу
     if (hour < 10) lcd.print("0");
    lcd.print(hour);
    lcd.print(":");
     if (minute < 10) lcd.print("0"); 
    lcd.print(minute);  
    lcd.print(" ");     
     if (dayOfMonth < 10) lcd.print("0");
    lcd.print(dayOfMonth);
    lcd.print("/");
     if (month < 10) lcd.print("0");
    lcd.print(month);
    lcd.print("/");
     if (year < 10) lcd.print("0");
    lcd.print(year);
    
    lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции
    
    if (KEY == 5 && pos < 13) pos += 3; // крутим позицию
    else if (KEY == 2 && pos > 1) pos -= 3;
    
    else if (pos == 1 && KEY == 3) hour++; // крутим значения
    else if (pos == 1 && KEY == 4) hour--;
    else if (pos == 4 && KEY == 3) minute++;
    else if (pos == 4 && KEY == 4) minute--;    
    else if (pos == 7 && KEY == 3) dayOfMonth++;
    else if (pos == 7 && KEY == 4) dayOfMonth--;    
    else if (pos == 10 && KEY == 3) month++;
    else if (pos == 10 && KEY == 4) month--;    
    else if (pos == 13 && KEY == 3) year++;
    else if (pos == 13 && KEY == 4) year--;  
    
    if (hour > 23) hour = 0;
    else if (minute > 59) minute = 0;
    else if (dayOfMonth > 31) dayOfMonth = 0;
    else if (month > 12) month = 1;
    else if (year > 99) year = 0;
  }// конец цикла
  
 setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year); 
   lcd.noBlink(); 
   lcd.clear();
   lcd.print("     Saved");
   delay(1500);
}///

void setOnOff(){    
  byte pos = 0;   
    lcd.clear();
    lcd.blink();

   while(key() != 1){ // крутим   цикл   
    byte KEY = key(); // читаем состояние кнопок
      delay(200);
    lcd.setCursor(1, 1);
    lcd.print("set to save");
    lcd.setCursor(0, 0);     // выводим инфу
     if (setHorClockOn < 10) lcd.print("0");
    lcd.print(setHorClockOn);
    lcd.print(":");
     if (setMinClockOn < 10) lcd.print("0"); 
    lcd.print(setMinClockOn);  
    lcd.print(" ");     
     if (setHorClockOff < 10) lcd.print("0");
    lcd.print(setHorClockOff);
    lcd.print(":");
     if (setMinClockOff < 10) lcd.print("0");
    lcd.print(setMinClockOff); 
    
    lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции
    
    if (KEY == 5 && pos < 9) pos += 3; // крутим позицию
    else if (KEY == 2 && pos > 1) pos -= 3;
    
    else if (pos == 0 && KEY == 3) setHorClockOn++; // крутим значения
    else if (pos == 0 && KEY == 4) setHorClockOn--;
    else if (pos == 3 && KEY == 3) setMinClockOn++;
    else if (pos == 3 && KEY == 4) setMinClockOn--;    
    else if (pos == 6 && KEY == 3) setHorClockOff++;
    else if (pos == 6 && KEY == 4) setHorClockOff--;    
    else if (pos == 9 && KEY == 3) setMinClockOff++;
    else if (pos == 9 && KEY == 4) setMinClockOff--;    
 
    
    if (setHorClockOn > 23) setHorClockOn = 0;
    else if (setMinClockOn > 59) setMinClockOn = 0;
    else if (setHorClockOff > 23) setHorClockOff = 0;
    else if (setMinClockOff > 59) setMinClockOff = 0;
    
  }// конец цикла
   lcd.noBlink(); 
   lcd.clear();

   EEPROM.write(0, setMinClockOn);
   EEPROM.write(1, setHorClockOn);
   EEPROM.write(3, setMinClockOff);
   EEPROM.write(4, setHorClockOff);

   lcd.print("     Saved");
   delay(1500);
}///
 
void menu(){
  lcd.clear();
  char menuTxt[2][14] = {"set ON/OFF >>", "set clock  >>"};
  byte pos = 0;
  
  while(1){  
    delay(200);  
    byte KEY = key();
    
    lcd.setCursor(0, 0);
    lcd.print(pos+1);
    lcd.print(".");
    lcd.print(menuTxt[pos]);
    
    if (KEY == 3 && pos != 0) pos--;
    else if (KEY == 4 && pos < 1) pos++;
    
    if (KEY == 5 && pos == 0) setOnOff();
    else if (KEY == 5 && pos == 1) setClock();
   if (KEY ==1) {lcd.clear(); break;} 
  }
}  
 
void setup(){
  Wire.begin(); 
  lcd.begin(16, 2);
  lcd.clear();
  
  pinMode(outPin, OUTPUT);
  digitalWrite(outPin, LOW);
  
  setMinClockOn = EEPROM.read(0);
  setHorClockOn = EEPROM.read(1);
  setMinClockOff = EEPROM.read(3);
  setHorClockOff = EEPROM.read(4);
}

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;  
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  // обработка кнопок
  if (key() == 1) menu(); // если нажата селект
  else if (key() == 3) digitalWrite(outPin, HIGH);
  else if (key() == 4) digitalWrite(outPin, LOW);

  // сравниваем время и управляем выходом// 
  if (setMinClockOff == minute && setHorClockOff == hour
      && second == 0) digitalWrite(outPin, LOW);
  if (setMinClockOn == minute && setHorClockOn == hour
      && second == 0) digitalWrite(outPin, HIGH);    
 
 
//   lcd.clear();
    lcd.setCursor(0, 0);
     if (hour < 10) lcd.print("0"); 
    lcd.print(hour); 
    lcd.print(":");
     if (minute < 10) lcd.print("0"); 
    lcd.print(minute);
//  lcd.print(":");
//   if (second < 10) lcd.print("0");
//  lcd.print(second);
//    lcd.setCursor(8, 0); 
//    lcd.print("    ");  
    lcd.setCursor(0, 1);
     if (dayOfMonth < 10) lcd.print("0");
    lcd.print(dayOfMonth);
    lcd.print("/");
     if (month < 10) lcd.print("0");
    lcd.print(month);
    lcd.print("/");
     if (year < 10) lcd.print("0");
    lcd.print(year);
     //
    lcd.setCursor(11, 0);
     if (setHorClockOn < 10) lcd.print("0"); 
    lcd.print(setHorClockOn); 
    lcd.print(":");
     if (setMinClockOn < 10) lcd.print("0"); 
    lcd.print(setMinClockOn);
    
    lcd.setCursor(11, 1);
     if (setHorClockOff < 10) lcd.print("0"); 
    lcd.print(setHorClockOff); 
    lcd.print(":");
     if (setMinClockOff < 10) lcd.print("0"); 
    lcd.print(setMinClockOff);      
   
    lcd.setCursor(7, 0);
    if (digitalRead(outPin)) lcd.print("ON ");
    else lcd.print("Off");
    
    delay(200); // нужно для нармальной работы кнопок
}

Ваши функции void setOnOff() и void menu().

196 строка - добавляете необходимые наименования экранов. стр.208-209 надо переделать на количество ваших экранов, там всего 2.  Условия на Ваши KEY*.  И добавить переменную, по которой в setOnOff будем определять какой таймер пишем (соответственно в какие ячейки. типа i=0; EEPROM.write(i+0,*). Для четырех значений времени  i=0, 4, 8 и т.д. Строки 225-228 перенести после 141. адрес считывать как и писать i+0)

А обработку ваших условий по времени брать непосредственно из EEPROM. (EEPROM.read(i+0)*60+EEPROM.read(i+1)

Как-то так.

Thorn
Offline
Зарегистрирован: 07.11.2014

Чесно говоря я этот самый пример и пытался ещё в декабре проспособить как пробу работы с ЕПРОМ и МЕНЮ для своего контроллера, однако так и несмог ПОБЕДИТЬ работу с кнопками автора и мою работу с IR-кнопками. Тоесть функцию автора:

byte key(){ //// для кнопок ЛСДшилда
int val = analogRead(0);
if (val < 50) return 5;
else if (val < 150) return 3;
else if (val < 350) return 4;
else if (val < 500) return 2;
else if (val < 800) return 1;
else return 0;
}

я представил как:

byte key(){
val = results.value;
if (results.value == 0x20DF4EB1) return 5;
if (results.value == 0x20DF8E71) return 4;
if (results.value == 0x20DFC639) return 3;
if (results.value == 0x20DF8679) return 2;
if (results.value == 0x20DFDA25) return 1;
else return 0;}

Вместо 0х20 описывал явно:

#define KEY1 0x20DF4EB1 //red
#define KEY2 0x20DF8E71 //green
#define KEY3 0x20DFC639 //yellow
#define KEY4 0x20DF8679 //blue
#define KEY5 0x20DFDA25 //exit

всёравно работала лиш самая последня  строчка из примера вашего 

// обработка кнопок
if (key() == 1) menu(); // если нажата селект
else if (key() == 3) digitalWrite(outPin, HIGH);
else if (key() == 4) digitalWrite(outPin, LOW);

// сравниваем время и управляем выходом//
if (setMinClockOff == minute && setHorClockOff == hour
&& second == 0) digitalWrite(outPin, LOW);
if (setMinClockOn == minute && setHorClockOn == hour
&& second == 0) digitalWrite(outPin, HIGH);

Само собой корректно прописал всё что касается IR - ибо уже могу :).

Далее тупняк сразу тут:

void setOnOff(){
byte pos = 0;
lcd.clear();
lcd.blink();

while(key() != 1){ // крутим цикл
byte KEY = key(); // читаем состояние кнопок

а именно byte KEY = key(); что это? как это преобразовать в мои IR кнопки?

Спасибо что приболемши вникаете и пытаетесь подсказать, однако это мне пока никак непоможет.

bwn
Offline
Зарегистрирован: 25.08.2014

byte key(){
val = results.value;
if (results.value == 0x20DF4EB1) return 5;
if (results.value == 0x20DF8E71) return 4;
if (results.value == 0x20DFC639) return 3;
if (results.value == 0x20DF8679) return 2;
if (results.value == 0x20DFDA25) return 1;
else return 0;}

А что вот в этом варианте возвращает функция key() ?

void loop{serial.println(key();DEC); delay(500);}  вроде так должно быть. у меня ir нет, не проверить.

Thorn
Offline
Зарегистрирован: 07.11.2014

Добрый вечерок :)

Прописал так в переменных:



#define KEY10 0x41BE30CF           //кнопка Setup вход в меню настроек параметров
#define KEY2 0x41BEC03F            //кнопка enter принятие установок и запись их
#define KEY1 0x41BED02F            //кнопка Up меню
#define KEY3 0x41BE609F            //кнопка Down возврата 
#define KEY6 0x41BE40BF            //уменьшение значения Left
#define KEY7 0x41BEB04F            //увеличение значения Right

byte key(){
  int val = results.value;
  if (results.value == 0x41BEB04F) return 5;
  if (results.value == 0x41BE40BF) return 4;
  if (results.value == 0x41BE609F) return 3;
  if (results.value == 0x41BEC03F) return 2;
  if (results.value == 0x41BED02F) return 1;
  else return 0; 

в loop влупил так:

void loop()
{
Serial.println(key(),DEC); delay(500);

далее идёт кусок с функцией меню:



void menu(){
//  lcd.clear();
  tft.fillScreen(ST7735_BLACK); // Clear screen
  tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
  char menuTxt[2][14] = {"set ON/OFF >>", "set clock  >>"};
  byte pos = 0;
  
  while(1){  
    delay(200);  
    byte KEY = key();
    
//    lcd.setCursor(0, 0);
tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
    tft.print(pos+1);
    tft.print(".");
    tft.print(menuTxt[pos]);
    
    if (KEY == 3 && pos != 0) pos--;
    else if (KEY == 4 && pos < 1) pos++;
    
    if (KEY == 5 && pos == 0) setOnOff();
    else if (KEY == 5 && pos == 1) setClock(); 
  }
}  

я в него захожу и всё , висит надпись "set ON/OFF >>" и кнопки никак нереагируют, в serial.print неидёт никакого возврата, если ранее ничего ненажато 0 0 0 0 0 каждый полсекунды (согласно delay) далее возврат нажатой кнопки 3 4 5, и как только попадаю в void menu(){ как-будто висяк :(

bwn
Offline
Зарегистрирован: 25.08.2014

Так, возвращает как и предполагалось от 0 до 5. В первом коде 9 строка вам не нужна. Во втором 7 надо куда нибудь до void setup(). К общему знаменателю привели, теперь будем мучать, там мне кажется какая то лажа в исходнике с задержками, потому как и на шилде срабатывало через раз. Мне в принципе сама реализация понравилась, и короче и понятней чем у меня. Теперь четкость срабатываня добить и нормальная такая менюшка получится.

Thorn
Offline
Зарегистрирован: 07.11.2014

Про 9 строчку догадывался что лишняя тоже, но пока нерешался.

Переносил 7 строчку везде, и до setup куда только - результат один - висяк. Спасиб за цель, буду пробовать попасть в неё теперь. Чесно по мне меню непонятно чуток, ну раз вы понимаете - тем лучьше - значит сможете разъяснить что к чему и что такое  char menuTxt[2][14] = {"set ON/OFF >>", "set clock >>"}; и что 

tft.print(pos+1);
tft.print(".");
tft.print(menuTxt[pos]);

Thorn
Offline
Зарегистрирован: 07.11.2014

Добавил в loop(0 кусочек с возвратом нажатой кнопки ИК на экранчик, выводися какая то шняга :)

вот такой кодик:

 tft.setCursor(20,150);
     tft.setTextColor(ST7735_RED,ST7735_BLACK);
     tft.setTextSize(1);
     tft.print(key());
     switch (key()){
       case 1:
       tft.print(" select");
       break;
       case 2:
       tft.print(" left");
       case 3:
       tft.print(" up");
       break;
       case 4:
       tft.print(" own");
       case 5:
       tft.print(" right");
       break;
     }

возвращает позицию правильно 0 1 2 3 4 5 а вот определение её как то толи складывает толи..вощем может при нажатии влево вернуть 2 и left up, вниз 4 down right .... вобщем непонятно. Изменил определение кнопок в соответсвии с шилдом. Выглядит так:

/*
#define KEY2 0x41BEC03F //кнопка enter принятие установок и запись их
#define KEY1 0x41BED02F //кнопка Up меню
#define KEY3 0x41BE609F //кнопка Down возврата
#define KEY6 0x41BE40BF //уменьшение значения Left
#define KEY7 0x41BEB04F //увеличение значения Right
*/
byte key(){
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0;
}

как видно и без определения #define всё заработало :) до определённого места

bwn
Offline
Зарегистрирован: 25.08.2014

char menuTxt[2][14] = {"set ON/OFF >>", "set clock >>"}; - это как раз строковый массив, что выводить на экран. Удобен, если строку надо вывести в разных местах программы+экономия памяти+легкость редактирования. [2] - число строк, [14] - число символов.

tft.print(pos+1); - массив считается с "0", здесь хотят чтобы на экране было с "1".
tft.print(".");
tft.print(menuTxt[pos]); - вывести строку с номером "pos"

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

Thorn
Offline
Зарегистрирован: 07.11.2014

Доброе утро bwn :) Есть минутка? Вобщем пока ничего неполучилось у меня. Кстати обратил внимание, что скетч странно стартует. После запуска на экранчик выводится возврат byte key() и пока IR неполучит хоть какогото сигнала (даже с "левого" пульта невыводит информации о времени\дате и On\Off нагрузки outPin. И вот ещё что если ничего ненажато и в serial идут 0 0 0 0 0 и тут нажать нашу setup для входа в char menuTxt[2][14] = {"set On/Off >>", "set clock >>"}; то неуспевает даже вернуться нажатая кнопка и невидно было -ли вообще чтолибо нажато, это с delay(1000); C задержкой в 100мс вход в char menuTxt иногда несрабатывает и даже если был возврат любой кнопки то возвращаться начинают 0, о как. Далее по второму-третьему нажатию setup сначала перестает отвечеть serial.Print и выводится текст char menuTxt. Может чегогто "зацикливается" в void menu()



void menu(){
  tft.fillScreen(ST7735_BLACK); // Clear screen
  tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
  char menuTxt[2][14] = {"set On/Off >>", "set clock >>"};
  byte pos = 0;
  
  while(1){  
//   delay(200);  
    byte KEY = key();
//    lcd.setCursor(0, 0);
     tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
    tft.print(pos+1);
    tft.print(".");
    tft.print(menuTxt[pos]);
    
    if (KEY == 3 && pos != 0) pos--;
    else if (KEY == 4 && pos < 1) pos++;
    
    if (KEY == 5 && pos == 0) setOnOff();
    else if (KEY == 5 && pos == 1) setClock(); 
  }
} 

Вот весь кусок с часами и таймером, вроде выкладывал но всеже:







#include <EEPROM.h>
#include <Wire.h>                            //Подключаем библиотеку для использования однопроводного интерфейса                                     
#include <OneWire.h>                         //Подключаем библиотеку для температурного датчика DS18B20
#include <IRremote.h>                        //Подключаем библиотеку для IR сенсора

 //=====Tft*
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define sclk 52
#define mosi 51
#define cs   4
#define dc   2
#define rst  3  // you can also connect this to the Arduino reset
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);

//=====IR*
#define RECV_PIN 11                          //IR-приемник
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;
//=====IR***

#define DS1307_I2C_ADDRESS 0x68

const byte outPin = 9; // выход нагрузки

byte setMinClockOn; 
byte setHorClockOn;
byte setMinClockOff; 
byte setHorClockOff;

/*
byte key(){ //// для кнопок 
  int val = analogRead(0);
    if (val < 50) return 5; //right
    else if (val < 150) return 3; //up
    else if (val < 350) return 4; //down
    else if (val < 500) return 2; //left
    else if (val < 800) return 1; //select
    else return 0;  
}
*/
/*
#define KEY2 0x41BEC03F            //кнопка enter принятие установок и запись их
#define KEY1 0x41BED02F            //кнопка Up меню
#define KEY3 0x41BE609F            //кнопка Down возврата 
#define KEY6 0x41BE40BF            //уменьшение значения Left
#define KEY7 0x41BEB04F            //увеличение значения Right
*/
byte key(){
  if (results.value == 0x41BEB04F) return 5;
  if (results.value == 0x41BE609F) return 4;
  if (results.value == 0x41BED02F) return 3;
  if (results.value == 0x41BE40BF) return 2;
  if (results.value == 0x41BEC03F) return 1;
  else return 0; 
}
/////////// часы ..
byte decToBcd(byte val){
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val){
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(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(DS1307_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 setup(){
  Wire.begin();
  Serial.begin(9600);
  irrecv.enableIRIn(); 
  tft.initR(INITR_BLACKTAB);   
  tft.fillScreen(ST7735_BLACK);                       // Clear screen  
  
  pinMode(outPin, OUTPUT);
  digitalWrite(outPin, HIGH);
  
  setMinClockOn = EEPROM.read(0);
  setHorClockOn = EEPROM.read(1);
  setMinClockOff = EEPROM.read(3);
  setHorClockOff = EEPROM.read(4);
}

void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_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 setClock(){ // установка часов
  byte pos = 1;
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; 
    getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
//    lcd.clear();
//    lcd.blink();
  tft.fillScreen(ST7735_BLACK); // Clear screen

   while(key() != 1){ // крутим   цикл   
    byte KEY = key(); // читаем состояние кнопок
      delay(200);
    tft.setCursor(1, 1);
    tft.print("set to save");
    tft.setCursor(0, 0);     // выводим инфу
     if (hour < 10) tft.print("0");
    tft.print(hour);
    tft.print(":");
     if (minute < 10) tft.print("0"); 
    tft.print(minute);  
    tft.print(" ");     
     if (dayOfMonth < 10) tft.print("0");
    tft.print(dayOfMonth);
    tft.print("/");
     if (month < 10) tft.print("0");
    tft.print(month);
    tft.print("/");
     if (year < 10) tft.print("0");
    tft.print(year);
    
    tft.setCursor(pos, 0); // устанавливаем курсор согласно позиции
    
    if (KEY == 5 && pos < 13) pos += 3; // крутим позицию
    else if (KEY == 2 && pos > 1) pos -= 3;
    
    else if (pos == 1 && KEY == 3) hour++; // крутим значения
    else if (pos == 1 && KEY == 4) hour--;
    else if (pos == 4 && KEY == 3) minute++;
    else if (pos == 4 && KEY == 4) minute--;    
    else if (pos == 7 && KEY == 3) dayOfMonth++;
    else if (pos == 7 && KEY == 4) dayOfMonth--;    
    else if (pos == 10 && KEY == 3) month++;
    else if (pos == 10 && KEY == 4) month--;    
    else if (pos == 13 && KEY == 3) year++;
    else if (pos == 13 && KEY == 4) year--;  
    
    if (hour > 23) hour = 0;
    else if (minute > 59) minute = 0;
    else if (dayOfMonth > 31) dayOfMonth = 0;
    else if (month > 12) month = 1;
    else if (year > 99) year = 0;
  }// конец цикла
  
 setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year); 
//   tft.noBlink(); 
//   tft.clear();
  tft.fillScreen(ST7735_BLACK); // Clear screen
   tft.print("     Saved");
   delay(1500);
}///

void setOnOff(){    
  byte pos = 0;   
//    tft.clear();
//    tft.blink();
  tft.fillScreen(ST7735_BLACK); // Clear screen

   while(key() != 1){ // крутим   цикл   
    byte KEY = key(); // читаем состояние кнопок
      delay(200);
    tft.setCursor(1, 1);
    tft.print("set to save");
    tft.setCursor(0, 0);     // выводим инфу
     if (setHorClockOn < 10) tft.print("0");
    tft.print(setHorClockOn);
    tft.print(":");
     if (setMinClockOn < 10) tft.print("0"); 
    tft.print(setMinClockOn);  
    tft.print(" ");     
     if (setHorClockOff < 10) tft.print("0");
    tft.print(setHorClockOff);
    tft.print(":");
     if (setMinClockOff < 10) tft.print("0");
    tft.print(setMinClockOff); 
    
    tft.setCursor(pos, 0); // устанавливаем курсор согласно позиции
    
    if (KEY == 5 && pos < 9) pos += 3; // крутим позицию
    else if (KEY == 2 && pos > 1) pos -= 3;
    
    else if (pos == 0 && KEY == 3) setHorClockOn++; // крутим значения
    else if (pos == 0 && KEY == 4) setHorClockOn--;
    else if (pos == 3 && KEY == 3) setMinClockOn++;
    else if (pos == 3 && KEY == 4) setMinClockOn--;    
    else if (pos == 6 && KEY == 3) setHorClockOff++;
    else if (pos == 6 && KEY == 4) setHorClockOff--;    
    else if (pos == 9 && KEY == 3) setMinClockOff++;
    else if (pos == 9 && KEY == 4) setMinClockOff--;    
 
    
    if (setHorClockOn > 23) setHorClockOn = 0;
    else if (setMinClockOn > 59) setMinClockOn = 0;
    else if (setHorClockOff > 23) setHorClockOff = 0;
    else if (setMinClockOff > 59) setMinClockOff = 0;
    
  }// конец цикла
//   lcd.noBlink(); 
//   lcd.clear();
  tft.fillScreen(ST7735_BLACK); // Clear screen

   EEPROM.write(0, setMinClockOn);
   EEPROM.write(1, setHorClockOn);
   EEPROM.write(3, setMinClockOff);
   EEPROM.write(4, setHorClockOff);

   tft.print("     Saved");
   delay(1500);
}///

void menu(){
  tft.fillScreen(ST7735_BLACK); // Clear screen
  tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
  char menuTxt[2][14] = {"set On/Off >>", "set clock >>"};
  byte pos = 0;
  
  while(1){  
//   delay(200);  
    byte KEY = key();
//    lcd.setCursor(0, 0);
     tft.setCursor(0,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(1);
    tft.print(pos+1);
    tft.print(".");
    tft.print(menuTxt[pos]);
    
    if (KEY == 3 && pos != 0) pos--;
    else if (KEY == 4 && pos < 1) pos++;
    
    if (KEY == 5 && pos == 0) setOnOff();
    else if (KEY == 5 && pos == 1) setClock(); 
  }
} 

void loop() {
  Serial.println(key(),DEC); delay(100);
   if (irrecv.decode(&results)){      //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
 //   if (results.value != 0xFFFFFFFF){ 
 //     val = results.value; }
  
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;  
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  // обработка кнопок
  if (key() == 1) menu(); // если нажата селект
  else if (key() == 3) digitalWrite(outPin, LOW);
  else if (key() == 4) digitalWrite(outPin, HIGH);

  // сравниваем время и управляем выходом// 
  if (setMinClockOff == minute && setHorClockOff == hour
      && second == 0) digitalWrite(outPin, HIGH);
  if (setMinClockOn == minute && setHorClockOn == hour
      && second == 0) digitalWrite(outPin, LOW);    
 
 
//   lcd.clear();
//   tft.fillScreen(ST7735_BLACK); // Clear screen
     tft.setCursor(15,5);
     tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     tft.setTextSize(2);
//    lcd.setCursor(0, 0);
     if (hour < 10)  tft.print("0"); 
     tft.print(hour); 
     tft.print(":");
     if (minute < 10)  tft.print("0"); 
     tft.print(minute);
    tft.print(":");
    if (second < 10) tft.print("0");
    tft.print(second);
 //   tft.setCursor(8, 0); 
 //   tft.print("    "); 
    
    tft.setCursor(15, 25);
     tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
     tft.setTextSize(1);
     if (dayOfMonth < 10) tft.print("0");
    tft.print(dayOfMonth);
    tft.print("/");
     if (month < 10) tft.print("0");
    tft.print(month);
    tft.print("/");
     if (year < 10) tft.print("0");
    tft.print(year);

    tft.setCursor(0, 50);
     if (setHorClockOn < 10) tft.print("0"); 
    tft.print(setHorClockOn); 
   tft.print(":");
     if (setMinClockOn < 10) tft.print("0"); 
    tft.print(setMinClockOn);
    
    tft.setCursor(0, 70);
     if (setHorClockOff < 10) tft.print("0"); 
    tft.print(setHorClockOff); 
    tft.print(":");
     if (setMinClockOff < 10) tft.print("0"); 
    tft.print(setMinClockOff);      
   
    tft.setCursor(0, 90);
    if (digitalRead(outPin)) tft.print("On ");
    else tft.print("Off");
  irrecv.resume(); 
  }
      tft.setCursor(20,150);
     tft.setTextColor(ST7735_RED,ST7735_BLACK);
     tft.setTextSize(1);
     tft.print(key());
     switch (key()){
       case 1:
       tft.print(" select");
       break;
       case 2:
       tft.print(" left");
       case 3:
       tft.print(" up");
       break;
       case 4:
       tft.print(" down");
       case 5:
       tft.print(" right");
       break;
     }
}

Thorn
Offline
Зарегистрирован: 07.11.2014

Кстати такая "задержка" в выводе в serial.Print харрактерна. Смотрите когда я нажимаю чтолибо - светик о активности serial на мгновение замираает пока НАЧИНАЕТСЯ прорисовка на еаею И если указана задежка в serial.Print 100мс то после нажатия именно с такой частотой и возвращается кнопка однако, как только нажимается setup то светик активности serial перестает "мигать" и висяк. Может это даст вам больше информации.

bwn
Offline
Зарегистрирован: 25.08.2014

Так, вроде как заработало. Сделал на 5 таймеров, с записью и считыванием из Епром. Проверку на одинаковые значения делать не стал, есть желание - сами прикрутите. При установке времени есть нестабильность небольшая, но там не победил. Если убираю delay(200) перестает работать blink на редактируемой позиции. Расширять по образу и подобию. Спрашивайте, если что не понятно.

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal.h>

#define DS1307_I2C_ADDRESS 0x68

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//_____________________________________________________________
//  Переменные для меню
byte setMinClockOn; 
byte setHorClockOn;
byte setMinClockOff;  
byte setHorClockOff;
byte win;              //Номер экрана меню
unsigned long temp[2]; //Массив для задержек меню
//_____________________________________________________________

void setup()
{
  Wire.begin(); 
  lcd.begin(16, 2);
  lcd.clear();
}

//______________________________________________________________
//   Здесь вставите свою функцию, которая возвращает от 0 до 5
byte key()
{ 
    int val = analogRead(0);
    if (val < 50) return 5;
    else if (val < 150) return 3;
    else if (val < 350) return 4;
    else if (val < 500) return 2;
    else if (val < 800) return 1;
    else return 0;  
}


//_____________________________________________________________

void setOnOff(){    
  byte pos = 0;   
     
      //Считываем записанные значения таймеров.
      //Адрес определяется как номер таймера*4+четыре ячейки.
  setMinClockOn = EEPROM.read(win*4+0); //
  setHorClockOn = EEPROM.read(win*4+1);
  setMinClockOff = EEPROM.read(win*4+2);
  setHorClockOff = EEPROM.read(win*4+3);
    
    lcd.clear();
    lcd.blink();

    while(key() != 1) //Крутим цикл пока не будет Setup
    {   
    byte KEY = key(); // читаем состояние кнопок
      delay(200); //Если убрать, не работает подсветка уст.позиции
    lcd.setCursor(1, 1);
    lcd.print("set to save");
    lcd.setCursor(0, 0);
    lcd.print(win+1,DEC);    //Печатаем номер прогр.таймера.
    lcd.setCursor(2, 0);     // выводим инфу
     if (setHorClockOn < 10) lcd.print("0");
    lcd.print(setHorClockOn,DEC);
    lcd.print(":");
     if (setMinClockOn < 10) lcd.print("0"); 
    lcd.print(setMinClockOn,DEC);  
    lcd.print(" ");     
     if (setHorClockOff < 10) lcd.print("0");
    lcd.print(setHorClockOff,DEC);
    lcd.print(":");
     if (setMinClockOff < 10) lcd.print("0");
    lcd.print(setMinClockOff,DEC); 
    
    lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции
    
    if (KEY == 5 && pos < 11) pos += 3; // крутим позицию право-лево
    else if (KEY == 2 && pos > 3) pos -= 3;
    
    else if (pos == 3 && KEY == 3) setHorClockOn++; // крутим значения
    else if (pos == 3 && KEY == 4) setHorClockOn--;
    else if (pos == 6 && KEY == 3) setMinClockOn++;
    else if (pos == 6 && KEY == 4) setMinClockOn--;    
    else if (pos == 9 && KEY == 3) setHorClockOff++;
    else if (pos == 9 && KEY == 4) setHorClockOff--;    
    else if (pos == 12 && KEY == 3) setMinClockOff++;
    else if (pos == 12 && KEY == 4) setMinClockOff--;    
 
    
    if (setHorClockOn > 23) setHorClockOn = 0;  //Ограничиваем значения
    else if (setMinClockOn > 59) setMinClockOn = 0;
    else if (setHorClockOff > 23) setHorClockOff = 0;
    else if (setMinClockOff > 59) setMinClockOff = 0;
    
  }// конец цикла
   lcd.noBlink(); 
   lcd.clear();

   EEPROM.write(win*4+0, setMinClockOn); //Записываем значения
   EEPROM.write(win*4+1, setHorClockOn);
   EEPROM.write(win*4+2, setMinClockOff);
   EEPROM.write(win*4+3, setHorClockOff);

   lcd.print("     Saved");
   delay(1500);
}///

//_________________________________________________________________
void menu()
{
  //tft.fillScreen(ST7735_BLACK); // Clear screen
  //tft.setCursor(0,5);
     //tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     //tft.setTextSize(1);
  
    //Массив с наименованиями для экрана
  char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
  byte pos = 0;
  byte KEY;
  
  while(1) //Бесконечный цикл
  {   
      KEY=0;
      if (temp[1]<millis()) KEY = key(); //Если прошел интервал, читаем код
     //tft.setCursor(0,5);
     //tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
     //tft.setTextSize(1);
    lcd.setCursor(0,0);
    lcd.print(pos+1);  //Печатаем номер.
    lcd.print(".");
    lcd.print(menuTxt[pos]); //Печатаем название
    
    // Уменьшить увеличить + блокировка кнопки
    if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
    if (KEY == 4 && pos < 4) {pos++; temp[1]=millis()+300;}
    
    win=pos; //Переменная номера таймера
    
    // Здесь переходим на подменю. Если останется как сейчас, то достаточно
    // if (KEY == 5) setOnOff();
    // Сейчас можно перейти на разные подменю.
    if (KEY == 5 && pos == 0) setOnOff();
    if (KEY == 5 && pos == 1) setOnOff();
    if (KEY == 5 && pos == 2) setOnOff();
    if (KEY == 5 && pos == 3) setOnOff();
    if (KEY == 5 && pos == 4) setOnOff();
    //Выход из меню с проверкой и установкой блокировки от возврата
    if (KEY ==1 && temp[0]<millis())        
       { 
         temp[0]=millis()+2000;
         lcd.clear(); 
         break;} 
  }
} 

//_________________________________________________________________

void loop()
{
  lcd.clear();
  //____________________________________________________________
  
   //***ВХОД В МЕНЮ и проверка блокировки от возврата.
  byte KEY=key();            //Принимаем код клавиши
  if (KEY==1 && temp[0]<millis()) 
      {
        temp[0]=millis()+2000;
        menu();
      }                       //Если setup идем в меню
  //____________________________________________________________
  
  lcd.setCursor(10,1);
  lcd.print("cikl");
}

 

Thorn
Offline
Зарегистрирован: 07.11.2014

Спасибо, все скопипастил, чуток подправил под tft (глупо но отлаживать приходится на нём а потом снова чуть менять и на i2c 20*4 переносить :)  ). Перво-напервно убрал из loop очистку lcd.clear(); иначе каждые 2 сек солгасно кода выводится "cikl" с очисткой экрана. Ну а далее все как и ранее...., как только доходит дело до входа в menu глушняк и нажатые кнопки невозвращаются. И раз пошла такая пьянка здесь СТО процентов "раком" впихнут код обработки IR кнопок, он НЕРАБОТАЕТ в функции  void menu() - я вижу первые строки массива "set menu1 >>" и пробежать по ним уже немогу. 

БУДУ сейчас сидеть до последнего, ваш код меню мне больше нравится чем мой с бесконечными if-ами. Думаю как победЮ IR то и сниму комментарий с очистки экрана в loop() потому как он срабатывает если 2 сек ничего ненажато и в меню невошли.

bwn
Offline
Зарегистрирован: 25.08.2014

Тогда добавьте после 132 строки переменную KEY на экран, посмотреть какие значения она принимает. У меня на обычных кнопках все срабатывало нормально.