подсветка дисплея 1602 i2c

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Помогите пожалуйста реализовать подсветку дисплея. Нужно чтобы при бездействии примерно 2 мин подсветка затухала на 50% а при нажатии на любую кнопку подсветка была на 100%. 

Заранее всем спосибо.

http://cloud.mail.ru/public/2D6P/3wTbTWhtr

vvadim
Offline
Зарегистрирован: 23.05.2012

с дисплеем с модулем i2c так не получится - подсветка или горит или нет.
можно подсветку вывести на отдельный пин - но это уже геморрррр.

 

 

sir_kimas
Offline
Зарегистрирован: 01.08.2016

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

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Между выводом "К" экрана (№16) и землей припаяй резистор, лучше переменный, регулировочный - 50К или 20К  или 100К... и покрути. У тебя получится, что подсветка не выключается полностью. То еть либо горит, либо "вполнакала". Яркость темной фазы - подбери.

Вот и всё. Ни какого дополнительного кода. lcd.backlight(); lcd.noBacklight().

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Спасибо. буду пробовать.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

резистор подобрал но как правильно вписать в скеч "lcd.backlight(); lcd.noBacklight()" не понимаю. подскажите пожалуйста.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

1. Пока ты не показал попыток решения ты не получишь никаких советов. Решать школьные задачки за тебя никто не станет.

2. Не знаю зачем ты дал некую ссылку на облако, но код размещают тут, и размещают по правилам.

sir_kimas
Offline
Зарегистрирован: 01.08.2016
/* pressure_swith_v4.ino 
  светодиод работа насоса  -> 14  1  вкл / 1 откл
  реле насоса              -> 16  1  вкл / 1 откл
  датчик давления          -> A1  0 нажата / 1 нет
  кнопка "SELECT"          -> 4   0 нажата / 1 нет
  кнопка "DOWN"            -> 5   0 нажата / 1 нет
  кнопка "UP"              -> 6   0 нажата / 1 нет
  кнопка "Manual OFF_PUMP" -> 7   0 нажата / 1 нет
  кнопка "Manual ON_PUMP"  -> 8   0 нажата / 1 нет

  0 экран - величина давления / режим индик реж авто-ручной / вкл-откл насос
  1 экран уст реж авто-ручной / величина вкл насоса/ величина откл насоса
*/
//# menu

unsigned long KPTimer = 0;//таймер для опроса кнопок
unsigned long PSTimer = 0;//таймер для обновления экрана
unsigned long MSRTimer = 0;//таймер для автовозврата к MainScreen
boolean f_key=0;//флаг для фиксации нажатия кнопки
#define MSRecovery 5000 //задержка автовозврата к MainScreen 3сек




#include "Cl_menu_A.h"
// шины выхода
#include "Cl_digitalOut.h"
Cl_digitalOut Out[] = {
  Cl_digitalOut(16) , // 0- выход 16  реле насоса
  Cl_digitalOut(14)   // 1- выход 14  работа насоса
};
// шины входа аналоговые
#include "Cl_analogIn.h"
Cl_analogIn aIn = Cl_analogIn(A1); // аналог.вход датчика давления
// шины входа цифровые
#include "Cl_digitalIn.h"
Cl_digitalIn In[] = {
  Cl_digitalIn(4), //  0- вход 4  кнопка "SET"
  Cl_digitalIn(5), //  1- вход 5  кнопка "DOWN"
  Cl_digitalIn(6), //  2- вход 6  кнопка "UP"
  Cl_digitalIn(7), //  3- вход 7  кнопка "Manual OFF_PUMP"
  Cl_digitalIn(8)  //  4- вход 8  кнопка "Manual ON_PUMP"
};

// насос
#include "Cl_led.h"
Cl_led * Pump = new Cl_led(&Out[0], 0); //0- реле насоса
// светодиод
Cl_led * Led  = new Cl_led(&Out[1], 1); //0- работа насоса
// кнопки
void Do_SELECT() {
  Menu_select();
}
void Do_DOWN() {
  Menu[line]->down();
}
void Do_UP() {
  Menu[line]->up();
}
void Do_MANUAL_OFF_PUMP() {
  if (!mode_Auto) {
    Pump->OFF();
    Pump_On = 0;
    Led->OFF();      // выключаем светодиод
  }
}
void Do_MANUAL_ON_PUMP() {
  if (! mode_Auto) {
    Pump->ON();
    Pump_On = 1;
    Led->blink(200); // мигать 0.2 сек вкл 0.2 сек выкл
  }
}
#include "Cl_do_btn.h"
Cl_do_btn * Btn[] =  {
  new Cl_do_btn(&In[0] , 0, &Do_SELECT         ) , //кнопка "SELECT"          0 нажата / 1 нет
  new Cl_do_btn(&In[1] , 0, &Do_DOWN           ) , //кнопка "DOWN"            0 нажата / 1 нет
  new Cl_do_btn(&In[2] , 0, &Do_UP             ) , //кнопка  "ON_PUMP"        0 нажата / 1 нет
  new Cl_do_btn(&In[3] , 0, &Do_MANUAL_OFF_PUMP) , //кнопка "Manual OFF_PUMP" 0 нажата / 1 нет
  new Cl_do_btn(&In[4] , 0, &Do_MANUAL_ON_PUMP )   //кнопка "Manual ON_PUMP"  0 нажата / 1 нет
};

// датчик давления
void Do_change();
#include "Cl_do_analog_sens.h"
Cl_do_analog_sens * Sens = new Cl_do_analog_sens(&aIn, &Do_change);
void Do_change() {
  pressure = Sens->value;
  if (mode_Auto) {
    if (pressure <= pressure_ON ) {
      Pump->ON();
      Pump_On = 1;
      Led->ON();  // включаем светодиод
    }
    if (pressure >= pressure_OFF ) {
      Pump->OFF();
      Pump_On = 0;
      Led->OFF(); // выключаем светодиод
    }
  }
}
void setup() {
  Menu_setup();// инициализация дисплея
  Sens->setup();
  Pump->setup();
  Led->setup();
  for (byte i = 0; i < 5; ++i)Btn[i]->setup();
  Pump_On = 0;
  Led->OFF();
}

void loop() {
  Do_change();
  Menu_viev();// вывод текущей информации
  Sens->loop();
  Pump->loop();
  Led->loop();
  for (byte i = 0; i < 5; ++i)Btn[i]->loop();
}



/*Cl_analogIn.h
*/
#ifndef Cl_analogIn_h
#define Cl_analogIn_h

class Cl_analogIn {
  public:
    Cl_analogIn(byte _pin) {
      pin = _pin;
    };
    void setup() {
      //pinMode(pin, INPUT);
    };
    int transferIn() {
      return analogRead(pin) ;
    };
  private:
    byte pin ;
};

#endif //Cl_analogIn_h


/*Cl_digitalIn.h
*/
#ifndef Cl_digitalIn_h
#define Cl_digitalIn_h

class Cl_digitalIn {
  public:
    Cl_digitalIn(byte _pin) {
      pin = _pin;
    };
    void setup() {
      pinMode(pin, INPUT);
    };
    bool transferIn() {
      return digitalRead(pin) ;
    };
  private:
    byte pin ;
};
#endif //Cl_digitalIn_h


/*Cl_digitalOut.h
*/
#ifndef Cl_digitalOut_h
#define Cl_digitalOut_h

#include "Arduino.h"
class Cl_digitalOut {
  public:
    Cl_digitalOut(byte _pin) {
      pin = _pin;
    };
    void setup() {
      pinMode(pin, OUTPUT);
    };
    void transferOut(bool data) {
      digitalWrite(pin, data) ;
    };
  private:
    byte pin ;
};
#endif //Cl_digitalOut_h


