Многоуровневое меню для Ардуино и строкового ЖК дисплея 16x2

junior_developer
Offline
Зарегистрирован: 27.11.2017

qwone пишет:


/**/
const int sensor =/*пин*/ A0; // сенсор подключен к этому выводу
int ReadSensor() {
  static int val = analogRead(sensor); //<-читается в начале
  static uint32_t lasttime = 0;
  const uint32_t delta = 1000;
  uint32_t mill = millis();
  if (mill - lasttime >= delta) val = analogRead(sensor);
  return val;
}
//---main()------------------------
void setup() {
  Serial.begin(9600);

}
void loop() {
  delay (200);
  Serial.println(ReadSensor());
}
/*Скетч использует 1968 байт (6%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 196 байт (9%) динамической памяти, оставляя 1852 байт для локальных переменных. Максимум: 2048 байт.
*/

я внимательно посмотрел Ваш код, и обнаружил, что переменная lasttime в нем не обновляется! А если и обновляется, то я не понимаю, как? Ведь там нету строки
 

lasttime = mill;

Если чтение будет происходить циелически, она нужна? Или нет?

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

забыл написать.

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

ЕвгенийП пишет:

 "Всякая найденная в программе последняя ошибка, на самом деле является предпоследней"

а у мня обычно получается так: В коде было 7 ошибок, 12 из них исправил, осталось 8. 

Клапауций 089
Клапауций 089 аватар
Offline
Зарегистрирован: 14.01.2018

DetSimen пишет:

а у мня обычно получается так: В коде было 7 ошибок, 12 из них исправил, осталось 8. 

то были не ошибки, а прикольные фичи.

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

Клапа, я рад тебя видеть. Мы соскучивались тут.  

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

Так и не довели до конца тему?    А мне вот нужно...

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

-NMi- пишет:

Так и не довели до конца тему?    А мне вот нужно...

Вы что разве не можете написать многоуровневое меню?? Начинается оно примитивно

const byte pageN   = 0;//погасить экран
const byte page0   = 5;//главный экран
const byte page1   = 10;//уровень 1
const byte page1_1 = 11;//уровень 1-1
const byte page1_2 = 12;//уровень 1-2
const byte page1_3 = 13;//уровень 1-3
const byte page2   = 20;//уровень 2
const byte page2_1 = 21;//уровень 2-1
const byte page2_2 = 22;//уровень 2-2
const byte page2_3 = 23;//уровень 2-3
byte page;
uint32_t past;
void goPage(byte p) {
  past = millis();
  page = p;
  switch (page) {
  }
}
void initMenu() {
  goPage(page0);
}
void runMenu() {}

void setup() {
  initMenu();
}

void loop() {
  runMenu();
}

 

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

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

PS: меню написано уже года 2 назад. Работает. Хочется большего функционала.

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

Итак, начнём:

Первое, что захотелось - индексация слов в меню. Например, нам нужно вывести на дисплей строку: Do you want start heating?  Yes/No.

Проиндексируем использованные слова:

1-Do

2-you

3-want  и так далее. По итогу вывод строки будет типа: функция(1,2,3,4,5,6,7,8,9,10)  (знаки ?  /  .  тоже учитываются )

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что это Вы пытаетесь делать? Память под тексты экономить? Если так, то мож лучше по Хаффману? Зазиповать текст нахрен, чем велосипед-то городить?

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

-NMi- пишет:

Итак, начнём:

Первое, что захотелось - индексация слов в меню. Например, нам нужно вывести на дисплей строку: Do you want start heating?  Yes/No.

Проиндексируем использованные слова:

1-Do

2-you

3-want  и так далее. По итогу вывод строки будет типа: функция(1,2,3,4,5,6,7,8,9,10)  (знаки ?  /  .  тоже учитываются )

#include "eeprom_Ref.h"
const char  pgm_s[] PROGMEM =
  "zero 0\0one 1\0two 2\0three 3\0four 4\0five 5\0six 6\0seven 7\0nine 9\0ten 10\0";
pgm_String pgm_S((String*)pgm_s);
void setup() {
  Serial.begin(9600);
  for (int i = 0; i <= 10; i++)
    Serial.println(pgm_S[i]);
}

void loop() {
}

eeprom_Ref.h

