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

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

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

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

Мда, а я уже обрадовался... было. Кстати язык мне простил моё невежество и прекрасно обрабатывает строки типа !digitalRead(OUT1) - как вы и писали OUT1 не может быть 1 или 0.

Пока выход из key2,3 при !digitalRead(OUT1) <200 это кнопочка power_key - она прекрасно выключает OUT2, 3 но НЕвключает - что и требуется, только ГАСИТЬ свет :)

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

Так это TRUE FALSE, только сбоку.

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

В общем я имел ввиду как то так, не шедевр.



#include <LiquidCrystal.h>

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

const byte OUT1 = 1;       //Реле названия ваши, пины пишите свои
const byte OUT2 = 2;
const byte OUT3 = 3;
const byte OUT4 = A5;      //Здесь ваш на диммирование

int periodDimm = 200;     //Период увеличения уменьшения яркости
//для разных задач задаем разный
byte analogData2 = 0;     //Ваш переменная диммирования
long tDimm = millis();    //Переменная задержки 
byte flagDimm=0;          //Флаг для обработки Power_Key 




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 setup()
{
  lcd.begin(16, 2);
  lcd.clear();
  
  pinMode(OUT1, OUTPUT);          //Исполнительные выходы на вывод
  pinMode(OUT2, OUTPUT);
  pinMode(OUT3, OUTPUT);
  digitalWrite(OUT1, HIGH);       //Реле выключить
  digitalWrite(OUT2, HIGH);
  digitalWrite(OUT3, HIGH);
  analogWrite(OUT4,analogData2); //Инициация диммера
}
  
  //****Увеличение яркости******
 void dimmUp()        
{
 if (analogData2<255) //Ограничение верхнего значения, ставите свое.
{
 analogData2++;  //Увеличиваем на единицу
 analogWrite(OUT4,analogData2);  //Пишем в порт
 
 // Включаем подсветку при значении больше 240
 if (analogData2>240) {digitalWrite(OUT2,LOW); digitalWrite(OUT3,LOW);} 
 
 // Включаем реле диммера на первом шаге
 if (analogData2>0) {digitalWrite(OUT1,LOW);}
 tDimm=millis()+periodDimm;      //Устанавливаем время следующего шага
 lcd.clear();
 lcd.print (analogData2,DEC);
}
}

//******Уменьшение яркости аналогично предыдущего******
 void dimmDown()
{
 if (analogData2>0)
{
 analogData2--;
 analogWrite(OUT4,analogData2);
  if (analogData2<240) {digitalWrite(OUT2,HIGH); digitalWrite(OUT3,HIGH);}
  if (analogData2==0) {digitalWrite(OUT1,HIGH);}
 tDimm=millis()+periodDimm;
 lcd.clear();
 lcd.print (analogData2,DEC);
}
}
 
 
 
  void loop()
  {

    //Считываем значение кнопки. Здесь вставляете свою функцию IR и условия меняете на KEYномер
    key();               
    if (key()==4&flagDimm==0) //Если KEY4 и не дана команда на полное выключение
    {
    //По достижении времени идем на увеличение яркости, период ставим комфортный для вас
    if (tDimm<millis()) {periodDimm=100; dimmUp();} 
    }
    if (key()==5&flagDimm==0)
    {
    //Здесь аналогично увеличению яркости
    if (tDimm<millis()) {periodDimm=100; dimmDown();}
    }
    if (key()==2&flagDimm==0)
    {
     //Если подсветка может быть включена, включаем-выключаем. Задержка нужна, чтобы не прыгало реле
     //при желании можно с флагами и millis()
      if (analogData2>240) { digitalWrite(OUT2, !digitalRead(OUT2));delay(200);}
    }
    if (key()==3&flagDimm==0)
    {
      if (analogData2>240) { digitalWrite(OUT3, !digitalRead(OUT3));delay(200);}
    }
    //Это ваша Power. Если диммер включен, устанавливаем флаг.
    if (key()==1 & analogData2!=0) {flagDimm=1;}
    
      if (flagDimm==1)  //Если флаг установлен, продолжаем уменьшение яркости
      {
        if (analogData2==0) {flagDimm=0;} //Яркость на 0, флаг сбросили.
        if (tDimm<millis()) {periodDimm=200; dimmDown();} //Последовательно уменьшаем яркость, кнопки заблокированы.
      }
    
  }
  

Закат рассвет этими же функция по часам и с флагами, только период изменения яркости увеличиваете до требуемого времени. Есть вроде косячок, а вроде правильно. Если выключили OUT2,3, при увеличении яркости свыше 240 они снова включатся. Можно поставить 255, тогда только на максимуме.

Спрашивайте, что непонятно.

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

На Lcd внимание не обращайте, я значение диммера контролировал

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

Ага, итак самое пока для меня интересное - а именно привязка кнопок IR вы пока пропустили, оставив кнопки с подтяжкой по резистору :)... Теперь код, я счас буду как-бы мысли вслух и с вами советоваться....

 //****Увеличение яркости******

тут я так понял диммируется мой (OUT4,analogData2) выход до значения почти максимального (на самом деле после 180-190) глазу практически незаметно приращение - если несчем сравнивать). Итак после 240 я могу сделать key2, 3 тоесть подать напряжение на драйвера НЕДИММИРУЕМЫХ светиков.

Далее немного то что я ожидал вначале, это 

// Включаем реле диммера на первом шаге

тут, если на analogData2 что т оесть то можно включать на него подачу питания (на драйвер) и это всё длится periodDimm.

Далее void loop() - тут только с примером я пойму - а он пример :) в виде деталек на работе остался.

Delay я в loop вообще нехотел-бы применять - приделаю к millis ибо опыт есть (вывод темпиратуры и напряжение именно по millis на LCD-экранчик.

Про кнопки мои.. пожалста покажите - как их описать взамен 

byte key(){ //// для кнопок ЛСДшилда
int val = analogRead(0);

мне в последующем это нера пригодится.

Думается моя задумка, ровно и как мой свет на самых простых COB-сборках для банок более 500л. -  вывзовет немалый интерес. Ведь контроль почти у всех одинаков, свет, темпиратура (пара-тройка мест), со2 и диммирование - всем нужно. Я вас обязательно укажу в своей теме на aqa.ru - отбоя небудет :)

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

IR-а у меня нет, если в условиях if (key()==?) проставить ваши KEY?, я думаю все заработает. IR опрашиваем в loop(). Мой опрос кнопок просто выбрасываете.

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

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

Выключение по Power автоматическое. Отменить нельзя. Только после выключения прибавить яркость.

Эти delay() работают только пока вы жмете кнопку, на loop они фактически не влияют.

P.S. По идее мои key() меняете на ваши  if (val == KEY4)

 

 

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

84 строку удаляем.

85 преобразуется if (key()==4 & flagDimm==0) на if (val==KEY4 & flagDimm==0)

остальные аналогично

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

Поправил код с вашими рекомендациями относительно IR:


#include <Wire.h>                                     
#include <LiquidCrystal_I2C.h>                     
#include <OneWire.h>                                  
#include <IRremote.h>
LiquidCrystal_I2C lcd(0x27,20,4);

const byte OUT1 = 22;       //Реле названия ваши, пины пишите свои
const byte OUT2 = 24;
const byte OUT3 = 26;
const byte OUT4 = 12;      //Здесь ваш на диммирование

int periodDimm = 200;     //Период увеличения уменьшения яркости
//для разных задач задаем разный
byte analogData2 = 0;     //Ваш переменная диммирования
long tDimm = millis();    //Переменная задержки 
byte flagDimm=0;          //Флаг для обработки Power_Key 


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;  
}

//=====IR*
#define RECV_PIN 11                          //IR-приемник
//Key
#define POWER_KEY 0x41BEF00F       //exit-power-OFF, коды кнопок пульта    
#define KEY1 0x41BED02F            //up_relay1_ON/OFF
#define KEY2 0x41BEC03F            //enter_relay2_ON/OFF
#define KEY3 0x41BE609F            //down_relay3_ON/OFF
#define KEY4 0x41BE10EF            //vol_up_dimmer-UP_relay1
#define KEY5 0x41BE708F            //vol_down_dimmer-DOWN_relay1
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;
//=====IR***

void setup()
{
 Wire.begin();
  irrecv.enableIRIn();
  lcd.init();                                   
  lcd.setBacklight(1);  
  lcd.clear();  
  
  pinMode(OUT1, OUTPUT);          //Исполнительные выходы на вывод
  pinMode(OUT2, OUTPUT);
  pinMode(OUT3, OUTPUT);
  digitalWrite(OUT1, HIGH);       //Реле выключить
  digitalWrite(OUT2, HIGH);
  digitalWrite(OUT3, HIGH);
  analogWrite(OUT4,analogData2); //Инициация диммера
}
  
  //****Увеличение яркости******
 void dimmUp()        
{
 if (analogData2<255) //Ограничение верхнего значения, ставите свое.
{
 analogData2++;  //Увеличиваем на единицу
 analogWrite(OUT4,analogData2);  //Пишем в порт
 
 // Включаем подсветку при значении больше 240
 if (analogData2>240) {digitalWrite(OUT2,LOW); digitalWrite(OUT3,LOW);} 
 
 // Включаем реле диммера на первом шаге
 if (analogData2>0) {digitalWrite(OUT1,LOW);}
 tDimm=millis()+periodDimm;      //Устанавливаем время следующего шага
 lcd.clear();
 lcd.print (analogData2,DEC);
}
}