/*Cl_do_analog_sens.h
*/
#ifndef Cl_do_analog_sens_h
#define Cl_do_analog_sens_h
const byte hysteresis = 5; // +- точность с которой считаем что ничего не изменилось
#include "Arduino.h"
#include "Cl_analogIn.h"
class Cl_do_analog_sens {
  public:
    Cl_do_analog_sens(Cl_analogIn * _wire, void (* _Do_change)()) {
      wire = _wire;
      Do_change = _Do_change;
    };
    void setup() {
      wire->setup();
      value = wire->transferIn(); // прочитать реальное значение на выводе
    };
    void loop() {
      value = wire->transferIn();
      if (millis() - past >= 100) {
        past = millis();
        value = wire->transferIn(); // прочитать реальное значение на выводе
        Do_change();
      }
    };
    int value;
  private:
    Cl_analogIn * wire ; // номер ноги на кнопке
    void (* Do_change)();
    uint32_t past = 0 ;
};
#endif //Cl_do_analog_sens_h


/*Cl_do_btn.h
*/
#ifndef Cl_do_btn_h
#define Cl_do_btn_h

#include "Arduino.h"
#include "Cl_digitalIn.h"
class Cl_do_btn {
  public:
    Cl_do_btn(Cl_digitalIn * _wire, bool _high, void (* _Do_Btn)()) {
      wire = _wire;
      high = _high;
      Do_Btn = _Do_Btn;
    };
    void setup() {
      wire->setup();
      btn = wire->transferIn() ^ ! high; // прочитать реальное значение на выводе
    };
    void loop() {
      if (! bounce_btn && btn == wire->transferIn() ^ high) { // если прошел фронт изм на выводн
        bounce_btn = 1;                                 // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_btn = 0;      // то снять флаг
        btn_old = btn ;
        btn = wire->transferIn() ^  ! high ; // прочитать реальное значение на выводе
        if (btn_old && ! btn)  Do_Btn();
      }
    };
  private:
    Cl_digitalIn * wire ; // номер ноги на кнопке
    bool high; // уровень когда кнопка нажата
    void (* Do_Btn)();
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
};
#endif //Cl_do_btn_h


/*Cl_led.cpp
*/
#include "Arduino.h"
#include "Cl_led.h"
Cl_led::Cl_led(Cl_digitalOut * _wire, bool high) {
  wire = _wire;
  low = ! high;
}
void Cl_led::ON() {
  stat_blink = 0;
  led = 1;
  wire->transferOut(led ^ low);
}
void Cl_led::OFF() {
  stat_blink = 0;
  led = 0;
  wire->transferOut(led ^ low);
}
void Cl_led::setup() {
  wire->setup();
  stat_blink = 0;
  led = 0;
  wire->transferOut(led ^ low);
}
void Cl_led::loop() {
  if (stat_blink) {
    if ( millis() - past >= time_blink) {
      past = millis();
      led = ! led;
      wire->transferOut(led ^ low);
    }
  }
}
void Cl_led::blink(uint16_t time) {
  time_blink = time;
  past = millis();
  stat_blink = 1;
  led = 1;
  wire->transferOut(led ^ low);
}


/*Cl_led.h
*/
#ifndef Cl_led_h
#define Cl_led_h

#include "Arduino.h"
#include "Cl_digitalOut.h"
class Cl_led {
  public:
    Cl_led(Cl_digitalOut * _wire, bool high);
    void ON();
    void OFF();
    void setup();
    void loop();
    void blink(uint16_t time = 500);
  private:
    Cl_digitalOut * wire ;
    uint32_t time_blink;
    bool low;
    bool led;// 0 не горит / 1 горит
    bool stat_blink;// 0 не мигает / 1 мигает
    uint32_t past = 0;
};
#endif //Cl_led_h


/*Cl_menu_A.cpp
*/
#include "Arduino.h"
#include "Cl_menu_A.h"
#include <EEPROM.h>

int line = 0; // текущая линия в меню
bool mode_Auto = 1; // 0 ручной режим / 1 автомат
void mode_Auto_minus() {
  mode_Auto = 0;
}

void mode_Auto_ON_plus() {
  mode_Auto = 1;
}

int On = 12;

bool Pump_On = 0;              // перем опред вкл-откл насоса  1 вкл/0 нет
int pressure;                  // величина давления
const int pressure_min = 103;  // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
int pressure_ON = 103;         // величина давления когда насос сам вкл
int pressure_OFF = 1023;       // величина давления когда насос сам выкл
//const uint16_t adr_mode_Auto = 1;
const uint32_t adr_pressure_ON = 2;
const uint32_t adr_pressure_OFF = 4;

//********************************************************

  float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data/100;
}
 
//********************************************************

void setup_eeprom() {
  byte a;
  EEPROM.get(0, a);
  if (a != 0) {
    EEPROM.put(0, a = 0);
    //    EEPROM.put(adr_mode_Auto, mode_Auto);
    EEPROM.put(adr_pressure_ON, pressure_ON);
    EEPROM.put(adr_pressure_OFF, pressure_OFF);
    return;
  }
  //  EEPROM.get(adr_mode_Auto   , mode_Auto   );
  EEPROM.get(adr_pressure_ON , pressure_ON );
  EEPROM.get(adr_pressure_OFF, pressure_OFF);
}
const byte delta = 1; // минимальное расстояние между pressure_ON и pressure_OFF
void pressure_ON_plus() {
  ++pressure_ON;
  if (pressure_ON > (pressure_OFF - delta))pressure_ON = pressure_OFF - delta;
}
void pressure_ON_minus() {
  --pressure_ON;
  if (pressure_ON < pressure_min)pressure_ON = pressure_min;
}
void pressure_OFF_plus() {
  ++pressure_OFF;
  if (pressure_OFF > pressure_max)pressure_OFF = pressure_max;
}
void pressure_OFF_minus() {
  --pressure_OFF;
  if (pressure_OFF < (pressure_ON + delta))pressure_OFF = pressure_ON + delta;
}

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
  LiquidCrystal_I2C lcd(0x3F , 16, 2);
    void Menu_setup() {  // инициализация дисплея
    setup_eeprom();
    lcd.init();        // инициируем LCD дисплей
    lcd.backlight();   // включаем подсветку LCD дисплея
   // lcd.setBacklight(1);
  }
    void Menu_viev() {   // вывод текущей информации
    static uint32_t past = 0;
    if (millis() - past >= 500) {
      past = millis();
      Menu[line]->viev();
    }
  }
  void viev_0() {
    lcd.setCursor(0, 0);
    lcd.print("P = ");
    lcd.print(AnalogToBar(pressure));
    lcd.setCursor(11, 0);
    if (Pump_On)lcd.print("ON ");
    else lcd.print("OFF");
    lcd.setCursor(0, 1);
    if (mode_Auto) lcd.print("Auto");
    else lcd.print("Manl");
    lcd.setCursor(4, 1);
    lcd.print(" ");
    lcd.print(AnalogToBar(pressure_ON));   //
    lcd.setCursor(9, 1);
    lcd.print(" / ");
    lcd.print(AnalogToBar(pressure_OFF));    //
  }
  void viev_1() {
    lcd.setCursor(0, 0);
    lcd.print("P = ");
    lcd.print(AnalogToBar(pressure));
    lcd.setCursor(11, 0);
    if (Pump_On)lcd.print("ON");
    else lcd.print("OFF");
    lcd.setCursor(0, 1);
    lcd.print(">");
    if (mode_Auto) lcd.print("Auto");
    else lcd.print("Manl");
    lcd.setCursor(5, 1);
    lcd.print(" ");
    lcd.print(AnalogToBar(pressure_ON));
    lcd.setCursor(10, 1);
    lcd.print("/ ");
    lcd.print(AnalogToBar(pressure_OFF));
  }
  void viev_2() {
    lcd.setCursor(0, 0);
    lcd.print("P = ");
    lcd.print(AnalogToBar(pressure));
    lcd.setCursor(11, 0);
    if (Pump_On)lcd.print("ON");
    else lcd.print("OFF");
    lcd.setCursor(0, 1);
    lcd.print(" ");
    if (mode_Auto) lcd.print("Auto");
    else lcd.print("Manl");
    lcd.setCursor(5, 1);
    lcd.print(">");
    lcd.print(AnalogToBar(pressure_ON));
    lcd.setCursor(10, 1);
    lcd.print("/ ");
    lcd.print(AnalogToBar(pressure_OFF));
  }
  void viev_3() {
    lcd.setCursor(0, 0);
    lcd.print("P = ");
    lcd.print(AnalogToBar(pressure));
    lcd.setCursor(11, 0);
    if (Pump_On)lcd.print("ON");
    else lcd.print("OFF");
    lcd.setCursor(0, 1);
    lcd.print(" ");
    if (mode_Auto) lcd.print("Auto");
    else lcd.print("Manl");
    lcd.setCursor(5, 1);
    lcd.print(" ");
    lcd.print(AnalogToBar(pressure_ON));
    lcd.setCursor(10, 1);
    lcd.print("/>");
    lcd.print(AnalogToBar(pressure_OFF));
  }
  void none() {} ; // заглушка

  Cl_menu_line * Menu[max_line] = {
    // экран ,переменная на экране,отображение экрана,действие вверх,действие вниз
    new Cl_menu_line( & viev_0 , & none              , & none             ),
    new Cl_menu_line( & viev_1, & mode_Auto_minus   , & mode_Auto_ON_plus),
    new Cl_menu_line( & viev_2, & pressure_ON_minus , & pressure_ON_plus ),
    new Cl_menu_line( & viev_3, & pressure_OFF_minus, & pressure_OFF_plus)
  };
  void Menu_select() {
    //  if (line == 1)EEPROM.update(adr_mode_Auto, mode_Auto);
    if (line == 2)EEPROM.update(adr_pressure_OFF, pressure_OFF);
    if (line == 3)EEPROM.update(adr_pressure_ON, pressure_ON);
    ++ line;
    if (line >= max_line) line = 0;
  }