/* Ref.h */
#ifndef EEPROM_REF_H
#define EEPROM_REF_H
//Ref.h-----------------------
#include <Arduino.h>
#include <avr/eeprom.h>
template <typename T>
class Ref {
  protected:
    T* pointer;
    void set(T data);
    T get();
  public:
    ~Ref();
    Ref() = delete;
    Ref(T* a);
    Ref(const Ref& other) = delete;
    Ref(Ref&& other);
    Ref& operator=(const Ref& other) = delete;
    Ref& operator=(Ref&& other);
    //
    operator T();
    Ref& operator=(T&& d);
    Ref& operator=(const T& d);
    Ref operator[] (const int index);
    Ref& operator +=(T&& d);
    Ref& operator -=(T&& d);
};
//Ref.cpp-----------------------
/* uint8_t */
template <>
void Ref<uint8_t>::set(uint8_t data) {
  eeprom_write_byte(pointer, data);
}
template <>
uint8_t Ref<uint8_t>::get() {
  return eeprom_read_byte(pointer);
}
/* int */
template <>
void Ref<int>::set(int data) {
  eeprom_write_word((uint16_t*)pointer, (uint16_t)data);
}
template <>
int Ref<int>::get() {
  return eeprom_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
void Ref<uint16_t>::set(uint16_t data) {
  eeprom_write_word(pointer, data);
}
template <>
uint16_t Ref<uint16_t>::get() {
  return eeprom_read_word(pointer);
}
/* uint32_t*/
template <>
void Ref<uint32_t>::set(uint32_t data) {
  eeprom_write_dword(pointer, data);
}
template <>
uint32_t Ref<uint32_t>::get() {
  return eeprom_read_dword(pointer);
}
/* float*/
template <>
void Ref<float>::set(float data) {
  eeprom_write_float(pointer, data);
}
template <>
float Ref<float>::get() {
  return eeprom_read_float(pointer);
}
/*общее*/
template <typename T>
Ref<T>::~Ref() {}
template <typename T>
Ref<T>::Ref(T* a): pointer(a) {}
template <typename T>
Ref<T>::Ref(Ref<T>&& other) {
  pointer = other.pointer;
}
template <typename T>
Ref<T>& Ref<T>::operator=(Ref<T>&& other) {
  if (pointer != other.pointer)
    set(other.get());
  return *this;
}
template <typename T>
Ref<T>::operator T() {
  return get();
}
template <typename T>
Ref<T>& Ref<T>::operator=(T&& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator=(const T& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T> Ref<T>::operator[] (const int index) {
  return Ref<T>(pointer + index);
}
template <typename T>
Ref<T>& Ref<T>::operator +=(T&& d) {
  set(get() + d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator -=(T&& d) {
  set(get() - d);
  return *this;
}
using eeprom_int      = Ref<int> ;
using eeprom_uint8_t  = Ref<uint8_t>;
using eeprom_uint16_t = Ref<uint16_t>;
using eeprom_uint32_t = Ref<uint32_t>;
using eeprom_float    = Ref<float>;
//pRef.h-----------------------------
#include <avr/pgmspace.h>
template <typename T>
class pRef {
  protected:
    const T* pointer;
    T get();
  public:
    ~pRef();
    pRef() = delete;
    pRef(const T* a);
    pRef(const pRef& other) = delete;
    pRef(pRef&& other);
    pRef& operator=(const pRef& other) = delete;
    pRef& operator=(pRef&& other);
    //
    operator T();
    pRef operator[] (const int index);
};
//pRef.cpp-----------------------------
/*uint8_t*/
template <>
uint8_t pRef<uint8_t>::get() {
  return pgm_read_byte(pointer);
}
/* int */
template <>
int pRef<int>::get() {
  return pgm_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
uint16_t pRef<uint16_t>::get() {
  return pgm_read_word(pointer);
}
/* uint32_t*/
template <>
uint32_t pRef<uint32_t>::get() {
  return pgm_read_dword(pointer);
}
/* float*/
template <>
float pRef<float>::get() {
  return pgm_read_float(pointer);
}
/*String*/
template <>
String pRef<String>::get() {
  return String(reinterpret_cast<const __FlashStringHelper *>(pointer));
}
template <>
pRef<String> pRef<String>::operator[] (const int index) {
  char *p = (char*)pointer;
  int i = index;
  while (i != 0) {
    p = (char*)strchrnul_P(p, 0);
    p++;
    i--;
  }
  return pRef<String>((String*)p);
}
/*общее*/
template <typename T>
pRef<T>::~pRef() {}
template <typename T>
pRef<T>::pRef(const T* a): pointer(a) {}
template <typename T>
pRef<T>::pRef(pRef<T>&& other)
  : pointer(other.pointer) {}

template <typename T>
pRef<T>& pRef<T>::operator=(pRef<T>&& other) {
  pointer = other.pointer;
  return *this;
}
template <typename T>
pRef<T>::operator T() {
  return get();
}
template <typename T>
pRef<T> pRef<T>::operator[] (const int index) {
  return pRef<T>(pointer + index);
}
//-------------------------------------------------
using pgm_int      = pRef<int>;
using pgm_uint8_t  = pRef<uint8_t>;
using pgm_uint16_t = pRef<uint16_t>;
using pgm_uint32_t = pRef<uint32_t>;
using pgm_float    = pRef<float>;
using pgm_String   = pRef<String>;
#endif

 

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

ЕвгенийП пишет:

А что это Вы пытаетесь делать? Память под тексты экономить?

Спасибо за интерес к теме. Что я пытаюсь делать в этом примере - многоязычное меню. Думаю так будет проще.

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

-NMi- пишет:
Спасибо за интерес к теме. Что я пытаюсь делать в этом примере - многоязычное меню. Думаю так будет проще.

Ну где-то так.

/**/
//-кнопки--------------------------------------
#include "Cl_btn.h"
Cl_btn BtnS(/*пин*/2);  //кнопка селект
Cl_btn BtnU(/*пин*/3);  //кнопка верх
Cl_btn BtnD(/*пин*/4);  //кнопка вниз
//-------------------------------------------
#include "eeprom_Ref.h"
byte language = 0;// 0-англ/ 1 итал/ 2 португ
//-meню--------------------------------------
#include "lcd1602_i2c.h"
const byte pageN   = 0;//погасить экран
const byte page0   = 5;//главный экран
const byte page1   = 10;//уровень 1
const byte page1_1 = 11;//уровень 1-1
const byte page1_2 = 12;//уровень 1-2
const byte page1_3 = 13;//уровень 1-3
const byte page2   = 20;//уровень 2
const byte page2_1 = 21;//уровень 2-1
const byte page2_2 = 22;//уровень 2-2
const byte page2_3 = 23;//уровень 2-3
const byte page3   = 30;//выбор языка
byte page;
uint32_t past;
void goPage(byte p) {
  past = millis();
  page = p;
  GTX display(LCD_W, LCD_H);
  switch (page) {
    case pageN://погасить экран
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page0);};
      { lcd.noBacklight();
      }
      break;
    case page0://главный экран
      BtnS.Do = [] {};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page1);};
      { static const char  txt1[] PROGMEM = "main\0schermata\0tela\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = " screen\0 iniziale\0 inicial\0";
        pgm_String message2((String*)txt2);
        lcd.backlight();
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page1://уровень 1
      BtnS.Do = [] {goPage(page1_1);};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page2);};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1\0 1\0 1\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page1_1://уровень 1-1
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-1\0 1-1\0 1-1\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page1_2://уровень 1-2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-2\0 1-2\0 1-2\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page1_3://уровень 1-3
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-3\0 1-3\0 1-3\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page2://уровень 2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {goPage(page1);};
      BtnD.Do = [] {goPage(page3);};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2\0 2\0 2\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page2_1://уровень 2-1
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-1 \0 2-1\0 2-1\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page2_2://уровень 2-2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-2\0 2-2\0 2-2\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page2_3://уровень 2-3
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level 2-3\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-3\0 2-3\0 2-3\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
    case page3 ://выбор языка
      BtnS.Do = [] {
        language++; if (language > 2)language = 0;
        goPage(page3);
      };
      BtnU.Do = [] {goPage(page2);};
      BtnD.Do = [] {goPage(page0);};
      { static const char  txt1[] PROGMEM = "choose a language:\0scegli una lingua:\0escolha um idioma:\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "English\0Italiano\0Portugues\0";
        pgm_String message2((String*)txt2);
        display << xy(0, 0) <<  message1[language];
        display << xy(0, 1) <<  message2[language];
      }
      break;
  }
  lcd.show(display);
}
void initMenu() {
  Serial.begin(9600);
  lcd.init();
  BtnS.init();
  BtnU.init();
  BtnD.init();
  goPage(page0);
}
void runMenu() {
  BtnS.run();
  BtnU.run();
  BtnD.run();
  if (page != pageN && millis() - past >= 6000) goPage(pageN);
}
//--выполнение-----------------------------
void setup() {
  initMenu();
}

void loop() {
  runMenu();
}

Cl_btn.h

/*Cl_btn.h*/
#ifndef Cl_btn_h
#define Cl_btn_h
//Cl_btn.h--------------------------------
typedef void (*pDo)();
class Cl_btn {
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init();
    void run();
  protected:
    void set(bool s);
    byte pin;
    bool state;
    unsigned long past;
};
//Cl_btn.cpp--------------------------------
void Cl_btn::set(bool s) {
  state = s;
  past = millis();
  if (s == true) Do();
}
void Cl_btn::init() {
  pinMode(pin, INPUT_PULLUP);
  set(false);
}
void Cl_btn::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;
    }
}
#endif