//******Уменьшение яркости аналогично предыдущего******
 void dimmDown()
{
 if (analogData2>0)
{
 analogData2--;
 analogWrite(OUT4,analogData2);
  if (analogData2<240) {digitalWrite(OUT2,HIGH); digitalWrite(OUT3,HIGH);}
  if (analogData2==0) {digitalWrite(OUT1,HIGH);}
 tDimm=millis()+periodDimm;
 lcd.clear();
 lcd.print (analogData2,DEC);
}
}
 
 
 
  void loop()
  {

    //Считываем значение кнопки. Здесь вставляете свою функцию IR и условия меняете на KEYномер
//    key();               
    if (val==KEY4 & flagDimm==0) //Если KEY4 и не дана команда на полное выключение
    {
    //По достижении времени идем на увеличение яркости, период ставим комфортный для вас
    if (tDimm<millis()) {periodDimm=100; dimmUp();} 
    }
    if (val==KEY5 & flagDimm==0)
    {
    //Здесь аналогично увеличению яркости
    if (tDimm<millis()) {periodDimm=100; dimmDown();}
    }
    if (val==KEY2 & flagDimm==0)
    {
     //Если подсветка может быть включена, включаем-выключаем. Задержка нужна, чтобы не прыгало реле
     //при желании можно с флагами и millis()
      if (analogData2>240) { digitalWrite(OUT2, !digitalRead(OUT2));delay(200);}
    }
    if (val==KEY3 & flagDimm==0)
    {
      if (analogData2>240) { digitalWrite(OUT3, !digitalRead(OUT3));delay(200);}
    }
    //Это ваша Power. Если диммер включен, устанавливаем флаг.
    if (val==KEY1 & analogData2!=0) {flagDimm=1;}
    
      if (flagDimm==1)  //Если флаг установлен, продолжаем уменьшение яркости
      {
        if (analogData2==0) {flagDimm=0;} //Яркость на 0, флаг сбросили.
        if (tDimm<millis()) {periodDimm=200; dimmDown();} //Последовательно уменьшаем яркость, кнопки заблокированы.
      }
    
  }
  

невыходит каменный цветок - мне кажется НЕОПРЕДЕЛЕНЫ мои кнопки. И да в чистом виде ваш скетч выводит на дисплейчик показания диммирования

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

А куда подевался кусок, который получал val от IR. Я ведь писал не полную программу, а кусок который с минимальной доработкой вставлять в ваш код. У вас том был кусочек который работал с IR и получал на выходе значение переменной val, которая равна KEY1 и т.д.

А по моей проге верно, роль реле исполняли светики, PWM не хватило, дисплей показывал значения. В таком виде оно делало как я хотел.

Фактически из моего вы должны взять функции dimmUp, dimmDown и логику работы из loop(). Добавить переменные которые не определены в вашем коде и модифицировать условия под ваш код (val==KEY). Все три части самодостаточны и могут быть использованы в любом коде. Только правильно использовать точки входа.

 

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

Там в 43 посте вы приводили код с IR. Если у вас вход в функцию IR-key происходит в цикле loop безусловно, можно попробовать мой кусок из loop вставить на место строк с 18 по 42 (только проверьте по соответствию количества фигурных скобок). Мои dimmUp и dimmDown лучше расположить чуть выше по коду чем IR-key. Иногда бывает необъяснимый косяк, что компилятор не видит функцию если она расположена ниже по коду, чем ее вызов (документация гласит, что можно в любом месте программы).

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

Ок, сорри тупанул. Итак. На сейчас получилось:

по KEY5 - начало диммирования (без удержания кнопки), в любой момент я могу остановить это кнопкой POWER_KEY - и это хорошо.

Далее диммирование с "0" и до 240 после включаются оба OUT2 и 3, в принципе это можно делать и руками уже но пока как вариант работы по ОДНОЙ кнопке KEY1 - очень неплохой вариант. 

Если

Удобно что в любое время можно диммировтаь как вверх по KEY5 так и вниз по KEY4.