/*Cl_menu_A.h
*/
#ifndef Cl_menu_A_h
#define Cl_menu_A_h
#include "Arduino.h"
#include "Cl_menu_line.h"
extern bool mode_Auto ; // 0 ручной режим / 1 автомат
extern bool Pump_On ;   // перем опред вкл-откл насоса  1 вкл/0 нет
extern int pressure;    // величина давления
extern int pressure_ON,pressure_OFF ;// величина давления когда насос сам вкл,сам выкл
extern int line;// текущая линия в меню
const int max_line = 4 ; // количество  линий в меню
extern Cl_menu_line * Menu[max_line];
extern void Menu_setup();   // инициализация экрана
extern void Menu_viev();   // текущий показ экрана
extern void Menu_select(); // переход на след строку
#endif //Cl_menu_A_h


/*Cl_menu_line.h
*/
#ifndef Cl_menu_line_h
#define Cl_menu_line_h
#include "Arduino.h"
//--------------------------
class Cl_menu_line {
  public:
    Cl_menu_line( void (* _viev)(), void (* _down)(), void (* _up)()) {
      viev   = _viev  ;
      down   = _down  ;
      up     = _up    ;
    }
    void (* viev)(); // показ нужной строки
    void (* down)(); // действие по наж кнопки up
    void (* up)();   // действие по наж кнопки up
};
#endif //Cl_menu_line_h


 

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Госпада помогите ни как не могу понять как и куда вставить стороки "lcd.backlight(); lcd.noBacklight()" перепробовал вроде все но никак.  Я в програмировании новичек и прошу сильно не пинать.

С одностраничным скечем вроде все получается а тут нет

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже это ваша программа это эволюция моего кода. Так что их надо ставить внутрь функции Menu_setup(). Но мне больше нравиться организовывать меню через автомат с лямда функциями - отсюда и далее #55  

ПС: Я уже не помню описание задачи что в программе надо получить. Так что Вам придется сначало найти место на форуме, где я этот код писал или же заново описать техническое задание.

 

ПСС: строка 410 где вкл подсветки есть.

Код для многостраничного меню по мне надо начинать так

/**/
const byte page1 = 0; // первая страница меню
const byte page2 = 10; // вторая страница меню
const byte page3 = 20; // третья страница меню
//----------------
void setup() {
}

void loop() {
}

 

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Спорить не буду. Код точно не мой. Переделал кое-что под себя. Интересует как можно сделать чтобы при бездействии выключалась подсветка.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Спасибо. Буду дальше разбираться.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
const byte page1 = 0; // первая страница меню
const byte page2 = 10; // вторая страница меню
const byte page3 = 20; // третья страница меню
byte page;// текущая страница
unsigned long past;
void goPage(byte p) {
  page = p;
  past = millis();
  switch (p) {
    case page1 :
      break;
    case page2 :
      break;
    case page3 :
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page == page1 && millis() - past >= 1000)goPage(page1);// обновлять если стоим на 1 странице
  if (page != page1 && millis() - past >= 10000)goPage(page1);// перейти на 1 страницу если долго стоми не на 1 странице
}
//----------------
void setup() {
  menu_init();
}

void loop() {
  menu_run();
}

 

enjoyneering
enjoyneering аватар
Offline
Зарегистрирован: 05.09.2016

можно сделать спомощью вот этой библиотеки  - https://github.com/enjoyneering/LiquidCrystal_I2C

для этого на i2c шильде надо снять перемычку в пластиковом корусе и подключить верхний или нижний (не помню уже) пин к PWM пину ардуино чеез рзистор в 470 Ом и в скетче вызвать функцию setBrightness(pin, value, polarity); где value - 0..255, polarity = POSITIVE или NEGATIVE

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Спасибо. Буду пробовать.

sadman41
Offline
Зарегистрирован: 19.10.2016

А можно ведь и просто analogWrite() сделать на  пин подсветки.

-NMi-
Offline
Зарегистрирован: 20.08.2018

Можно.

enjoyneering
enjoyneering аватар
Offline
Зарегистрирован: 05.09.2016

sadman41 пишет:

А можно ведь и просто analogWrite() сделать на  пин подсветки.

так и сделано

/**************************************************************************/
/*
    setBrightness()
    NOTE:
    - to use this function, the "LED" jumper on the back of backpack has
      to be removed & the top pin has to be connected to one of Arduino
      PWM pin in series with 470 Ohm resistor
    - recomended min. value = 25, max. value = 255 (0.5v .. 4.5v)
                 min. value = 0,  max. value = 255 (0.0v .. 4.5v)  
*/
/**************************************************************************/
void LiquidCrystal_I2C::setBrightness(uint8_t pin, uint8_t value, backlightPolarity polarity)
{
  pinMode(pin, OUTPUT);

  if (polarity == NEGATIVE) value = 255 - value;

  analogWrite(pin, value);
}

 

sir_kimas
Offline
Зарегистрирован: 01.08.2016

qwone пишет:

/**/
const byte page1 = 0; // первая страница меню
const byte page2 = 10; // вторая страница меню
const byte page3 = 20; // третья страница меню
byte page;// текущая страница
unsigned long past;
void goPage(byte p) {
  page = p;
  past = millis();
  switch (p) {
    case page1 :
      break;
    case page2 :
      break;
    case page3 :
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page == page1 && millis() - past >= 1000)goPage(page1);// обновлять если стоим на 1 странице
  if (page != page1 && millis() - past >= 10000)goPage(page1);// перейти на 1 страницу если долго стоми не на 1 странице
}
//----------------
void setup() {
  menu_init();
}

void loop() {
  menu_run();
}

 

Мозг кипит! ничего не выходит.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

[qwone]


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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

sir_kimas пишет:

[qwone]


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

Пух - знатный аратор.  

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

/*
Экран Serial
кнопки на 2 и 3 пина
*/

