Меню на дисплее 2004 и BME280

iDDiP

✩✩✩✩✩✩✩
8 Ноя 2023
1
0
C++:
////////////////////////////////////////БИБЛИОТЕКИ///////////////////////////////////
#include "GyverEncoder.h"
#include "MatroskinMenu.h"
#include <GyverBME280.h>
/////////////////////////////////////////ОБЪЕКТ///////////////////////////////////
GyverBME280 bme;
//////////////////////////////////////////ПИНЫ//////////////////////////////////////
#define CLK 2                                              // Пины энкодера
#define DT 3
#define SW 0
#define BINARY_ALGORITHM
//#define QUANTITY_SCREENS 5                               // количество экранов
//#define QUANTITY_LINES 7                                 // количество сторок
////////////////////////////////////// ////ОБЪЕКТ//////////////////////////////////////
Encoder enc1(CLK, DT, SW);                                 //Объект энкодера
Menu menu_one;                                             //Объект меню
////////////////////////////////////////ПЕРЕМЕННЫЕ////////////////////////////////////
//float temp = 0;                                         //Температура
uint16_t pokazometr = 8;
uint16_t brigh = 20;
uint16_t flagind;
uint8_t ledPin1 = 11, ledPin2 = 10;
bool flag = 1;
//////////////////////////////////////////ПИНЫ//////////////////////////////////////
void isr() {     // Энкодер отработка в прерывании
  enc1.tick();
}

void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  lcd.clear();
  lcd.init();
  lcd.backlight();
////////////////////////////////////////ЭНКОДЕР///////////////////////////////////
  attachInterrupt(0, isr, CHANGE);   //Прерывания на пинах энкодера
  attachInterrupt(1, isr, CHANGE);
  enc1.setType(TYPE2);               // Тип энкодера
////////////////////////////////////////BME280///////////////////////////////////
  bme.setFilter(FILTER_COEF_8);                     // Настраиваем коофициент фильтрации
  bme.setTempOversampling(OVERSAMPLING_8);          // Настраиваем передискретизацию для датчика температуры
  bme.setPressOversampling(OVERSAMPLING_16);        // Настраиваем передискретизацию для датчика давления
  bme.setStandbyTime(STANDBY_500MS);                // Устанавливаем время сна между измерениями (у нас обычный циклический режим)
  bme.begin();                                      // Если на этом настройки окончены - инициализируем датчик
  /*Формирование и заполнение непосредственно самого меню. Задаем названия экранов,
    пунктов меню и переменную для отображения в конце строки (если нужна предаем по адресу (&))
    Пример: menu_one.SetNames(uint8_t Номер экрана, uint8_t Номер строки, "Название пункта меню", & прееменная для отображения в конце строки (тип uint16_t));
  */
  menu_one.SetNames(0, 0, "Monitoring");
  menu_one.SetNames(0, 1, "Temperature  C", &pokazometr);
  menu_one.SetNames(0, 2, "humidity     p");
  menu_one.SetNames(0, 3, "light      lux ");
  menu_one.SetNames(0, 4, "gas        ppm");
 
  menu_one.SetNames(1, 0, "Set values");
  menu_one.SetNames(1, 1, "Temperature C");
  menu_one.SetNames(1, 2, "humidity    p");
  menu_one.SetNames(1, 3, "light     lux");
  menu_one.SetNames(1, 4, "gas       ppm");

  menu_one.SetNames(2, 0, "Time");
  menu_one.SetNames(2, 1, "light", &brigh);
  menu_one.SetNames(2, 2, "vent");

  menu_one.SetNames(3, 0, "Data");
  menu_one.SetNames(3, 1, "LCD Light", &flagind);
  menu_one.SetNames(3, 2, "time");
  menu_one.SetNames(3, 3, "date");

  /*
    Привязка пользовательских функций к пунктам меню, максимум две
    Пример для привязки первой функции: menu_one.SetFunc1 (uint8_t Номер экрана, uint8_t Номер строки, название функции (void));
  */
  menu_one.SetFunc1 (0, 1, pok_pluss);  //Подключаем первую прикрепленную функцию (Нулевой экран, первая строка)
  menu_one.SetFunc2 (0, 1, pok_minuss); //Подключаем вторую прикрепленную функцию (Нулевой экран, вторая строка)
 
  menu_one.SetFunc1 (1, 2, LedOn);
  menu_one.SetFunc2 (1, 2, LedOff);

  menu_one.SetFunc1 (2, 1, brigh_up);
  menu_one.SetFunc2 (2, 1, brigh_down);

  menu_one.SetFunc1 (3, 1, LcdLightOn);
  menu_one.SetFunc2 (3, 1, LcdLightOff);


  menu_one.MakeMenu( 2, 2);             //Обновляем информацию на экране
}
void loop() {
  enc1.tick();
  if (enc1.isRight()) {                // Событие перемещения по списку строк вниз (следующая строка)
    menu_one.MakeMenu( 1, 2);
  };
  if (enc1.isLeft()) {                 // Событие перемещения по списку строк вверх (предыдущая строка)
    menu_one.MakeMenu( 0, 2);
  };
  if (enc1.isClick()) {                // Событие переключения следующего экрана меню
    menu_one.MakeMenu( 2, 1);
  }
  if (enc1.isHolded()) {              // Событие переключения предыдущего экрана меню    //Расскомментиовать и подстватить условие если нужно
     menu_one.MakeMenu( 2, 0);
    }

  /*Вызов прикрепленных  к строкам меню функций (правый нажатый поворот энкодера первая функция, левый - вторая)*/

  if (enc1.isRightH()) {               //Событие для прикрепленной функции 1 (ПРАВЫЙ нажатый поворот энкодера)
    menu_one.RunFunction1();
  };

  if (enc1.isLeftH()) {                //Событие для прикрепленной функции 2 (ЛЕВЫЙ нажатый поворот энкодера)
    menu_one.RunFunction2();
  };
}

