/**/
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;
Если чтение будет происходить циелически, она нужна? Или нет?
/**/ 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 байт. */Если чтение будет происходить циелически, она нужна? Или нет?
забыл написать.
"Всякая найденная в программе последняя ошибка, на самом деле является предпоследней"
а у мня обычно получается так: В коде было 7 ошибок, 12 из них исправил, осталось 8.
а у мня обычно получается так: В коде было 7 ошибок, 12 из них исправил, осталось 8.
то были не ошибки, а прикольные фичи.
Клапа, я рад тебя видеть. Мы соскучивались тут.
Так и не довели до конца тему? А мне вот нужно...
Так и не довели до конца тему? А мне вот нужно...
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(); }У меня другое. Оптимизация. Завтра постараюсь изложить вкратце. Пока сам не пойму, что хочу.
PS: меню написано уже года 2 назад. Работает. Хочется большего функционала.
Итак, начнём:
Первое, что захотелось - индексация слов в меню. Например, нам нужно вывести на дисплей строку: Do you want start heating? Yes/No.
Проиндексируем использованные слова:
1-Do
2-you
3-want и так далее. По итогу вывод строки будет типа: функция(1,2,3,4,5,6,7,8,9,10) (знаки ? / . тоже учитываются )
А что это Вы пытаетесь делать? Память под тексты экономить? Если так, то мож лучше по Хаффману? Зазиповать текст нахрен, чем велосипед-то городить?
Итак, начнём:
Первое, что захотелось - индексация слов в меню. Например, нам нужно вывести на дисплей строку: 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А что это Вы пытаетесь делать? Память под тексты экономить?
Спасибо за интерес к теме. Что я пытаюсь делать в этом примере - многоязычное меню. Думаю так будет проще.
/**/ //-кнопки-------------------------------------- #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; } } #endifeeprom_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>; #endiflcd1602_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Скетч похожий на выше, но под 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; } } #endifeeprom_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Вот спасибо. Буду разбираться как там всё устроено и переписывать под себя.