//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      switch (s) {
        case false:
          break;
        case true:
          Do();
          break;
      }
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn BtnU(/*пин*/2);  //кнопка верх
Cl_btn BtnD(/*пин*/3);  //кнопка верх
//--меню--------------------------
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page1 = 0; // первая страница меню
const byte page2 = 10; // вторая страница меню
const byte page3 = 20; // третья страница меню
byte page;// текущая страница
unsigned long past;
void goPage(byte p) {
  page = p;
  past = millis();
  switch (p) {
    case page1 :
      Serial << "\nPAGE 1"; // Выдать сообщение на экран
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      break;
    case page2 :
      Serial << "\nPAGE 2";
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      break;
    case page3 :
      Serial << "\nPAGE 3";
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {};
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page == page1 && millis() - past >= 1000)goPage(page1);// обновлять если стоим на 1 странице
  if (page != page1 && millis() - past >= 6000)goPage(page1);// перейти на 1 страницу если долго стоми не на 1 странице
}
//----------------
void setup() {
  Serial.begin(9600);
  BtnU.init();
  BtnD.init();
  menu_init();
}

void loop() {
  BtnU.run();
  BtnD.run();
  menu_run();
}

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот некая эмуляция решения вашей задачи.

/*
  Экран Serial
  кнопки на 2 и 3 пина
*/

//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      switch (s) {
        case false:
          break;
        case true:
          Do();
          break;
      }
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn BtnU(/*пин*/2);  //кнопка верх
Cl_btn BtnD(/*пин*/3);  //кнопка верх
//--меню--------------------------
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5; // первая страница меню
const byte page2 = 10; // вторая страница меню
const byte page3 = 20; // третья страница меню
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  switch (p) {
    case page0 :
      Serial << "\n ==OFF=="; // Выдать сообщение на экран
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      break;
    case page1 :
      Serial << "\nPAGE 1"; // Выдать сообщение на экран
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      break;
    case page2 :
      Serial << "\nPAGE 2";
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      break;
    case page3 :
      Serial << "\nPAGE 3";
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {};
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 10000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  Serial.begin(9600);
  BtnU.init();
  BtnD.init();
  menu_init();
}

void loop() {
  BtnU.run();
  BtnD.run();
  menu_run();
}

ПС: конечно код сыроват, но банально дает направление для решения задачи

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Я вроде это все понимаю но куда и как все это вставить не могу понять. Буду дальше разбираться.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Буду пробовать

sir_kimas
Offline
Зарегистрирован: 01.08.2016

не могу понять. Куда и как вможно вставить. нНе могу разобраться много страниц в скетче. Сидел до 5 утра а толку 0! Помогите плиз!!!!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

sir_kimas
Offline
Зарегистрирован: 01.08.2016

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

sir_kimas пишет:

уже охото нажраться.

Just do it.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

make sure.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну немного не до конца скетч сделан.

/*
  Экран Serial
  кнопки на 2,3,4,5,6 пина
  реле 12
  светодиод 13
*/
//----------------------------------------
bool pump_state = false;
bool avto_state = false;
int pressure;                  // величина давления
const int pressure_min = 103;  // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
int pressure_ON = 103;         // величина давления когда насос сам вкл
int pressure_OFF = 1023;       // величина давления когда насос сам выкл