Теперь ложка дёгтю :(

при значении analogData2 = 255 все OUT2, 3 имеют LOW (инверсно ВКЛЮЧЕНЫ), и нажимая KEY2 или 3 я получаю бесконечные щелчки (0, 1) .

При значениях analogData2 = 255-- происходит следующее, на 240 OUT2, 3 переходят в HIGH (инверсно выключены) и опять любое нажатие KEY2, 3 вызывает щелчок (выглядеть будет как вспышка света)

И ещё одно при analogData2 > 0 также в люой момент можно нажать KEY2,3 при этом диммирование прекращается и снова на OUT2, 3 LOW (инверсно ВКЛЮЧЕНЫ) - теряется задумка диммирования. В моем примере KEY2, 3 могли обрабатыватсья после 200 к примеру. Вобщем буду крутить ваш код - мне интересна задумка такая, кстати я неубирал вовсе обработку своих кнопок по IR однако они неработают и неконфликтуют с вашей обработкой.

Вот ещё. вы опредиляли выходы как: const byte OUT1 = 22; а  я как: #define OUT1 22 

на пальцах, в чём разница то?

Собственно сам код, точне ечасть кнопок IR и диммирование:

#include <Wire.h>                                     
#include <LiquidCrystal_I2C.h>                     
#include <OneWire.h>                                  
#include <IRremote.h>
LiquidCrystal_I2C lcd(0x27,20,4); 

//=====IR*
#define RECV_PIN 11                          //IR-приемник
//#define OUT1 22                              //Используем цифровой ПОРТ 22 для 1 канала свето-релейного модуля
//#define OUT2 24                              //Используем цифровой ПОРТ 24 для 2 канала свето-релейного модуля
//#define OUT3 26                              //Используем цифровой ПОРТ 26 для 3 канала свето-релейного модуля
//#define OUT4 12                              //Используем цифровой ПОРТ 12 для SunSet канала (dimmer)
const byte OUT1 = 22;       //Реле названия ваши, пины пишите свои
const byte OUT2 = 24;
const byte OUT3 = 26;
const byte OUT4 = 12;      //Здесь ваш на диммирование
int periodDimm = 200;     //Период увеличения уменьшения яркости
//для разных задач задаем разный
byte analogData2 = 0;     //Ваш переменная диммирования
long tDimm = millis();    //Переменная задержки 
byte flagDimm=0;          //Флаг для обработки Power_Key

//Key
#define POWER_KEY 0x41BEF00F       //exit-power-OFF, коды кнопок пульта    
#define KEY1 0x41BED02F            //up_relay1_ON/OFF
#define KEY2 0x41BEC03F            //enter_relay2_ON/OFF
#define KEY3 0x41BE609F            //down_relay3_ON/OFF
#define KEY4 0x41BE10EF            //vol_up_dimmer-UP_relay1
#define KEY5 0x41BE708F            //vol_down_dimmer-DOWN_relay1
//byte analogData1, analogData2 = 0;            //Значения аналоговых выходов dimmer, пока только analogata2
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;
//=====IR***

void setup(){
  Wire.begin();
  irrecv.enableIRIn();                              //Включение IR-сенсора
     pinMode(OUT1,OUTPUT);
     pinMode(OUT2,OUTPUT);
     pinMode(OUT3,OUTPUT);
     pinMode(OUT4,OUTPUT);
  digitalWrite(OUT1,HIGH);
  digitalWrite(OUT2,HIGH);
  digitalWrite(OUT3,HIGH);
  //digitalWrite(OUT4,LOW);
  analogWrite(OUT4,analogData2); //Инициация диммера
      lcd.init();                                   //Инициализируем ЖК дисплей
      lcd.setBacklight(1);  
      lcd.clear();
      lcd.setCursor(15, 3);
      lcd.print("%=");
}

//====================================================================//==================================================================================
//****Увеличение яркости******
//====================================================================//==================================================================================

 void dimmUp()        
{
 if (analogData2<255) //Ограничение верхнего значения, ставите свое.
{
 analogData2++;  //Увеличиваем на единицу
 analogWrite(OUT4,analogData2);  //Пишем в порт
 
 // Включаем подсветку при значении больше 240
 if (analogData2>240) {digitalWrite(OUT2,LOW); digitalWrite(OUT3,LOW);} 
 
 // Включаем реле диммера на первом шаге
 if (analogData2>0) {digitalWrite(OUT1,LOW);}
 tDimm=millis()+periodDimm;      //Устанавливаем время следующего шага
}
}

//******Уменьшение яркости аналогично предыдущего******
 void dimmDown()
{
 if (analogData2>0)
{
 analogData2--;
 analogWrite(OUT4,analogData2);
  if (analogData2<240) {digitalWrite(OUT2,HIGH); digitalWrite(OUT3,HIGH);}
  if (analogData2==0) {digitalWrite(OUT1,HIGH);}
 tDimm=millis()+periodDimm;
}
}

//====================================================================//==================================================================================
//                             Обработка IR-кнопок
//====================================================================//==================================================================================
void IR_key(){
  lcd.setCursor(17, 3);
  lcd.print(analogData2);
  lcd.print(" ");
  lcd.setCursor(17, 3);
  lcd.print(analogData2);
    lcd.setCursor(1, 3);
    lcd.print(!digitalRead(OUT1));
    lcd.setCursor(3, 3);
    lcd.print(!digitalRead(OUT2));
    lcd.setCursor(5, 3);
    lcd.print(!digitalRead(OUT3));

if (irrecv.decode(&results)) {        //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
    if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
      val = results.value;            //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)    
    }                                 //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
           if (val == KEY5){      
       if (analogData2 != 0)analogData2--;  
       analogWrite(OUT4, analogData2);
    }    
     if (val == KEY4){      
       if (analogData2 < 255 && digitalRead(OUT1) ==0) analogData2++;  
       analogWrite(OUT4, analogData2); 
  }
    if (results.value == KEY1 && analogData2 == 0) digitalWrite(OUT1, !digitalRead(OUT1));
    if (results.value == KEY1 && analogData2 != 0) digitalWrite(OUT1, digitalRead(OUT1));

     if (results.value == KEY2 && digitalRead(OUT1) ==0 && analogData2 > 10) 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 > 10) digitalWrite(OUT3, !digitalRead(OUT3));
  else if (results.value == KEY3 && digitalRead(OUT1) ==0 && analogData2 != 0) digitalWrite(OUT3, digitalRead(OUT3));
  
     else if (results.value == POWER_KEY) {
             if (digitalRead(OUT2) || digitalRead(OUT3)){ // digitalRead(OUT1) || digitalRead(OUT4)
        digitalWrite(OUT2, HIGH);
        digitalWrite(OUT3, HIGH);
      }
      else {
        digitalWrite(OUT2, LOW);
        digitalWrite(OUT3, LOW);
      } 
     }

  irrecv.resume(); 
}
} 
void loop()  {                                     //Отработка в цикле
    IR_key();
    
    //Считываем значение кнопки. Здесь вставляете свою функцию IR и условия меняете на KEYномер
//    key();               
    if (val==KEY4 & flagDimm==0) //Если KEY4 и не дана команда на полное выключение
    {
    //По достижении времени идем на увеличение яркости, период ставим комфортный для вас
    if (tDimm<millis()) {periodDimm=100; dimmUp();} 
    }
    if (val==KEY5 & flagDimm==0)
    {
    //Здесь аналогично увеличению яркости
    if (tDimm<millis()) {periodDimm=100; dimmDown();}
    }
    if (val==KEY2 & flagDimm==0)
    {
     //Если подсветка может быть включена, включаем-выключаем. Задержка нужна, чтобы не прыгало реле
     //при желании можно с флагами и millis()
      if (analogData2>240) { digitalWrite(OUT2, !digitalRead(OUT2));delay(200);}
    }
    if (val==KEY3 & flagDimm==0)
    {
      if (analogData2>240) { digitalWrite(OUT3, !digitalRead(OUT3));delay(200);}
    }
    //Это ваша Power. Если диммер включен, устанавливаем флаг.
    if (val==KEY1 & analogData2!=0) {flagDimm=1;}
    
      if (flagDimm

 

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

Значит все таки что то с IR (сигналы кнопок приходят иначе). Должно было быть key4,5 - увеличение уменьшение пока нажата кнопка. 2,3 короткие нажатия выключает-включает подсветки если диммер >240. delay(200) задержка 0.2сек успеть отпустить кнопку.

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

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

Если по вашему последнему коду, то возможно как раз совместные условия и конфликтуют. Попробуйте как я писал в 61 посте. Ваши условия все уберите. Фактически при вызове IR-key сперва отрабатывают ваши условия, потом пытаются работать мои. Логика совсем другая. Пороги впишите как у вас - 255 у меня диммер максимальный.

А в чем разница между const и #define и сам не знаю. Делаю и так и эдак - работает.

 

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

Кстати KEY1 условия у меня нет вообще. Он не нужен. Диммер либо включен, либо выключен. Ручное выключение убавлением яркости или power_key - у меня это как-раз KEY1 (замените, сразу не заметил)

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

Ну что Вам сказать, спасибо - ничего несказать :). Огромное СПАСИБО, всё с диммированием по ОДНОЙ кнопке работает как часы- проблеммы были именно из-за кофликта моего и вашего кодов. Получился такой код:

Жмём KEY4 - включается реле на OUT1 и начало диммирования от 0 до 255, при 200 включаются дополнительные реле на OUT2, 3

Если в процессе диммирования на analogData2 > 0 в любой момент нажать KEY1, 2, 3 - диммирования ОСТАНАВЛИВАЕТСЯ и его можно как в -- так и в ++ запустить по KEY4

При analogData2 = 255 кнопка power_key делает analogData2 --, на 240 отключаются реле OUT2, 3 и уже остановтьэто процесс никак нельзя, на то она и POWER_KEY

И снова кусочек пакости при analogData2 = 255 нажатие KEY2,3 вызыват цикл OUT2, 3 (HIGH-LOW) щелчки... пока снова не начнёш диммировать либо POWER_KEY

код:

#include <Wire.h>                                     
#include <LiquidCrystal_I2C.h>                     
#include <OneWire.h>                                  
#include <IRremote.h>
LiquidCrystal_I2C lcd(0x27,20,4); 

//=====IR*
#define RECV_PIN 11                          //IR-приемник
#define OUT1 22                              //Используем цифровой ПОРТ 22 для 1 канала свето-релейного модуля
#define OUT2 24                              //Используем цифровой ПОРТ 24 для 2 канала свето-релейного модуля
#define OUT3 26                              //Используем цифровой ПОРТ 26 для 3 канала свето-релейного модуля
#define OUT4 12                              //Используем цифровой ПОРТ 12 для SunSet канала (dimmer)
//Key
#define POWER_KEY 0x41BEF00F       //exit-power-OFF, коды кнопок пульта    
#define KEY1 0x41BED02F            //up_relay1_ON/OFF
#define KEY2 0x41BEC03F            //enter_relay2_ON/OFF
#define KEY3 0x41BE609F            //down_relay3_ON/OFF
#define KEY4 0x41BE10EF            //vol_up_dimmer-UP_relay1
#define KEY5 0x41BE708F            //vol_down_dimmer-DOWN_relay1
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;
//=====IR***
//=====Dimmer*
int periodManualDimm = 200;    //Период увеличения уменьшения яркости, для разных задач задаем разный
byte analogData2 = 0;           //Ваш переменная диммирования
byte flagDimm=0;                //Флаг для обработки Power_Key
long tDimm = millis();          //Переменная задержки 
//=====Dimmer***

void setup(){
  Wire.begin();
  irrecv.enableIRIn();                              //Включение IR-сенсора
     pinMode(OUT1,OUTPUT);
     pinMode(OUT2,OUTPUT);
     pinMode(OUT3,OUTPUT);
     pinMode(OUT4,OUTPUT);
  digitalWrite(OUT1,HIGH);
  digitalWrite(OUT2,HIGH);
  digitalWrite(OUT3,HIGH);
  analogWrite(OUT4,analogData2);                   //Инициация диммера
      lcd.init();                                   //Инициализируем ЖК дисплей
      lcd.setBacklight(1);  
      lcd.clear();
      lcd.setCursor(15, 3);
      lcd.print("%=");
}
//====================================================================//
//                             Обработка IR-кнопок
//====================================================================//
void IR_key(){
  lcd.setCursor(17, 3);
  lcd.print(analogData2);
  lcd.print(" ");
  lcd.setCursor(17, 3);
  lcd.print(analogData2);
    lcd.setCursor(1, 3);
    lcd.print(!digitalRead(OUT1));
    lcd.setCursor(3, 3);
    lcd.print(!digitalRead(OUT2));
    lcd.setCursor(5, 3);
    lcd.print(!digitalRead(OUT3));

if (irrecv.decode(&results)) {        //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
    if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
      val = results.value;            //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)    
    }                                 //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
irrecv.resume(); 
}
} 
//====================================================================//
//                             Увеличение яркости
//====================================================================//
  void dimmUp()
{
     if (analogData2<255)                            //Ограничение верхнего значения, ставите свое.
{
   analogData2++;                                    //Увеличиваем на единицу
    analogWrite(OUT4,analogData2);                   //Пишем в порт
 
     if (analogData2>20) {digitalWrite(OUT2,LOW); digitalWrite(OUT3,LOW);} // Включаем подсветку при значении больше 20
     if (analogData2>0) {digitalWrite(OUT1,LOW);}    // Включаем реле диммера на первом шаге
 tDimm=millis()+periodManualDimm;                    //Устанавливаем время следующего шага
}
}
//====================================================================//
//                             Уменьшение яркости
//====================================================================//
  void dimmDown()
{
 if (analogData2>0)
{
 analogData2--;
 analogWrite(OUT4,analogData2);
  if (analogData2<240) {digitalWrite(OUT2,HIGH); digitalWrite(OUT3,HIGH);}
  if (analogData2==0) {digitalWrite(OUT1,HIGH);}
 tDimm=millis()+periodManualDimm;
}
}
//====================================================================//
//                             Обработка нажатия
//====================================================================//    
    void Dimmer()
{
    //Считываем значение кнопки. Здесь вставляете свою функцию IR и условия меняете на KEYномер
    if (val==KEY4 & flagDimm==0) //Если KEY4 и не дана команда на полное выключение
    {
    //По достижении времени идем на увеличение яркости, период ставим комфортный для вас
    if (tDimm<millis()) {periodManualDimm=100; dimmUp();} 
    }
    if (val==KEY5 & flagDimm==0)
    {
    //Здесь аналогично увеличению яркости
    if (tDimm<millis()) {periodManualDimm=100; dimmDown();}
    }
    if (val==KEY2 & flagDimm==0)
    {
     //Если подсветка может быть включена, включаем-выключаем. Задержка нужна, чтобы не прыгало реле
     //при желании можно с флагами и millis()
      if (analogData2>240) { digitalWrite(OUT2, !digitalRead(OUT2));delay(200);}
    }
    if (val==KEY3 & flagDimm==0)
    {
      if (analogData2>240) { digitalWrite(OUT3, !digitalRead(OUT3));delay(200);}
    }
   //Это ваша Power. Если диммер включен, устанавливаем флаг.
    if (val==POWER_KEY & analogData2!=0) {flagDimm=1;}
    
      if (flagDimm==1)  //Если флаг установлен, продолжаем уменьшение яркости
      {
        if (analogData2==0) {flagDimm=0;} //Яркость на 0, флаг сбросили.
        if (tDimm<millis()) {periodManualDimm=200; dimmDown();} //Последовательно уменьшаем яркость, кнопки заблокированы.
      }
}

