Нужна помощь со скетчем (две кнопки)

stormaggedon
Offline
Зарегистрирован: 08.05.2019

Итак, элементарная задача: есть кнопки ВКЛ и ВЫКЛ, и светодиод, которым они управляют. Нужно, чтобы при нажатии ВКЛ светодиод включался, и выключался при нажатии на ВЫКЛ не зависимо от того, зажата ли в это время ВКЛ. Далее, если при выключении кнопка ВКЛ была зажата, дождаться её выключения, и начать заново.

Для этого был написан незамысловатый код:

const int button1Pin = 7; 
const int button2Pin = 5; 
const int ledPin = 13; 


int button1State = 0; 
int button2State = 0; 

void setup() { 


pinMode(ledPin, OUTPUT); 


pinMode(button1Pin, INPUT); 
pinMode(button2Pin, INPUT); 
} 

void loop(){ 

do button1State = digitalRead(button1Pin); 
while (button1State == LOW) ; 

digitalWrite(ledPin, HIGH); 

do button2State = digitalRead(button2Pin); 
while button2State == LOW); 


digitalWrite(ledPin, LOW); 


do 
button1State = digitalRead(button1Pin); 
while (button1State == HIGH); 
 
}

Тем не менее, при зажатой ВКЛ, кнопка ВЫКЛ не выключает светодиод, что не так, не могу понять.

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

stormaggedon пишет:

 Далее, если при выключении кнопка ВКЛ была зажата, дождаться её выключения, и начать заново.

Скетч сам должен нажать заново? Или кто? У Вас вообще непонятно кто на ком стоит. 

Собственно потому у Вас и не получается - как только Вы сможете внятно и логично описать алгоритм,то все получится.

vvadim
Offline
Зарегистрирован: 23.05.2012
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

странная задача

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

Жаль что в задаче нет 3 кнопки что бы светодиод еще мигал #6

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Подпишусь за Евгения #1. Нужен логичный и непротиворечивый алгоритм. По шагам - нажали кнопку Вкл - то-то, не отпуская  нажали кнопку Выкл - то-то, отпустили кнопку Вкл... и т.д.

Можно оформить графически. Почитайте. После этого программа возникнет сама.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

mykaida пишет:

Подпишусь за Евгения #1. Нужен логичный и непротиворечивый алгоритм. По шагам - нажали кнопку Вкл - то-то, не отпуская  нажали кнопку Выкл - то-то, отпустили кнопку Вкл... и т.д.

Можно оформить графически. Почитайте. После этого программа возникнет сама.

я так понимаю ТС имеет желание реализовать простейшую схему аналога запитки пускателя с самоблокировкой где имеются две кнопки пуск и стоп, и пока нажата стоп пускатель не срабатывает???
Такой скетчик где-то есть у меня, с него и начинал изучение адуины

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ua6em пишет:

я так понимаю ТС имеет желание реализовать простейшую схему аналога запитки пускателя с самоблокировкой где имеются две кнопки пуск и стоп, и пока нажата стоп пускатель не срабатывает???

Такой скетчик где-то есть у меня, с него и начинал изучение адуины

А зачем здесь ардуина? Это можно реализовать с помощью реле с двумя контактами. Зачем множить сучности?

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

mykaida пишет:

ua6em пишет:

я так понимаю ТС имеет желание реализовать простейшую схему аналога запитки пускателя с самоблокировкой где имеются две кнопки пуск и стоп, и пока нажата стоп пускатель не срабатывает???

Такой скетчик где-то есть у меня, с него и начинал изучение адуины

А зачем здесь ардуина? Это можно реализовать с помощью реле с двумя контактами. Зачем множить сучности?

 тоже хотел это спросить ... только вдруг это студент с таким заданием

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Муж_Долговой пишет:

mykaida пишет:

ua6em пишет:

я так понимаю ТС имеет желание реализовать простейшую схему аналога запитки пускателя с самоблокировкой где имеются две кнопки пуск и стоп, и пока нажата стоп пускатель не срабатывает???

