Неправильно работает скетч

poolman
Offline
Зарегистрирован: 15.06.2017
#include <LiquidCrystal.h>

const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2;
const int BUTTON_DOWN   = 3;
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;

int x = 0;

int y = 0;

int button;

int getPressedButton()
{
  int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) 
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
}

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

void setup() {
  lcd.begin(16, 2);
}

void loop() {
 button = getPressedButton();
  switch (button)
  {
  case BUTTON_RIGHT:
    x+=1;
    break;
  case BUTTON_LEFT:
    x-=1;
    break;
  case BUTTON_UP:
    y-=1;
    break;
  case BUTTON_DOWN:
    y+=1;
    break;
  case BUTTON_SELECT:
    lcd.setCursor(x,y);
    lcd.print(0);
    break;
  }
}

По идее, этот скетч должен перемещать курсор Вправо-Влево-Вверх-Вниз, по нажатию соответствующей кнопки, а по нажатию кнопки SELECT рисовать 0 в позиции курсора, но почему-то происходит иначе: кнопки работают как-то непонятно, курсор двигается в не пойми какое место, и по нажатию SELECT 0 рисуется не всегда.

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

границы не отслеживаешь.  И кнопки дребежжять. 

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

После строки 42 поставьте вывод в сериал значения переменной button - узнаете много интересного :)

poolman
Offline
Зарегистрирован: 15.06.2017

И как с этим борьтя :)?

poolman
Offline
Зарегистрирован: 15.06.2017

> И кнопки дребежжять.

 

В каком смысле?

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

poolman пишет:

И как с этим борьтя :)?

Ну, я же Вам сказал что сделать. Сделали? Посмотрите что выдаёт и подумайте.

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

poolman пишет:

> И кнопки дребежжять.

В каком смысле?

В самом прямом. Сделайте то, что я сказал - увидите.

poolman
Offline
Зарегистрирован: 15.06.2017

Выдает аналоговое значение A0, внезапно. И что мне теперь делать?

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

poolman пишет:

> И кнопки дребежжять.

В каком смысле?

Вы никогда не слышали про дребезг кнопки (дребезг контактов)? 

https://ru.wikipedia.org/wiki/%D0%94%D1%80%D0%B5%D0%B1%D0%B5%D0%B7%D0%B3...

https://uscr.ru/drebezg-kontaktov-i-sposoby-podavleniya-drebezga/

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

poolman пишет:

Выдает аналоговое значение A0, внезапно. И что мне теперь делать?

А Вы ЭТО сделали? Или теоретизируете? 

Какое нахрен A0?

Вас что просили выдавать? Переменную button . Она у Вас может быть равна 1-5 и ничему другому и означает какая кнопка нажата.

Вот и выдайте и посмотрите что (и сколько раз)  по мнению компьютера Вы нажимаете.

poolman
Offline
Зарегистрирован: 15.06.2017

А с аналоговым входом способ, описанный во второй ссылке, сработает?

poolman
Offline
Зарегистрирован: 15.06.2017

Один раз. Без нажатия кнопки выводится 263.

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

poolman пишет:

Один раз. Без нажатия кнопки выводится 263.

это потому что вариант "ни одна кнопка не нажата" в скетче вообще не предусмотрен и не обрабатывается

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

poolman пишет:

Один раз. Без нажатия кнопки выводится 263.

Закройте дыру в функции getPressedButton (после строки 32 напишите "else return NO_BUTTON;" )

Разумеется, определите константу NO_BUTTON выше.

После строки 42 поставьте "if (button == NO_BUTTON) return;"

И только после этого печать. Тогда она (печать) не будет Вам весь экран засирать.

Затем смотрите что выдаётся, соотвтетсвует ли это нажатым клавишам.

Заодно можете поставить печать x и y после строки 61. Тогда Вы сможете оценить адекватно ли программа отреагировала на нажатую клавишу.

Смотрите и разбирайтесь.

poolman
Offline
Зарегистрирован: 15.06.2017

Правильно ли я понимаю, что с BUTTON_NONE проверка в getPressedButton должна быть buttonValue = 0? Этот код:

 

#include <LiquidCrystal.h>

const int BUTTON_NONE   = 0;
const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2;
const int BUTTON_DOWN   = 3;
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;

int x = 0;

int y = 0;

int button;

int getPressedButton()
{
  int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) 
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
  else if (buttonValue = 0){
    return BUTTON_NONE;
  }
}

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