void loop()  {                                     //Отработка в цикле
    Dimmer();
    IR_key();
  }

 

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

Эт хорошо, что заработало. Теперь вылизывать.

строка 81 - включение подсветки при диммере 20, это не очень ярко?

порог включения подсветки лучше везде одинаковый. реле я думаю щелкают из-за разных условий на включение стр. 81, 95, 120, 124. Его опять же подбирать по банке визуально.

Для комфортного включения подсветки поигрйте с delay(200), чтобы успевать отпустить кнопку. Они только на кнопках, loop() фактически не затормозят.

строки 137 138 логично поменять местами, в данном случае без разницы, но шаговой логики лучше придерживатся.

максимум диммера надо ограничить величиной, где визуально  прибавка уже незаметна, думаю сэкономим ресурс светиков

ну и дальше железо юзать.

 

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

Thorn пишет:

Если в процессе диммирования на analogData2 > 0 в любой момент нажать KEY1, 2, 3 - диммирования ОСТАНАВЛИВАЕТСЯ и его можно как в -- так и в ++ запустить по KEY4

Вот здесь непонятно. -- и ++ должны работать только при нажатых KEY4 - 5. Остановка в момент отпускания кнопки. Одновременные нажатия нескольких не предусматривалось.

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

хехе, я тоже счас думал именно про оптимизацию :). По поводу 20 это чтоб удобнее и быстрее получить результат на макете. В реале кончно будет не ниже 200-220.

Строки также думал поменять и уже поменял. 137-138

Про светки вы мою ветку читали кстати? Я их уже по току итак ограничил вместо 0,9-1,0А на 10Вт получаю неболее 0,65-0,75А а это всего 7-8Вт также при их стоимости  1уе за штучку Но экономия электроэнергии уже будет присутсвовать надеюсь при ШИМ-на ледиках.

И вот, этот кусочек кода - он для ручного управления - как он изменит мне автоматический таймер? В таймере придется описывать диммирование  дополнительно?

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

bwn пишет:

Thorn пишет:

Если в процессе диммирования на analogData2 > 0 в любой момент нажать KEY1, 2, 3 - диммирования ОСТАНАВЛИВАЕТСЯ и его можно как в -- так и в ++ запустить по KEY4

Вот здесь непонятно. -- и ++ должны работать только при нажатых KEY4 - 5. Остановка в момент отпускания кнопки. Одновременные нажатия нескольких не предусматривалось.

нене всё нормально по KEY4 в ++ а по KEY5 в -- диммирование прдолжится с момента останова

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

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

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

Thorn пишет:

хехе, я тоже счас думал именно про оптимизацию :). По поводу 20 это чтоб удобнее и быстрее получить результат на макете. В реале кончно будет не ниже 200-220.

Про светки вы мою ветку читали кстати? Я их уже по току итак ограничил вместо 0,9-1,0А на 10Вт получаю неболее 0,65-0,75А а это всего 7-8Вт также при их стоимости  1уе за штучку Но экономия электроэнергии уже будет присутсвовать надеюсь при ШИМ-на ледиках.

Для более быстрого цикла, логичнее менять periodManualDimm, он для этого и существует.

А по токам на светиках- зачем тратить время и ресурсы если взгляду все равно не видно. ИМХО

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

Доброго вечера. Часики мои так и непришли, надож так вляпаться было. Зато с пульта я вам скажу так удобно теперь - ненужно лезть кнопоки нажимать :)

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