Такой скетчик где-то есть у меня, с него и начинал изучение адуины

А зачем здесь ардуина? Это можно реализовать с помощью реле с двумя контактами. Зачем множить сучности?

 тоже хотел это спросить ... только вдруг это студент с таким заданием

ну если студент, то надо помочь )))

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ua6em пишет:
надо помочь )))
В смысле - меня позвать?

stormaggedon
Offline
Зарегистрирован: 08.05.2019

Всем спасибо за ответы.

Почему такая платформа? Потому что под рукой имеется ардуина, которая позже будет задействована и для других задач, и два уже установленных куда нужно микропереключателя. Собственно, в системе не тупо кнопки и лампочка, но описание было упрощено, ибо на код не повлияет.

В голове есть чёткая задача, видимо, не получилось объяснить. Попробую так:

0. Диод не горит, кнопки не тронуты.

1. Идёт проверка состояния кнопки ВКЛ, пока она не будет нажата. С её нажатием диод загорается.

2. Идёт проверки кнопки ВЫКЛ, пока она не будет нажата. С её нажатием светодиод гаснет.

3. Идёт проверка кнопки ВКЛ:

- если кнопка не нажата, возвращение к началу скетча

- если кнопка нажата, идёт её проверка до тех пор, пока она не будет отпущена, затем возвращение к началу скетча

(диод на протяжении пункта 3 не должен гореть)

 

У меня проблема с 3 пунктом: если сначала была нажата и отпущена кнопка ВКЛ, затем нажата и отпущена ВЫКЛ, диод работает как надо. Но если при зажатой ещё в 1 пункте ВКЛ затем нажать на ВЫКЛ, диод не гаснет (хотя должен).

stormaggedon
Offline
Зарегистрирован: 08.05.2019

Не студент, задача лично для себя

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

stormaggedon пишет:

У меня проблема с 3 пунктом: если сначала была нажата и отпущена кнопка ВКЛ, затем нажата и отпущена ВЫКЛ, диод работает как надо. Но если при зажатой ещё в 1 пункте ВКЛ затем нажать на ВЫКЛ, диод не гаснет (хотя должен).

Ну а если нажата кнопка ВЫКЛ,, то это должно быть приоритетной задачей. Без циклов и прочей шняги - если есть ВЫКЛ, - то все гасим.

Пропишите это в программе и все будет хорошо.

I

if(кнопка==выкл){

digitalWrite(Лампа,0);

}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

косяк логики, а ненажатие стоп кто проверять будет в пункте 1

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

stormaggedon пишет:

В голове есть чёткая задача,

Нету. Если бы была, то и проблем бы не было. Я могу подсказать тебе как формализовать задачу, а когда ты это сделаешь, то программа появится сама собой путём переписывания задачи на if'ы. Только это потребует от тебя поработать. Делать за тебя тут вряд ли кто будет. А сам, хочешь - делай.

Итак, у тебя автомат с восемью состояниями и четырьмя входными воздействиями.

Входные воздействия:

1) нажали кнопку №1;
2) отпустили кнопку №1;
3) нажали кнопку №2;
4) отпустили кнопку №2;

Здесь под "нажали" и "отпустили" понимается однократное действие а не удержание

Состояния

1) кнопка №1 отпущена; кнопка №2 отпущена; светодиод погашен;
2) кнопка №1 отпущена; кнопка №2 отпущена; светодиод светится;
3) кнопка №1 отпущена; кнопка №2 нажата; светодиод погашен;
4) кнопка №1 отпущена; кнопка №2 нажата; светодиод светится;
5) кнопка №1 нажата; кнопка №2 отпущена; светодиод погашен;
6) кнопка №1 нажата; кнопка №2 отпущена; светодиод светится;
7) кнопка №1 нажата; кнопка №2 нажата; светодиод погашен;
8) кнопка №1 нажата; кнопка №2 нажата; светодиод светится;

Здесь "нажата" и "отпущена" - это как раз перманентные состояния, а не действия, т.е. "нажата" == "удерживается"

