Полив. Прошу совета. (Nano)

arcon73
Offline
Зарегистрирован: 06.04.2017

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

Спросить некого, да и сам не много знаю.

Модули:

Экран 20x4 по I2C
Nano v3.0 (328)

Модуль реле 8x

часы 3231 с 24с32

Преобразователь 12v на 5v (2А)

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

Может от дребезга? Хотя вроде старался жёстко ограничить параметры. 
Код только на стадии прорисовки меню...А уже такая проблема не комфортная.

Может ткнет кто пальцем где ошибся?

З.Ы.  Есть ещё вопрос о прикручивании 1-4 датчиков(поплавков). Смысл такой же как и на кнопки ( либо использовать 1 главный (налилось/неналилось) или же несколько, поделить эти данные на несколько....
А на чём реализовать? Думаю нужны транзисторы... Как именно не сообразил. Ибо 30-40 метров преодолевать по витой паре 5V будет затруднительно, показалось что следует взять 12 от главного источника....

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

/*  

*/


#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Sodaq_DS3231.h>


LiquidCrystal_I2C lcd(0x27, 20, 4); //определение LCD 

    #define relay1Pin 2 //реле
    #define relay2Pin 3
    #define relay3Pin 4
    #define relay4Pin 5
    #define relay5Pin 6
    #define relay6Pin 7
    #define KB A0 //порт клавы
    int menu_num = 0; //первоначально
    int menu_sub1=0;
    int menu_sub2=0;
    //int menu_sub3=0;
    //int KEYS_DELAY = 50;
//DateTime dt(2017, 3, 27, 23, 36, 0, 1);
int K=0; //переменная клавы
char CL_STR[]="                     ";//буфер чистой строки

void setup () 
{
  Serial.begin(9600);//инит порта
//rtc.setDateTime(dt);
lcd.init();
lcd.init();//инит LCD
Wire.begin();//
rtc.begin();//
lcd.clear();//очистка
lcd.backlight();//подсветка
      
      pinMode (KB,INPUT); // порт клавы
      //digitalWrite(KB, HIGH); //подтягивающий
      pinMode(relay1Pin, OUTPUT); // объявляем реле1 в качестве выхода
      digitalWrite(relay1Pin, HIGH); // выключаем реле
      pinMode(relay2Pin, OUTPUT); // объявляем реле2 в качестве выхода
      digitalWrite(relay2Pin, HIGH);
      pinMode(relay3Pin, OUTPUT); // объявляем реле3 в качестве выхода
      digitalWrite(relay3Pin, HIGH);
      pinMode(relay4Pin, OUTPUT); // объявляем реле4 в качестве выхода
      digitalWrite(relay4Pin, HIGH);
      pinMode(relay5Pin, OUTPUT); // объявляем реле5 в качестве выхода
      digitalWrite(relay5Pin, HIGH);
      pinMode(relay6Pin, OUTPUT); // объявляем реле5 в качестве выхода
      digitalWrite(relay6Pin, HIGH);
      
byte openRelay[8] =
{
  B11111,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B11111,
};
byte closeRelay[8] =
{
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
};
lcd.createChar(1, openRelay); //регистрация знака
lcd.createChar(2, closeRelay);
}

void print_relay() // вывод индикации знаков реле
{     
     if (digitalRead(relay1Pin)==LOW){lcd.setCursor(5, 3); lcd.print("\1");} else if (digitalRead(relay1Pin)==HIGH) {lcd.setCursor(5, 3); lcd.print("\2");}
     if (digitalRead(relay2Pin)==LOW){lcd.setCursor(7, 3); lcd.print("\1");} else if (digitalRead(relay2Pin)==HIGH){lcd.setCursor(7, 3); lcd.print("\2");}
     if (digitalRead(relay3Pin)==LOW){lcd.setCursor(9, 3); lcd.print("\1");} else if (digitalRead(relay3Pin)==HIGH){lcd.setCursor(9, 3); lcd.print("\2");}
     if (digitalRead(relay4Pin)==LOW){lcd.setCursor(11, 3); lcd.print("\1");} else if (digitalRead(relay4Pin)==HIGH){lcd.setCursor(11, 3); lcd.print("\2");}
     if (digitalRead(relay5Pin)==LOW){lcd.setCursor(13, 3); lcd.print("\1");} else if (digitalRead(relay5Pin)==HIGH){lcd.setCursor(13, 3); lcd.print("\2");}
}
     
void printDigits(int digits)  //конструктор для 2х знаков с 0
{
   if (digits < 10) 
   {
    lcd.print('0');
   }
  lcd.print(digits);
}

char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };   //день недели

