Кнопка на три режима..

NVN Plus
Offline
Зарегистрирован: 04.12.2017

Пробую делать трех-режимный селектор на одной кнопке. При нажатии на кнопку происходит переключение на следующий режим и так по кругу ...1-2-3-1-2-3...  Ниже код в котором переключение происходит в нужном порядке, но если перестаю нажимать на кнопку, то номер режима, к примеру первый - многократно печатается в сериал мониторе и ни как не могу придумать способ его остановить. Буду признателен за помощь. 

 

const int btn = 2;
int selector = 0;
bool but_state;

void setup() {
  Serial.begin(9600);
  pinMode(btn, INPUT_PULLUP);
}
void loop() {
  if (digitalRead(btn) == true && but_state == false )
  {
    but_state = true;

    selector++;
    if (selector > 3) {
      selector = 0;

    } else if (digitalRead(btn) == HIGH)
    {
      but_state = false;
    }
    switch (selector) {
      case 0:
        Serial.println("Case 0");
        break;
      case 1:
        Serial.println("Case 1");
        break;
      case 2:
        Serial.println("Case 2");
        break;
    }
  }
}

 

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

У вас в коде какой-то бардак с логикой.

Можете обьяснить, зачем нужен else if() в строке 18 и вообще какова функция переменной but_state? Почему она обнуляется только если selector не равен нулю?

NVN Plus
Offline
Зарегистрирован: 04.12.2017

Вставил не ту версию кода. Та была до того как определился с окончательной версией.

 

Вот:

const int btn = 2;
int selector = 0;
bool but_state = 0;