Теперь тебе надо составить таблицу в которой кажая строка соответсвует состоянию, а столбец - действию. Типа такой

 

  1) нажали кнопку №1; 2) отпустили кнопку №1; 3) нажали кнопку №2; 4) отпустили кнопку №2;
1) кнопка №1 отпущена; кнопка №2 отпущена; светодиод погашен;        
2) кнопка №1 отпущена; кнопка №2 отпущена; светодиод светится;        
3) кнопка №1 отпущена; кнопка №2 нажата; светодиод погашен;        
4) кнопка №1 отпущена; кнопка №2 нажата; светодиод светится;        
5) кнопка №1 нажата; кнопка №2 отпущена; светодиод погашен;        
6) кнопка №1 нажата; кнопка №2 отпущена; светодиод светится;        
7) кнопка №1 нажата; кнопка №2 нажата; светодиод погашен;        
8) кнопка №1 нажата; кнопка №2 нажата; светодиод светится;        

 

После этого ты должен заполнить таблицу следующим образом. Ставишь карандаш в пустую ячейку, смотришь на заголовки строки и столбца данной ячейки и рассуждаешь: Если система находится в таком состоянии, то при появлении такого действия, необходимо сделать ххх. И вот это ххх вписываешь в ячейку.

И вот когда ты заполнишь таким образом все ячейки, у тебя будет точный и однозначные алгоритм "что делать в любой ситуации".

Тогда останется только написать программу, которая ждёт событий, дождавшись проверяет в каком состоянии находится автомат и выполняет необходимое действие. Всё, больше там ничего нет. Всё тривиально, как два пальца.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Ворота пишет:

Браво - лучшей иллюстрации этого примера сложно придумать (а скорее всего невозможно)!

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Так это ж обычный конечный автомат (не квономат, а обыкновенный - классический автомат).

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Ворота пишет:

Так это ж обычный конечный автомат (не квономат, а обыкновенный - классический автомат).

Дык правильно, но пока мы пытались донести это до ТС, Вы расписали матрицу состояний, что очень показательно. И если ТС не полный идиот, то у него возникнет программа.

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

Вернусь к теме: Нужна помощь со скетчем (две кнопки)-включить дурака ,выключить дурака. А то без кнопок оно самопроизвольно происходит. :)

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

На. Вот вся твоя нехитрая логика: 

const uint8_t btnOnPin = 7;
const uint8_t btnOffPin = 5;
const uint8_t ledPin = 13;



void setup() {


	pinMode(ledPin, OUTPUT);


	pinMode(btnOnPin, INPUT_PULLUP);    // ты ж его на землю замыкаешь? Значить, нужна падтяшка
	pinMode(btnOffPin, INPUT_PULLUP);
}

void loop() {

	static bool ledState = false;

	digitalWrite(ledPin, ledState);


	if (digitalRead(btnOffPin) == LOW) {
		ledState = false;
		return;
	}


	if (digitalRead(btnOnPin) == LOW) ledState = true;
	
}

Антидребезгу нету, не абессуть. 

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

с тебя 100 рублей, купи своим детям мароженае в честь Праздника. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

с тебя 100 рублей, купи своим детям мароженае в честь Праздника. 

витиевато...не дается мне полёт твоей мысли

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

 const int onnButton = 3;  //Кнопка "Пуск"
 const int offButton = 4;   //Кнопка "Стоп"
 const int pinMotor = 12;   // На реле включение мотора
 int bloc = 1; // Некиий аналог блокконтактов (разомкнут)
void setup() {
  pinMode(onnButton, INPUT_PULLUP); //Кнопка не нажата
  pinMode(offButton, INPUT_PULLUP); //Кнопка не нажата
  // придвукнопочном управлении антидребезг не нужен
  pinMode (pinMotor, OUTPUT);
  digitalWrite(pinMotor, LOW);  
  }