eeprom_Ref.h

/* eeprom_Ref.h */
#ifndef EEPROM_REF_H
#define EEPROM_REF_H
//Ref.h-----------------------
#include <Arduino.h>
#include <avr/eeprom.h>
template <typename T>
class Ref {
  protected:
    T* pointer;
    void set(T data);
    T get();
  public:
    ~Ref();
    Ref() = delete;
    Ref(T* a);
    Ref(const Ref& other) = delete;
    Ref(Ref&& other);
    Ref& operator=(const Ref& other) = delete;
    Ref& operator=(Ref&& other);
    //
    operator T();
    Ref& operator=(T&& d);
    Ref& operator=(const T& d);
    Ref operator[] (const int index);
    Ref& operator +=(T&& d);
    Ref& operator -=(T&& d);
};
//Ref.cpp-----------------------
/* uint8_t */
template <>
void Ref<uint8_t>::set(uint8_t data) {
  eeprom_write_byte(pointer, data);
}
template <>
uint8_t Ref<uint8_t>::get() {
  return eeprom_read_byte(pointer);
}
/* int */
template <>
void Ref<int>::set(int data) {
  eeprom_write_word((uint16_t*)pointer, (uint16_t)data);
}
template <>
int Ref<int>::get() {
  return eeprom_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
void Ref<uint16_t>::set(uint16_t data) {
  eeprom_write_word(pointer, data);
}
template <>
uint16_t Ref<uint16_t>::get() {
  return eeprom_read_word(pointer);
}
/* uint32_t*/
template <>
void Ref<uint32_t>::set(uint32_t data) {
  eeprom_write_dword(pointer, data);
}
template <>
uint32_t Ref<uint32_t>::get() {
  return eeprom_read_dword(pointer);
}
/* float*/
template <>
void Ref<float>::set(float data) {
  eeprom_write_float(pointer, data);
}
template <>
float Ref<float>::get() {
  return eeprom_read_float(pointer);
}
/*общее*/
template <typename T>
Ref<T>::~Ref() {}
template <typename T>
Ref<T>::Ref(T* a): pointer(a) {}
template <typename T>
Ref<T>::Ref(Ref<T>&& other) {
  pointer = other.pointer;
}
template <typename T>
Ref<T>& Ref<T>::operator=(Ref<T>&& other) {
  if (pointer != other.pointer)
    set(other.get());
  return *this;
}
template <typename T>
Ref<T>::operator T() {
  return get();
}
template <typename T>
Ref<T>& Ref<T>::operator=(T&& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator=(const T& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T> Ref<T>::operator[] (const int index) {
  return Ref<T>(pointer + index);
}
template <typename T>
Ref<T>& Ref<T>::operator +=(T&& d) {
  set(get() + d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator -=(T&& d) {
  set(get() - d);
  return *this;
}
using eeprom_int      = Ref<int> ;
using eeprom_uint8_t  = Ref<uint8_t>;
using eeprom_uint16_t = Ref<uint16_t>;
using eeprom_uint32_t = Ref<uint32_t>;
using eeprom_float    = Ref<float>;
//pRef.h-----------------------------
#include <avr/pgmspace.h>
template <typename T>
class pRef {
  protected:
    const T* pointer;
    T get();
  public:
    ~pRef();
    pRef() = delete;
    pRef(const T* a);
    pRef(const pRef& other) = delete;
    pRef(pRef&& other);
    pRef& operator=(const pRef& other) = delete;
    pRef& operator=(pRef&& other);
    //
    operator T();
    pRef operator[] (const int index);
};
//pRef.cpp-----------------------------
/*uint8_t*/
template <>
uint8_t pRef<uint8_t>::get() {
  return pgm_read_byte(pointer);
}
/* int */
template <>
int pRef<int>::get() {
  return pgm_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
uint16_t pRef<uint16_t>::get() {
  return pgm_read_word(pointer);
}
/* uint32_t*/
template <>
uint32_t pRef<uint32_t>::get() {
  return pgm_read_dword(pointer);
}
/* float*/
template <>
float pRef<float>::get() {
  return pgm_read_float(pointer);
}
/*String*/
template <>
String pRef<String>::get() {
  return String(reinterpret_cast<const __FlashStringHelper *>(pointer));
}
template <>
pRef<String> pRef<String>::operator[] (const int index) {
  char *p = (char*)pointer;
  int i = index;
  while (i != 0) {
    p = (char*)strchrnul_P(p, 0);
    p++;
    i--;
  }
  return pRef<String>((String*)p);
}
/*общее*/
template <typename T>
pRef<T>::~pRef() {}
template <typename T>
pRef<T>::pRef(const T* a): pointer(a) {}
template <typename T>
pRef<T>::pRef(pRef<T>&& other)
  : pointer(other.pointer) {}

template <typename T>
pRef<T>& pRef<T>::operator=(pRef<T>&& other) {
  pointer = other.pointer;
  return *this;
}
template <typename T>
pRef<T>::operator T() {
  return get();
}
template <typename T>
pRef<T> pRef<T>::operator[] (const int index) {
  return pRef<T>(pointer + index);
}
//-------------------------------------------------
using pgm_int      = pRef<int>;
using pgm_uint8_t  = pRef<uint8_t>;
using pgm_uint16_t = pRef<uint16_t>;
using pgm_uint32_t = pRef<uint32_t>;
using pgm_float    = pRef<float>;
using pgm_String   = pRef<String>;
#endif

lcd1602_i2c.h

/*lcd1602_i2c.h*/
#ifndef LCD1602_I2C_H
#define LCD1602_I2C_H
// xy.h------------------------------------
class xy { // класс задание позиции
  public:
    int x, y;
    explicit xy(): x(0), y(0) {}
    explicit xy(int _x, int _y): x(_x), y(_y) {}
};
// xy.cpp----------------------------------
// GTX.h------------------------------------
class Lcd1602_i2c;
class GTX : public Print {
    friend class Lcd1602_i2c;
  protected:
    uint8_t W, H;
    uint8_t* buffer;
    int posX, posY;
  public:
    ~GTX();
    GTX();
    GTX(uint8_t w, uint8_t h);
    GTX(const GTX& other) = delete;
    GTX(GTX&& other );
    GTX& operator=(const GTX& other) = delete;
    GTX& operator=(GTX&& other);
    //
    void clear();
    void setCursor(uint8_t x, uint8_t y);
    inline size_t write(uint8_t c);
    template <typename T> GTX& operator<< (T n);
};
// GTX.cpp------------------------------------
GTX::~GTX() {
  delete[] buffer;
}
GTX::GTX()
  : W(1), H(1), buffer(new uint8_t[1]) {
  buffer[0] = ' ';
}
GTX::GTX(uint8_t w, uint8_t h)
  : W(w), H(h), buffer(new uint8_t[W * H]),
    posX(0), posY(0) {
  clear();
}
GTX::GTX(GTX&& other )
  : W(other.W), H(other.H), buffer(other.buffer),
    posX(0), posY(0) {
  other.buffer = nullptr;
}
GTX& GTX::operator=(GTX&& other) {
  W = other.W, H = other.H,
  buffer = other.buffer, other.buffer = nullptr,
  posX = 0, posY = 0;
  return *this;
}
//
void GTX::clear() {
  memset(buffer, 0x20, W * H);
  posX = posY = 0;
}
void GTX::setCursor(uint8_t x, uint8_t y) {
  posX = x; posY = y;
}
size_t GTX::write(uint8_t c) {
  if (c == '\n') {
    posX = 0;
    posY = (posY < H) ? (posY + 1) : H;
    return 1;
  }
  if (posX < W && posY < H) {
    buffer[posY * W + posX] = c;
    posX++;
  }
  return 1;
}
template<>
GTX& GTX::operator<< (xy n) {
  posX = n.x;
  posY = n.y;
  return *this;
}
template <typename T> GTX& GTX::operator<< (T n) {
  this->print(n);
  return *this;
}
// Lcd1602_i2c.h------------------------------------
//канальный класс
#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 LCD_W 16
#define LCD_H 2

#define En B00000100  // Бит разрешения
#define Rw B00000010  // Чтение / запись бит
#define Rs B00000001  // Бит выбора регистра

class Lcd1602_i2c { // класс канала передачи
  public:
    Lcd1602_i2c(uint8_t a): adr(a) {}
    void init();               // иницирование
    void backlight(void);      // подсветка вкл
    void noBacklight(void);    // подсветка выкл
    void show(const GTX &obj); // отправить информацию из qGTX на экран
  private:
    /*внутрение функции*/
    inline void out(uint8_t value);
    inline void command(uint8_t value);
    void send(uint8_t value, uint8_t mode);
    void write4bits(uint8_t value);
    void expanderWrite(uint8_t _data);
    void pulseEnable(uint8_t _data);
  protected:
    uint8_t adr;
    uint8_t _backlightval;
    uint8_t _displayfunction;
    uint8_t _displaycontrol;
    uint8_t _displaymode;
};
// Lcd1602_i2c.cpp------------------------------------
void Lcd1602_i2c::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);
}
void Lcd1602_i2c::backlight(void) {
  _backlightval = LCD_BACKLIGHT;
  expanderWrite(0);
}
void Lcd1602_i2c::noBacklight(void) {
  _backlightval = LCD_NOBACKLIGHT;
  expanderWrite(0);
}
void Lcd1602_i2c::show(const GTX &obj) {
  command(LCD_SETDDRAMADDR + 0x00);
  for (uint8_t i = 0; i < obj.W; i++ )out(obj.buffer[i]);
  command(LCD_SETDDRAMADDR + 0x40);
  for (uint8_t i = obj.W; i < 2 * obj.W; i++ )out(obj.buffer[i]);
}
void Lcd1602_i2c::out(uint8_t value) {
  send(value, Rs);
}
void Lcd1602_i2c::command(uint8_t value) {
  send(value, 0);
}
void Lcd1602_i2c::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 Lcd1602_i2c::write4bits(uint8_t value) {
  expanderWrite(value);
  pulseEnable(value);
}
void Lcd1602_i2c::expanderWrite(uint8_t _data) {
  Wire.beginTransmission(adr);
  Wire.write((int)(_data | _backlightval));
  Wire.endTransmission();
}
void Lcd1602_i2c::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
}
//GTX display(LCD_W, LCD_H);
Lcd1602_i2c lcd(0x27);//0x3F
#endif

 

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

Скетч похожий на выше, но под LCD5110 синенькую c выключением подсветки 

/**/
//-кнопки--------------------------------------
#include "Cl_btn.h"
Cl_btn BtnS(/*пин*/2);  //кнопка селект
Cl_btn BtnU(/*пин*/3);  //кнопка верх
Cl_btn BtnD(/*пин*/4);  //кнопка вниз
//-------------------------------------------
#include "eeprom_Ref.h"
byte language = 0;// 0-англ/ 1 итал/ 2 португ
//-meню--------------------------------------
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// Hardware SPI (faster, but must use certain hardware pins):
// SCK is LCD serial clock (SCLK) - this is pin 13 on Arduino Uno
// MOSI is LCD DIN - this is pin 11 on an Arduino Uno
// pin 5 - Data/Command select (D/C) 10
// pin 4 - LCD chip select (CS) 9
// pin 3 - LCD reset (RST) 8
Adafruit_PCD8544 display = Adafruit_PCD8544(/*D/C*/10,/*CS*/9,/*RST*/8);
const byte ledPin =/*пин*/7;
void initBacklight() {
  pinMode(ledPin, OUTPUT);
}
void noBacklight() {
  digitalWrite(ledPin, LOW);
}
void backlight() {
  digitalWrite(ledPin, HIGH);
}
const byte pageN   = 0;//погасить экран
const byte page0   = 5;//главный экран
const byte page1   = 10;//уровень 1
const byte page1_1 = 11;//уровень 1-1
const byte page1_2 = 12;//уровень 1-2
const byte page1_3 = 13;//уровень 1-3
const byte page2   = 20;//уровень 2
const byte page2_1 = 21;//уровень 2-1
const byte page2_2 = 22;//уровень 2-2
const byte page2_3 = 23;//уровень 2-3
const byte page3   = 30;//выбор языка
byte page;
uint32_t past;
void goPage(byte p) {
  past = millis();
  page = p;
  display.clearDisplay();
  switch (page) {
    case pageN://погасить экран
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page0);};
      { noBacklight();
      }
      break;
    case page0://главный экран
      BtnS.Do = [] {};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page1);};
      { static const char  txt1[] PROGMEM = "main\0schermata\0tela\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = " screen\0 iniziale\0 inicial\0";
        pgm_String message2((String*)txt2);
        backlight();
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page1://уровень 1
      BtnS.Do = [] {goPage(page1_1);};
      BtnU.Do = [] {goPage(page0);};
      BtnD.Do = [] {goPage(page2);};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1\0 1\0 1\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page1_1://уровень 1-1
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-1\0 1-1\0 1-1\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page1_2://уровень 1-2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-2\0 1-2\0 1-2\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page1_3://уровень 1-3
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "1-3\0 1-3\0 1-3\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page2://уровень 2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {goPage(page1);};
      BtnD.Do = [] {goPage(page3);};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2\0 2\0 2\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page2_1://уровень 2-1
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-1 \0 2-1\0 2-1\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page2_2://уровень 2-2
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-2\0 2-2\0 2-2\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page2_3://уровень 2-3
      BtnS.Do = [] {goPage(page0);};
      BtnU.Do = [] {};
      BtnD.Do = [] {};
      { static const char  txt1[] PROGMEM = "level 2-3\0livello\0nivel\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "2-3\0 2-3\0 2-3\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 8);
        display.print(message2[language]);
      }
      break;
    case page3 ://выбор языка
      BtnS.Do = [] {
        language++; if (language > 2)language = 0;
        goPage(page3);
      };
      BtnU.Do = [] {goPage(page2);};
      BtnD.Do = [] {goPage(page0);};
      { static const char  txt1[] PROGMEM = "choose a\nlanguage:\0scegli una\nlingua:\0escolha um\nidioma:\0";
        pgm_String message1((String*)txt1);
        static const char  txt2[] PROGMEM = "English\0Italiano\0Portugues\0";
        pgm_String message2((String*)txt2);
        display.setCursor(0, 0);
        display.print(message1[language]);
        display.setCursor(0, 16);
        display.print(message2[language]);
      }
      break;
  }
  display.display();
}
void initMenu() {
  Serial.begin(9600);
  initBacklight();
  display.begin();
  display.setContrast(50);
  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0, 0);
  BtnS.init();
  BtnU.init();
  BtnD.init();
  goPage(page0);
}
void runMenu() {
  BtnS.run();
  BtnU.run();
  BtnD.run();
  if (page != pageN && millis() - past >= 6000) goPage(pageN);
}
//--выполнение-----------------------------
void setup() {
  initMenu();
}