//Примеры простейших внешних функций:

void LedOn () {                       //Включаем и отключаем синий светодиод
  digitalWrite(ledPin2, HIGH);
}
void LedOff () {
  digitalWrite(ledPin2, LOW);
}

void brigh_up () {                    //Меняем яркость красного светодиода
  analogWrite(ledPin1, brigh);
  brigh += 10;
  brigh = constrain (brigh,10, 240);
}
void brigh_down () {
  analogWrite(ledPin1, brigh);
  brigh -= 10;
  brigh = constrain (brigh, 10, 240);
}

void pok_pluss() {                   //Просто увеличиваем и уменньшаем значение переменной
  pokazometr++ ;
}
  void pok_minuss() {
    pokazometr--;
  }

void LcdLightOn() {                  //Включаем и отключаем подсветку экрана     
  flag = 1;
  lcd.setBacklight(flag);
  flagind = flag;
}
void LcdLightOff() {
  flag = 0;
  lcd.setBacklight(flag);
  flagind = flag;
}
На основе данной библиотеки и кода хочу сделать автоматическую теплицу. На первом экране меню выводит данные с датчиков в реально времени, а на втором заданные значения для реле/серво.
Вопрос: не получается сделать вывод температуры с датчика на дисплей. Возможно надо использоваться указатель, но я не понял, как в данном способе должна выглядеть реализация.
 

Serge_Aminov

✩✩✩✩✩✩✩
1 Мар 2022
1
0
Пробовал с этим меню подобное творить, без танцев с бубном памяти у обычной НАНО не хватит, ну это так, вступление.
А по поводу экрана, так там же статически выводится на него инфа, пока не перейдешь в другое меню, либо энкодером не пошевелишь, поэтому ни датчики, ни время в реалтайме не будут отображаться, надо обновлять экран, но этим забьешь тики с энкодера и будут пропуски.

Я поступил проще, взял за основу Гайвер Портал и esp8266 и теперь просто с телефона управляю кранами, насосом, смотрю температуру, нюхаю влажность. ОООчень рекомендую либо Портал, либо Хаб... мне достаточно портала оказалось

1701150619868.png