void loop() {
  digitalRead (onnButton);   // Опрос кнопки пуск
 if ((onnButton ==LOW) ||  (pinMotor == HIGH)){ //Нажимаем кнопку "Пуск"
  bloc = 0; //При этом замыкается блокконтакт
 }
  digitalRead (offButton); // опрос кнопки стоп
 if(bloc == 0 && offButton ==HIGH){
  digitalWrite(pinMotor, HIGH); //Включается мотор и удерживается блокконтакт
 }
}

Забыл индикацию добавить. .. Если bloc =0  то светодиод (13) горит

sadman41
Offline
Зарегистрирован: 19.10.2016

Что делают строки #13 и #17 ?

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

sadman41 пишет:

Что делают строки #13 и #17 ?

Это лична просьба автора ... опрос кнопок

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

Муж_Долговой пишет:

sadman41 пишет:

Что делают строки #13 и #17 ?

Это лична просьба автора ... опрос кнопок

и в куда оне опрашиваются? ты бы хоть почитал чонить за digitalRead() штоли.

b707
Offline
Зарегистрирован: 26.05.2017

Муж долговой - вы как напишете - хоть стой хоть падай. Не умеете программить - лучше б не писали.

А еще обижаетесь. что вас ена форуме тролят...

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

а он счас расскажет, что у него всё работает.

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

а он счас расскажет, что у него всё работает.

ну, в прошлый раз-то мы выбили из него самоличное признание, что он облажался. правда это заняло 2 дня... И похоже, ничему его не научило.

b707
Offline
Зарегистрирован: 26.05.2017

Муж - вместо того. чтоб минусы ставить - лучше б исправили свой бредовый код. На замечания не обижаться надо - а выводы делать и учиться. Такие ошибки даже самым зеленым новичкам стыдно делать.

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

Вот скажи мне, муж, неизвесночей, нахрена ты под номера пинов отводишь переменную типа int?  У тебя есть Uno, где пинов 65536, да еще половина мнимых?

b707
Offline
Зарегистрирован: 26.05.2017

DetSimen пишет:

Вот скажи мне, муж, неизвесночей, нахрена ты под номера пинов отводишь переменную типа int?

да какая нафик разница на фоне строк 13 и 17 ? :)

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

да тут и это 

if ((onnButton ==LOW) ||  (pinMotor == HIGH))

клиника

sadman41
Offline
Зарегистрирован: 19.10.2016

Там еще || (pinMotor == HIGH) доставляет.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

да тут и это 

if ((onnButton ==LOW) ||  (pinMotor == HIGH))

клиника

 а так не пойдёт?
 

#define LED 13
#define pusk 5
#define stops 6

void setup() {
 pinMode(LED, OUTPUT);
 pinMode(stops,INPUT_PULLUP);     // в состоянии замкнута
 pinMode(pusk,INPUT);             // в состоянии разомкнута
                                  // подтянуть резистором 10k к шине GND
}

void loop() {
  if(digitalRead(pusk) == HIGH && digitalRead(LED)==LOW) digitalWrite(LED,HIGH);
  if(digitalRead(stops) == LOW && digitalRead(LED)==HIGH) digitalWrite(LED,LOW);

}

 

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

Теперь подумай тщательно, должен быть приоритет кнопки стоп.  А у тебя - пуск.  У меня то написано, что если нажат стоп, то выключить и прекратить дальнейший опрос 

24     if (digitalRead(btnOffPin) == LOW) {
25         ledState = false;
26         return;
27     }
 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

я подумаю, но только уже не сегодня )))
Я жеж не wdrakula для меня не тока 2000 литров, 2000мл много )))

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

DetSimen пишет:

а он счас расскажет, что у него всё работает.

Скомпиллировалось. А это уже 90% успеха.

int пишу потому, что (Булеан) никак не запомню.

И вопрос?