void printTime()            // конструктор вывода дата/время                 
{
  DateTime now = rtc.now();                            
  lcd.setCursor(0,0);
  printDigits(now.date());
  lcd.print("/");
  printDigits(now.month());
  lcd.print("/");
  lcd.print(weekDay[now.dayOfWeek()]);
  
  lcd.setCursor(12,0);
  printDigits(now.hour());
  lcd.print(":");
  printDigits(now.minute());
  lcd.print(":");
  printDigits(now.second());
  delay(500);
}

void displayUpdate(void)      //конструктор отображения              
{          
  printTime();
  printTemp();
  print_relay();
}

void printTemp()  //конструктор вывода температуры                               
{
  
  //lcd.setCursor(0,2);
  //lcd.print(rtc.getTemperature());
  lcd.setCursor(9,0);
  lcd.print(int(rtc.getTemperature()));
}

void CLR_STR(int N) //функция очистки строки
{
  lcd.setCursor(0,N);
  lcd.print(CL_STR);
}

  uint8_t keys() // первичный опрос КB
 { 
  K=analogRead(KB);
  if (235<K && K < 335)   return 1; //назад
  else if (415<K && K < 515) return 2;  //вправо
  else if (545<K && K < 645) return 3;  //вниз
  else if (647<K && K < 747) return 4; //ОК
  else if (747<K && K < 847) return 5; //влево
  else if (847< K && K < 947) return 6; //вверх
  else return 0  ;
 }
 
