Программирование lcd дисплея с кнопками для управления
- Войдите на сайт для отправки комментариев
Сб, 17/08/2019 - 17:13
ПРОЕКТ:
Проект возможно покажется довольно мрачным, но я всегда хотел вотворить его в жизнь для того, чтобы постояно заряжатся мотивацией от того, что мы все не вечны.
Суть проекта - В верхней строке находится постоянная надпись "Мне осталось:", в нижней строке показывается это время в днях и неделях. Чтобы поменять режим(дни или недели), нужно нажать на кнопку "BUTTON_ON_SWAP" , чтобы регулировать кол-во дней или недель есть две дополнительные кнопки - "BUTTON_DOWN" и "BUTTON_UP"(первая уменьшает кол-во, вторая повышает)
КОД:
Компилятор пишет непонятную ошибку. Перепроверил всё до иголочки. Код приведён ниже, заранее спасибо
#include <LiquidCrystal.h>
LiquidCrystal lcd(2,3,4,5,6,7);
const int BUTTON_DOWN = 9;
const int BUTTON_UP = 10;
const int BUTTON_ON_SWAP = 11;
// Переменные для хранения статусов кнопок
boolean currentDownButton = LOW;
boolean lastDownButton = LOW;
boolean currenUpButton = LOW;
boolean lastUpButton = LOW;
boolean lastOnSwapButton = LOW;
boolean currentOnSwapButton = LOW;
//Переменные кол-ва дней и недель
int days = 14000;
int weeks = 2000;
// Переменная значения статуса lcd(статус это режим дней или недель)
int ledMode = 0;
void setup()
{
pinMode(BUTTON_DOWN, INPUT);
pinMode(BUTTON_UP, INPUT);
pinMode(BUTTON_ON_SWAP, INPUT);
lcd.begin(16,2);
lcd.print("Мне осталось:");
}
// ----------ПРОТИВО-ДРЕБЕЗГОВАЯ ЗАЩИТА--------------
boolean debounce(boolean last, int pin)
{
boolean current = digitalRead(pin);
if (last != current)
{
delay(5);
current = digitalRead(pin);
}
return current;
}
// ------------------------------------------------
// ------------ПЕРЕКЛЮЧЕНИЕ РЕЖИМОВ С ПОМОЩЬЮ КНОПКИ BUTTON_ON_SWAP--------------
void setMode(int mode)
{
// Дни
if (mode == 1)
{
lcd.setCursor(0,1);
lcd.print("DAYS:");
lcd.setCursor(6,10);
lcd.print("days");
}
// Недели
else if (mode == 2)
{
lcd.setCursor(0,1);
lcd.print("WEEKS:");
lcd.setCursor(7,1);
lcd.print("weeks");
}
}
//------------------------------------------------------------------------------
void loop()
{
currentDownButton = debounce(lastDownButton, BUTTON_DOWN);
currentUpButton = debounce(lastUpButton, BUTTON_UP);
// Регулировка дней с помощью кнопок
if (lastDownButton == LOW && currentDownButton == HIGH && mode == 1)
{
days--;
}
else if (lastUpButton == LOW && currentUpButton == HIGH && mode == 1)
{
days++;
}
// Регулировка недель с помощью кнопок
else if(lastDownButton == LOW && currentDownButton == HIGH && mode == 2)
{
weeks--;
}
else if (lastUpButton == LOW && currentUpButton == HIGH && mode == 2)
{
weeks++;
}
// Переключение режимов с помощью кнопки BUTTON_ON_SWAP
currentOnSwapButton = debounce(lastOnSwapButton, BUTTON_ON_SWAP);
if (lastOnSwapButton == LOW && currentOnSwapButton == HIGH )
{
ledMode++;
}
currentOnSwapButton = debounce(lastOnSwapButton, BUTTON_ON_SWAP);
currentDownButton = debounce(lastDownButton, BUTTON_DOWN);
currentUpButton = debounce(lastUpButton, BUTTON_UP);
// Если все режимы прошили сброс на начальный вариант
if (ledMode == 3)
{
ledMode = 0;
setMode(ledMode);
}
}
А ошибка то где?
Боюсь даже предположить, что Вы там проверяли и какими иголочками, только переменные currentUpButton (строка №78) и mode (строка №81) нигде не описаны. Собственно компилятор Вам именно это и сказал - неясно почему Вы не поняли и не исправили.
Первую ошибку понял(строка №78), опечатался, а вторую ошибку понять не могу , я ведь описал mode в строке №57 и создал аргумент int mode в строке №54
главная ошибка - неправильно организована программа- очень сложно ловить в ней косяки.
побочная ошибка- неправильно организован опрос кнопок. Очень сложно переназначать их обработчик при переключении в меню.
ПС: #43
Можете тогда направить в нужное русло чтобы я понял как правильно организовывать программу, а то мне сейчас пока не совсем понятен ход мыслей
Жевать эту тему долго. Особенно если у Вас маловато базовых знаний :( Прежде всего меню надо расметривать как цифровой автомат. Каждая позиция экрана это состояние. И при переходе на новое состояние надо отразить новую информацию на экране и перезадать обработчики кнопок. Ведь при каждой позиции меню даже одна и таже кнопка делает различное действие.
я ведь описал mode в строке №57
Есть ощущение, что Вы не очень понимаете, что делаете или не знаете терминологии. В строке №57 нет никакого описания. Там эта переменная используется.
создал аргумент int mode в строке №54
Какое отнощение имеет аргумент функции setMode к функци loop в которой Вы эту переменную пытаетесь использовать (в строке 81)? Подсказка - никакого, от слова "совсем".
Ой, да, я забыл что эта переменная локальная, переделал - добавил новые две глобальные переменные mode1 =1 и mode2 =2, компилятор доволен:
#include <LiquidCrystal.h> LiquidCrystal lcd(2,3,4,5,6,7); const int BUTTON_DOWN = 9; const int BUTTON_UP = 10; const int BUTTON_ON_SWAP = 11; // Переменные для хранения статусов кнопок boolean currentDownButton = LOW; boolean lastDownButton = LOW; boolean currentUpButton = LOW; boolean lastUpButton = LOW; boolean lastOnSwapButton = LOW; boolean currentOnSwapButton = LOW; //Переменные кол-ва дней и недель int days = 14000; int weeks = 2000; // Переменная значения статуса lcd(статус это режим дней или недель) int ledMode = 0; int mode1 = 1; int mode2 = 2; void setup() { pinMode(BUTTON_DOWN, INPUT); pinMode(BUTTON_UP, INPUT); pinMode(BUTTON_ON_SWAP, INPUT); lcd.begin(16,2); lcd.print("Мне осталось:"); } // ----------ПРОТИВО-ДРЕБЕЗГОВАЯ ЗАЩИТА-------------- boolean debounce(boolean last, int pin) { boolean current = digitalRead(pin); if (last != current) { delay(5); current = digitalRead(pin); } return current; } // ------------------------------------------------ // ------------ПЕРЕКЛЮЧЕНИЕ РЕЖИМОВ С ПОМОЩЬЮ КНОПКИ BUTTON_ON_SWAP-------------- void setMode(int mode) { // Дни if (mode == mode1) { lcd.setCursor(0,1); lcd.print("DAYS:"); lcd.setCursor(6,10); lcd.print("days"); } // Недели else if (mode == mode2) { lcd.setCursor(0,1); lcd.print("WEEKS:"); lcd.setCursor(7,1); lcd.print("weeks"); } } //------------------------------------------------------------------------------ void loop() { currentDownButton = debounce(lastDownButton, BUTTON_DOWN); currentUpButton = debounce(lastUpButton, BUTTON_UP); // Регулировка дней с помощью кнопок if (lastDownButton == LOW && currentDownButton == HIGH && mode1) { days--; } else if (lastUpButton == LOW && currentUpButton == HIGH && mode1) { days++; } // Регулировка недель с помощью кнопок else if(lastDownButton == LOW && currentDownButton == HIGH && mode2) { weeks--; } else if (lastUpButton == LOW && currentUpButton == HIGH && mode2) { weeks++; } // Переключение режимов с помощью кнопки BUTTON_ON_SWAP currentOnSwapButton = debounce(lastOnSwapButton, BUTTON_ON_SWAP); if (lastOnSwapButton == LOW && currentOnSwapButton == HIGH ) { ledMode++; } currentOnSwapButton = debounce(lastOnSwapButton, BUTTON_ON_SWAP); currentDownButton = debounce(lastDownButton, BUTTON_DOWN); currentUpButton = debounce(lastUpButton, BUTTON_UP); // Если все режимы прошили сброс на начальный вариант if (ledMode == 3) { ledMode = 0; setMode(ledMode); } }Хорошо, я тогда попробую побольше углубится в этой теме
Проект возможно покажется довольно мрачным, но я всегда хотел вотворить его в жизнь для того, чтобы постояно заряжатся мотивацией от того, что мы все не вечны.
В последнее время эта тема стала довольно популярной. Я, как минимум, 3-м делал подобное, в разных вариациях. В годах, месяцах, днях, часах, минутах, секундах. Кто то даже хотел и в десятках мс.) И кто то даже пытался на этом делать бизнес.)))
/**/ //---кнопки----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); if (s == true) Do(); } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn BtnD(/*пин*/9); //кнопка вниз Cl_btn BtnU(/*пин*/10); //кнопка верх Cl_btn BtnS(/*пин*/11); //кнопка селект //Переменные кол-ва дней и недель int days = 14000; int weeks = 2000; #include <LiquidCrystal.h> LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // Переменная значения статуса lcd(статус это режим дней или недель) const byte page0 = 0;// главный экран const byte page1 = 1;// регулировка дней const byte page2 = 2;//регулировка недель byte page;// текущий экран // ------------ПЕРЕКЛЮЧЕНИЕ РЕЖИМОВ С ПОМОЩЬЮ КНОПКИ BUTTON_ON_SWAP-------------- void goPage(byte p) { if (p > page2) p = page0 ; page = p; lcd.clear(); switch (page) { case page0 : { lcd.print("Мне осталось:"); lcd.print(days); } BtnU.Do = [] {}; BtnD.Do = [] {}; BtnS.Do = [] { goPage(page1); }; break; case page1 : { lcd.setCursor(0, 1); lcd.print("DAYS:"); lcd.print(days); lcd.setCursor(6, 10); lcd.print("days"); } BtnU.Do = [] { days++; goPage(page1); }; BtnD.Do = [] { days--; goPage(page1); }; BtnS.Do = [] { goPage(page2); }; break; case page2 : { lcd.setCursor(0, 1); lcd.print("WEEKS:"); lcd.print(weeks); lcd.setCursor(7, 1); lcd.print("weeks"); } BtnU.Do = [] { weeks++; goPage(page2); }; BtnD.Do = [] { weeks--; goPage(page2); }; BtnS.Do = [] { goPage(page0); }; break; } } void setup() { BtnU.init(); BtnD.init(); BtnS.init(); lcd.begin(16, 2); goPage(page0); } void loop() { BtnU.run(); BtnD.run(); BtnS.run(); }Разумеется в железе не проверял. И да косяки в программе связаны с тем что ТС невнятно написал ТЗ.
Спасибо, попробую проанализировать Ваш код