void ir_manual_key(){
if (irrecv.decode(&results)){ 
if (results.value != 0xFFFFFFFF){ 
val = results.value;

ЛЮБАЯ кнопка с пульта, которая была определена и даже НЕ определна прерывала выполнение

void dimmUp(){ и  void dimmDown(){

так-что зря я грешил на KEY2, 3 - я их вообще убрал из вашего примера кода :) чтобы немешались.

Теперь можно в одно касание по KEY4, 5 диммировать и включать релюшки дополнительнызх светиков так и по KEY6, 7 удержанием кнопки остановится на любом удобном analogData2 и принудительно отключать OUT3, 4 дабы использовать аквариум в качестве светильника перед сном. Вот кусок кода с кнопками, хотя нет вот весь, тут термореле, вольтметр и кнопки:

#include <Wire.h>                            //Подключаем библиотеку для использования однопроводного интерфейса                                     
#include <LiquidCrystal_I2C.h>               //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h>                         //Подключаем библиотеку для температурного датчика DS18B20
#include <IRremote.h>                        //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4);	     //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
//=====IR*
#define RECV_PIN 11                          //IR-приемник
#define OUT1 22                              //Используем цифровой ПОРТ 22 для 1 канала свето-релейного модуля
#define OUT2 24                              //Используем цифровой ПОРТ 24 для 2 канала свето-релейного модуля
#define OUT3 26                              //Используем цифровой ПОРТ 26 для 3 канала свето-релейного модуля
#define OUT4 12                              //Используем цифровой ПОРТ 12 для SunSet канала (dimmer)
//Key
/*
#define POWER_KEY 0xFF906F        //eq-power-OFF, коды кнопок пульта    
#define KEY1 0xFFA25D             //ch-_relay1_ON/OFF
#define KEY2 0xFF629D             //ch_relay2_ON/OFF
#define KEY3 0xFFE21D             //ch+_relay3_ON/OFF
#define KEY4 0xFFA857             //vol+_dimmer-UP_relay1
#define KEY5 0xFFE01F             //vol-_dimmer-DOWN_relay1
*/
#define POWER_KEY 0x41BEF00F       //exit-power-OFF, коды кнопок пульта    
#define KEY1 0x41BED02F            //up_relay1_ON/OFF
#define KEY2 0x41BEC03F            //enter_relay2_ON/OFF
#define KEY3 0x41BE609F            //down_relay3_ON/OFF
#define KEY4 0x41BE10EF            //vol_up_dimmer-UP_relay1
#define KEY5 0x41BE708F            //vol_down_dimmer-DOWN_relay1
#define KEY6 0x41BE40BF            //left_down_dimmer-DOWN_relay1_manual
#define KEY7 0x41BEB04F            //right_up_dimmer-UP_relay1_manual
uint32_t val; 
IRrecv irrecv(RECV_PIN);
decode_results results;
//=====IR***
//=====IR_Dimmer*
int periodManualDimm = 2000;        //Период увеличения уменьшения яркости, для разных задач задаем разный
byte analogData2 = 0;               //Ваш переменная диммирования
byte flagDimm=0;                    //Флаг для обработки Power_Key
long tDimm = millis();              //Переменная задержки 
//=====IR_Dimmer***
//=====TermoRelay*
const int RelayChn1 = 30;		      //Используем цифровой ПОРТ 30 для ПЕРВОГО канала термо-релейного модуля
const int RelayChn2 = 32;		      //Используем цифровой ПОРТ 32 для ВТОРОГО канала термо-релейного модуля
//=====TermoRelay***
//=====VoltMeter*
int analogInput = 0;
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;
//=====VoltMeter***
//=====TermoSensor*
int TSensorPin = 10;                         //Определяем порт шины OneWire (IC) для температурного датчика DS18B20                               
OneWire ds(TSensorPin);                        //Создаем объект для работы с термометром
byte data[12];
byte addr1[8] = {0x28, 0xF2, 0x29, 0xEB, 0x05, 0x00, 0x00, 0xE1};     //адрес датчика DS18B20
byte addr2[8] = {0x28, 0x86, 0x48, 0xEA, 0x05, 0x00, 0x00, 0xF6};     //адрес датчика DS18B20
unsigned int raw;                            //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
float temp1, temp2;                          //Температура аквариума \ радиаторов Led
float t0 = 25.5;
float t00 = 26.5;
float tGistrsis = 0.5;
//=====TermoSensor***
//=====Millis*
long prvMlsTm = 0;                            //предыдущее показание миллисекунд для обновления показания часов
long prvMlsLght = 0;                          //предыдущее показание миллисекунд для проверки временного интервала
long prvMlsVo = 0;                            //предыдущее показание миллисекунд для обновления показания вольтметра
long voIntv = 500;                            //Интервал для обновления напряжения
long prvMlsTemp = 0;                          //предыдущее показание миллисекунд для обновления показания температуы
long tempIntv = 1000;                         //Интервал для обновления температур
//=====Millis***

void setup() {
  Wire.begin();
  irrecv.enableIRIn();                              //Включение IR-сенсора
    pinMode(analogInput,INPUT);                     //Вход вольтметра
    pinMode(RelayChn1,OUTPUT);                      //Выход 1-термо-релейного модуля охлаждения радиаторов Led
    pinMode(RelayChn2,OUTPUT);                      //Выход 2-термо-релейного модуля охлаждения воды аквариума 
  digitalWrite(RelayChn1,HIGH);                     //Определяем инверсный выход в HIGH охлаждения радиаторов Led
  digitalWrite(RelayChn2,HIGH);                     //Определяем инверсный выход в HIGH охлаждения воды аквариума
     pinMode(OUT1,OUTPUT);
     pinMode(OUT2,OUTPUT);
     pinMode(OUT3,OUTPUT);
  digitalWrite(OUT1,HIGH);
  digitalWrite(OUT2,HIGH);
  digitalWrite(OUT3,HIGH);
  analogWrite(OUT4,analogData2);                    //Инициация диммера
      lcd.init();                                   //Инициализируем ЖК дисплей
      lcd.setBacklight(1);  
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Aqua  Controller");
      lcd.setCursor(2, 1);
      lcd.print("      v1.0      ");
  delay(1000);
      lcd.clear();                                   //Очистка дисплея и вывод статичной информации
      lcd.setCursor(0, 0);
      lcd.print("Time");
      lcd.setCursor(0, 2);
      lcd.print("t1=");
      lcd.setCursor(10, 2);
      lcd.print("t2=");
      lcd.setCursor(0, 3);
      lcd.print("r");
      lcd.setCursor(2, 3);
      lcd.print(":");
      lcd.setCursor(4, 3);
      lcd.print(":");
      lcd.setCursor(7, 3);
      lcd.print("v=");
      lcd.setCursor(15, 3);
      lcd.print("%=");
}
//====================================================================//==================================================================================
//========== Обработка IR-кнопок, ручное управление реле и диммером
//====================================================================//==================================================================================
void ir_manual_key(){
   if (irrecv.decode(&results)){      //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную 
    if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
      val = results.value;            //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)    
    }                                 //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
//====================================================================//
//========== Увеличение яркости (удержание кнопки)
//====================================================================//           
      if (val == KEY7){      
      if (analogData2 < 255) analogData2++;  
         analogWrite(OUT4, analogData2);
         if (analogData2>0) {                             //Включаем реле диммера на первом шаге
         digitalWrite(OUT1,LOW);
         }
      if (analogData2>20) {                            //Включаем подсветку при значении больше 20 на втором реле
         digitalWrite(OUT2,LOW);
         }    
      if (analogData2>40) {                             //Включаем подсветку при значении больше 40 на третьем реле
         digitalWrite(OUT3,LOW);
         }
    }
//====================================================================//
//========== Уменьшение яркости (удержание кнопки)
//====================================================================//
        if (val == KEY6){      
       if (analogData2 != 0) analogData2--;  
       analogWrite(OUT4, analogData2);
       if (analogData2<35) {
          digitalWrite(OUT3,HIGH);
          }
       if (analogData2<25) {
          digitalWrite(OUT2,HIGH); 
          }
       if (analogData2==0) {
          digitalWrite(OUT1,HIGH);
          }
     }
//====================================================================//
//========== Отключение НЕдиммируемых реле
//====================================================================// 
     if (results.value == KEY2 && !digitalRead(OUT1) !=0 && analogData2 > 10) 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 > 10) 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.print(" ");
    lcd.setCursor(17, 3);
    lcd.print(analogData2);
      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<50)                    //Ограничение верхнего значения, (0-255)
  {
   analogData2++;                           //Увеличиваем на единицу
   analogWrite(OUT4,analogData2);           //Пишем в порт
    if (analogData2>0) {                    //Включаем реле диммера на первом шаге
   digitalWrite(OUT1,LOW);
   }
    if (analogData2>20) {                    //Включаем подсветку при значении больше 20 на втором реле
   digitalWrite(OUT2,LOW);
   }    
   if (analogData2>40) {                     //Включаем подсветку при значении больше 40 на третьем реле
  digitalWrite(OUT3,LOW);
  }
 tDimm=millis()+periodManualDimm;            //Устанавливаем время следующего шага
  }
}
//====================================================================//
//========== Уменьшение яркости (одно нажатие)
//====================================================================//
  void dimmDown(){
    if (analogData2>0)
  {
   analogData2--;
     analogWrite(OUT4,analogData2);
  if (analogData2<35) {
  digitalWrite(OUT3,HIGH);
  }
  if (analogData2<25) {
  digitalWrite(OUT2,HIGH); 
  }
  if (analogData2==0) {
  digitalWrite(OUT1,HIGH);
  }
 tDimm=millis()+periodManualDimm;
  }
}
//====================================================================//
//========== Обработка нажатия (одно нажатие)
//====================================================================//    
void auto_key_dimmer(){                    //Считываем значение кнопки. 
 
    if (val==KEY4 & flagDimm==0){          //Если KEY4 и не дана команда на полное выключение
    //По достижении времени идем на увеличение яркости, период ставим комфортный для вас
    if (tDimm<millis()) {
      periodManualDimm=500; dimmUp();
       } 
  }
    if (val==KEY5 & flagDimm==0){          //Здесь аналогично увеличению яркости
    if (tDimm<millis()) {periodManualDimm=200; dimmDown();}
        }
    if (val==POWER_KEY & analogData2!=0){  //Power. Если диммер включен, устанавливаем флаг.
    flagDimm=1;
  }
    if (flagDimm==1){                     //Если флаг установлен, продолжаем уменьшение яркости
    if (analogData2==0){                  //Яркость на 0, флаг сбросили.
    flagDimm=0;
        }
    if (tDimm<millis()){                  //Последовательно уменьшаем яркость, кнопки заблокированы.
    periodManualDimm=500; dimmDown();
        } 
    }
}
//====================================================================//==================================================================================
//========== Считывание напряжения
//====================================================================//==================================================================================
void printVolt (){
   value = analogRead(analogInput);                //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
      }
   lcd.setCursor(9, 3);
   lcd.print(vin);
}
//====================================================================//==================================================================================
//=========== Считывание темпиратур
//====================================================================//==================================================================================
float DS18B20(byte *adres){
    ds.reset();
  ds.select(adres);
  ds.write(0x44,1);                             //Start conversion, with parasite power on at the end
    ds.reset();
  ds.select(adres);
  ds.write(0xBE);                               //Read Scratchpad
  for (byte i = 0; i < 9; i++) {                //We need 9 bytes
    data[i] = ds.read ();
    }
  raw =  (data[1] << 8) | data[0];              //Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
   }
//====================================================================//==================================================================================
//                             Обработка Термо-Реле
//====================================================================//==================================================================================
  void printTemp (){
    temp1 = DS18B20(addr1);
    temp2 = DS18B20(addr2);
   if (temp1 > t0-tGistrsis/2)
      {
        digitalWrite(RelayChn1,LOW);                 //Термо-реле 1-включается
        lcd.setCursor(8, 2);
        lcd.print("*");
      }     
    else if (temp1 < t0+tGistrsis/2)
      {
        digitalWrite(RelayChn1,HIGH);                //Термо-реле 1-выключается
        lcd.setCursor(8, 2);
        lcd.print("-");
      } 
   if (temp2 > t00-tGistrsis/2)
      {
        digitalWrite(RelayChn2,LOW);                 //Термо-реле 2-включается
        lcd.setCursor(18, 2);
        lcd.print("*");
      }     
    else if (temp2 < t00+tGistrsis/2)
      {
        digitalWrite(RelayChn2,HIGH);                //Термо-реле 2-выключается
        lcd.setCursor(18, 2);
        lcd.print("-");
      } 
  lcd.setCursor(3, 2);                       
  lcd.print(temp1);
  lcd.setCursor(13, 2);                          
  lcd.print(temp2);     
} 
//====================================================================//
//========== Обработка в цикле
//====================================================================//    
void loop(){ 
    ir_manual_key();
    auto_key_dimmer();
  unsigned long currentMillis = millis();
  if(currentMillis - prvMlsTemp > tempIntv) {      //Проверяем интервал для обновления температуры
    prvMlsTemp = currentMillis;
    printTemp();
    }
  if(currentMillis - prvMlsVo > voIntv) {          //проверяем интервал для обновления напряжения
    prvMlsVo = currentMillis;
    printVolt();
    }
}

 Скажите, пока нелазал по инету но чую что можно програмно сделать часики - благо у меня нетак много наворотов и МЕГА думаю справится.

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

Кажись нашёл - а попробуюка чтонибудь пока из того что есть http://arduino.ru/forum/programmirovanie/chasy-i-arduino

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

Если все работает, значит нормально.

Что не понравилось:

Пороги включения и выключения подсветки для каждого реле лучше везде поставить одинаковые. Хоть визуально и не видно, но все равно работает некорректно. А это грабли.

Зачем так часто измерять напряжение и температуру. Прыгающие значения каждые 0,5 сек. на вольтметре должны раздражать - 5сек. Температура кушает ценные ресурсы процессора, при 1сек датчик работает практически без перерыва. На мой взгляд для LED-дов - 20-30сек., для банки и 3 минуты за глаза.

Не уверен в корректности работы блока температуры. Между строками 259 и 260 должна быть задержка в 750мС. Лучше это разбить на две функции. Запустили конвертацию, через 750мС считали. В строке 259 убрать 1, она нужна для двухпроводной линии.

Делать часы програмно - грабли. Сбой питания - ставь по новой, проблема убегания будет сильнее чем на 1307. Лучше дождатся и делать нормально.

А пока начинать юзать меню. Тоже задача веселая))).

 

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

