Программируемая кнопка

Stoun
Offline
Зарегистрирован: 28.06.2017

Доброго времени суток, уважаемые форумчане!

 
Прошу сразу не пинать, новичок в программировании Ардуинки.
 
Задача такая, на TFT экране есть программная кнопка ВКЛ/ВЫКЛ, при клике на нее надо,
чтобы цвет кнопки поменялся с зеленного на красный (это реализовано) и при повторном клике,
цвет менялся обратно, т.е. с красного на зеленный. Вот небольшой пример из скетча.
 
#include <UTFT.h>                //*********
#include <UTouch.h>              //* Подключаем библиотек

extern uint8_t Various_Symbols_32x32[]; 

UTFT  myGLCD(17, 38,39,40,41);   
UTouch      myTouch(6,5,4,3,2);  

int x, y;
boolean onoff;

void setup() {
  myGLCD.InitLCD(); //Инициализируем экран
  myGLCD.clrScr(); //Очищаем экран
  myTouch.InitTouch(); //Инициализируем тачскрин
  myTouch.setPrecision(PREC_MEDIUM);
  onoff = false; // кнопка выключена
  DrawHomeScreen(); //Инициализация программной кнопки
}

void DrawHomeScreen(){
    //кнопка вкл/выкл
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillRoundRect (252, 172, 312, 218);
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (252, 172, 312, 218);
    myGLCD.setBackColor(0, 255, 0);
    myGLCD.setFont(Various_Symbols_32x32);
    myGLCD.print("l", 268, 179);
}

