LCD I2C дисплей и обработка кнопок
- Войдите на сайт для отправки комментариев
Втр, 02/01/2018 - 23:01
Есть arduino, LCD I2C дисплей и 4 кнопки(up, down, next, set). Хочется сделать так чтобы при запуске на экран выводилось число допустим 000( объявил через массив byte dig[] = { 0, 0, 0 }). Здесь для удобства число разбито на цифры. При нажатии на set должна мигать самая левая цифра. Затем при нажатии на next переходим к следующей цифре(мигает) и так по кругу(только одна мигает). Кнопками up, down можно +/-1 к выбранной цифре. Нужна помощь в настройке мигания цифры и с функциями кнопок set, next. Беда если значение цифры <0 или >9, выводит не понятные символы. Предложите идею как решить проблемы.
#include <Wire.h> // библиотека для управления устройствами по I2C
#include <LiquidCrystal_I2C.h> // подключаем библиотеку для LCD 1602
#include "OneButton.h"
LiquidCrystal_I2C lcd(0x3F,20,4); // присваиваем имя lcd для дисплея 20х2
unsigned long prevmillis = 0; //счетчик прошедшего времени для мигания изменяемых значений.
#define interv 100UL //интервал мигания изменяемых значений
boolean i=LOW;
// кнопки
OneButton upPin(8, true); // Установить кнопку 1 на пин 8.
OneButton downPin(9, true); // Установить кнопку 2 на пин 9.
OneButton nextPin(10, true); // Установить кнопку 2 на пин 9.
OneButton setPin(11, true); // Установить кнопку 2 на пин 9.
byte dig[] = { 0, 0, 0 };
byte flag=0; byte state=0; //byte c=2;
void IntToChar(byte d0, byte d1, byte d2, char *text)
{
text[0] = d0 + '0';
text[1] = d1 + '0';
text[2] = d2 + '0';
}
void setup() {
lcd.begin(); // инициализация LCD дисплея
lcd.backlight(); // включение подсветки дисплея
upPin.attachClick(click1); // Функции 1 кнопки
downPin.attachClick(click2); // Функции 2 кнопки
nextPin.attachClick(click3); // Функции 3 кнопки
setPin.attachClick(click4); // Функции 4 кнопки
}
void loop() {
/* беда */
if(dig[0]<0 && dig[0]>9)
{
flag=1; // присваиваем пременной значение 1
dig[0]=0; //обнуляем переменную таймера
}
// Вызов функции, обрабатывающей состояния кнопки:
setPin.tick();
upPin.tick();
downPin.tick();
nextPin.tick();
lcd.setCursor(0,0); // ставим курсор на 1 символ первой строки
lcd.print("T=");
char str[] = " ";
IntToChar(dig[0], dig[1], dig[2], &str[0]);
if(millis() - prevmillis >= interv) { //Если счетчик превысил интервал,
i = !i; prevmillis = prevmillis+interv; } //меняем значение переменной i, добавляем к переменной интервал
/* тут хотелось бы сделать мигание */
if (i) { lcd.setCursor(2, 0); lcd.print(str); }
// if (!i) { lcd.setCursor(2, 0); lcd.print(" "); } не работает как надо
// В этом месте могут быть другие вызовы неблокирующих
// функций и процедур, выполняющих какие-либо действия в
// программе.
delay(10);
}
// Эта функция будет вызвана, когда setPin был нажат в 1 раз
void click1() {
}
// Эта функция будет вызвана, когда upPin был нажат в 1 раз
void click2() {
dig[0]++;
}
// Эта функция будет вызвана, когда downPin был нажат в 1 раз
void click3() {
dig[0]--;
}
// Эта функция будет вызвана, когда nextPin был нажат в 1 раз
void click4() {
lcd.setCursor(0,2);
lcd.print("nextPin click");
}
Программирую arduino год, подскажите что не так делаю
Еще хотелось бы избавиться в процессе от delay(10)
Это чё? Типа нам такое задание? Ты препод? Или сержант? А чего не сапоги почистить?
И не хотелось бы загромождать код кучей переменных, отзовитесь, я знаю здесь много обсуждалось про оброботку кнопок, но с OneButton почти ничего нету
Мне бы идейку подкинул кто
Сапоги еще начищу
Ворота, я не требую полностью готовый код, мне нужны хотя бы ссылки на что то подобное, каковых я не увидел в инете и на куче форумов
if (dig[0] < 9) { dig[0]++; }
http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukomment...
Спасибо, но код не совсем верный, постоянно отображается 9, при нажатии на кнопки+/- ничего не меняется.
Спасибо и за ссылку, буду теперь знать, на форуме сегодня первый день
#include <Wire.h> // библиотека для управления устройствами по I2C #include <LiquidCrystal_I2C.h> // подключаем библиотеку для LCD 1602 #include "OneButton.h" LiquidCrystal_I2C lcd(0x3F,20,4); // присваиваем имя lcd для дисплея 20х4 unsigned long prevmillis = 0; //счетчик прошедшего времени для мигания изменяемых значений. #define interv 100UL //интервал мигания изменяемых значений boolean i=LOW; // кнопки OneButton upPin(8, true); // Установить кнопку 1 на пин 8. OneButton downPin(9, true); // Установить кнопку 2 на пин 9. OneButton nextPin(10, true); // Установить кнопку 2 на пин 10. OneButton setPin(11, true); // Установить кнопку 2 на пин 11. byte dig[] = { 0, 0, 0 }; byte flag=0; byte state=0; //byte c=2; void IntToChar(byte d0, byte d1, byte d2, char *text) { text[0] = d0 + '0'; text[1] = d1 + '0'; text[2] = d2 + '0'; } void setup() { lcd.begin(); // инициализация LCD дисплея lcd.backlight(); // включение подсветки дисплея upPin.attachClick(click1); // Функции 1 кнопки downPin.attachClick(click2); // Функции 2 кнопки nextPin.attachClick(click3); // Функции 3 кнопки setPin.attachClick(click4); // Функции 4 кнопки } void loop() { /****/ //if(val>=0 && val<10) /*if(dig[0]<0 && dig[0]>9) { flag=1; // присваиваем переменной значение 1 dig[0]=0; //обнуляем переменную таймера }*/ if (dig[0] < 9) { dig[0]++; } // Вызов функции, обрабатывающей состояния кнопки: setPin.tick(); upPin.tick(); downPin.tick(); nextPin.tick(); lcd.setCursor(0,0); // ставим курсор на 1 символ первой строки lcd.print("T="); char str[] = " "; IntToChar(dig[0], dig[1], dig[2], &str[0]); if(millis() - prevmillis >= interv) { //Если счетчик превысил интервал, i = !i; prevmillis = prevmillis+interv; } //меняем значение переменной i, добавляем к переменной время интервала. if (i) { lcd.setCursor(2, 0); lcd.print(str); } // if (!i) { lcd.setCursor(2, 0); lcd.print(" "); } // В этом месте могут быть другие вызовы неблокирующих // функций и процедур, выполняющих какие-либо действия в // программе. delay(10); } // Эта функция будет вызвана, когда setPin был нажат в 1 раз void click1() { //state = 1; lcd.setCursor(0,1); lcd.print("setPin click"); } // Эта функция будет вызвана, когда upPin был нажат в 1 раз void click2() { dig[0]++; } // Эта функция будет вызвана, когда downPin был нажат в 1 раз void click3() { dig[0]--; } // Эта функция будет вызвана, когда nextPin был нажат в 1 раз void click4() { lcd.setCursor(0,2); lcd.print("nextPin click"); }Да с этим вообще печаль - беда /*if(dig[0]<0 && dig[0]>9) { flag=1; // присваиваем переменной значение 1 dig[0]=0; //обнуляем переменную таймера }Спасибо, но код не совсем верный, постоянно отображается 9, при нажатии на кнопки+/- ничего не меняется.
В каком месте он неверный? Он не исправляет всю вашу программу, а не дает счетчику уйти за цифру 9, чтобы ваша беда не проявлялась.
Не пинайте так сильно, программировать научусь, да и arduino и хороший програмист две разные вещи
У вас должны быть 5 (ПЯТЬ) переменных- обработчиков функций - 4 на кнопки и 1 на экран. При переходе с одной позицию на другую им должны присваиваться новые . И так по кругу. Опять же что бы не гемороить надо организовать целую структуру.
Как я вас правильно понял, для каждой из этих функций должна задаваться своя переменная, и еще одна для обновления lcd // Эта функция будет вызвана, когда setPin был нажат в 1 раз void click1() { } // Эта функция будет вызвана, когда upPin был нажат в 1 раз void click2() { dig[0]++; } // Эта функция будет вызвана, когда downPin был нажат в 1 раз void click3() { dig[0]--; } // Эта функция будет вызвана, когда nextPin был нажат в 1 раз void click4() { }Так не по Сеньке шапка - но я не поставил невыполнимую задачу
#include <Wire.h> // библиотека для управления устройствами по I2C #include <LiquidCrystal_I2C.h> // подключаем библиотеку для LCD 1602 LiquidCrystal_I2C lcd(0x3F,20,4); // присваиваем имя lcd для дисплея 20х2 long previousMillisTime = 0; //счетчик прошедшего времени для мигания изменяемых значений. long intervalTime = 1000; //интервал мигания изменяемых значений double i=0; void setup() { lcd.begin(); // инициализация LCD дисплея lcd.backlight(); // включение подсветки дисплея } void loop() { lcd.setCursor(1,0); // ставим курсор на 1 символ первой строки if(millis() - previousMillisTime >= intervalTime) { //Если счетчик превысил интервал, i = !i; previousMillisTime = previousMillisTime+intervalTime; } //меняем значение переменной i, добавляем к переменной время интервала. if (i) lcd.print(1); if (!i) lcd.print(" "); }Ну скорее всего так начал ;)
/**/ unsigned long mill; // переменная под millis() typedef (*pDo)(); //-------------------------------- // класс кнопка class Cl_btm { protected: byte pin; public: pDo Do;//обработчик /*конструктор*/ Cl_btm(byte p): pin(p) {} /*инициализация-вставить в setup()*/ void init() {} /*работа-вставить в loop()*/ void run() {} }; //--------------------- // класс кнопка class Cl_viev { protected: public: pDo Do;//обработчик /*конструктор*/ Cl_viev() {} /*инициализация-вставить в setup()*/ void init() {} /*работа-вставить в loop()*/ void run() {} }; //---Компоновка----------------------------- Cl_btm Btn1(/*пин*/2); Cl_btm Btn2(/*пин*/3); Cl_btm Btn3(/*пин*/4); Cl_btm Btn4(/*пин*/5); Cl_viev viev; //---main----------------------------- void setup() { Btn1.init(); Btn2.init(); Btn3.init(); Btn4.init(); viev.init(); } void loop() { mill = millis(); Btn1.run(); Btn2.run(); Btn3.run(); Btn4.run(); viev.run(); } /*Скетч использует 544 байт (1%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт. */Скетч мигания символа на дисплее
С OneButton бы хотелось, привык к ней, но то что скетч так мало весит заставляет задуматься ;)
Для мигания цифры вполне подойдет эта конструкция, но я думаю добавить в условие дополнительную переменную типа boolean flag для условия !i для запуска мигания только при нажатии set
lcd.setCursor(1,0); // ставим курсор на 1 символ первой строки if(millis() - previousMillisTime >= intervalTime) { //Если счетчик превысил интервал, i = !i; previousMillisTime = previousMillisTime+intervalTime; } //меняем значение переменной i, добавляем к переменной время интервала. if (i) lcd.print(1); if (!i) lcd.print(" ");Есть библиотека micromenu. Поищите в интернете. Она заточена под управление меню с помощью кнопок. Работает и с четырьмя кнопками и i2c lcd1602. Позволяет легко написать и меню и в нем изменение параметров. Вот только строк получается много. Но работает.
Да я видел называется Menu Backend
https://pandauino.com/en/one-button-menu-arduino/
/**/ unsigned long mill; // переменная под millis() typedef (*pDo)(); //-------------------------------- // класс кнопка class Cl_btm { protected: byte pin; public: pDo Do;//обработчик /*конструктор*/ Cl_btm(byte p): pin(p) {} /*инициализация-вставить в setup()*/ void init() {} /*работа-вставить в loop()*/ void run() {} /*записать*/ void write(pDo Do_) { Do = Do_; } }; //--------------------- // класс кнопка class Cl_viev { protected: public: pDo Do;//обработчик /*конструктор*/ Cl_viev() {} /*инициализация-вставить в setup()*/ void init() {} /*работа-вставить в loop()*/ void run() {} /*записать*/ void write(pDo Do_) { Do = Do_; } }; //--------------------------- typedef struct MenuUnit { pDo up; pDo down; pDo left; pDo right; pDo viev; }; //---Компоновка----------------------------- void up1() {} void up2() {} void up3() {} void up4() {} void up5() {} void down1() {} void down2() {} void down3() {} void down4() {} void down5() {} void left1() {} void left2() {} void left3() {} void left4() {} void left5() {} void right1() {} void right2() {} void right3() {} void right4() {} void right5() {} void viev1() {} void viev2() {} void viev3() {} void viev4() {} void viev5() {} MenuUnit MN[] = { {up1, down1, left1, right1, viev1}, {up2, down2, left2, right2, viev2}, {up3, down3, left3, right3, viev3}, {up4, down4, left4, right4, viev4}, {up5, down5, left5, right5, viev5} }; Cl_btm Btn1(/*пин*/2); Cl_btm Btn2(/*пин*/3); Cl_btm Btn3(/*пин*/4); Cl_btm Btn4(/*пин*/5); Cl_viev viev; //---main----------------------------- void setup() { Btn1.init(); Btn2.init(); Btn3.init(); Btn4.init(); viev.init(); } void loop() { mill = millis(); Btn1.run(); Btn2.run(); Btn3.run(); Btn4.run(); viev.run(); } /*Скетч использует 544 байт (1%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт. */Меню я собирался отдельно реализовать в помощью switch
qwone объясните пожалуйсто смысл того фрагмента кода что вы написали, раньше читал про классы но не разобрался
http://mypractic.ru/urok-7-klassy-v-programmax-arduino-knopka-kak-obekt....
Что бы не жевать много раз одно и тоже. Вот мои идеи http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov
Но это так самая малость.
Меню я собирался отдельно реализовать в помощью switch
Можно но это так глубоко устаревший способ. Можно запутаться в скетче.
ПС:
/**/ unsigned long mill; // переменная под millis() typedef (*pDo)(); //-------------------------------- // класс кнопка class Cl_btm { protected: byte pin; public: pDo Do;//обработчик /*конструктор*/ Cl_btm(byte p): pin(p) {} /*инициализация-вставить в setup()*/ void init() {} /*работа-вставить в loop()*/ void run() {} /*записать*/ void write(pDo Do_) { Do = Do_; } }; //--------------------- // класс показ class Cl_viev { protected: unsigned long past; public: pDo Do;//обработчик /*конструктор*/ Cl_viev() {} /*инициализация-вставить в setup()*/ void init() { } /*работа-вставить в loop()*/ void run() { if (mill - past >= 1000)// выводить раз в 1 сек past = mill; Do(); } /*записать*/ void write(pDo Do_) { Do = Do_; } }; //--------------------------- typedef struct MenuUnit { pDo up; pDo down; pDo next; pDo set; pDo viev; }; //---Компоновка----------------------------- void up1() {} void up2() {} void up3() {} void up4() {} void up5() {} void down1() {} void down2() {} void down3() {} void down4() {} void down5() {} void next1() {} void next2() {} void next3() {} void next4() {} void next5() {} void set1() {} void set2() {} void set3() {} void set4() {} void set5() {} void viev1() {} void viev2() {} void viev3() {} void viev4() {} void viev5() {} int screen = 0; //номер позиции MenuUnit MN[5] = { {&up1, &down1, &next1, &set1, &viev1}, {&up2, &down2, &next2, &set2, &viev2}, {&up3, &down3, &next3, &set3, &viev3}, {&up4, &down4, &next4, &set4, &viev4}, {&up5, &down5, &next5, &set5, &viev5} }; Cl_btm upBtn(/*пин*/2); Cl_btm downBtn(/*пин*/3); Cl_btm nextBtn(/*пин*/4); Cl_btm setBtn(/*пин*/5); Cl_viev viev; //---main----------------------------- void setup() { screen = 0; upBtn.init(); upBtn.write(MN[screen].up); downBtn.init(); downBtn.write(MN[screen].down); nextBtn.init(); nextBtn.write(MN[screen].next); setBtn.init(); setBtn.write(MN[screen].set); viev.init(); viev.write(MN[screen].viev); } void loop() { mill = millis(); upBtn.run(); downBtn.run(); nextBtn.run(); setBtn.run(); viev.run(); } /*Скетч использует 836 байт (2%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 83 байт (4%) динамической памяти, оставляя 1965 байт для локальных переменных. Максимум: 2048 байт. */