Да, еще, в блоке измерения температуры есть смысл добавить проверку CRC и обрыв линии. Для банки и LED-ов это критично. Надо alarm кричать.

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

Да, часики содрал, поправил под свои LSD выглядит кошмар :). - однако я в любом случае с ними поиграю как с таймером суточным на пару заданий, ОДНАКО - их нужно устанавливать и таймер нужно устанавливать, а это кнопки (в моем случае с IR) вот это и буду пробовать. 

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

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;
}

а как мне свои подставить здесь results.value == KEY2 итп 

Тоесть мень на кнопках от IR.

 

И да ваша замечание о .... Между строками 259 и 260 должна быть задержка в 750мС. я пытался в прошлый раз поправить но так и несмог понять как вставить, с delay все просто а тут ника невкурю. Вот как вы предлагали:

tzad=millis()+750; flag=1;

в loop:

if (flag==0) {DallasStartTemp()}

if (tzad<millis()) {tempDallas()}

в tempDallas() считываем и производим расчет температуры. flag=0;

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

Кстати не страшно если я на эту тему ссылочку дам, там человек в соседней теме мается и руки уже опустил.

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

Блин счас смотрю ваш первый скетч для меня - он шикарен, атк здорово всё описано, нужно было на время закоментить влажность на DHT датчике, добавить диммирование, и прочее мое - меню у вас уже есть лиш поменять кнопки на мои IR. Однако тогда я ничему ненаучился бы как сейчас, спустя почти три недели тыканий по кнопками и читке Refrence

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

Не неполучается прсто так закоментить, началось грабли на нехватку библиотек, а когда вроде вот уже и можно просто глянуть на экранчик - ОПА и на эту строки в вашем коде:

if (ReadEEPROM_Word(0)<400) {WriteEEPROM_Word(0, 510);} //Значение клавиши Set

и ту тя понял чт EPROM непобедим :)

ПО поводу строк 259 и 260 должна быть задержка в 750мС... сделал так. В инициализации прописал (по аналогии как вы сделали в dimmUP и dimmDOWN:

long tzad=millis();
byte flagDallas=0;

и собственно в считываение темпиратур:

//==================================================================================
//=========== Считывание темпиратур
//==================================================================================
float DS18B20(byte *adres){
ds.reset();
ds.select(adres);
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750; flagDallas=1;
ds.reset();
ds.select(adres);
ds.write(0xBE); //Read Scratchpad
for (byte i = 0; i < 9; i++) { //We need 9 bytes
data[i] = ds.read ();
}
raw = (data[1] << 8) | data[0]; //Пересчитываем в температуру
float celsius = (float)raw / 16.0;
return celsius;
}

а вот в loop  как добавить, я же Неиспользую библиотек Dallas!!!!

Хотя и счас все работает :)

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

Строки 257-259 в отдельную функцию. Строку 258 меняем на  ds.write(0xCC);      //Команда инициации

Строку 256 перед 260 с нее начинается другая функция.

С millis() вы вроде работать научились. Теперь в loop() идем в первую функцию, там дополнительно задаем задержку в 750мС и поднимаем флаг. Флаг нужен чтобы не запускать повторно конвертацию, если она уже идет. После истечения времени можем идти во вторую функцию или на ваш void printTemp () из которого и вызовем вторую функцию (название можете ваши оставить)

 

После считывания опустить флаг. Попробуйте сами. Не получится, помогу.

 

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

Библиотека Dallas это обертка для Wire, на мой взгляд не самая удобная. На EEPROMе у меня меню и константы типа кода клавиш. И он вполне победим. Вам меню оптимальнее делать с пульта. С eeprom и той библой мне 2-х дней хватило, больше с косяками намучился. Если не будете использовать отрицательные, дробные величины и более 255, так и ардуиновских функций достаточно.

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

bwn пишет:

Библиотека Dallas это обертка для Wire, на мой взгляд не самая удобная. На EEPROMе у меня меню и константы типа кода клавиш. И он вполне победим. Вам меню оптимальнее делать с пульта. С eeprom и той библой мне 2-х дней хватило, больше с косяками намучился. Если не будете использовать отрицательные, дробные величины и более 255, так и ардуиновских функций достаточно.

Мда, без вашей мудрой помощщи ГУРУ я бы счас наделал..., то как я вставил:

ds.select(adres);
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750; flagDallas=1; 

спустя некоторое время вызывало такой КОЛЛАПС что LED-экранчик  выводил некое подобие бегущих строк с кирилицей (само собой которая у меня выводлистя всякими козябрами). Хотя могу предположить что виной всему именно в питании, сейчас всё это макетно запитано от USB и в пики сработки релюшек проседает до 3,98-4,08В (Вольт). И функционал слхраняется (тоесть все гаснет и щёлкает) но выводится "раком" на экранчик.

А по остальному ход понятен буду пробовать!!!

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

Релюшки на USB не есть хорошо, можно без порта остатся. Лучше уж зарядку какую нибудь приспособить.

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

Вместо них я обычно светики пробую (но из-за инверсности путают они) и небыло проблемм а счас снял с аквариума, поправил апараметры analogData2 и прочее для удобства и скорости тестов и натебе. Кстати БП импульсный что я питаю ЛЕДики свои удобен ещё и тем то имеет +3,3 и +5,0В неплохо стабилизированных и высокоТОчных - как раз если МЕГУ R3 осталю как макетку а НАНУ воткну в работу и релюшки также 5-ти Вольтовые выбирал из за этого.

На сегодня думаю все, вам спасибо и нетолько, привет рыбасикам вашим.

Кстати первое время от сильных "дум" - ночами ардуинка с её туда-сюда кодом снилась :) несмотря на возраст.

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

Так вы светики не к 0, а к +5 подтяните. вот и инверсия.

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

bwn пишет:

Так вы светики не к 0, а к +5 подтяните. вот и инверсия.

Ёлки-палки, точно тоесть всего то надо "перевернуть" и не к 22,24,26 пинам ина "о" или как принято на "gnd" а на +5В, точчно!!!. 

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

Тяк, утро вечера мудренее. С меню - изначально, забейте на кнопки вы с ними уже умеете работать. Берем бумажку, расписываем что мы хотим видеть в меню. Прикидываем нужно ли субменю или обойдемся одним уровнем. Как мы хотим видеть и какие переменные в меню, можем хранить только пока есть питание или все же EEPROM. Прикидываем алгоритм как мы это сделаем. После этого уже можно подумать чем будем увеличивать - уменьшать переменную и подтверждать. Не забываем, что потом с нашими данными будет работать и основной код.

А рыбок у меня нет, если карасей в пруду не считать))).

 

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

Доброго времени суток.

bwn пишет:

Строки 257-259 в отдельную функцию. Строку 258 меняем на  ds.write(0xCC);      //Команда инициации

-сдлал и вышло вот так:





//=============================================================
// Считывание темпиратур
//=============================================================
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){
  ds.reset();
  ds.select(adres);
  ds.write(0xBE);                               //Read Scratchpad
  for (byte i = 0; i < 9; i++) {                //We need 9 bytes
    data[i] = ds.read ();
    }
  raw =  (data[1] << 8) | data[0];              //Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
   }

bwn пишет:
Строку 256 перед 260 с нее начинается другая функция.

-всё поправил.

bwn пишет:
Теперь в loop() идем в первую функцию, там дополнительно задаем задержку в 750мС и поднимаем флаг. Флаг нужен чтобы не запускать повторно конвертацию, если она уже идет. После истечения времени можем идти во вторую функцию или на ваш void printTemp ()