void setup() {
  Serial.begin(9600);
  pinMode(btn, INPUT_PULLUP);
}
void loop() {
  if (digitalRead(btn) == true && but_state == false )
  {
    but_state = true;

    selector++;
    if (selector > 3)
      selector = 0;

  } else if (digitalRead(btn) == false)
  {
    but_state = false;
  }
  switch (selector) {
    case 0:
      Serial.println("Case 0");
      break;
    case 1:
      Serial.println("Case 1");
      break;
    case 2:
      Serial.println("Case 2");
      break;
  }
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Ну начнем с того, что у тебя не 3 режима а 4.
Условие для трёх должно быть :
if(selector>=3)

А можно без всяких if, просто:
selector++;
selector%=3;

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Так в чем проблема-то?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Тс , ты определись, тебе "шашечки или ехать ? "

У тебя в теле switch стоит вывод в порт в каждом проходе.

Ты либо флагами все case обвешай(будет много мусора), либо отдельно выводи если значение изменилось.

static int _selector=selector;
if(_selector!=selector){
_selector=selector;
Serial.print("Case ");
Serial.println(selector);
}

 

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

NVN Plus, зачем тут нужен but_state - так и осталось не понятным.

А чтобы значение selector не мусорило в Монитор - достаточно в коде из #2 перенести блок Switch() в 17 строку

NVN Plus
Offline
Зарегистрирован: 04.12.2017

b707 пишет:

NVN Plus, зачем тут нужен but_state - так и осталось не понятным.

А чтобы значение selector не мусорило в Монитор - достаточно в коде из #2 перенести блок Switch() в 17 строку

 

but_state - это я дребезг устранял, хвосты.. Switch() перенёс, не компилируется..( 

NVN Plus
Offline
Зарегистрирован: 04.12.2017

Kakmyc пишет:
Ну начнем с того, что у тебя не 3 режима а 4. Условие для трёх должно быть : if(selector>=3) А можно без всяких if, просто: selector++; selector%=3;

Ну, я пока так не умею, учусь.. спасибо за примерчик.

 

NVN Plus
Offline
Зарегистрирован: 04.12.2017

Kakmyc пишет:

Тс , ты определись, тебе "шашечки или ехать ? "

У тебя в теле switch стоит вывод в порт в каждом проходе.

Ты либо флагами все case обвешай(будет много мусора), либо отдельно выводи если значение изменилось.

static int _selector=selector;
if(_selector!=selector){
_selector=selector;
Serial.print("Case ");
Serial.println(selector);
}

 

Это что, все запихать в case??? Разве так можно?

П.С. Мне лучше с комментариями, хочется все-таки понять как правильно..

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

NVN Plus пишет:

Switch() перенёс, не компилируется..( 

Весь блок switch со всеми case переносить нужно

const int btn = 2;
int selector = 0;
bool but_state = 0;

void setup() {
  Serial.begin(9600);
  pinMode(btn, INPUT_PULLUP);
}
void loop() {
  if (digitalRead(btn) == true && but_state == false )
  {
    but_state = true;

    selector++;
    if (selector > 3)
      selector = 0;

    switch (selector) {
      case 0:
        Serial.println("Case 0");
        break;
      case 1:
        Serial.println("Case 1");
        break;
      case 2:
        Serial.println("Case 2");
        break;
    }
  } else if (digitalRead(btn) == false)
  {
    but_state = false;
  }
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

NVN Plus пишет:

Это что, все запихать в case??? Разве так можно?

П.С. Мне лучше с комментариями, хочется все-таки понять как правильно..

Это не надо пихать в кейс.
Это нужно разместить после блока switch, убрав из всех case'ов вывод в порт.
Если нужно обязательно пихать в case, тогда примерно так:
Объявляем переменные
boolean serial_flag=1;
int _selector=selector;

В кейсах будет:
case 0:
if(serial.flag=1){Serial.println("Case 0");serial_flag=0;}
break;

За пределами switch:
if(_selector!=selector){
_selector=selector;
serial_flag=1;}

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

Kakmyc пишет:
В кейсах будет: case 0: if(serial.flag=1){Serial.println("Case ...

он ведь так и напишет. А нам опять разгребать

Kakmyc
Offline
Зарегистрирован: 15.01.2018

DetSimen пишет:

Kakmyc пишет:
В кейсах будет: case 0: if(serial.flag=1){Serial.println("Case ...

он ведь так и напишет. А нам опять разгребать

Ну пусть хоть малость подумает.
Очевидно же

NVN Plus
Offline
Зарегистрирован: 04.12.2017

DetSimen пишет:

Kakmyc пишет:
В кейсах будет: case 0: if(serial.flag=1){Serial.println("Case ...

он ведь так и напишет. А нам опять разгребать

Не, не напишу - кейсы лучше не загромождать - читал..)

В общем всем спасибо! Ваши подсказки помогли! Пока не все понял, но буду разбираться - пищи для размышлений предостаточно. Добавил антидребезг и все ваши поправки - код преобразился.) Доволен!

const int btn = 2;
int selector = 0;
bool but_state = false;
unsigned long last_press;

void setup() {
  Serial.begin(9600);
  pinMode(btn, INPUT_PULLUP);
}
void loop() {
  if ( (digitalRead(btn) == true && but_state == false ) && (millis() - last_press > 5) )
  {
    but_state = true;
    last_press = millis();

    selector++;
    selector %= 3;

    switch (selector) {
      case 0:
        Serial.print("Case ");
        Serial.println(selector);
        break;
      case 1:
        Serial.print("Case ");
        Serial.println(selector);
        break;
      case 2:
        Serial.print("Case ");
        Serial.println(selector);
        break;
    }
    static int _selector = selector;
    if (_selector != selector) {
      _selector = selector;
    }
  } else if ( (digitalRead(btn) == false && but_state == true ) && (millis() - last_press > 5) )
  {
    but_state = false;
    last_press = millis();
  }
}

 

anatoli_nik
Offline
Зарегистрирован: 17.01.2019

А разве вместо case switch не проще

​if (selector!=_selector)
Serial.println("Case "+ selector);
_selector = selector;

 

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

anatoli_nik пишет:

А разве вместо case switch не проще

​if (selector!=_selector)
Serial.println("Case "+ selector);
_selector = selector;

 

Гыгыгы.