void setup() {
  lcd.begin(16, 2);
}

void loop() {
 button = getPressedButton();
 lcd.print(button);
 delay(1000);
}

Тоже выводит 263 до бесконечности.

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

неправильно. Строки 34-35 должны быть

 else {
   return BUTTON_NONE;}

 

poolman
Offline
Зарегистрирован: 15.06.2017

Теперь работает. Правда, на кнопки надо нажимать очень сильно, прямо давить, иначе выводится 0. Проблема, скорее всего, аппаратная. Щас проверим еще кое-что.

poolman
Offline
Зарегистрирован: 15.06.2017

Сделал это. При нажатии кнопок LEFT и RIGHT выводится бесконечный набор случайных символов, хотя должны выводиться x и y. При UP, DOWN и SELECT все ok. Правда, при UP и DOWN x и y почему-то не выводятся. Код:

#include <LiquidCrystal.h>

const int BUTTON_NONE   = 0;
const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2;
const int BUTTON_DOWN   = 3;
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;

int x = 0;

int y = 0;

int button;

int getPressedButton()
{
  int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) 
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
  else return BUTTON_NONE;
}

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

void setup() {
  lcd.begin(16, 2);
}

void loop() {
 button = getPressedButton();
 lcd.setCursor(x,y);
 switch (button)
  {
  case BUTTON_RIGHT:
    x+=1;
    lcd.print(x, y);
    break;
  case BUTTON_LEFT:
    x-=1;
    lcd.print(x, y);
    break;
  case BUTTON_UP:
    y-=1;
    lcd.print(x, y);
    break;
  case BUTTON_DOWN:
    y+=1;
    lcd.print(x, y);
    break;
  case BUTTON_SELECT:
    lcd.print(0);
    break;
  }
  
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Господа! Он сам никогда не догадается... я сегодня буду "добрым самаритянином"....

==============

2ТС:

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

Поэтому нужно в статик или глобальной переменной помнить ПРОШЛОЕ значение кнопки.

Войда в loop() и опросив кнопки нужно выполнять свой свич ТОЛЬКО, если прошлое нажатие было NO_BUTTON, или как-там-ты-его-назвал.

При выходе из loop() нужно запомнить текущее состояние, как прошлое.

----------------------------

Понятно? Если нет - сорри. У меня не прокачен коррекционный педагог.

poolman
Offline
Зарегистрирован: 15.06.2017

А если предыдущее состояние не было равно NO_BUTTON, то цикл будет один раз отрабатывать вхолостую?

poolman
Offline
Зарегистрирован: 15.06.2017

Теперь вообще ничего не работает...

Код:

#include <LiquidCrystal.h>

const int BUTTON_NONE   = 0;
const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2;
const int BUTTON_DOWN   = 3;
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;

int x = 0;

int y = 0;

int button;

int previous_button;

int getPressedButton()
{
  int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) 
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
  else return BUTTON_NONE;
}

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

void setup() {
  lcd.begin(16, 2);
}