float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data / 100;
}
//---светодиод-----------------------------
class Cl_led {
  protected:
    static const byte sOFF      = 0;
    static const byte sON       = 1;
    static const byte sBlinkOFF = 2;
    static const byte sBlinkON  = 3;
    byte pin;
    byte state;
    unsigned long past, time;
    void set(byte s) {
      state = s;
      past = millis();
      switch (s) {
        case sOFF :
        case sBlinkOFF:
          digitalWrite(pin, LOW);
          break;
        case sON :
        case sBlinkON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      set(sOFF);
    }
    void run() {
      if (state == sBlinkON && millis() - past >= time)set(sBlinkOFF);
      if (state == sBlinkOFF && millis() - past >= time)set(sBlinkON);
    }
    void ON() {
      set(sON);
    }
    void OFF() {
      set(sOFF);
    }
    void blink(unsigned long t) {
      time = t;
      set(sBlinkON);
    }
};
Cl_led led(/*пин*/13);
Cl_led pump(/*пин*/12);
//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      if (s == true) Do();
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn    BtnU(/*пин*/2);  //кнопка верх
Cl_btn    BtnD(/*пин*/3);  //кнопка вниз
Cl_btn    BtnS(/*пин*/4);  //кнопка селект
Cl_btn BtnMoff(/*пин*/5);  //кнопка ручное вкл насоса
Cl_btn  BtnMon(/*пин*/6);  //кнопка ручное выкл насоса
//--меню--------------------------
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27 , 16, 2);
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5;  // оперативное отображение
const byte page2 = 10; // переключ автомат/ручн
const byte page3 = 20; // установка мин
const byte page4 = 30; // устнаовка мах
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  lcd.clear();
  switch (p) {
    case page0 :
      lcd.noBacklight();
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page1 :
      lcd.backlight();
      lcd.setCursor(0, 0); lcd << "P = " << AnalogToBar(pressure);
      lcd.setCursor(11, 0);
      if (pump_state)lcd << "ON ";
      else lcd << "OFF";
      lcd.setCursor(0, 1);
      if (avto_state) lcd << "Auto";
      else lcd << " Manl";
      lcd.setCursor(5, 1); lcd << " " << AnalogToBar(pressure_ON);
      lcd.setCursor(10, 1); lcd << "/ " << AnalogToBar(pressure_OFF);
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page2 :
      lcd << "P = " << AnalogToBar(pressure);
      lcd.setCursor(11, 0);
      if (pump_state)lcd << "ON";
      else lcd << "OFF";
      lcd.setCursor(0, 1); lcd << ">";
      if (avto_state) lcd << "Auto";
      else lcd << "Manl";
      lcd.setCursor(5, 1); lcd << " " << AnalogToBar(pressure_ON);
      lcd.setCursor(10, 1); lcd << "/ " << AnalogToBar(pressure_OFF);
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page3 :
      lcd << "P = " << AnalogToBar(pressure);
      lcd.setCursor(11, 0);
      if (pump_state)lcd << "ON";
      else lcd << "OFF";
      lcd.setCursor(0, 1); lcd << " ";
      if (avto_state) lcd << "Auto";
      else lcd << "Manl";
      lcd.setCursor(5, 1) ; lcd << ">"  << AnalogToBar(pressure_ON);
      lcd.setCursor(10, 1); lcd << "/ " << AnalogToBar(pressure_OFF);
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {
        goPage(page4);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page4 :
      lcd << "P = " << AnalogToBar(pressure);
      lcd.setCursor(11, 0);
      if (pump_state)lcd << "ON";
      else lcd << "OFF";
      lcd.setCursor(0, 1); lcd << " ";
      if (avto_state) lcd << "Auto";
      else lcd << "Manl";
      lcd.setCursor(5, 1); lcd << " " << AnalogToBar(pressure_ON);
      lcd.setCursor(10, 1); lcd << "/>" << AnalogToBar(pressure_OFF);
      BtnU.Do = [] {
        goPage(page3);
      };
      BtnD.Do = [] {};
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 10000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  lcd.init();
  led.init();
  pump.init();
  BtnU.init();
  BtnD.init();
  BtnS.init();
  BtnMon.init();
  BtnMoff.init();
  BtnMon.Do = [] {
    if (!avto_state) {
      pump_state = true;
      pump.ON();
      led.blink(200);
    }
  };
  BtnMoff.Do = [] {
    if (!avto_state) {
      pump_state = false;
      pump.OFF();
      led.OFF();
    }
  };
  menu_init();
}
void loop() {
  led.run();
  pump.run();
  BtnU.run();
  BtnD.run();
  BtnS.run();
  BtnMon.run();
  BtnMoff.run();
  menu_run();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Дальная модификация скетча

/*
  Экран Serial
  кнопки на 2,3,4,5,6 пина
  реле 12
  светодиод 13
*/
//----------------------------------------
bool pump_state = false;
bool avto_state = false;
int pressure;                  // величина давления
const int pressure_min = 103;  // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
int pressure_ON = 103;         // величина давления когда насос сам вкл
int pressure_OFF = 1023;       // величина давления когда насос сам выкл

float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data / 100;
}
void sens_init() {
}
void sens_run() {
  if (avto_state) {

  }
}
//---светодиод-----------------------------
class Cl_led {
  protected:
    static const byte sOFF      = 0;
    static const byte sON       = 1;
    static const byte sBlinkOFF = 2;
    static const byte sBlinkON  = 3;
    byte pin;
    byte state;
    unsigned long past, time;
    void set(byte s) {
      state = s;
      past = millis();
      switch (s) {
        case sOFF :
        case sBlinkOFF:
          digitalWrite(pin, LOW);
          break;
        case sON :
        case sBlinkON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      set(sOFF);
    }
    void run() {
      if (state == sBlinkON && millis() - past >= time)set(sBlinkOFF);
      if (state == sBlinkOFF && millis() - past >= time)set(sBlinkON);
    }
    void ON() {
      set(sON);
    }
    void OFF() {
      set(sOFF);
    }
    void blink(unsigned long t) {
      time = t;
      set(sBlinkON);
    }
};
Cl_led led(/*пин*/13);
Cl_led pump(/*пин*/12);
//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      if (s == true) Do();
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn    BtnU(/*пин*/2);  //кнопка верх
Cl_btn    BtnD(/*пин*/3);  //кнопка вниз
Cl_btn    BtnS(/*пин*/4);  //кнопка селект
Cl_btn BtnMoff(/*пин*/5);  //кнопка ручное вкл насоса
Cl_btn  BtnMon(/*пин*/6);  //кнопка ручное выкл насоса
//--меню--------------------------
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27 , 16, 2);
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5;  // оперативное отображение
const byte page2 = 10; // переключ автомат/ручн
const byte page3 = 20; // установка мин
const byte page3e = 21; // редактирование мин
const byte page4  = 30; // устнаовка мах
const byte page4e = 31; // редактирование мах
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  lcd.clear();
  switch (p) {
    case page0 ://------------погашеный экран-----------------------
      lcd.noBacklight();
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page1 ://----------оперативное отображение-------------------
      {
        lcd.backlight();
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON ");
        else lcd << F("OFF");
        lcd.setCursor(0, 1);
        if (avto_state) lcd << F(" Auto "); else lcd << F(" Manl ");
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      BtnS.Do = [] { };
      break;
    case page2 ://-------------переключ автомат/ручн---------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd  << F(">");
        if (avto_state) lcd << F("Auto "); else lcd << F("Manl ") ;
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      BtnS.Do = [] {
        avto_state = !avto_state;
        goPage(page2);
      };
      break;
    case page3 ://----------------/ установка мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" ");
        if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << ">" << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {
        goPage(page4);
      };
      BtnS.Do = [] {
        goPage(page3e);
      };
      break;
    case page3e ://----------------ред мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" ");
        if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << "*" << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
      };
      BtnD.Do = [] {
      };
      BtnS.Do = [] {
        goPage(page3);
      };
      break;
    case page4 ://--------------/ установка мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" ");
        if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/>") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page3);
      };
      BtnD.Do = [] {};
      BtnS.Do = [] {
        goPage(page4e);
      };
      break;
    case page4e ://--------------редактирование мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" ");
        if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/*") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      BtnS.Do = [] {
        goPage(page4);
      };
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 10000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  sens_init();
  lcd.init();
  led.init();
  pump.init();
  BtnU.init();
  BtnD.init();
  BtnS.init();
  BtnMon.init();
  BtnMoff.init();
  BtnMon.Do = [] {
    if (!avto_state) {
      pump_state = true;
      pump.ON();
      led.blink(200);
    }
  };
  BtnMoff.Do = [] {
    if (!avto_state) {
      pump_state = false;
      pump.OFF();
      led.OFF();
    }
  };
  menu_init();
}
void loop() {
  sens_run();
  led.run();
  pump.run();
  BtnU.run();
  BtnD.run();
  BtnS.run();
  BtnMon.run();
  BtnMoff.run();
  menu_run();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Окончательный результат . Проверку с насосом и настройку не проводил, так как этой хни у меня нет ;))

/*
  Экран Serial
  кнопки на 2,3,4,5,6 пина
  реле 12
  светодиод 13
*/
//---светодиод-----------------------------
class Cl_led {
  protected:
    static const byte sOFF      = 0;
    static const byte sON       = 1;
    static const byte sBlinkOFF = 2;
    static const byte sBlinkON  = 3;
    byte pin;
    byte state;
    unsigned long past, time;
    void set(byte s) {
      state = s;
      past = millis();
      switch (s) {
        case sOFF :
        case sBlinkOFF:
          digitalWrite(pin, LOW);
          break;
        case sON :
        case sBlinkON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      set(sOFF);
    }
    void run() {
      if (state == sBlinkON && millis() - past >= time)set(sBlinkOFF);
      if (state == sBlinkOFF && millis() - past >= time)set(sBlinkON);
    }
    void ON() {
      set(sON);
    }
    void OFF() {
      set(sOFF);
    }
    void blink(unsigned long t) {
      time = t;
      set(sBlinkON);
    }
};
Cl_led led(/*пин*/13);
Cl_led pump(/*пин*/12);
//----------------------------------------
#include <EEPROM.h>
const byte sensPin =/*пин*/13;
bool pump_state = false;
bool avto_state = false;
unsigned long past2;
int pressure;                 // величина давления
const int pressure_min = 103; // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
const byte delta = 1; // минимальное расстояние между pressure_ON и pressure_OFF
int pressure_;
int pressure_ON;        // величина давления когда насос сам вкл
int pressure_OFF;       // величина давления когда насос сам выкл
int  pressure_ON_adr = 2;
int  pressure_OFF_adr = 4;
float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data / 100;
}
void sens_init() {

  pressure_ON = 103;
  pressure_OFF = 1023;
  EEPROM.put(pressure_ON_adr, pressure_ON);
  EEPROM.put(pressure_OFF_adr, pressure_OFF);

  EEPROM.get(pressure_ON_adr, pressure_ON);
  EEPROM.get(pressure_OFF_adr, pressure_OFF);
  past2 = millis();
}
void sens_run() {
  if (millis() - past2 >= 100) {
    if (avto_state) {
      pressure = analogRead(sensPin);
      if (pressure <= pressure_ON ) {
        pump_state = true;
        pump.ON();
        led.blink(200);
      }
      if (pressure >= pressure_OFF ) {
        pump_state = false;
        pump.OFF();
        led.OFF();
      }
    }
  }
}
//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      if (s == true) Do();
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn    BtnU(/*пин*/2);  //кнопка верх
Cl_btn    BtnD(/*пин*/3);  //кнопка вниз
Cl_btn    BtnS(/*пин*/4);  //кнопка селект
Cl_btn BtnMoff(/*пин*/5);  //кнопка ручное вкл насоса
Cl_btn  BtnMon(/*пин*/6);  //кнопка ручное выкл насоса
//--меню--------------------------
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27 , 16, 2);
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5;  // оперативное отображение
const byte page2 = 10; // переключ автомат/ручн
const byte page3 = 20; // установка мин
const byte page3e = 21; // редактирование мин
const byte page4  = 30; // устнаовка мах
const byte page4e = 31; // редактирование мах
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  lcd.clear();
  switch (p) {
    case page0 ://------------погашеный экран-----------------------
      {
        lcd.noBacklight();
      }
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page1 ://----------оперативное отображение-------------------
      {
        lcd.backlight();
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); if (avto_state) lcd << F(" Auto "); else lcd << F(" Manl ");
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      BtnS.Do = [] {};
      break;
    case page2 ://-------------переключ автомат/ручн---------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd  << F(">"); if (avto_state) lcd << F("Auto "); else lcd << F("Manl ") ;
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      BtnS.Do = [] {
        avto_state = !avto_state;
        goPage(page2);
      };
      break;
    case page3 ://----------------/ установка мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << ">" << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {
        goPage(page4);
      };
      BtnS.Do = [] {
        pressure_ = pressure_ON;
        goPage(page3e);
      };
      break;
    case page3e ://----------------ред мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << "*" << AnalogToBar(pressure_) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        ++pressure_ ;
        if (pressure_ > (pressure_OFF - delta))pressure_ = pressure_OFF - delta;
        goPage(page3e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < pressure_min)pressure_ = pressure_min;
        goPage(page3e);
      };
      BtnS.Do = [] {
        pressure_ON = pressure_;
        EEPROM.put(pressure_ON_adr, pressure_ON);
        goPage(page3);
      };
      break;
    case page4 ://--------------/ установка мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/>") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page3);
      };
      BtnD.Do = [] {};
      BtnS.Do = [] {
        pressure_ = pressure_OFF;
        goPage(page4e);
      };
      break;
    case page4e ://--------------редактирование мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/*") << AnalogToBar(pressure_);
      }
      BtnU.Do = [] {
        ++pressure_;
        if (pressure_ > pressure_max)pressure_ = pressure_max;
        goPage(page4e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < (pressure_ON + delta))pressure_ = pressure_ON + delta;
        goPage(page4e);
      };
      BtnS.Do = [] {
        pressure_OFF = pressure_;
        EEPROM.put(pressure_OFF_adr, pressure_OFF);
        goPage(page4);
      };
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 10000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  sens_init();
  lcd.init();
  led.init();
  pump.init();
  BtnU.init();
  BtnD.init();
  BtnS.init();
  BtnMon.init();
  BtnMoff.init();
  BtnMon.Do = [] {
    if (!avto_state) {
      pump_state = true;
      pump.ON();
      led.blink(200);
    }
  };
  BtnMoff.Do = [] {
    if (!avto_state) {
      pump_state = false;
      pump.OFF();
      led.OFF();
    }
  };
  menu_init();
}
void loop() {
  sens_run();
  led.run();
  pump.run();
  BtnU.run();
  BtnD.run();
  BtnS.run();
  BtnMon.run();
  BtnMoff.run();
  menu_run();
}

 

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Спасибо за труд. 

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