void BtnOnOff(){
  
   if (myTouch.dataAvailable())
    {
      myTouch.read();
      x=myTouch.getX();
      y=myTouch.getY();
      
      if ((x >= 252) && (x <= 312))
      {
        if ((y>172) && (y<218) && (onoff == false)){
        myGLCD.setColor(255, 0, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(255, 0, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = true; 
        }
        }
       else
       {
        if ((y>172) && (y<218) && (onoff == true)){
        myGLCD.setColor(0, 255, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(0, 255, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = false;
        }
      }
   }
 }
void loop() {
BtnOnOff();
}

При нажатии на кнопку меняется цвет, при повторном нажатии, цвет остается.

Подскажите пожалуйста, что не так сделано? 
Перелопатил инет, решения так и не нашел.
 
Заранее, оргомное спасибо!
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я так понимаю, что в первый раз цвет меняется в строка 43-50.

А обратно Вы надеетесь поменять его в строках 55-63.

Но строки 55-63 находятся в ветке else оператора if из строки 40. Т.е. они будут выполняться, когда нажатие было ВНЕ кнопки по x - попробуйте!

А как попробуете, выставьте правильно условия.

Stoun
Offline
Зарегистрирован: 28.06.2017

я для этого добавил логический тип данных onoff, по умолчанию false;
далее в условиях прописал, что нажимая по координатам на кнопку и имея в условии либо false, либо true, выполнить условие 42, прорисовать код 46-49, перевести onoff в true, что бы можно было выполнить условие 55, т.е. по следующему тапу кнопки с указанными координатами и условием onoff=true, выполнился код 56-62.
но else не срабатывает.

 

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

Вы решили со мной поспорить? А может, лучше внимательно свой код почитать?

Хорошо, Выпишите мне ВСЕ условия при которых Вы фиксируете нажатие на кнопку.

Я правильно понимаю, что нажатие на кнопку фикисруется при выполнеии следующего: 

(x >= 252) && (x <= 312) && (y>172) && (y<218) 

что означет, что в кнопку "попали" пальцем, а промахнулись.

Правильно?

Если правильно, то перечитайте мой пост ещё раз и исправляйте ошибки.

Stoun
Offline
Зарегистрирован: 28.06.2017

Евгений!
Я спорить ни скем не собираюсь, только прошу помощи.
Голова уже кипит от всевозможных вариантов, вот мозги и замылились.
Правильно, координаты кнопки (252, 312, 172, 218)
И по условию, что если я тапну в этой области тачскрина, то попаду в кнопку.
А почему промахнулся?
Подправил пример, но мой мозг взорвался. Кнопка правильно не работает.Теперь при нажатие моргает, и как отпустишь, не угадаешь, каим она будет цветом.

 

#include <UTFT.h>                //*********
#include <UTouch.h>              //* Подключаем библиотек

extern uint8_t Various_Symbols_32x32[]; 

UTFT  myGLCD(17, 38,39,40,41);   
UTouch      myTouch(6,5,4,3,2);  

int x, y;
boolean onoff;

void setup() {
  myGLCD.InitLCD(); //Инициализируем экран
  myGLCD.clrScr(); //Очищаем экран
  myTouch.InitTouch(); //Инициализируем тачскрин
  myTouch.setPrecision(PREC_MEDIUM);
  onoff = false; // кнопка выключена
  DrawHomeScreen(); //Инициализация программной кнопки
}

void DrawHomeScreen(){
    //кнопка вкл/выкл
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillRoundRect (252, 172, 312, 218);
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (252, 172, 312, 218);
    myGLCD.setBackColor(0, 255, 0);
    myGLCD.setFont(Various_Symbols_32x32);
    myGLCD.print("l", 268, 179);
}

void BtnOnOff(){
  
   if (myTouch.dataAvailable())
    {
      myTouch.read();
      x=myTouch.getX();
      y=myTouch.getY();
      
      if ((x >= 252) && (x <= 312) && (y>172) && (y<218))
      {
        if (onoff == false){
        myGLCD.setColor(255, 0, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(255, 0, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = true; 
        }
       else
       if (onoff == true){
        myGLCD.setColor(0, 255, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(0, 255, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = false;
       
       }
   }
 }
}
void loop() {
BtnOnOff();
}

Я так понял, надо править loop?

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

Давайте вернёмся к Вашему первому коду. Он почти хороший.

Вы можете мой первый пост прочесть наконец внимательно? Там написано

ЕвгенийП пишет:

Но строки 55-63 находятся в ветке else оператора if из строки 40. Т.е. они будут выполняться, когда нажатие было ВНЕ кнопки по x - попробуйте!

Внимательно читайте!

1. if в сороковой строке задаёт условие попадания по X

2. строки 55-63 находятся в ветке ELSE этого if. Значит эти строки будут выполняться ТОЛЬКО если Вы по X промахнулись!

Внимательно это прочитайте и осознайте. Вы просто запутались в условиях.

Получилось?

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

А еще учтите пожалуста, что МК(микроконтролер) и человек живут с разными скоростями . Там где МК сделает 100тыс операций для человека пойдет о,1 секунда.  Так что надо ловить момент когда не было "тапа вообще" и "тап" появился в нужном месте(нужной площадке). Вот только тогда надо переключать цвет.  "Нет тапа"-> "тап в нужном месте " == идет переключение

Stoun
Offline
Зарегистрирован: 28.06.2017

Условие подправил, только теперь моргает, как и раньше писал.

#include <UTFT.h>                //*********
#include <UTouch.h>              //* Подключаем библиотек

extern uint8_t Various_Symbols_32x32[]; 

UTFT  myGLCD(17, 38,39,40,41);   
UTouch      myTouch(6,5,4,3,2);  

int x, y;
boolean onoff;

void setup() {
  myGLCD.InitLCD(); //Инициализируем экран
  myGLCD.clrScr(); //Очищаем экран
  myTouch.InitTouch(); //Инициализируем тачскрин
  myTouch.setPrecision(PREC_MEDIUM);
  onoff = false; // кнопка выключена
  DrawHomeScreen(); //Инициализация программной кнопки
}

void DrawHomeScreen(){
    //кнопка вкл/выкл
    myGLCD.setColor(0, 255, 0);
    myGLCD.fillRoundRect (252, 172, 312, 218);
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (252, 172, 312, 218);
    myGLCD.setBackColor(0, 255, 0);
    myGLCD.setFont(Various_Symbols_32x32);
    myGLCD.print("l", 268, 179);
}

void BtnOnOff(){
  
   if (myTouch.dataAvailable())
    {
      myTouch.read();
      x=myTouch.getX();
      y=myTouch.getY();
      
      if ((x >= 252) && (x <= 312))
      {
        //if ((y>172) && (y<218)){
        if ((y>172) && (y<218) && (onoff == false)){
        myGLCD.setColor(255, 0, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(255, 0, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = true; 
        }
       else 
       {
       // if ((y>172) && (y<218)){
        if ((y>172) && (y<218) && (onoff == true)){
        myGLCD.setColor(0, 255, 0);
        myGLCD.fillRoundRect (252, 172, 312, 218);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (252, 172, 312, 218);
        myGLCD.setBackColor(0, 255, 0);
        myGLCD.setFont(Various_Symbols_32x32);
        myGLCD.print("l", 268, 179);
        onoff = false;
        }
      }
   }
 }
}

void loop() {
BtnOnOff();
}

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Я больше не могу на этот изврат смотреть!

#include <UTFT.h>                //*********
#include <UTouch.h>              //* Подключаем библиотек

extern uint8_t Various_Symbols_32x32[];

UTFT  myGLCD(17, 38, 39, 40, 41);
UTouch      myTouch(6, 5, 4, 3, 2);

int x, y;
boolean onoff;

void setup() {
  myGLCD.InitLCD(); //Инициализируем экран
  myGLCD.clrScr(); //Очищаем экран
  myTouch.InitTouch(); //Инициализируем тачскрин
  myTouch.setPrecision(PREC_MEDIUM);
  onoff = false; // кнопка выключена
  DrawHomeScreen(); //Инициализация программной кнопки
}

void DrawHomeScreen() {
  //кнопка вкл/выкл
  myGLCD.setColor(0, 255, 0);
  myGLCD.fillRoundRect (252, 172, 312, 218);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (252, 172, 312, 218);
  myGLCD.setBackColor(0, 255, 0);
  myGLCD.setFont(Various_Symbols_32x32);
  myGLCD.print("l", 268, 179);
}

void BtnOnOff() {

  if (myTouch.dataAvailable()) {
    myTouch.read();
    x = myTouch.getX();
    y = myTouch.getY();

    if ((x >= 252) && (x <= 312) && (y > 172) && (y < 218)) {
      if (onoff == false) {
        myGLCD.setColor(255, 0, 0);
        myGLCD.setBackColor(255, 0, 0);
      } else {
        myGLCD.setColor(0, 255, 0);
        myGLCD.setBackColor(0, 255, 0);
      }
      myGLCD.fillRoundRect (252, 172, 312, 218);
      myGLCD.setColor(255, 255, 255);
      myGLCD.drawRoundRect (252, 172, 312, 218);
      myGLCD.setFont(Various_Symbols_32x32);
      myGLCD.print("l", 268, 179);
      onoff = !onoff;
    }
  }
}

void loop() {
  BtnOnOff();
}

 

Stoun
Offline
Зарегистрирован: 28.06.2017

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

За Вас весь код дописать ?

Да нужен еще тригер отпускания пальца с тача, в простейшем варианте поставьте задержку после 52 строки.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
#include <UTFT.h>                //*********
#include <UTouch.h>              //* Подключаем библиотек

extern uint8_t Various_Symbols_32x32[];

UTFT  myGLCD(17, 38, 39, 40, 41);
UTouch      myTouch(6, 5, 4, 3, 2);

int x, y;
boolean onoff;

void setup() {
  myGLCD.InitLCD(); //Инициализируем экран
  myGLCD.clrScr(); //Очищаем экран
  myTouch.InitTouch(); //Инициализируем тачскрин
  myTouch.setPrecision(PREC_MEDIUM);
  onoff = false; // кнопка выключена
  DrawHomeScreen(); //Инициализация программной кнопки
}

void DrawHomeScreen() {
  //кнопка вкл/выкл
  myGLCD.setColor(0, 255, 0);
  myGLCD.fillRoundRect (252, 172, 312, 218);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (252, 172, 312, 218);
  myGLCD.setBackColor(0, 255, 0);
  myGLCD.setFont(Various_Symbols_32x32);
  myGLCD.print("l", 268, 179);
}

void BtnOnOff() {
  static bool btn = 0;
  if ( !btn && myTouch.dataAvailable()) {
    btn = 1;
    myTouch.read();
    x = myTouch.getX();
    y = myTouch.getY();
    if (x >= 252 && x <= 312 && y > 172 && y < 218) {
      if (onoff == false) {
        myGLCD.setColor(255, 0, 0);
        myGLCD.setBackColor(255, 0, 0);
      } else {
        myGLCD.setColor(0, 255, 0);
        myGLCD.setBackColor(0, 255, 0);
      }
      myGLCD.fillRoundRect (252, 172, 312, 218);
      myGLCD.setColor(255, 255, 255);
      myGLCD.drawRoundRect (252, 172, 312, 218);
      myGLCD.setFont(Various_Symbols_32x32);
      myGLCD.print("l", 268, 179);
      onoff = !onoff;
    }
  } else btn = 0;
}

void loop() {
  BtnOnOff();
}

Криво. Надо программу строить через ООП.

Stoun
Offline
Зарегистрирован: 28.06.2017

Спасибо боьшое! Писать не надо, дальше буду разбираться сам.
В ардуино новичек, предупреждал же. После С++, РНР, туговато идет, тем более если день мозги ломать (((

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

Stoun пишет:

После С++, РНР, туговато идет, тем более если день мозги ломать (((

После С++ @_@. Да вы наверно  жопой думали , когда программы писали. Ардуино ведь работает от Си через С++ вплодь до ООП. Вот только народ тупит по черному.

Stoun
Offline
Зарегистрирован: 28.06.2017

Для С++ есть среда разработки, есть объекты (в т.ч. Buttons), здесь все условно.

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

О чем вы? А это что?

/* Cl_Mech_BTN.ino
  (Светодиод+R=1кОм)    ардуина
  пин 1 <==> пин 13
  пин 2 <==> GND
  кнопка1    ардуина
  пин 1 <==> пин 2 программная подтяжка
  пин 2 <==> GND
    кнопка2    ардуина
  пин 1 <==> пин 3 программная подтяжка
  пин 2 <==> GND
    кнопка3    ардуина
  пин 1 <==> пин 4 программная подтяжка
  пин 2 <==> GND
    кнопка4    ардуина
  пин 1 <==> пин 5 программная подтяжка
  пин 2 <==> GND
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_LED------------------------------------------------------------
class Cl_LED {
    byte pin; // нога для подключения светодиода
    bool inv; // 0 светодиод горит при 1/ 1 светодиод горит при 0
    bool stat_ON = 0, led = 0;
    uint32_t time = 500, past = 0;
  public:
    //указатель на следующий компонент
    Cl_LED *pnt_LED;
    //конструктор
    Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // loop()
    void loop() {
      if (stat_ON && millis() - past >= time)OFF();
    }
    // включить светодиод
    void ON() {
      stat_ON = 0;
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // включить светодиод на время
    void ON( uint32_t _time) {
      time = _time;
      stat_ON = 1;
      past = millis();
      led = 1;
      digitalWrite(pin, led ^ inv) ; // зажечь светодиод
    }
    // выключить светодиод
    void OFF() {
      stat_ON = 0;
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
};
//----------------Cl_Mech_BTN------------------------------------------------------------
// класс на механич кнопку подкл к кнопке Ардуины.
class Cl_Mech_BTN {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN *pnt_Mech_BTN;
    //конструктор
    Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_LED * Start_LED = NULL;
    Cl_Mech_BTN * Start_Mech_BTN = NULL;
    void setup() {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->setup();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN) i->setup();
    }
    void loop () {
      for (Cl_LED *i = Start_LED; i != NULL; i = i->pnt_LED) i->loop ();
      for (Cl_Mech_BTN *i = Start_Mech_BTN; i != NULL; i = i->pnt_Mech_BTN)  i->loop ();
    }
};
//-----------------конструкторы классов вход в систему-------------------------------
Cl_LED::Cl_LED(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt_LED = Sys->Start_LED;
  Sys->Start_LED = this;
}
Cl_Mech_BTN::Cl_Mech_BTN(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt_Mech_BTN = Sys->Start_Mech_BTN;
  Sys->Start_Mech_BTN = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
Cl_LED *LED1 = new Cl_LED(Sys,/*пин*/13,/*инверсия*/0);// создать светодиод LED1
void Do_BTN1() {
  LED1->ON();
}
void Do_BTN2() {
  LED1->ON(1000);
}
void Do_BTN3() {
  LED1->ON(2000);
}
void Do_BTN4() {
  LED1->OFF();
}
Cl_Mech_BTN *BTN1 = new Cl_Mech_BTN(Sys,/*пин*/2,/*обработчик*/Do_BTN1);// создать кнопку BTN1
Cl_Mech_BTN *BTN2 = new Cl_Mech_BTN(Sys,/*пин*/3,/*обработчик*/Do_BTN2);// создать кнопку BTN2
Cl_Mech_BTN *BTN3 = new Cl_Mech_BTN(Sys,/*пин*/4,/*обработчик*/Do_BTN3);// создать кнопку BTN3
Cl_Mech_BTN *BTN4 = new Cl_Mech_BTN(Sys,/*пин*/5,/*обработчик*/Do_BTN4);// создать кнопку BTN4
//------------------ main()----------------------------------------------------------
void setup() {
  Sys->setup();
}

void loop() {
  Sys->loop();

}

Тоже самое можно организовать и с графическими кнопками.

Stoun
Offline
Зарегистрирован: 28.06.2017

Я же говорю, что здесь новичек)))
Ардуинку только вчера в руки взял, пока разобрался технически, а тут уже и в бой.
Надо успеть подарок сделать человеку.
Всем огромное спасибо! ЕвгенийП за терпенье и подсказку, xDriver за скетч и оптимизацию, Вам тоже за скетч и введение в програие на девайсе.