Программирование режимов светодиода
- Войдите на сайт для отправки комментариев
Здравствуйте, друзья! Реализовал небольшое устройство на Arduino, для собственного развития. Суть состоит в следующем: имеется светодиод, 3 кнопки и LCD дисплей (16х2). На дисплее выводится меню. Всего имеется 2 пункта. В первом пункте происходит включение/выключение светодиода, во втором меню - выбор режимов работы. Кнопками (назовем их L,R,OK) , происходит переключение между пунктами (L,R кнопки), а также изменение текущего состояния светодиода (кнопка ОК). Вот скетч такого устройства:
//подключение библиотеки для работы с LCD
#include <LiquidCrystal.h>
//управляющие кнопки
int button_L = 8; //кнопка переключения влево
int button_OK = 7; //кнопка переключения вправо
int button_R = 9; //кнопка ОК
//управляемый светодиод
int led = 6;
//состояние кнопки
boolean lastButton_L = LOW;
boolean currentButton_L = LOW;
boolean lastButton_R = LOW;
boolean currentButton_R = LOW;
boolean lastButton_OK = LOW;
boolean currentButton_OK = LOW;
//переменная отвечающая за пункт меню
int punkt = 0; //0 - включить/выключить, 1 - меню режима
//переменные отвечающие за параметры светодиода
boolean mode_led = LOW; //режим светодиода
boolean on_off = LOW; //включен или выключен
//инициализируем LCD с указанием контактов
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
//====================================================
void setup()
{
//инициализируем пины
pinMode(button_L, INPUT);
pinMode(button_R, INPUT);
pinMode(button_OK, INPUT);
pinMode(led,OUTPUT);
//начало работы, с указанием размерности экрана
lcd.begin(16,2);
}
//====================================================
void loop()
{
//проверяем нажатие кнопки button_L
F_button_L();
//проверяем нажатие кнопки button_R
F_button_R();
//проверяем нажатие кнопки button_OK
F_button_OK();
//переводим светодиод в настроенное состояние
F_led();
//очищаем экран
lcd.clear();
//выводим на экран текущее состояние
enable_print();
//выводим внизу экрана меню
menu();
//небольшая задержка между кадрами
delay(50);
}
//=================проверяем нажатие кнопки button_L
void F_button_L()
{
if (lastButton_L != digitalRead(button_L))
{
delay(5);
currentButton_L = digitalRead(button_L);
}
if (lastButton_L == LOW && currentButton_L == HIGH)
{
if (punkt >0)//чтобы не выходить за заданное количество пунктов меню
{
punkt--; //если нажата кнопка, переключаем на предыдущее меню
}
else punkt = 1;
}
lastButton_L = currentButton_L;
}
//=================проверяем нажатие кнопки button_R
void F_button_R()
{
if (lastButton_R != digitalRead(button_R))
{
delay(5);
currentButton_R = digitalRead(button_R);
}
if (lastButton_R == LOW && currentButton_R == HIGH)
{
//чтобы не выходить за заданное количество пунктов меню
if (punkt < 1)
{
punkt++; //если нажата кнопка, переключаем на следующее меню
}
else punkt = 0;
}
lastButton_R = currentButton_R;
}
//=================проверяем нажатие кнопки button_OK
void F_button_OK()
{
if (lastButton_OK != digitalRead(button_OK))
{
delay(5);
currentButton_OK = digitalRead(button_OK);
}
if (lastButton_OK == LOW && currentButton_OK == HIGH)
{
tools(); //если нажали кнопку ОК, переходим в настройку состояния
}
lastButton_OK = currentButton_OK;
}
//==========================изменяем параметры системы
void tools()
{
if (punkt == 0)
{
if (!on_off)
{
on_off=HIGH; //переводим состояние светодиода в ВКЛЮЧЕНО
}
else
{
on_off=LOW; //переводим состояние светодиода в ВЫКЛЮЧЕНО
}
}
else
{
if (!mode_led)
{
mode_led = HIGH;
}
else
{
mode_led = LOW;
}
}
}
//=================выводим на экран текущее состояние
void enable_print()
{
if (punkt == 0) //если в первом пункте меню
{
if (!on_off) //если светодиод выключен
{
lcd.print("LED: OFF!");
}
else //если светодиод включен
{
lcd.print("LED: ON!");
}
}
else //если во втором пункте меню
{
if (!mode_led)
{
lcd.print("MODE: 1");
}
else
{
lcd.print("MODE: 2");
}
}
}
//=======================настройка режимов светодиода
void F_led()
{
if (on_off)
{
if (!mode_led)
{
digitalWrite(led,HIGH);
}
else
{
analogWrite(led,100);
}
}
else digitalWrite(led,LOW);
}
//==========================выводим внизу экрана меню
void menu()
{
lcd.setCursor(0,1);
lcd.print("<--");
lcd.setCursor(7,1);
lcd.print("OK");
lcd.setCursor(13,1);
lcd.print("-->");
}
//===================================================
Этот код полностью рабочий. Реализовано 2 режима. 1 - свечение светодиода с максимальной яркостью. 2- светодиод горит тусклее.
Прошу, если будут какие-то недочеты по коду, тыкать в эти места носом, так как я только учусь, и хотелось бы видеть и понимать свои ошибки.
Теперь перейдем к самой проблеме. Изначально хотелось сделать 3 режима. 1 - горит постоянно. 2- моргает. 3 - сначала загорается плавно, потом плавно погасает. Но когда начал делать это. То получалось следующее: все работало без ошибок на первом режиме. Как только переходил на режим 2, кнопками уже ничего не мог сделать. Т.к выполнялся цикл мигания. И нужно было ждать до конца. А хотелось бы сделать так, чтобы светодиод выполнял свою работу, а я мог в это же время нажимать кнопки, и просматривать меню. Не могли бы Вы помочь разобраться с данной проблемой?
А смысл какой, прилагать рабочий скетч? В нем проблем нет, согласно Вашей же информации.
В код не заглядывал, но, судя по словесному описанию, Вам нужно как следуект радобраться в "blink without delay".
Так кода и нет, заглядывать некуда. В приложенном коде delay(100500) отсутствует. Короче это не тот код, по которому описана проблема.
Код был добавлен специально, т.к я знаю что можно было бы описать все иначе и проще. Думал поправите. Нерабочий код вот в этой строке:
//=======================настройка режимов светодиода void F_led() { if (on_off) { if (!mode_led) //режим 1 { digitalWrite(led,HIGH); } else //режим 2 { digitalWrite(led,HIGH); delay(500); digitalWrite(led,LOW); delay(500); } } else digitalWrite(led,LOW); }И вернемся к самой сути проблемы:
Теперь перейдем к самой проблеме. Изначально хотелось сделать 3 режима. 1 - горит постоянно. 2- моргает. 3 - сначала загорается плавно, потом плавно погасает. Но когда начал делать это. То получалось следующее: все работало без ошибок на первом режиме. Как только переходил на режим 2, кнопками уже ничего не мог сделать. Т.к выполнялся цикл мигания. И нужно было ждать до конца. А хотелось бы сделать так, чтобы светодиод выполнял свою работу, а я мог в это же время нажимать кнопки, и просматривать меню. Не могли бы Вы помочь разобраться с данной проблемой?
А теперь найдите этот кусок из сообщения #4 в скетче, который приложили в первом сообщении.
Ответ на вопрос уже прозвучал в сообщении #2.
А теперь найдите этот кусок из сообщения #4 в скетче, который приложили в первом сообщении.
Я приложил тот скетч для проверки. Чтобы просто посмотрели и сделали замечания по написанию. А на счет режимов просто хотелось узнать. Можно ли сделать так, чтобы светодиод выполнял свою работу (моргал, потухал и снова начинал светиться), а я в это время мог спокойно перемещаться по меню.
Суть вашего замечания я понял, спасибо.
К первому - нет замечаний.
Так ответ по существу проблемы уже прозвучал: "Ответ на вопрос уже прозвучал в сообщении #2."
Или еще проще: ДА
guliyev34 Посмотрите этот код, старался по максимому сохранить Ваш чтоб Вам было легче розобраться. Здесь можно ставить меню не 3 а больше немного подправив код. Думаю разберетесь
//подключение библиотеки для работы с LCD #include <LiquidCrystal.h> //управляющие кнопки int button_L = 8; //кнопка переключения влево int button_OK = 7; //кнопка переключения вправо int button_R = 9; //кнопка ОК //управляемый светодиод int led = 6; //состояние кнопки boolean lastButton_L = LOW; boolean currentButton_L = LOW; boolean lastButton_R = LOW; boolean currentButton_R = LOW; boolean lastButton_OK = LOW; boolean currentButton_OK = LOW; //переменная отвечающая за пункт меню int f_punkt = 0;//Временная для ОК int punkt = 0; //0 - включить/выключить, 1 - меню режима int t1 = 500; //Время для мигания unsigned long x; //Переменная для прошедшего периода "led" int brightness = 0; // яркость светодиода int fadeAmount = 3; // шаг изменения яркости //инициализируем LCD с указанием контактов LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); //==================================================== void setup() { //инициализируем пины pinMode(button_L, INPUT); // пин, как вход + подтягивающий резистор pinMode(button_R, INPUT); pinMode(button_OK, INPUT); pinMode(led, OUTPUT); //начало работы, с указанием размерности экрана lcd.begin(16, 2); Serial.begin(9600); } //==================================================== //=================проверяем нажатие кнопки button_L void F_button_L() { if (lastButton_L != digitalRead(button_L)) { delay(5); currentButton_L = digitalRead(button_L); } if (lastButton_L == LOW && currentButton_L == HIGH) { f_punkt--; //если нажата кнопка, переключаем на предыдущее меню if (f_punkt <= 0)f_punkt = 1; //чтобы не выходить за заданное количество пунктов меню } lastButton_L = currentButton_L; } //=================проверяем нажатие кнопки button_R void F_button_R() { if (lastButton_R != digitalRead(button_R)) { delay(5); currentButton_R = digitalRead(button_R); } if (lastButton_R == LOW && currentButton_R == HIGH) { f_punkt++; //если нажата кнопка, переключаем на следующее меню if (f_punkt >= 4)f_punkt = 1;//чтобы не выходить за заданное количество пунктов меню } lastButton_R = currentButton_R; } //=================проверяем нажатие кнопки button_OK void F_button_OK() { if (lastButton_OK != digitalRead(button_OK)) { delay(5); currentButton_OK = digitalRead(button_OK); } if (lastButton_OK == LOW && currentButton_OK == HIGH) { punkt = f_punkt; //если нажали кнопку ОК, переходим в настройку состояния Serial.println(punkt); //Выводим на монитор } lastButton_OK = currentButton_OK; } //=================экран текущее состояние void enable_print() { switch (punkt) { case 1: lcd.print("MODE: 1"); break; case 2: lcd.print("MODE: 2"); break; case 3: lcd.print("MODE: 3"); break; } } //=======================настройка режимов светодиода void F_led() { switch (punkt) { case 1: digitalWrite(led, HIGH); break; case 2: if (x != (millis() / t1)) { x = millis() / t1; digitalWrite(led, !digitalRead(led)); } break; case 3: if (x != (millis() / 20)) { analogWrite(led, brightness); // устанавливаем значение на 6 ножке brightness = brightness + fadeAmount; // прибавляем шаг яркости // если достигли мин. или макс. значения, то идем в обратную сторону if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } x = millis() / 20; } break; } } //==========================выводим внизу экрана меню void menu() { lcd.setCursor(0, 1); lcd.print("<--"); lcd.setCursor(7, 1); lcd.print("OK"); lcd.setCursor(13, 1); lcd.print("-->"); } void loop() { //проверяем нажатие кнопки button_L F_button_L(); //проверяем нажатие кнопки button_R F_button_R(); //проверяем нажатие кнопки button_OK F_button_OK(); //переводим светодиод в настроенное состояние F_led(); //очищаем экран lcd.clear(); //выводим на экран текущее состояние enable_print(); //выводим внизу экрана меню menu(); //небольшая задержка между кадрами delay(50); }vosara Спасибо большое за код. Очень интресно, а главное все заработало. Правда есть недработки, например, при первом запуске устройства на экране выводится только нижнее меню. А также для переключения режима, недостаточно просто нажать кнопку ОК, нужно сначала нажать Левую кнопку, а затем уже Ок. Но это все не важно, главное сама идея. Вы не могли бы объяснить работу режима, на примере вот этих строк:
case 2: if (x != (millis() / t1)) { x = millis() / t1; digitalWrite(led, !digitalRead(led)); } break;Я понимаю то, что у нас будут выполняться эти строки, когда punkt будет равен 2. Также понятно, что break завершает switch функцию, а благодаря этой строке: digitalWrite(led, !digitalRead(led)) , состояние светодиода, при каждом проходе, будет меняться, и будет создаваться эффект мигания. Но вот операции с millis не совсем понятны.
Например, при первом проходе, x мы объявили, tl у нас равно 500. Значит, условие будет выполнено и x у нас не будет равно millis/tl. Мы присваем x значение millis/tl. И изменяем состояние светодиода (было LOW - стало HIGH). Потом прирываем switch? И дальше делаем все сначала? Т.е переходим снова в функцию loop и проверяем были ли нажаты кнопки? Я просто немного не понимаю как это все работает :((
Да, именно так. Я пока только учусь. Вот решил сделать такое устройство, свого рода контроль управления.
Получается что через каждые 500 мсек(tl) происходит переключение на операцию мигания светодиода? А все остальное время мы можем тыкать кнопки?
Спасибо большое за помощь, многое стало на свои места)) Побольше бы таких людей