sir_kimas
Offline
Зарегистрирован: 01.08.2016

sir_kimas пишет:

Спасибо за труд. 

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

 

С EEPROM разобрался.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

С мерцанием экрана тоже разобрался

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

sir_kimas пишет:

С мерцанием экрана тоже разобрался

Мой вариант этот #74 Просто поменять библиотеку.

ZIA
ZIA аватар
Offline
Зарегистрирован: 04.02.2017

Вот это терпение у ТС )))

sir_kimas
Offline
Зарегистрирован: 01.08.2016

библиотеку менять не стал. просто немного изменил скеч. А вот с тормозом по мах не могу пока понять. 

/*
  Экран - I2C
  Датчик давления пин - А1
  Кнопки пин - 2,3,4,5,6
  реле пин - 16
  светодиод пин - 14
*/
//---светодиод-----------------------------
class Cl_led {
  protected:
    static const byte sOFF      = 0;
    static const byte sON       = 1;
    static const byte sBlinkOFF = 2;
    static const byte sBlinkON  = 3;
    byte pin;
    byte state;
    unsigned long past, time;
    void set(byte s) {
      state = s;
      past = millis();
      switch (s) {
        case sOFF :
        case sBlinkOFF:
          digitalWrite(pin, LOW);
          break;
        case sON :
        case sBlinkON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      set(sOFF);
    }
    void run() {
      if (state == sBlinkON && millis() - past >= time)set(sBlinkOFF);
      if (state == sBlinkOFF && millis() - past >= time)set(sBlinkON);
    }
    void ON() {
      set(sON);
    }
    void OFF() {
      set(sOFF);
    }
    void blink(unsigned long t) {
      time = t;
      set(sBlinkON);
    }
};
Cl_led led(/*пин*/14);
Cl_led pump(/*пин*/16);
//----------------------------------------
#include <EEPROM.h>
const byte sensPin =/*пин*/A1;
bool pump_state = false;
bool avto_state = false;
unsigned long past2;
int pressure;                 // величина давления
const int pressure_min = 103; // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
const byte delta = 1; // минимальное расстояние между pressure_ON и pressure_OFF
int pressure_;
int pressure_ON;        // величина давления когда насос сам вкл
int pressure_OFF;       // величина давления когда насос сам выкл
int avto_state_adr = 1;
int pressure_ON_adr = 2;
int pressure_OFF_adr = 4;