void loop(){ 
    ir_manual_key();
    auto_key_dimmer();
    dallas();
  unsigned long currentMillis = millis();
  if(currentMillis - prvMlsTemp > tempIntv) {      //Проверяем интервал для обновления температуры
    prvMlsTemp = currentMillis;
    printTemp();
    }
  if(currentMillis - prvMlsVo > voIntv) {          //проверяем интервал для обновления напряжения
    prvMlsVo = currentMillis;
    printVolt();
    }
}

Чую что то упустил :) и подразумеваю флаги flagDallas=() в loop; верно?

И у меня ещё одна новость - приделал отключение включение подсветки LCD, тыкался тыкался но пока ненашол как делать её ПЛАВНОЙ типа analogWrite.

для этого добавил в определение:

LiquidCrystal_I2C lcd(0x27,20,4); //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0; //Переменная включения подсветки LCD

и в void (кнопок):

lcd.setBacklight(currentLight);
if (results.value == KEY8) {
currentLight=!currentLight;
tzad=millis()+1000;
}

но как то всеравно срабатывает неаккуратно, может и мигнуть а может и никак несреагировать, думаю не в тот loop () воткнул строки. я их поставил сразу после определения удержания if (results.value != 0xFFFFFFFF)

Кстати находил упоминание о 750мС тут http://catethysis.ru/stm32-1-wire-18b20/ , здест mdct комманды для работы с ним (для меня чуть проясняется но всерано темновато).

А вкл\выкл подсветки я сделал не прсото так я сначала увидел как им мигают и поверьте выглядит весьма (это я применю к обрыву при измерении темпиратур, потере адреса вроде называется) будет ALLERT и tone зуммером 

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

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

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

так следуя вашим рекомендациям. Темпиратуру 1 раз в минуту, это будет так:

long tempIntv = 60000; //Интервал для обновления температур

и напряжени(й), все возможные от 12 до 3,3 (есл ив дальнейшем получится "листать" экран lcd выведу их отдельно, ну может, итак напряжений 1 раз в 3мин:

long voIntv = 18000; //Интервал для обновления напряжения

НО мне кажется можно как то перевести 18000 и 6000 в мин, хотя и так сойдёт. Просто пока всё "на столе" - удобнее и вывод ускорит (зажать и нагреть датчик быстрее проверить термореле) и также с дммирование не 255 а всего 50.

 

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

Про меню, я так понял это ТО что выводится на lcd + то что потмо настраиватеся. С выводом я уже кое-как определился хотя периодически "двигаю" туда-сюда. А вот с установками тут просто. Время и дату (ну а вдруг), далее таймеры поочереди (вкл\выкл) каждого OUT1, 2, 3 .Далее Время начала  прдолжительность analogData2++ (диммирование) и тоже самое вниз-- (и тут хитрость мне же нужно пару раз в день делать analogData2++ (утром и вечером) и тоже с -- (утром и вечером). И собственно контроль темпиратур (верхний\нижний предел для охлаждения\нагрева) и само собой к нему Гистерезис (инертность некую). Условие ручного\автоматического управления нашими OUT и analogData2 с пульта - выговорили будут сложности. Вот самые основне моменты. впоследствии если захочу добавить таймер какой я уже буду знать как к 3-м имеющимся добавить ещё, ровно как и к диммированию если смогу ВСЕ 30 штук объединить. Может автокормушку на моторчике от fdd добавлю - снова поаналогии вставлю. Так-же с темпиратурами.

Вобщем как вы научили меня с кнопками и задержками а также с if работать также и тут пойму.

Кстати на аквафоруме был проект один в один как я понял - идея как у меня, именно функционал  вот видео с него - там ну все как я думал и количество и функционал и меню однако с форума человек пропал года два и никак недостучаться. Вот ссылка на видео:

http://www.youtube.com/watch?v=-Bl5KrHvWDA 

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

Значит так, простой вариант - строка 4 второго кода вход при условии flagDallas==0; в шестую строку добавляем еще одно условие tzad<millis(). После 10 строки первого кода flagdallas=0;

Вариант более кошерный: перед 10 строкой второго кода - если tzad<millis() то flagdallas=0; в шестой строке как выше.

Сами попробуете разобратся в чем разница?

Плавную подсветку на LCD I2C по моему нереально, если только библу не переписать, чтобы вывод ШИМ-ом дрыгал или провода подсветки отдельно на шим выводить. Выключать ее наверно лучше автоматически по интервалу, а вот включать по нажатию любой кнопки или по событию.

Переводить в минуты интервалы смысла нет, тогда добавится математика пересчета обратно в millis(). Можно заморочится если из меню захотим регулировать.

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

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

Время диммирования опять можем уложить в BYTE в виде минут, пересчет вести в программе. Это если не коммерческая версия. Там ставить жестко.

Температура - или допускаем только целые числа и тогда BYTE, либо FLOAT с прелестями расчлененки или библиотеки. Гистерезис в меню наверно лишнее. Забить в программу и не вспоминать.

OUT и analogData2 я имел в виду запрет кнопок на время рассвета-заката, либо предусматривать выход из этой процедуры по нажатию клавиши. Иначе у вас закат, а вы начинаете прибавлять, и пошла борьба кто быстрее.

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

Посмотрел видео, лично по мне - сильно загроможден экран. Регулировать RGB отдельными рукоятками имея контроллер, зачем? Рабочая зона подсветки сужена минимум на 30% при ярком не понять, но думаю тоже не мало.

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

Меню, да красивое.  Для исполнения весьма сложное.

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

Thorn пишет:

НО мне кажется можно как то перевести 18000 и 6000 в мин, хотя и так сойдёт. Просто пока всё "на столе" - удобнее и вывод ускорит (зажать и нагреть датчик быстрее проверить термореле) и также с дммирование не 255 а всего 50.

 

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

То же самое и с порогами диммирования, включения-выключения

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

bwn пишет:

Значит так, простой вариант - строка 4 второго кода вход при условии flagDallas==0; в шестую строку добавляем еще одно условие tzad<millis(). После 10 строки первого кода flagdallas=0;

Вариант более кошерный: перед 10 строкой второго кода - если tzad<millis() то flagdallas=0; в шестой строке как выше.

Сами попробуете разобратся в чем разница?

Прямо как на экзамене почувствовал себя, без которого дальше пути небудет :). В первом случае строка 4 и  выполнение функции void dallas(); возможно при условии если переменная == 0 в коде так:

 dallas(); flagDallas==0;

далее 6 строка если текущее количество миллисекунд с момента начала выполнения МИНУС предыдущее показание миллисекунд для обновления показания темпиратуы БОЛЬШЕ указанного интервала для обновления температуры то предыдущее РАВНО текущему и вывод на экранчик lcd. Мы добавляем сюда интервал задержки (целочисленное значение) МЕНЬШЕ текущего интервала и только тогда prvMlsTemp = currentMillis; Выглядеть будет так:

if(currentMillis - prvMlsTemp > tempIntv && tzad<millis()) { //Проверяем интервал для обновления температуры
prvMlsTemp = currentMillis;
printTemp();
}

После 10 строки первого кода flagdallas=0; здесь перед сбросом, выбором чтения всех адресов и чтением регистров ds18b20  переменная присвоен 0.

ВО втором варианте, перед 10 строкой второго кода получилось так:

prvMlsTemp = currentMillis;
printTemp();
tzad<millis(); flagDallas=0;
}

после приравнивания предыдущего интервала к текущему вывод темпиратур и если заданный интервал для Dallas меньше интервала !!!  тогда переменная Dallas присвоен 0. 

Блин как же сложно, счас я склонен полагать что они одинаково работают для чтения устройства на линии и нужно дать время на измерение, (не менее 375 милисекунд). Вобщем написал что сам непонял - нужно начать запуск измерения на втором Dallas если на перовом уже чтение результата началось +750 мсек задержки, так? И flagDallas определяет какой из датчиков уже отмерил свое и считывает результаты.

С кодом чт ото нето у меня и в таком виде: if(currentMillis - prvMlsTemp > tempIntv && tzad<millis()) у меня пустые ячейки темпиратур, ничего невыводится. Пока я иссяк инемогу вам ничего отвтеить больше.

bwn пишет:
Время диммирования опять можем уложить в BYTE в виде минут, пересчет вести в программе. Это если не коммерческая версия. Там ставить жестко.