void readKey() //описание действий КВ
{
  lcd.setCursor(0,1);
  lcd.print("KB=");
  lcd.print(keys());
  //menu_num = 0; //первоначально
  //menu_sub1=0;
  //menu_sub2=0;
  //menu_sub3=0;
  switch (keys())
  { case 1://назад
    if (menu_num != 0 && menu_sub1== 0 && menu_sub2==0) menu_num = 0; // возврат в 0 меню
    if (menu_num != 0 && menu_sub1!= 0 && menu_sub2==0) menu_sub1 = 0; // возврат в -,0 столбец
    if (menu_num != 0 && menu_sub1!= 0 && menu_sub2!= 0) menu_sub2 = 0; // возврат в -,-,0 столбец
    break; 
    case 2://вправо
    if (menu_num == 3 && menu_sub1== 0) menu_num= -1; // переход по кругу
    if(menu_num != 0 && menu_sub1== 0) menu_num= menu_num++; // перелистывание
    break;
    case 3://вниз
    if (menu_num != 0 && menu_sub1 != 0) menu_sub1=menu_sub1++;
    if (menu_num == -1 && menu_sub1 == 7) menu_sub1=1; // доп условие 1 ряда
    if (menu_num == 1 && menu_sub1 == 2) menu_sub1=1;  // доп условие 2 ряда
    if (menu_num == 2 && menu_sub1 == 3) menu_sub1=1;  // доп условие 3 ряда
    break;
    case 4://ОК
    if (menu_num == -1 && menu_sub1== 1) {digitalWrite(relay1Pin, HIGH); digitalWrite(relay2Pin, HIGH); digitalWrite(relay3Pin, HIGH); digitalWrite(relay4Pin, HIGH); digitalWrite(relay5Pin, HIGH); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 2) {digitalWrite(relay1Pin, LOW); digitalWrite(relay2Pin, LOW); digitalWrite(relay3Pin, LOW); digitalWrite(relay4Pin, LOW); digitalWrite(relay5Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 3) {digitalWrite(relay1Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 4) {digitalWrite(relay2Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 5) {digitalWrite(relay3Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 6) {digitalWrite(relay4Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 7) {digitalWrite(relay5Pin, LOW); menu_num = 0; menu_sub1= 0;}
    if (menu_num == -1 && menu_sub1== 0) menu_sub1= 1; // переход в -,1,0
    if (menu_num == 1 && menu_sub1== 0) menu_sub1= 1; // переходы в -,1,0
    if (menu_num == 2 && menu_sub1== 0) menu_sub1= 1; // переходы в -,1,0
    if (menu_num == 3 && menu_sub1== 0) menu_sub1= 1; // переходы в -,1,0
    break;
    case 5://влево
     if (menu_num == -1 && menu_sub1== 0) menu_num= 3; // переход по кругу
     if(menu_num != 0 && menu_sub1== 0) menu_num= menu_num--; // перелистывание
    break;
    case 6://вверх
    if (menu_num != 0 && menu_sub1 != 0) menu_sub1=menu_sub1--;
    if (menu_num == -1 && menu_sub1 == 1) menu_sub1=7; // доп условие 1 ряда
    if (menu_num == 1 && menu_sub1 == 1) menu_sub1=2;  // доп условие 2 ряда
    if (menu_num == 2 && menu_sub1 == 1) menu_sub1=3;  // доп условие 3 ряда
    break;
  }
}

void Menu() //отображение в меню
{
  //menu_num = 0; //первоначально
  //menu_sub1=0;
  //menu_sub2=0;
  //menu_sub3=0;
  switch (menu_num) // 0,-,-
  {
   case -1:
   //CLR_STR(2);
   lcd.setCursor(3,2);
   lcd.print("RELAY ON / OFF");
   break;
   case 0:
   //CLR_STR(2);
   break;
   case 1:
   //CLR_STR(2);
   lcd.setCursor(8,2);
   lcd.print("INFO");
   break;
   case 2:
   //CLR_STR(2);
   lcd.setCursor(6,2);
   lcd.print("OPTIONS");
   break;
   case 3:
   //CLR_STR(2);
   lcd.setCursor(8,2);
   lcd.print("Logs");
   break;
  }
  
    switch (menu_sub1)  // -,0,-
  {
   case 0:
   break;
   case 1:
   if (menu_num == -1)
     {// CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("CLOSE ALL");
     }
   if (menu_num == 1)
     {// CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("Programm1");
     }
   if (menu_num == 2)
     {// CLR_STR(2); 
       lcd.setCursor(8,2); 
       lcd.print("TIME");
     }
   break;
   case 2:
   if (menu_num == -1)
     {// CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("OPEN ALL");
     }
   if (menu_num == 1)
     {// CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("Programm2");
      }
   if (menu_num == 2)
     { //CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("Programm1");
     }
   break;
   case 3:
   if (menu_num == -1)
     { //CLR_STR(2); 
       lcd.setCursor(6,2); 
       lcd.print("OPEN 1");
     }
   if (menu_num == 2)
     { //CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("Programm2");
     }
   break;
   case 4:
   if (menu_num == -1)
     { //CLR_STR(2); 
       lcd.setCursor(6,2); 
       lcd.print("OPEN 2");
     }
   break;
   case 5:
   if (menu_num == -1)
     { //CLR_STR(2); 
       lcd.setCursor(6,2); 
       lcd.print("OPEN 3");
     }
   break;
   case 6:
   if (menu_num == -1)
     { //CLR_STR(2); 
       lcd.setCursor(6,2); 
       lcd.print("OPEN 4");
      }
   break;
   case 7:
   if (menu_num == -1)
     { //CLR_STR(2); 
       lcd.setCursor(5,2); 
       lcd.print("OPEN 5");
      }
   break;
  }
  
    switch (menu_sub2) // -,-,0
  {
   case 1:      
   break;
   case 2:
   break;
   case 3:
   break;
   case 4:   
   break;
   }
}

void loop () 
{
    displayUpdate();
    readKey();
    Menu();
    delay(300);
}
 

Схема в протеусе и код присутсвует https://yadi.sk/d/WTL9er4z3GjCDe

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Я для полива параметры в EEPROM держу. Там надо то - один раз настроил и поехали...

arcon73
Offline
Зарегистрирован: 06.04.2017

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

renoshnik
Offline
Зарегистрирован: 11.04.2013
arcon73
Offline
Зарегистрирован: 06.04.2017

хм... ну как бы да... подсмотреть только неоткуда. 
и некоторые фунции по клапанам будут не по расписанию...

arcon73
Offline
Зарегистрирован: 06.04.2017

ошибку нашёл.... рисует....

странно... но думал что операция x++ прокатывает....

исправленый кейс

 

 case 2://вправо
    if (menu_num >= -2 && menu_sub1== 0) menu_num= menu_num+1; // предел -2 от глюка перехода
    if (menu_num == 4 && menu_sub1== 0) menu_num= -1; // переход по кругу
    break;


  case 5://влево
     if(menu_num >= -3 && menu_sub1== 0) menu_num= menu_num-1;
     if (menu_num == -2 && menu_sub1== 0) menu_num= 3; // переход по кругу