void loop() {
 button = getPressedButton();
 lcd.setCursor(x,y);
 if (previous_button = BUTTON_NONE){
 switch (button)
  {
  case BUTTON_RIGHT:
    x+=1;
    break;
  case BUTTON_LEFT:
    x-=1;
    break;
  case BUTTON_UP:
    y-=1;
    break;
  case BUTTON_DOWN:
    y+=1;
    break;
  case BUTTON_SELECT:
    lcd.setCursor(x, y);
    lcd.print(0);
    break;
  }
 }
  previous_button = button;
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Одаренный Вы человек!

Понятно ли то, что на ОДНО нажатие должно быть ОДНО действие программы?

Попробуйте думать! Просто представить себе как именно работает программа, вами же и написанная.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

СТОРОКА 48 "=" вместо "=="

poolman
Offline
Зарегистрирован: 15.06.2017

Спасибо. Отвык от си-синтаксиса, уж извините.

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

А это что бы вас еще запутать в Cи(Си++ и.т.д) Скетч рабочий

/*Cl_an_btn5.ino
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_an_btn5-----------------
class Cl_an_btn5 {
    byte pin ; // нога аналог клавиатуры
    void (*Do_right)(), (*Do_up)(), (*Do_down)(), (*Do_left)(), (*Do_select)();
    byte read() {
      const int Right  =  60; // ниже = нажата кнопка  Right
      const int Up     = 200; // ниже = нажата кнопка  Up
      const int Down   = 400; // ниже = нажата кнопка  Down
      const int Left   = 600; // ниже = нажата кнопка  Left
      const int Select = 800; // ниже = нажата кнопка  Select
      static int a ;
      a = analogRead(pin);
      if (a < Right) return 1;
      else if (a < Up) return 2;
      else if (a < Down) return 3;
      else if (a < Left) return 4;
      else if (a < Select) return 5;
      else return 0;
    }
    byte abtn, abtn_old; // старый и новый номер нажатой клавиши
    bool bounce_abtn = 0; // антидребезговый флаг
    uint32_t past = 0 ; // временной отчет
  public:
    // указатель на следующий элемент
    Cl_an_btn5 *pnt;
    // конструктора
    Cl_an_btn5(Cl_Sys *Sys, byte _pin, void (* _Do_right)(), void (* _Do_up)(), void (* _Do_down)(), void (* _Do_left)(), void (* _Do_select)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      abtn = read() ; // прочитать реальное значение на выводе
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_abtn && abtn != read()) { // если прошел фронт изм на выводн
        bounce_abtn = 1;                     // выставить флаг
        past = millis();                     // сделать временую засветку
      }
      else if ( bounce_abtn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_abtn = 0;      // то снять флаг
        abtn_old = abtn ;
        abtn = read() ; // прочитать реальное значение на выводе
        if (abtn_old == 0) {
          if (abtn == 1) Do_right()  ;
          if (abtn == 2) Do_up()     ;
          if (abtn == 3) Do_down()   ;
          if (abtn == 4) Do_left()   ;
          if (abtn == 5) Do_select() ;
        }
      }
    }
};
//-----Cl_Sys-----------------
class Cl_Sys {
  public:
    Cl_an_btn5 *Start_btn5 = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_an_btn5 *i = Start_btn5; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_an_btn5 *i = Start_btn5; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_an_btn5::Cl_an_btn5(Cl_Sys *Sys, byte _pin, void (* _Do_right)(), void (* _Do_up)(), void (* _Do_down)(), void (* _Do_left)(), void (* _Do_select)())
  : pin(_pin), Do_right(_Do_right), Do_up( _Do_up), Do_down(_Do_down), Do_left(_Do_left), Do_select(_Do_select) {
  pnt = Sys->Start_btn5;
  Sys->Start_btn5 = this;
}
//----------Компоновка---------------------
#include <LiquidCrystal.h>
LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*D4*/ 4,/*D5*/5,/*D6*/6,/*D7*/7);
void Do_right () {
  lcd.setCursor(10, 1);
  lcd.print ("Right ");
}
void Do_up    () {
  lcd.setCursor(10, 1);
  lcd.print ("Up    ");
}
void Do_down  () {
  lcd.setCursor(10, 1);
  lcd.print ("Down  ");
}
void Do_left  () {
  lcd.setCursor(10, 1);
  lcd.print ("Left  ");
}
void Do_select() {
  lcd.setCursor(10, 1);
  lcd.print ("Select");
}
Cl_an_btn5 *A_Btn = new Cl_an_btn5(&Sys,/*пин*/A0,
                                   /*обработчик Right*/Do_right,/*обработчик Right*/Do_up,
                                   /*обработчик Down*/Do_down,/*обработчик Left*/Do_left,/*обработчик Select*/Do_select);
//-----------Main()-----------------------
void setup() {
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("LCD Key Shield");
  lcd.setCursor(0, 1);
  lcd.print("Press Key:");

  Sys.setup();
}

void loop() {
  Sys.loop();
}

 

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

poolman пишет:

Правильно ли я понимаю, что с BUTTON_NONE проверка в getPressedButton должна быть buttonValue = 0? 

Блин, ну я же Вам писал: "после строки 32 напишите "else return NO_BUTTON;" " А Вы чего написали?

Ага, Вижу, Вам уже подсказали и со второго раза до Вас дошло :)

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

poolman,

я категорически отказываюсь продолжать попытки Вам помочь и прошу коллег присоединиться.

Я Вам ДВАЖДЫ писал - поставьте печать и смотрите, что выводится! ДВАЖДЫ! Где в Вашем скетче печать? Что выводится?

У меня ощущение, что я зря трачу время.

Хотите помощи, делайте, что Вам говорят - не хотите - идите нафиг!