тут я выпал в осадок, от коммерческой версии эко вы как закрутили. Все переменные исключительно в BYTE чтобы как вы уже говорили их ПРЯМО записывать в адрес EPROM. А занчит ВСЁ округлять и диммирование (достаточно не то что ЧАСА всего ДЕСЯТКОВ минут, и темпиратуры - вывод будет красив с точнойстью до сотых а срабатывать пусть будет на целочисленных значениях. Банка с одой штука весьма ИНЕРТНАЯ тут +-градус-другой для воды и десяток градусов для светиков некритичен.

bwn пишет:
Меню, да красивое. Для исполнения весьма сложное.
Это навернео и подкупило, про RGB парень конечно перегнул крутить руками - это я первым делом сделаю с пультика как поставлю deepBlue и RED 620нм для глубокого цвета, но  (в ближайшем будущем, с ростом доллара ebay подождёт) - а таймером просто задать пределы и устанавливать их при диммировани чтобы непересвечивать синевой и краснотой. Но в остальном я смотрел и опнимал - моё, так я и думал сделать, кинулся на форум с просьбой о скетчике, потмоу как экранчик такойже, кнопок минимум, функционально то что надо - а его и след простыл пару лет почти назад.

Однако ТО что сейчас получилось БОЛЬШЕ чем ожидал уже.

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

Доброго дня и с наступающим. По вопросу разобратся, такой развернутый ответ не нужен. Вывод там один - в первом случае вы считаете температуру с опозданием на минуту, во втором не более 1 секунды. Первый вариант я понял работает корректно, а второй нет. Если не трудно, сбросьте ваш вариант скетча с температурой по 2 варианту, покручу - возможно сам накосячил.

"Блин как же сложно, счас я склонен полагать что они одинаково работают для чтения устройства на линии и нужно дать время на измерение, (не менее 375 милисекунд). Вобщем написал что сам непонял - нужно начать запуск измерения на втором Dallas если на перовом уже чтение результата началось +750 мсек задержки, так? И flagDallas определяет какой из датчиков уже отмерил свое и считывает результаты." -              Команду на конвертацию 0х44, мы даем для всех датчиков на линии 0хСС и через 750мС все они готовы нам ее отдать. flagDallas должен был блокировать вход в функцию конвертации пока не взяли температуру с датчиков. Где то здесь я ошибся. Надо искать.

Задержка на даллас >=750mC в нашем варианте. Более низкие при меньшей разрядности, ее надо задавать до запуска на конвертацию. И там будет другой алгоритм пересчета.

А про пультик, что контроллер может делать сам, он и должен делать, оставляя хозяину возможность для корректировки, ИМХО. Вы все время пытаетесь поставить приоритет на пульт, хотя он вторичен. Со всеми регулировками вы наиграетесь за неделю, а дальше девайс будет жить своей жизнью и желательно как можно реже о себе напоминать.

Коммерческая версия, а почему нет?  Все что нам предлагают бренды - имеет минимум раза в два, три заряженную цену. Китайцы копируют массовый продукт. И достаточно много таких самоделок идет потом в мелкие серии.

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

Доброго времени, и вас с наступающими. Счас суета спасибо что уже откликаетесь. Постараюсь до 03 незадавать вопросов и мног пробовать самому.

Получилось вот так в цикле, это loop():

void loop(){
ir_manual_key();
auto_key_dimmer();
dallas();
unsigned long currentMillis = millis();
if(currentMillis - prvMlsTemp > tempIntv && tzad<millis()) { //Проверяем интервал для обновления температуры
prvMlsTemp = currentMillis;
printTemp();
tzad < millis(); flagDallas = 0;
}
if(currentMillis - prvMlsVo > voIntv) { //проверяем интервал для обновления напряжения
prvMlsVo = currentMillis;
printVolt();
}
}

и так в функции опроса Dallas, это void():

void dallas (){
  ds.reset();
  ds.write(0xCC);                             //Команда инициации  
  ds.write(0x44);                               
 tzad=millis()+750; flagDallas=1;
}
float DS18B20(byte *adres){
//  flagDallas=0;
  ds.reset();
  ds.select(adres);
  ds.write(0xBE);                               
  for (byte i = 0; i < 9; i++) {               
    data[i] = ds.read ();
    }
  raw =  (data[1] << 8) | data[0];              //Пересчитываем в температуру
  float celsius =  (float)raw / 16.0;
  return celsius;
   }

Про пульт, он ВТОРИЧЕН ровно как и ДИСПЛЕЙ, прост она этом этапе он очнеь выручает а потмо настроил и забыл (меню и setup параметров) - однако как досветка акавариумом комнаты он необходим будет думаю часто.

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

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

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

С Праздником, уважаемые Форумчане и форумчанки! Желаю успехов в начинаниях, неостанавливатсья на достигнутом :) и доводить все до готового продукта :)) !!!!

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

Получилось вот что. Часики вот:

#include <Wire.h>                                     

long previousMillis = 0;  //переменная для хранения значений таймера
long prevmicros=0;        //переменная для хранения значений таймера
int sek=0;                //значение секунд
int minut=0;               //значение минут
int chas=0;               //значение часов
boolean counter=false;    // счетчик для полусекунд

void setup() {
 Wire.begin();
 lcd.init();                                   //Инициализируем ЖК дисплей
 lcd.setBacklight(1);  
 lcd.clear();
  }
void loop() {
if (micros() - prevmicros >500000)
 {    prevmicros = micros();  //принимает значение каждые полсекунды
   counter=!counter;
   if (counter==false)
   {     sek++;              //переменная секунда + 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(" ");    // мигание :
   }
   
   if(sek>59)//если переменная секунда больше 59 ...
   {
     sek=0;//сбрасываем ее на 0
     minut++;//пишем +1 в переменную минута
   }
   if(minut>59)//если переменная минута больше 59 ...
   {
     minut=0;//сбрасываем ее на 0
     chas++;//пишем +1 в переменную час
   }
   if(chas>23)//если переменная час больше 23 ...
   {
     chas=0;//сбрасываем ее на 0
   }
      
   lcd.setCursor(0,0);//выводим значение часов 
   if (chas>=0 && chas<10) {
     lcd.print("0");
     lcd.print(chas);}//количество часов
     else lcd.print(chas);
     
   lcd.setCursor(3,0);//выводим значение минут
   if (minut>=0 && minut<10) {
     lcd.print("0");
     lcd.print(minut);}//количество минут
     else lcd.print(minut);
     
   lcd.setCursor(6,0);//выводим значение секунд
   if (sek>=0 && sek<10) {
     lcd.print("0");
     lcd.print(sek);}//количество секунд
     else lcd.print(sek);
 }
}

Далее вот такой кусочек для обработки таймера ВТОРОГО канала освещения (недиммируемого), обращаю внимание что для удобства и скорости приравнивал значнеия НЕ к часам и минутам а к СЕКУНДАМ, ну чтоб наглядно увидеть срабатывает реле или нет, итак вот кусочек по таймеру:

byte lghtStat1 = 0;                //Флаг освещения, если включена, то в 1
byte lghtStat2 = 0;                //Флаг освещения, если включена, то в 1
byte lghtStat3 = 0;                //Флаг освещения, если включена, то в 1
byte upLghtTime = 8;              //Флаг включаения в 8 
byte downLghtTime = 17;           //Флаг выключаения в 17
byte isNight = 0;                 //Если включаем на ночь, т.е. начальное время больше конечного
byte prevSec = 0;                 //Предыдущее показание секунд для перезапуска если остановились
byte isLght1 = 0;                 //Флаг для обработки необходимости включить реле освещения на 1 канале
byte isLght2 = 0;                 //Флаг для обработки необходимости включить реле освещения на 2 канале
byte isLght3 = 0;                 //Флаг для обработки необходимости включить реле освещения на 3 канале

// в setup добавить
if (upLghtTime > downLghtTime) {          //если ночное время
    isNight = 1;

void light () {                          //Включаем/выключаем освещение аквариума
  if (isNight == 0) {                    //если день
  
    if (sek >= upLghtTime && sek < downLghtTime) {           //проверяем интервал
      isLght2 = 1;                       //если необходимо включить свет
    } 
    else {
      isLght2 = 0;
    }
 }
  else {                               //если ночь
    if(sek - upLghtTime >= 0) {        //если больше или равно верхнему значению, то необходимо включить свет
      isLght2 = 1;                     //если необходимо включить свет
    } else {
      if(sek < downLghtTime) {        //если меньше нижнего значения, то необходимо включить свет
        isLght2 = 1;                  //если необходимо включить свет
      } else {
        isLght2 = 0;
      }
    }
  }                                 

  if((isLght2 == 1) && (lghtStat2 == 0)) {   //если свет еще не включен и выставлен флаг необходимости включить
       lghtStat2 = 1;
       digitalWrite(OUT2, LOW);     //собственно, включаем 
        lcd.setCursor(3, 3);
        lcd.print(!digitalRead(OUT2));

   } else {
     if(isLght2 == 0 && lghtStat2 == 1) {
         lghtStat2 = 0;
        digitalWrite(OUT2, HIGH);    //собственно, выключаем 
        lcd.setCursor(3, 3);
        lcd.print(!digitalRead(OUT2));
     }
   }    
}

Очень переживал что Небудь корректно работать с ручным управлением (с пульта) поначалу так и было и кнопки неработали :( - пока нерешил использовать ФЛАГ isLght2 - для проверки необходимости вкл\выкл и сразу все пучком и без разницы выключился или включился таймер - я могу с кнопки его обрабатывать. 

Пока только на один канал, добавлю аткойже точно на второй а вот с каналом на диммирование пока незнаю как. Там же сначала   analogData2 = 0 после этого нужно OUT1, LOW (это включить инверсно) и потмо диммировтаь по типу ручного, может какт овставлю void этого самого диммирования в void таймера, такого непробовал пока. Сейчас поисчу в закромах аккумулятор какой-нибудь 12В к небу ВС-down до 7вольт - чтоб часики несбивались и ардуинка жила долго и попробую поставить в таком полурабочем виде в банку.