А разве  if ((vkl ==LOW) ||  (pinMotor == HIGH))    {      //Нажимаем кнопку "Пуск"

не означает : Если кнопка включения нажата или мотор включён, то удерживать блокконтакт?

Эти две вертикальные чёрточки || разве не "или"? А как тогда "или"?

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

Муж_Долговой пишет:

И вопрос?

А разве  if ((vkl ==LOW) ||  (pinMotor == HIGH))    {      //Нажимаем кнопку "Пуск"

не означает : Если кнопка включения нажата или мотор включён, то удерживать блокконтакт?

Эти две вертикальные чёрточки || разве не "или"? А как тогда "или"?

Нет, не означает. 

Впрочем, вопросов больше не имею. 

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

DetSimen пишет:

Муж_Долговой пишет:

sadman41 пишет:

Что делают строки #13 и #17 ?

Это лична просьба автора ... опрос кнопок

и в куда оне опрашиваются? ты бы хоть почитал чонить за digitalRead() штоли.

Так ТС же не говорил куда. Должны опрашиваться - опрашиваются. Чего ещё надо-то?

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

Муж_Долговой пишет:

Скомпиллировалось. А это уже 90% успеха.

Боюсь Вас огорчить, но это даже не 0,001% успеха. Это просто подготовительная операция ПЕРЕД началом собственно отладки :)

Муж_Долговой пишет:

int пишу потому, что (Булеан) никак не запомню.

boolean для номеров пинов? Вы бы лучше для них void запомнили.

Муж_Долговой пишет:

А разве  if ((vkl ==LOW) ||  (pinMotor == HIGH))    {      //Нажимаем кнопку "Пуск"

не означает : Если кнопка включения нажата или мотор включён, то удерживать блокконтакт?

Нет, это означает, что если кнопка нажата и мотор подключён к первому пину, то ...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Муж_Долговой пишет:

А разве  if ((vkl ==LOW) ||  (pinMotor == HIGH))  

не означает : Если кнопка включения нажата или мотор включён, то удерживать блокконтакт?

Нет. Переменная pinMotor не может быть ни HIGH, ни LOW. Она содержит только номер пина, к которому подключен мотор. Вам уже писали, прочитайте про digitalRead() и не пишите больше такую чушь... Я бы вообще Ваш пост удалил, а то новички скопипастят и потом замучают форум вопросами "а почему оно не работает!?"

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Муж_Долговой пишет:

int пишу потому, что (Булеан) никак не запомню.

Не boolean тут нужен, а byte или uint8_t. Про типы данных Вам тоже не помешало бы почитать.

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

вот внук через час уедет ... тогда и отладку сделаю.

Хотя и так вижу, что если учесть замечание Деда Семёна,

и написать примерно так

  int vkl = digitalRead (onnButton);   // Опрос кнопки пуск
 if (vkl ==LOW ||  pinMotor == HIGH){ //Нажимаем кнопку "Пуск"
то всё будет работать. А int, long, Байт - это придирки.
Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Муж_Долговой пишет:

то всё будет работать. 

Не будет, т.к. переменная pinMotor НИКОГДА не станет HIGH (и LOW тоже).

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Jeka_M пишет:

Муж_Долговой пишет:

то всё будет работать. 

Не будет, т.к. переменная pinMotor НИКОГДА не станет HIGH (и LOW тоже).

Исправим, если что. Пробный пуск покажет.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Для ускорения понимания ошибки предлагаю Вам перед строкой if (vkl ==LOW ||  pinMotor == HIGH) добавить Serial.print(pinMotor); и посмотреть в мониторе порта значение переменной pinMotor.

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

Jeka_M пишет:

Для ускорения понимания ошибки предлагаю Вам перед строкой if (vkl ==LOW ||  pinMotor == HIGH) добавить строку Serial.print(pinMotor); и посмотреть в мониторе порта значение переменной pinMotor.

а что с этой строкой не так?

digitalWrite (pinMotor, HIGH);

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

я смарю, тебе здесь надо читателем быть еще минимум год. 

Муж_Долговой
Муж_Долговой аватар
Offline
Зарегистрирован: 07.10.2018

DetSimen пишет:

я смарю, тебе здесь надо читателем быть еще минимум год. 

Так  же уходил от тебя на другой форум, под другим именем. Так ты меня и там доставал.

Пришлось вернуться.