void loop() {
  runMenu();
}

Cl_btn.h

/*Cl_btn.h*/
#ifndef Cl_btn_h
#define Cl_btn_h
//Cl_btn.h--------------------------------
typedef void (*pDo)();
class Cl_btn {
  public:
    Cl_btn(byte p): pin(p) {}
    pDo Do = [] {};
    void init();
    void run();
  protected:
    void set(bool s);
    byte pin;
    bool state;
    unsigned long past;
};
//Cl_btn.cpp--------------------------------
void Cl_btn::set(bool s) {
  state = s;
  past = millis();
  if (s == true) Do();
}
void Cl_btn::init() {
  pinMode(pin, INPUT_PULLUP);
  set(false);
}
void Cl_btn::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;
    }
}
#endif

eeprom_Ref.h

/* eeprom_Ref.h */
#ifndef EEPROM_REF_H
#define EEPROM_REF_H
//Ref.h-----------------------
#include <Arduino.h>
#include <avr/eeprom.h>
template <typename T>
class Ref {
  protected:
    T* pointer;
    void set(T data);
    T get();
  public:
    ~Ref();
    Ref() = delete;
    Ref(T* a);
    Ref(const Ref& other) = delete;
    Ref(Ref&& other);
    Ref& operator=(const Ref& other) = delete;
    Ref& operator=(Ref&& other);
    //
    operator T();
    Ref& operator=(T&& d);
    Ref& operator=(const T& d);
    Ref operator[] (const int index);
    Ref& operator +=(T&& d);
    Ref& operator -=(T&& d);
};
//Ref.cpp-----------------------
/* uint8_t */
template <>
void Ref<uint8_t>::set(uint8_t data) {
  eeprom_write_byte(pointer, data);
}
template <>
uint8_t Ref<uint8_t>::get() {
  return eeprom_read_byte(pointer);
}
/* int */
template <>
void Ref<int>::set(int data) {
  eeprom_write_word((uint16_t*)pointer, (uint16_t)data);
}
template <>
int Ref<int>::get() {
  return eeprom_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
void Ref<uint16_t>::set(uint16_t data) {
  eeprom_write_word(pointer, data);
}
template <>
uint16_t Ref<uint16_t>::get() {
  return eeprom_read_word(pointer);
}
/* uint32_t*/
template <>
void Ref<uint32_t>::set(uint32_t data) {
  eeprom_write_dword(pointer, data);
}
template <>
uint32_t Ref<uint32_t>::get() {
  return eeprom_read_dword(pointer);
}
/* float*/
template <>
void Ref<float>::set(float data) {
  eeprom_write_float(pointer, data);
}
template <>
float Ref<float>::get() {
  return eeprom_read_float(pointer);
}
/*общее*/
template <typename T>
Ref<T>::~Ref() {}
template <typename T>
Ref<T>::Ref(T* a): pointer(a) {}
template <typename T>
Ref<T>::Ref(Ref<T>&& other) {
  pointer = other.pointer;
}
template <typename T>
Ref<T>& Ref<T>::operator=(Ref<T>&& other) {
  if (pointer != other.pointer)
    set(other.get());
  return *this;
}
template <typename T>
Ref<T>::operator T() {
  return get();
}
template <typename T>
Ref<T>& Ref<T>::operator=(T&& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator=(const T& d) {
  set(d);
  return *this;
}
template <typename T>
Ref<T> Ref<T>::operator[] (const int index) {
  return Ref<T>(pointer + index);
}
template <typename T>
Ref<T>& Ref<T>::operator +=(T&& d) {
  set(get() + d);
  return *this;
}
template <typename T>
Ref<T>& Ref<T>::operator -=(T&& d) {
  set(get() - d);
  return *this;
}
using eeprom_int      = Ref<int> ;
using eeprom_uint8_t  = Ref<uint8_t>;
using eeprom_uint16_t = Ref<uint16_t>;
using eeprom_uint32_t = Ref<uint32_t>;
using eeprom_float    = Ref<float>;
//pRef.h-----------------------------
#include <avr/pgmspace.h>
template <typename T>
class pRef {
  protected:
    const T* pointer;
    T get();
  public:
    ~pRef();
    pRef() = delete;
    pRef(const T* a);
    pRef(const pRef& other) = delete;
    pRef(pRef&& other);
    pRef& operator=(const pRef& other) = delete;
    pRef& operator=(pRef&& other);
    //
    operator T();
    pRef operator[] (const int index);
};
//pRef.cpp-----------------------------
/*uint8_t*/
template <>
uint8_t pRef<uint8_t>::get() {
  return pgm_read_byte(pointer);
}
/* int */
template <>
int pRef<int>::get() {
  return pgm_read_word((uint16_t*)pointer);
}
/* uint16_t*/
template <>
uint16_t pRef<uint16_t>::get() {
  return pgm_read_word(pointer);
}
/* uint32_t*/
template <>
uint32_t pRef<uint32_t>::get() {
  return pgm_read_dword(pointer);
}
/* float*/
template <>
float pRef<float>::get() {
  return pgm_read_float(pointer);
}
/*String*/
template <>
String pRef<String>::get() {
  return String(reinterpret_cast<const __FlashStringHelper *>(pointer));
}
template <>
pRef<String> pRef<String>::operator[] (const int index) {
  char *p = (char*)pointer;
  int i = index;
  while (i != 0) {
    p = (char*)strchrnul_P(p, 0);
    p++;
    i--;
  }
  return pRef<String>((String*)p);
}
/*общее*/
template <typename T>
pRef<T>::~pRef() {}
template <typename T>
pRef<T>::pRef(const T* a): pointer(a) {}
template <typename T>
pRef<T>::pRef(pRef<T>&& other)
  : pointer(other.pointer) {}

template <typename T>
pRef<T>& pRef<T>::operator=(pRef<T>&& other) {
  pointer = other.pointer;
  return *this;
}
template <typename T>
pRef<T>::operator T() {
  return get();
}
template <typename T>
pRef<T> pRef<T>::operator[] (const int index) {
  return pRef<T>(pointer + index);
}
//-------------------------------------------------
using pgm_int      = pRef<int>;
using pgm_uint8_t  = pRef<uint8_t>;
using pgm_uint16_t = pRef<uint16_t>;
using pgm_uint32_t = pRef<uint32_t>;
using pgm_float    = pRef<float>;
using pgm_String   = pRef<String>;
#endif

 

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

Вот спасибо. Буду разбираться как там всё устроено и переписывать под себя.