  float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data / 100;
}
void sens_init() {

  pressure_ON = 103;
  pressure_OFF = 1023;
  byte a;
  EEPROM.get(0, a);
  if (a != 0) {
  EEPROM.put(0, a = 0);
  EEPROM.put(pressure_ON_adr, pressure_ON);
  EEPROM.put(pressure_OFF_adr, pressure_OFF);
  EEPROM.put(avto_state_adr   , avto_state   );
  return;
  }

  EEPROM.get(pressure_ON_adr, pressure_ON);
  EEPROM.get(pressure_OFF_adr, pressure_OFF);
  EEPROM.get(avto_state_adr   , avto_state   );
  past2 = millis();
}
void sens_run() {
  if (millis() - past2 >= 100) {
    if (avto_state) {
      pressure = analogRead(sensPin);
      if (pressure <= pressure_ON ) {
        pump_state = true;
        pump.ON();
        led.blink(200);
      }
      if (pressure >= pressure_OFF ) {
        pump_state = false;
        pump.OFF();
        led.OFF();
      }
    }
  }
}
//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      if (s == true) Do();
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn    BtnU(/*пин*/5);  //кнопка верх
Cl_btn    BtnD(/*пин*/6);  //кнопка вниз
Cl_btn    BtnS(/*пин*/4);  //кнопка селект
Cl_btn BtnMoff(/*пин*/7);  //кнопка ручное вкл насоса
Cl_btn  BtnMon(/*пин*/8);  //кнопка ручное выкл насоса
//--меню--------------------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f , 16, 2);
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5;  // оперативное отображение
const byte page2 = 10; // переключ автомат/ручн
const byte page3 = 20; // установка мин
const byte page3e = 21; // редактирование мин
const byte page4  = 30; // устнаовка мах
const byte page4e = 31; // редактирование мах
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  //lcd.clear();
  switch (p) {
    case page0 ://------------погашеный экран-----------------------
      {
        lcd.noBacklight();
      }
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page1 ://----------оперативное отображение-------------------
      {
        lcd.backlight();
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
       // lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON "); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); 
        if (avto_state) lcd << F(" Auto "); 
        else lcd << F(" Manl ");
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      BtnS.Do = [] {};
      break;
    case page2 ://-------------переключ автомат/ручн---------------
      {
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
        //lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0);
        if (pump_state)lcd << F("ON"); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd  << F(">"); 
        if (avto_state) lcd << F("Auto "); 
        else lcd << F("Manl ") ;
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      BtnS.Do = [] {
        avto_state = !avto_state;
        EEPROM.put(avto_state_adr   , avto_state   );
        goPage(page2);
      };
      break;
    case page3 ://----------------/ установка мин-------------------------------
      {
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
        //lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); 
        if (pump_state)lcd << F("ON "); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); 
        if (avto_state) lcd << F("Auto"); 
        else lcd << F("Manl");
        lcd << ">" << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {
        goPage(page4);
      };
      BtnS.Do = [] {
        pressure_ = pressure_ON;
        goPage(page3e);
      };
      break;
    case page3e ://----------------ред мин-------------------------------
      {
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
        //lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); 
        if (pump_state)lcd << F("ON"); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); 
        if (avto_state) lcd << F("Auto"); 
        else lcd << F("Manl");
        lcd << "*" << AnalogToBar(pressure_) << F("/ ") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        ++pressure_ ;
        if (pressure_ > (pressure_OFF - delta))pressure_ = pressure_OFF - delta;
        goPage(page3e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < pressure_min)pressure_ = pressure_min;
        goPage(page3e);
      };
      BtnS.Do = [] {
        pressure_ON = pressure_;
        EEPROM.put(pressure_ON_adr, pressure_ON);
        goPage(page3);
      };
      break;
    case page4 ://--------------/ установка мax----------------------------------------
      {
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
        //lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); 
        if (pump_state)lcd << F("ON "); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); 
        if (avto_state) lcd << F("Auto"); 
        else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/>") << AnalogToBar(pressure_OFF);
      }
      BtnU.Do = [] {
        goPage(page3);
      };
      BtnD.Do = [] {};
      BtnS.Do = [] {
        pressure_ = pressure_OFF;
        goPage(page4e);
      };
      break;
    case page4e ://--------------редактирование мax----------------------------------------
      {
        lcd.setCursor(0, 0);
        lcd.print("P = ");
        lcd.print(AnalogToBar(pressure));
        lcd.setCursor(8, 0);
        lcd.print("  ");
        //lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); 
        if (pump_state)lcd << F("ON "); 
        else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); 
        if (avto_state) lcd << F("Auto"); 
        else lcd << F("Manl");
        lcd << " " << AnalogToBar(pressure_ON) << F("/*") << AnalogToBar(pressure_);
      }
      BtnU.Do = [] {
        ++pressure_;
        if (pressure_ > pressure_max)pressure_ = pressure_max;
        goPage(page4e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < (pressure_ON + delta))pressure_ = pressure_ON + delta;
        goPage(page4e);
      };
      BtnS.Do = [] {
        pressure_OFF = pressure_;
        EEPROM.put(pressure_OFF_adr, pressure_OFF);
        goPage(page4);
      };
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 120000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  sens_init();
  lcd.init();
  led.init();
  pump.init();
  BtnU.init();
  BtnD.init();
  BtnS.init();
  BtnMon.init();
  BtnMoff.init();
  BtnMon.Do = [] {
    if (!avto_state) {
      pump_state = true;
      pump.ON();
      led.blink(200);
    }
  };
  BtnMoff.Do = [] {
    if (!avto_state) {
      pump_state = false;
      pump.OFF();
      led.OFF();
    }
  };
  menu_init();
}
void loop() {
  sens_run();
  led.run();
  pump.run();
  BtnU.run();
  BtnD.run();
  BtnS.run();
  BtnMon.run();
  BtnMoff.run();
  menu_run();
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

основной тормоз это  lcd.clear(); Ну аппаратно это вышло. Потом  I2C потому что печать отдельных строчек и переход на другую позицию это время. Быстрее завести буфер в ОЗУ и там печатать. А потом когда надо отправить в два пакета для обновление нового экрана. Могранния не будет. Я же не тупому решил подправить эту библиотеку. Тоже моргание задрало.

sir_kimas
Offline
Зарегистрирован: 01.08.2016

Это понятно. Поэтому и убрал lcd.clear(); моргание пропало. А вот как решить проблему с тормозом изменения параметра мах не пойму.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

/*
  Экран Serial
  кнопки на 2,3,4,5,6 пина
  реле 12
  светодиод 13
*/
//---светодиод-----------------------------
class Cl_led {
  protected:
    static const byte sOFF      = 0;
    static const byte sON       = 1;
    static const byte sBlinkOFF = 2;
    static const byte sBlinkON  = 3;
    byte pin;
    byte state;
    unsigned long past, time;
    void set(byte s) {
      state = s;
      past = millis();
      switch (s) {
        case sOFF :
        case sBlinkOFF:
          digitalWrite(pin, LOW);
          break;
        case sON :
        case sBlinkON:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      set(sOFF);
    }
    void run() {
      if (state == sBlinkON && millis() - past >= time)set(sBlinkOFF);
      if (state == sBlinkOFF && millis() - past >= time)set(sBlinkON);
    }
    void ON() {
      set(sON);
    }
    void OFF() {
      set(sOFF);
    }
    void blink(unsigned long t) {
      time = t;
      set(sBlinkON);
    }
};
Cl_led led(/*пин*/13);
Cl_led pump(/*пин*/12);
//----------------------------------------
#include <EEPROM.h>
const byte sensPin =/*пин*/13;
bool pump_state = false;
bool avto_state = false;
unsigned long past2;
int pressure;                 // величина давления
const int pressure_min = 103; // величина давления минимально возможное
const int pressure_max = 1023; // величина давления максимумально возможное
const byte delta = 1; // минимальное расстояние между pressure_ON и pressure_OFF
int pressure_;
int pressure_ON;        // величина давления когда насос сам вкл
int pressure_OFF;       // величина давления когда насос сам выкл
int  pressure_ON_adr = 2;
int  pressure_OFF_adr = 4;
float AnalogToBar(int Bar) {
  float data = map(Bar, 103, 1023, 0, 1200);
  if (data < 0) return 0;
  return data / 100;
}
void sens_init() {

  pressure_ON = 103;
  pressure_OFF = 1023;
  EEPROM.put(pressure_ON_adr, pressure_ON);
  EEPROM.put(pressure_OFF_adr, pressure_OFF);

  EEPROM.get(pressure_ON_adr, pressure_ON);
  EEPROM.get(pressure_OFF_adr, pressure_OFF);
  past2 = millis();
}
void sens_run() {
  if (millis() - past2 >= 100) {
    if (avto_state) {
      pressure = analogRead(sensPin);
      if (pressure <= pressure_ON ) {
        pump_state = true;
        pump.ON();
        led.blink(200);
      }
      if (pressure >= pressure_OFF ) {
        pump_state = false;
        pump.OFF();
        led.OFF();
      }
    }
  }
}
//---кнопки-----------------------------
typedef void (*pDo)();
class Cl_btn {
  protected:
    byte pin;
    bool state;
    unsigned long past;
    void set(bool s) {
      state = s;
      past = millis();
      if (s == true) Do();
    }
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100)
        switch (state) {
          case false:
            if (!digitalRead(pin))set(true);
            break;
          case true:
            if (digitalRead(pin))set(false);
            if (millis() - past >= 300)set(false);
            break;
        }
    }
};
Cl_btn    BtnU(/*пин*/2);  //кнопка верх
Cl_btn    BtnD(/*пин*/3);  //кнопка вниз
Cl_btn    BtnS(/*пин*/4);  //кнопка селект
Cl_btn BtnMoff(/*пин*/5);  //кнопка ручное вкл насоса
Cl_btn  BtnMon(/*пин*/6);  //кнопка ручное выкл насоса
//--меню--------------------------
//------дисплей lcd1602_i2c-----------------------------
// даташит <a href="https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf" title="https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf" rel="nofollow">https://www.sparkfun.com/datasheets/LCD/ADM1602K-NSW-FBS-3.3v.pdf</a>
// на русском <a href="http://www.melt.aha.ru/pdf/mt-16s2h.pdf" title="http://www.melt.aha.ru/pdf/mt-16s2h.pdf" rel="nofollow">http://www.melt.aha.ru/pdf/mt-16s2h.pdf</a>
#include <Wire.h>
// команды
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// флаги для режима ввода дисплея
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// флаги для управления включением / выключением дисплея
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// флаги для отображения / сдвига курсора
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// флаги для набора функций
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// флаги для управления подсветкой
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En B00000100  // Бит разрешения
#define Rw B00000010  // Чтение / запись бит
#define Rs B00000001  // Бит выбора регистра
class Cl_lcd1602_i2c : public Print {
  protected:
    uint8_t adr, posX, posY;
    uint8_t _backlightval;
    uint8_t _displayfunction;
    uint8_t _displaycontrol;
    uint8_t _displaymode;
    byte buffer[32];
  public:
    Cl_lcd1602_i2c(uint8_t a): adr(a) {}
    void init() {
      Wire.begin();
      write4bits(0x03 << 4);
      delayMicroseconds(4500); // wait min 4.1ms
      write4bits(0x03 << 4);
      delayMicroseconds(4500); // wait min 4.1ms
      write4bits(0x03 << 4);
      delayMicroseconds(150);
      write4bits(0x02 << 4);
      delay(50);
      _backlightval = LCD_NOBACKLIGHT;
      expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1)
      // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек
      _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS;
      command(LCD_FUNCTIONSET | _displayfunction);
      // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает
      _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
      command(LCD_DISPLAYCONTROL | _displaycontrol);
      // режим ввода текста в память-начинать слева с движением в право
      _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
      command(LCD_ENTRYMODESET | _displaymode);
      clear();
    }
    // подсветку вкл/выкл
    void backlight(void) {
      _backlightval = LCD_BACKLIGHT;
      expanderWrite(0);
    }
    void noBacklight(void) {
      _backlightval = LCD_NOBACKLIGHT;
      expanderWrite(0);
    }
    // очистить буфер
    void clear() {
      for (byte i = 0; i < 32; i++ )buffer[i] = 0x20;
      posX = 0; posY = 0;
    }
    // отправить информацию из буфера на экран
    void show() {
      line(0);
      for (byte i = 0; i < 16; i++ )out(buffer[i]);
      line(1);
      for (byte i = 16; i < 32; i++ )out(buffer[i]);
    }
    void setCursor(byte x, byte y) {
      if (x > 16) x = 16;
      else posX = x;
      if (y > 2) x = 2;
      else posY = y;
    }
  private:
    /*внутрение функции*/
    void line(byte l) {
      if (l == 0) command(LCD_SETDDRAMADDR | 0x00);
      else command(LCD_SETDDRAMADDR | 0x40);
    }
    inline void out(uint8_t value) {
      send(value, Rs);
    }
    inline size_t write(uint8_t value) {
      if (posX < 16 && posY < 2) {
        buffer[posY * 16 + posX] = value;
        posX++;
      }
      return 1;
    }
    /*команды низкоуровневого управления*/
    inline void command(uint8_t value) {
      send(value, 0);
    }
    void send(uint8_t value, uint8_t mode) {
      uint8_t highnib = value & 0xf0;
      write4bits((highnib) | mode);
      uint8_t lownib = (value << 4) & 0xf0;
      write4bits((lownib) | mode);
    }
    void write4bits(uint8_t value) {
      expanderWrite(value);
      pulseEnable(value);
    }
    void expanderWrite(uint8_t _data) {
      Wire.beginTransmission(adr);
      Wire.write((int)(_data) | _backlightval);
      Wire.endTransmission();
    }
    void pulseEnable(uint8_t _data) {
      expanderWrite(_data | En);  // En high
      delayMicroseconds(1);   // enable pulse must be >450ns
      expanderWrite(_data & ~En); // En low
      delayMicroseconds(50);    // commands need > 37us to settle
    }
};
Cl_lcd1602_i2c lcd(0x27);
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
const byte page0 = 0; // погашеный экран
const byte page1 = 5;  // оперативное отображение
const byte page2 = 10; // переключ автомат/ручн
const byte page3 = 20; // установка мин
const byte page3e = 21; // редактирование мин
const byte page4  = 30; // устнаовка мах
const byte page4e = 31; // редактирование мах
byte page;// текущая страница
unsigned long past, past1;
void goPage(byte p, byte c = 1) {
  page = p;
  past = millis();
  if (c == 1)past1 = millis();
  lcd.clear();
  switch (p) {
    case page0 ://------------погашеный экран-----------------------
      {
        lcd.noBacklight();
        lcd.show();
      }
      BtnU.Do = [] {          // Поменять обработчики кнопок
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page1);
      };
      BtnS.Do = [] {
        goPage(page1);
      };
      break;
    case page1 ://----------оперативное отображение-------------------
      {
        lcd.backlight();
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); if (avto_state) lcd << F(" Auto "); else lcd << F(" Manl ");
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
        lcd.show();
      }
      BtnU.Do = [] {};      // Поменять обработчики кнопок
      BtnD.Do = [] {
        goPage(page2);
      };
      BtnS.Do = [] {};
      break;
    case page2 ://-------------переключ автомат/ручн---------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd  << F(">"); if (avto_state) lcd << F("Auto "); else lcd << F("Manl ") ;
        lcd << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
        lcd.show();
      }
      BtnU.Do = [] {
        goPage(page1);
      };
      BtnD.Do = [] {
        goPage(page3);
      };
      BtnS.Do = [] {
        avto_state = !avto_state;
        goPage(page2);
      };
      break;
    case page3 ://----------------/ установка мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << F(">") << AnalogToBar(pressure_ON) << F("/ ") << AnalogToBar(pressure_OFF);
        lcd.show();
      }
      BtnU.Do = [] {
        goPage(page2);
      };
      BtnD.Do = [] {
        goPage(page4);
      };
      BtnS.Do = [] {
        pressure_ = pressure_ON;
        goPage(page3e);
      };
      break;
    case page3e ://----------------ред мин-------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON"); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << F("*") << AnalogToBar(pressure_) << F("/ ") << AnalogToBar(pressure_OFF);
        lcd.show();
      }
      BtnU.Do = [] {
        ++pressure_ ;
        if (pressure_ > (pressure_OFF - delta))pressure_ = pressure_OFF - delta;
        goPage(page3e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < pressure_min)pressure_ = pressure_min;
        goPage(page3e);
      };
      BtnS.Do = [] {
        pressure_ON = pressure_;
        EEPROM.put(pressure_ON_adr, pressure_ON);
        goPage(page3);
      };
      break;
    case page4 ://--------------/ установка мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << F(" ") << AnalogToBar(pressure_ON) << F("/>") << AnalogToBar(pressure_OFF);
        lcd.show();
      }
      BtnU.Do = [] {
        goPage(page3);
      };
      BtnD.Do = [] {};
      BtnS.Do = [] {
        pressure_ = pressure_OFF;
        goPage(page4e);
      };
      break;
    case page4e ://--------------редактирование мax----------------------------------------
      {
        lcd << F("P = ") << AnalogToBar(pressure);
        lcd.setCursor(11, 0); if (pump_state)lcd << F("ON "); else lcd << F("OFF");
        lcd.setCursor(0, 1); lcd << F(" "); if (avto_state) lcd << F("Auto"); else lcd << F("Manl");
        lcd << F(" ") << AnalogToBar(pressure_ON) << F("/*") << AnalogToBar(pressure_);
        lcd.show();
      }
      BtnU.Do = [] {
        ++pressure_;
        if (pressure_ > pressure_max)pressure_ = pressure_max;
        goPage(page4e);
      };
      BtnD.Do = [] {
        --pressure_;
        if (pressure_ < (pressure_ON + delta))pressure_ = pressure_ON + delta;
        goPage(page4e);
      };
      BtnS.Do = [] {
        pressure_OFF = pressure_;
        EEPROM.put(pressure_OFF_adr, pressure_OFF);
        goPage(page4);
      };
      break;
  }
}
void menu_init() {
  goPage(page1);
}
void menu_run() {
  if (page != page0) { // если экран не погашен
    if (page == page1 && millis() - past >= 1000)goPage(page1, 0); // обновлять если стоим на 1 странице
    if (page != page1 && millis() - past >= 5000)goPage(page1, 0); // перейти на 1 страницу если долго стоми не на 1 странице
    if (millis() - past1 >= 10000) goPage(page0);// если долго не стучали кнопками то погасить экран
  }
}
//----------------
void setup() {
  sens_init();
  lcd.init();
  led.init();
  pump.init();
  BtnU.init();
  BtnD.init();
  BtnS.init();
  BtnMon.init();
  BtnMoff.init();
  BtnMon.Do = [] {
    if (!avto_state) {
      pump_state = true;
      pump.ON();
      led.blink(200);
    }
  };
  BtnMoff.Do = [] {
    if (!avto_state) {
      pump_state = false;
      pump.OFF();
      led.OFF();
    }
  };
  menu_init();
}
void loop() {
  sens_run();
  led.run();
  pump.run();
  BtnU.run();
  BtnD.run();
  BtnS.run();
  BtnMon.run();
  BtnMoff.run();
  menu_run();
}