Вопрос по конструкторы класса ...

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Почитав форум ... получается, что в классе "принято" использовать только констуктор по-умолчанию, без параметров? Т.е. использование перегрузки конструкторов, так же как и методов в ардуино ИДЕ не приемлемо?

Я првавильно понимаю?

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

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

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

ulis пишет:

Почитав форум ... получается, что в классе "принято" использовать только констуктор по-умолчанию, без параметров? Т.е. использование перегрузки конструкторов, так же как и методов в ардуино ИДЕ не приемлемо?

Я првавильно понимаю?

неправильно понимаешь - в дуино ИДЕ есть С++ в котором есть всё, что положено иметь С++

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011
class myClass
{
  myClass();
  myClass(int parametr);
  myClass(int parametr1, float parametr2);  
};

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

Клапауций 112 пишет:

неправильно понимаешь - в дуино ИДЕ есть С++ в котором есть всё, что положено иметь С++

Т.е. если все "включено", можно не заморачиваться, а писать прям на чистом С++?

Надо же, действительно компилируется ...

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

ulis пишет:

Надо же, действительно компилируется ...

в следующий раз, прежде чем спросить - проверяй наличие проблемы, а не выдумывай её.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
class myClass
{
public:  // <--- это потерял
  myClass();
  myClass(int parametr);
  myClass(int parametr1, float parametr2);  
};

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

public:  // <--- это потерял

если скомпиллировалось, значит - не потерял

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Клапауций 112 пишет:

public:  // <--- это потерял

если скомпиллировалось, значит - не потерял

Да, точно, паблик забыл

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

Клапауций 112 пишет:

public:  // <--- это потерял

если скомпиллировалось, значит - не потерял

Так он же класс в скетче не создал. Напишет создать объект и ошибка вот она.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011
class myClass
{
  public:
  myClass();
  myClass(int parametr);
  myClass(int parametr1, float parametr2);
}
 
  myClass _Rest(1);

void setup() {
}

void loop() {
}

qwone пишет:

Клапауций 112 пишет:

public:  // <--- это потерял

если скомпиллировалось, значит - не потерял

Так он же класс в скетче не создал. Напишет создать объект и ошибка вот она.

Именно, ошибка вылазит .... получается низя?

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

qwone пишет:

Клапауций 112 пишет:

public:  // <--- это потерял

если скомпиллировалось, значит - не потерял

Так он же класс в скетче не создал. Напишет создать объект и ошибка вот она.

вот, когда напишет... а, пока всё работает.

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

ulis пишет:

Почитав форум ... получается, что в классе "принято" использовать только констуктор по-умолчанию, без параметров? Т.е. использование перегрузки конструкторов, так же как и методов в ардуино ИДЕ не приемлемо?

Я првавильно понимаю?

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

DHT _mrDHT(pinDHT, DHT22);
OneWire oneWire(one_wire_bus);
DallasTemperature sensors(&oneWire);

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

Это вопрос был чисто поиздеваться над нами?

Я правильно понимаю?

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

ulis пишет:
можно не заморачиваться, а писать прям на чистом С++?

Блин, а Вы НА КАКОМ пишете? На грязном? Так помойте его!

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

ulis пишет:

 .... получается низя?

да - я запретил

class myClass
{
  public:
  myClass() {}
  myClass(int parametr) {}
  myClass(int parametr1, float parametr2) {}
};

myClass test1;
myClass test2(5);
myClass test3(5, 10);

void setup() {}
void loop() {}

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Клапауций 112 пишет:

ulis пишет:

 .... получается низя?

да - я запретил

class myClass
{
  public:
  myClass() {}
  myClass(int parametr) {}
  myClass(int parametr1, float parametr2) {}
};

myClass test1;
myClass test2(5);
myClass test3(5, 10);

void setup() {}
void loop() {}

 

Все понятно, спасибо

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

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

 

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

DHT _mrDHT(pinDHT, DHT22);
OneWire oneWire(one_wire_bus);
DallasTemperature sensors(&oneWire);

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

Это вопрос был чисто поиздеваться над нами?

Я правильно понимаю?

А вы что, не используете сторонние библиотеки в своем коде?

И не надо нервничать, вы не правильно понимаете

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

ulis пишет:

И не надо нервничать, вы не правильно понимаете

прекращай тупить!

DHT _mrDHT(pinDHT, DHT22);
OneWire oneWire(one_wire_bus);
DallasTemperature sensors(&oneWire);
myClass test1;
myClass test2(5);
myClass test3(5, 10);

 

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

ulis пишет:

А вы что, не используете сторонние библиотеки в своем коде?

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

Вот я и подумал, что издеваетесь (и продолжаю так думать).

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

А это для того, кому интересно.

/*Cl_Blink.ino
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Blink-----------------
class Cl_Blink {
    byte pin;
    bool led;
    uint32_t time;
    uint32_t past = 0;
  public:
    // указатель на следующий элемент
    Cl_Blink *pnt;
    // конструктора
    Cl_Blink() {}
    Cl_Blink(Cl_Sys *Sys, byte _pin, uint32_t _time = 1000);
    void setup() {
      pinMode     (pin, OUTPUT);
      digitalWrite(pin, led = 0);
    }
    // setup()
    void loop() {
      if (millis() - past >= time) {
        past = millis();
        digitalWrite(pin, led = !led);
      }
    }
};
//-----Cl_Sys-----------------
class Cl_Sys {
  public:
    Cl_Blink *Startl_Blink = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_Blink *i = Startl_Blink; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_Blink *i = Startl_Blink; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_Blink::Cl_Blink(Cl_Sys *Sys, byte _pin, uint32_t _time = 1000): pin(_pin), time(_time) {
  pnt = Sys->Startl_Blink;
  Sys->Startl_Blink = this;
}
//----------Компоновка---------------------
Cl_Blink *Blink_1 = new Cl_Blink(&Sys,/*пин*/2,/*полупериод*/500) ; // создать мигалку Blink_1
Cl_Blink *Blink_2 = new Cl_Blink(&Sys,/*пин*/3,/*полупериод*/1000); // создать мигалку Blink_2
Cl_Blink *Blink_3 = new Cl_Blink(&Sys,/*пин*/4,/*полупериод*/2000); // создать мигалку Blink_3
Cl_Blink *Blink_4 = new Cl_Blink(&Sys,/*пин*/5,/*полупериод*/4000); // создать мигалку Blink_4
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

qwone пишет:

А это для того, кому интересно.

/*Cl_Blink.ino
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Blink-----------------
class Cl_Blink {
    byte pin;
    bool led;
    uint32_t time;
    uint32_t past = 0;
  public:
    // указатель на следующий элемент
    Cl_Blink *pnt;
    // конструктора
    Cl_Blink() {}
    Cl_Blink(Cl_Sys *Sys, byte _pin, uint32_t _time = 1000);
    void setup() {
      pinMode     (pin, OUTPUT);
      digitalWrite(pin, led = 0);
    }
    // setup()
    void loop() {
      if (millis() - past >= time) {
        past = millis();
        digitalWrite(pin, led = !led);
      }
    }
};
//-----Cl_Sys-----------------
class Cl_Sys {
  public:
    Cl_Blink *Startl_Blink = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_Blink *i = Startl_Blink; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_Blink *i = Startl_Blink; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_Blink::Cl_Blink(Cl_Sys *Sys, byte _pin, uint32_t _time = 1000): pin(_pin), time(_time) {
  pnt = Sys->Startl_Blink;
  Sys->Startl_Blink = this;
}
//----------Компоновка---------------------
Cl_Blink *Blink_1 = new Cl_Blink(&Sys,/*пин*/2,/*полупериод*/500) ; // создать мигалку Blink_1
Cl_Blink *Blink_2 = new Cl_Blink(&Sys,/*пин*/3,/*полупериод*/1000); // создать мигалку Blink_2
Cl_Blink *Blink_3 = new Cl_Blink(&Sys,/*пин*/4,/*полупериод*/2000); // создать мигалку Blink_3
Cl_Blink *Blink_4 = new Cl_Blink(&Sys,/*пин*/5,/*полупериод*/4000); // создать мигалку Blink_4
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

Я надеюсь, что мои следующие вопросы не будут восприняты как издевательство, настроение нормальное? :)

3-я строка - это что?

в 5-й и 29 - объявление одного и тогоже класса?

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

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

ulis пишет:

А вы что, не используете сторонние библиотеки в своем коде?

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

Вот я и подумал, что издеваетесь (и продолжаю так думать).

Вы единственный, кто принял мой вопрос как издевательство (нельзя так близко все принимать к сердцу :), хотя применили местоимение ОНИ ...

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

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

ulis пишет:

3-я строка - это что?

в 5-й и 29 - объявление одного и тогоже класса?

Видишь ли. Оба класса ссылаются друг на друга. Но в Си надо описать функцию , а потом применить. Скорее это в правильном Си с правильными компилятором.  Но иногда надо обходить это препятствие. Сначало объявляют, что есть такая функция, потом применяют, а затем ниже описывают, что она делает.  Так что строка 3 это объявление что есть такой класс Cl_Sys, а вот структура его будет ниже, как и описание методов в нем. строка 5 и 29 это разные классы Cl_Blink и Cl_Sys А вот строка 42 конструктор класса Cl_Blink. Его пришлось вынести ниже описания класса Cl_Sys , так как в конструкторе используется знание, как устроен Cl_Sys Вот такие пироги с котятами. На что только не пойдешь ,что бы сделать вменяемый графический интерфейс и упростить разработку сложных систем. И да : объект класса Cl_Sys является владельцем(родителем) 4-х объектов класса Cl_Blink

ulis пишет:
Ну да ладно, вопрос мой возник по причине уверенности, что язык программирования ардуино это лишь подмножество полноценного си++.
 Это так засирают новичкам мозги, что даже знающие язык Си, считают что на Ардуине надо программировать убого.  Я два года назад когда начал программировать на Ардуне не мог понять, почему так. А оказалось - маркетинг, или проще бабки.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

qwone пишет:

Видишь ли. Оба класса ссылаются друг на друга. Но в Си надо описать функцию , а потом применить. Скорее это в правильном Си с правильными компилятором.  Но иногда надо обходить это препятствие. Сначало объявляют, что есть такая функция, потом применяют, а затем ниже описывают, что она делает.  Так что строка 3 это объявление что есть такой класс Cl_Sys, а вот структура его будет ниже, как и описание методов в нем. строка 5 и 29 это разные классы Cl_Blink и Cl_Sys А вот строка 42 конструктор класса Cl_Blink. Его пришлось вынести ниже описания класса Cl_Sys , так как в конструкторе используется знание, как устроен Cl_Sys Вот такие пироги с котятами. На что только не пойдешь ,что бы сделать вменяемый графический интерфейс и упростить разработку сложных систем. И да : объект класса Cl_Sys является владельцем(родителем) 4-х объектов класса Cl_Blink

Хорошо ... (что на ты) :) Запустил для пробы код на нано - работает ... счас нет времени разбираться, иначе жена отлучит от обеда или вообще прибьет ... вечером отпишусь

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

Вот еще пример такой сборки 

/*Cl_Led.ino
*/
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;
    // конструктора
    Cl_Led(Cl_Sys *Sys, byte _pin, bool _inv);
    void setup() {
      pinMode(pin, OUTPUT);// подключить светодиод
      led = 0;
      digitalWrite(pin, led ^ inv) ; // погасить светодиод
    }
    // setup()
    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_Btn-----------------
class Cl_Btn {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_Btn *pnt = NULL;
    // конструктора
    Cl_Btn() {}
    Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // setup()
    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 *Startl_Led = NULL;
    Cl_Btn *Start_Btn = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_Led *i = Startl_Led; i != NULL; i = i->pnt) i->setup();
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->loop();
      for (Cl_Led *i = Startl_Led; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_Led::Cl_Led(Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv) {
  pnt = Sys->Startl_Led;
  Sys->Startl_Led = this;
}
Cl_Btn::Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt = Sys->Start_Btn;
  Sys->Start_Btn = this;
}
//----------Компоновка---------------------
Cl_Led *Led1 = new Cl_Led(&Sys,/*пин*/13,/*инверсия*/0); // создать Led_1
void Do_Btn1() {
  Led1->ON();
}
void Do_Btn2() {
  Led1->OFF();
}
void Do_Btn3() {
  Led1->ON();
}
void Do_Btn4() {
  Led1->OFF();
}
Cl_Btn *Btn_1 = new Cl_Btn(&Sys,/*пин*/2,/*обработчик*/Do_Btn1); // создать кнопку Btn_1
Cl_Btn *Btn_2 = new Cl_Btn(&Sys,/*пин*/3,/*обработчик*/Do_Btn2); // создать кнопку Btn_2
Cl_Btn *Btn_3 = new Cl_Btn(&Sys,/*пин*/4,/*обработчик*/Do_Btn3); // создать кнопку Btn_3
Cl_Btn *Btn_4 = new Cl_Btn(&Sys,/*пин*/5,/*обработчик*/Do_Btn4); // создать кнопку Btn_4
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

или такой 

/*Cl_Label.ino
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x3F
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Label-----------------
class Cl_Label {
  public:
    byte x, y   ; // положение надписи
    char * txt = NULL ; // указатель на надпись
    // указатель на следующий элемент
    Cl_Label *pnt;
    // конструктор
    Cl_Label(Cl_Sys *Sys, char *_txt , byte _x , byte _y );
    void setup() {
    }
    // setup()
    void loop() {
    }
    // сделать надпись
    void Caption(char *_txt, byte _x = 0, byte _y = 0) {
      txt = _txt; x = _x; y = _y;
    }
};
//-----Cl_Btn-----------------
class Cl_Btn {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_Btn *pnt = NULL;
    // конструктор
    Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // setup()
    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 {
    uint32_t past = 0;
  public:
    Cl_Label *Startl_Label = NULL;
    Cl_Btn *Start_Btn = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      lcd.init();
      lcd.backlight();
      for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) i->setup();
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->loop();
      // вывод обновленой информации раз в 0.5 сек
      if (millis() - past >= 500) {
        past = millis();
        for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) {
          lcd.setCursor(i->x, i-> y);
          lcd.print(i->txt);
        }
      }
    }
} Sys;
//---------описание классов------------
Cl_Label::Cl_Label(Cl_Sys *Sys, char *_txt , byte _x = 0 , byte _y = 0):  x(_x), y(_y) {
  txt = _txt,
  pnt = Sys->Startl_Label;
  Sys->Startl_Label = this;
}
Cl_Btn::Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt = Sys->Start_Btn;
  Sys->Start_Btn = this;
}
//----------Компоновка---------------------
Cl_Label *Label = new Cl_Label(&Sys,/*текст*/"Label",/*поз х*/0,/*поз y*/0); // создать объект Лабел
void Do_Btn1() {
  Label->Caption("Btn 1");
}
void Do_Btn2() {
  Label->Caption("Btn 2");
}
void Do_Btn3() {
  Label->Caption("Btn 3");
}
void Do_Btn4() {
  Label->Caption("Btn 4");
}
Cl_Btn *Btn_1 = new Cl_Btn(&Sys,/*пин*/2,/*обработчик*/Do_Btn1); // создать кнопку Btn_1
Cl_Btn *Btn_2 = new Cl_Btn(&Sys,/*пин*/3,/*обработчик*/Do_Btn2); // создать кнопку Btn_2
Cl_Btn *Btn_3 = new Cl_Btn(&Sys,/*пин*/4,/*обработчик*/Do_Btn3); // создать кнопку Btn_3
Cl_Btn *Btn_4 = new Cl_Btn(&Sys,/*пин*/5,/*обработчик*/Do_Btn4); // создать кнопку Btn_4
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

И наконец такой :)

/*Cl_LcdBtn_in_Nokia5110.ino
 *  синий экран
  Serial clock out   5(SCLK) -->3
  Serial data out     4(DIN) -->4
  Data/Command select 3(D/C) -->5
  LCD chip select      2(CS) -->6
  LCD reset           1(RST) -->7
                      6(Vcc) -->3.3V
                       7(BL) -->3.3V
                      8(GND) -->GND
  кнопка 1           (Btn_1) -->8
  кнопка 2           (Btn_2) -->9
  кнопка 3           (Btn_3) -->10
*/
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>


Adafruit_PCD8544 display = Adafruit_PCD8544(/*SCLK*/3,/*DIN*/4,/*D/C*/5,/*CS*/6,/*RST*/7);

class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Label-----------------
class Cl_Label {
  public:
    byte x, y   ; // положение надписи
    char * txt = NULL ; // указатель на надпись
    // указатель на следующий элемент
    Cl_Label *pnt;
    // конструктор
    Cl_Label(Cl_Sys *Sys, char *_txt , byte _x , byte _y );
    void setup() {
    }
    // setup()
    void loop() {
    }
    // сделать надпись
    void Caption(char *_txt) {
      txt = _txt;
    }
};
//-----Cl_LcdBtn-----------------
class Cl_LcdBtn {
    byte pin; // номер ноги на кнопке
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    void (* Do1)(), (* Do2)(); // указатель на обработчики нажатия,отжатия
    byte x, y   ; // положение надписи
    char * txt = NULL ; // указатель на надпись
    // указатель на следующий элемент
    Cl_LcdBtn *pnt = NULL;
    // конструктор
    Cl_LcdBtn(Cl_Sys *Sys, byte _pin, void (* _Do1)(), void (* _Do2)(), char *_txt , byte _x , byte _y );
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // setup()
    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) Do1(); // если произошло нажатие
        if (!btn_old && btn) Do2(); // если произошло отжатие
      }
    }
    // сделать надпись
    void Caption(char *_txt) {
      txt = _txt;
    }
};
//-----Cl_Sys-----------------
class Cl_Sys {
    uint32_t past = 0;
  public:
    Cl_Label *Startl_Label = NULL;
    Cl_LcdBtn *Start_Btn = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      display.begin();              // Инициализация дисплея
      display.setContrast(60);      // Устанавливаем контраст
      display.setTextColor(BLACK);  // Устанавливаем цвет текста
      display.setTextSize(1);       // Устанавливаем размер текста
      display.clearDisplay();       // Очищаем дисплей
      display.display();
      for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) i->setup();
      for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) i->loop();
      // вывод обновленой информации раз в 0.5 сек
      if (millis() - past >= 500) {
        past = millis();
        display.clearDisplay();       // Очищаем дисплей
        for (Cl_LcdBtn *i = Start_Btn; i != NULL; i = i->pnt) {
          display.setCursor(i->x, i-> y);
          display.print(i->txt);
        }
        for (Cl_Label *i = Startl_Label; i != NULL; i = i->pnt) {
          display.setCursor(i->x, i-> y);
          display.print(i->txt);
        }
        display.display();
      }
    }
} Sys;
//---------описание классов------------
Cl_Label::Cl_Label(Cl_Sys *Sys, char *_txt , byte _x = 0 , byte _y = 0):  x(_x), y(_y) {
  txt = _txt,
  pnt = Sys->Startl_Label;
  Sys->Startl_Label = this;
}
Cl_LcdBtn::Cl_LcdBtn(Cl_Sys *Sys, byte _pin, void (* _Do1)(), void (* _Do2)(), char *_txt , byte _x = 0 , byte _y = 0)
  : pin(_pin), Do1(_Do1), Do2(_Do2),  txt(_txt), x(_x), y(_y) {
  pnt = Sys->Start_Btn;
  Sys->Start_Btn = this;
}
//----------Компоновка---------------------
Cl_Label *Label = new Cl_Label(&Sys,/*текст*/"Label",/*поз х*/0,/*поз y*/0); // создать объект Лабел
void Do1_Btn1();// объявим что есть такие обработчики
void Do2_Btn1();
void Do1_Btn2();
void Do2_Btn2();
void Do1_Btn3();
void Do2_Btn3();
Cl_LcdBtn *Btn_1 = new Cl_LcdBtn(&Sys,/*пин*/8 ,/*обработчик*/Do1_Btn1,/*обработчик*/Do2_Btn1,/*текст*/"1of",/*поз х*/0*8  ,/*поз y*/5*8); // создать кнопку Btn_1
Cl_LcdBtn *Btn_2 = new Cl_LcdBtn(&Sys,/*пин*/9 ,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*текст*/"2of",/*поз х*/4*8  ,/*поз y*/5*8); // создать кнопку Btn_2
Cl_LcdBtn *Btn_3 = new Cl_LcdBtn(&Sys,/*пин*/10,/*обработчик*/Do1_Btn3,/*обработчик*/Do2_Btn3,/*текст*/"3of",/*поз х*/8*8 ,/*поз y*/5*8); // создать кнопку Btn_3
void Do1_Btn1() {
  Label->Caption("Btn 1");
  Btn_1->Caption("1on");
}
void Do2_Btn1() {
  Btn_1->Caption("1of");
}
void Do1_Btn2() {
  Label->Caption("Btn 2");
  Btn_2->Caption("2on");
}
void Do2_Btn2() {
  Btn_2->Caption("2of");
}
void Do1_Btn3() {
  Label->Caption("Btn 3");
  Btn_3->Caption("3on");
}
void Do2_Btn3() {
  Btn_3->Caption("3of");
}
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Пока только выяснил, для чего используется предварительное описание класса. Как пишут умные книги, в больших проектах для ускорения компиляции, если изменения коснулись небольшой части. Но разве в ардуино бывают такие проекты, что компиляция идет часами, или это просто сила привычки?

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

ulis пишет:

Пока только выяснил, для чего используется предварительное описание класса. Как пишут умные книги, в больших проектах для ускорения компиляции, если изменения коснулись небольшой части. Но разве в ардуино бывают такие проекты, что компиляция идет часами, или это просто сила привычки?

 Это как в анекдоте: " Британские ученые провели исследования и выяснили, что британские ученые это те, которые находятся в Британии". 

   А по теме: какое нафиг ускорение. Тут иначе банально не скомпилировалось.

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

qwone пишет:

ulis пишет:

Пока только выяснил, для чего используется предварительное описание класса. Как пишут умные книги, в больших проектах для ускорения компиляции, если изменения коснулись небольшой части. Но разве в ардуино бывают такие проекты, что компиляция идет часами, или это просто сила привычки?

 Это как в анекдоте: " Британские ученые провели исследования и выяснили, что британские ученые это те, которые находятся в Британии". 

   А по теме: какое нафиг ускорение. Тут иначе банально не скомпилировалось.

Так я о том же и говорю ...

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Тема закрыта, расходимся по домам

Ev_geniy
Offline
Зарегистрирован: 24.05.2017

Стоять! Куда расходимся? Еще вопросы есть!

To: qwone

Основной: я правильно понимаю, что это вы для микроконтроллеров программируете? Для тех самых у которых памяти фиг целых цать десятых?

Для ATtiny13 тоже так писать будете? Очень интересно было бы посмотреть код для этой микросхемы в вашем стиле для опроса DS1820 и зависимый от него шим с регулировкой диапазона кнопкой/ми.

Logik
Offline
Зарегистрирован: 05.08.2014

Ну чего стоять то? ulis был послан  (и по делу ибо зашел с дибильыім вопросом) , огрызнулся но пошел, попращался со всеми, расходимся. Чего Вы шумите про самых маленьких. Писать можна по разному (вот я Вам новость выдал, да? )) И размер и производительность разные получим. Чего тут обсуждать. Или вы думаете ктото бросится реализовывать 1ware в заданом стиле, далеко не лучшем кстати.

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

Стиль как стиль. У меня другого нету. Этот стиль позволяет производить сборку из проверенных кусков такого же стиля. Разумеется куски программ написаных в разных стилях не соберутся. И да под этот стиль у меня нет большой библиотеки проверенных кусков. Их мне предстоит написать. Не хватит памяти, перейду на чипы по мощнее. Если надо загонять в процессоры с меньшей памятью, то придется резать и оптимизировать код этого стиля. Только и всего. А так я хочу организовать графический интерфейс с аналоговым джойстиком вместо мыши. Ну и попутно понять, как это может быть устроено на базе Ардуино, в частности UNO(nano).

ПС : #23 программы рабочие, я проверил. Пока памяти хватает и тормозов не заметил.

Модуль аналоговый джойстик

/*Cl_aJoystick.ino
  Джойстик (GND) --> GND
         (+5V) --> +5V
         (VRx) --> A0
         (VRy) --> A1
          (SW) --> A2
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_aJoystick-----------------
const int delta = 5; // колебание значения на аналоговых выходах, которые можно игнорировать
class Cl_aJoystick {
    byte VRx_pin ; // номер ноги на выводе VRx
    byte VRy_pin ; // номер ноги на выводе VRy
    byte SW_pin  ; // номер ноги на выводе SW
    void (* Do_x )(); //указатель на обработчик кнопки VRx
    void (* Do_y )(); //указатель на обработчик кнопки VRy
    void (* Do_SW)(); //указатель на обработчик кнопки SW
    int VRx_old; // старые значение на канале X
    int VRy_old; // старые значение на канале Y
    bool SW, SW_old;
    bool   bounce_VRx = 0, bounce_VRy = 0, bounce_SW = 0; // антидребезговый флаг
    uint32_t past_VRx = 0, past_VRy = 0  , past_SW = 0   ;
  public:
    // указатель на следующий элемент
    Cl_aJoystick *pnt;
    // конструктора
    Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_x)(), void (* _Do_y)(), void (* _Do_SW)());
    void setup() {
      pinMode(VRx_pin, INPUT)       ;// подключить вывод VRx
      pinMode(VRy_pin, INPUT)       ;// подключить вывод VRy
      pinMode(SW_pin , INPUT_PULLUP);// подключить вывод SW с подтяжкой
      VRx = analogRead (VRx_pin);
      VRy = analogRead (VRy_pin);
      SW = digitalRead(SW_pin) ;
    }
    // setup()
    void loop() {
      // проверяем аналог канал х
      int analog = analogRead (VRx_pin);
      if (! bounce_VRx && (VRx < analog - delta || VRx > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRx = 1;                    // выставить флаг
        past_VRx = millis();               // сделать временую засветку
      } else if ( bounce_VRx && millis() - past_VRx >= 5 ) { // если прошло антидребезговое время
        bounce_VRx = 0;      // то снять флаг
        VRx_old = VRx ;
        VRx = analog ; // прочитать реальное значение на выводе
        Do_x();
      }
      // проверяем аналог канал y
      analog = analogRead (VRy_pin);
      if (! bounce_VRy && (VRy < analog - delta || VRy > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRy = 1;                    // выставить флаг
        past_VRy = millis();               // сделать временую засветку
      } else if ( bounce_VRy && millis() - past_VRy >= 5 ) { // если прошло антидребезговое время
        bounce_VRy = 0;      // то снять флаг
        VRy_old = VRy ;
        VRy = analog ; // прочитать реальное значение на выводе
        Do_y();
      }
      // проверяем кнопку SW
      if (! bounce_SW && SW != digitalRead(SW_pin)) { // если прошел фронт изм на выводн
        bounce_SW = 1;                    // выставить флаг
        past_SW = millis();               // сделать временую засветку
      } else if ( bounce_SW && millis() - past_SW >= 5 ) { // если прошло антидребезговое время
        bounce_SW = 0;      // то снять флаг
        SW_old = SW ;
        SW = digitalRead(SW_pin) ; // прочитать реальное значение на выводе
        if (! SW_old && SW)  Do_SW();
      }
    }
    int VRx ; // значение на канале X
    int VRy ; // значение на канале Y
};
//-----Cl_Sys-----------------
class Cl_Sys {
  public:
    Cl_aJoystick *Startl_aJoystick = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_aJoystick *i = Startl_aJoystick; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_aJoystick *i = Startl_aJoystick; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_aJoystick::Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_x)(), void (* _Do_y)(), void (* _Do_SW)())
  :                              VRx_pin(_1pin), VRy_pin(_2pin), SW_pin(_3pin), Do_x(_Do_x), Do_y(_Do_y), Do_SW(_Do_SW) {
  pnt = Sys->Startl_aJoystick;
  Sys->Startl_aJoystick = this;
}
//----------Компоновка---------------------
void Do_x();// объявление
void Do_y();
void Do_SW();
Cl_aJoystick * aJoystick = new Cl_aJoystick(&Sys,/*VRx*/A0,/*VRy*/A1,/*SW*/A2,/*обработчик движ X*/Do_x,/*обработчик движ Y*/Do_y,/*обработчик наж SW*/Do_SW); // создать aJoystick_1
void Do_x() { // описание
  Serial.println();
  Serial.print("X=");
  Serial.print(aJoystick->VRx);
}
void Do_y() {
  Serial.println();
  Serial.print("Y=");
  Serial.print(aJoystick->VRy);
}
void Do_SW() {
  Serial.println();
  Serial.print("Press SW");
}
//-----------Main()-----------------------
void setup() {
  Serial.begin(9600);
  Sys.setup();
}

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

А вот этот же джойстик но совместно с экраном Нокия 5110 (можно игрушку замутить)

/*Cl_aJoystick_v2.ino
      синий экран
  Serial clock out   5(SCLK) -->3
  Serial data out     4(DIN) -->4
  Data/Command select 3(D/C) -->5
  LCD chip select      2(CS) -->6
  LCD reset           1(RST) -->7
                      6(Vcc) -->3.3V
                       7(BL) -->3.3V
                      8(GND) -->GND
  Джойстик (GND) --> GND
           (+5V) --> +5V
           (VRx) --> A0
           (VRy) --> A1
            (SW) --> A2
*/
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(/*SCLK*/3,/*DIN*/4,/*D/C*/5,/*CS*/6,/*RST*/7);
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_aJoystick-----------------
const int delta = 5; // колебание значения на аналоговых выходах, которые можно игнорировать
class Cl_aJoystick {
    byte VRx_pin ; // номер ноги на выводе VRx
    byte VRy_pin ; // номер ноги на выводе VRy
    byte SW_pin  ; // номер ноги на выводе SW
    void (* Do_SW)(); //указатель на обработчик кнопки SW
    int VRx_old; // старые значение на канале X
    int VRy_old; // старые значение на канале Y
    bool SW, SW_old;
    bool   bounce_VRx = 0, bounce_VRy = 0, bounce_SW = 0; // антидребезговый флаг
    uint32_t past_VRx = 0, past_VRy = 0  , past_SW = 0   ;
  public:
    byte x, y   ; // положение надписи
    char * txt = NULL ; // указатель на надпись
    // указатель на следующий элемент
    Cl_aJoystick *pnt;
    // конструктора
    Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)());
    void setup() {
      pinMode(VRx_pin, INPUT)       ;// подключить вывод VRx
      pinMode(VRy_pin, INPUT)       ;// подключить вывод VRy
      pinMode(SW_pin , INPUT_PULLUP);// подключить вывод SW с подтяжкой
      VRx = analogRead (VRx_pin);
      VRy = analogRead (VRy_pin);
      SW = digitalRead(SW_pin) ;
    }
    // setup()
    void loop() {
      // проверяем аналог канал х
      int analog = analogRead (VRx_pin);
      if (! bounce_VRx && (VRx < analog - delta || VRx > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRx = 1;                    // выставить флаг
        past_VRx = millis();               // сделать временую засветку
      } else if ( bounce_VRx && millis() - past_VRx >= 5 ) { // если прошло антидребезговое время
        bounce_VRx = 0;      // то снять флаг
        VRx_old = VRx ;
        VRx = analog ; // прочитать реальное значение на выводе
        x = map( VRx, 0, 1023, 0, 83);

      }
      // проверяем аналог канал y
      analog = analogRead (VRy_pin);
      if (! bounce_VRy && (VRy < analog - delta || VRy > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRy = 1;                    // выставить флаг
        past_VRy = millis();               // сделать временую засветку
      } else if ( bounce_VRy && millis() - past_VRy >= 5 ) { // если прошло антидребезговое время
        bounce_VRy = 0;      // то снять флаг
        VRy_old = VRy ;
        VRy = analog ; // прочитать реальное значение на выводе
        y = map( VRy, 0, 1023, 0, 47);
      }
      // проверяем кнопку SW
      if (! bounce_SW && SW != digitalRead(SW_pin)) { // если прошел фронт изм на выводн
        bounce_SW = 1;                    // выставить флаг
        past_SW = millis();               // сделать временую засветку
      } else if ( bounce_SW && millis() - past_SW >= 5 ) { // если прошло антидребезговое время
        bounce_SW = 0;      // то снять флаг
        SW_old = SW ;
        SW = digitalRead(SW_pin) ; // прочитать реальное значение на выводе
        if (! SW_old && SW)  Do_SW();
      }
    }
    int VRx ; // значение на канале X
    int VRy ; // значение на канале Y
};
//-----Cl_Sys-----------------
class Cl_Sys {
    uint32_t past = 0;
  public:
    Cl_aJoystick *Start_aJoystick = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      display.begin();              // Инициализация дисплея
      display.setContrast(60);      // Устанавливаем контраст
      display.setTextColor(BLACK);  // Устанавливаем цвет текста
      display.setTextSize(1);       // Устанавливаем размер текста
      display.clearDisplay();       // Очищаем дисплей
      display.display();
      for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->setup();
    }
    // loop()
    void loop() {
      for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->loop();
      // вывод обновленой информации раз в 0.5 сек
      if (millis() - past >= 100) {
        past = millis();
        display.clearDisplay();       // Очищаем дисплей
        for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) {
          display.setCursor(i->x, i-> y);
          display.print(i->txt);
          display.display();
        }
      }
    }
    void onClick() {}
} Sys;
//---------описание классов------------
Cl_aJoystick::Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)())
  :                              VRx_pin(_1pin), VRy_pin(_2pin), SW_pin(_3pin), Do_SW(_Do_SW) {
  x = 0; y = 0; txt = "^";
  pnt = Sys->Start_aJoystick;
  Sys->Start_aJoystick = this;
}
//----------Компоновка---------------------
void Do_SW() {
  Sys.onClick();
}
Cl_aJoystick * aJoystick = new Cl_aJoystick(&Sys,/*VRx*/A0,/*VRy*/A1,/*SW*/A2,/*обработчик наж SW*/Do_SW); // создать aJoystick_1

//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

 

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

Ну я наверное всех задолбал. Выкладываю недо графический интерфейс на Дисплее Нокия и аналоговом джойстике вместо мышки. В верху метка, а внизу 3 графические кнопки . Клик на них вызывает изменение надписи на метке.

/*Cl_aJoystick_v3.ino
      синий экран
  Serial clock out   5(SCLK) -->3
  Serial data out     4(DIN) -->4
  Data/Command select 3(D/C) -->5
  LCD chip select      2(CS) -->6
  LCD reset           1(RST) -->7
                      6(Vcc) -->3.3V
                       7(BL) -->3.3V
                      8(GND) -->GND
  Джойстик (GND) --> GND
           (+5V) --> +5V
           (VRx) --> A0
           (VRy) --> A1
            (SW) --> A2
*/
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(/*SCLK*/3,/*DIN*/4,/*D/C*/5,/*CS*/6,/*RST*/7);
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_aJoystick-------------------------------------------------------
const int delta = 5; // колебание значения на аналоговых выходах, которые можно игнорировать
class Cl_aJoystick {
    byte VRx_pin ; // номер ноги на выводе VRx
    byte VRy_pin ; // номер ноги на выводе VRy
    byte SW_pin  ; // номер ноги на выводе SW
    void (* Do_SW)(byte, byte); //указатель на обработчик кнопки SW
    int VRx_old; // старые значение на канале X
    int VRy_old; // старые значение на канале Y
    bool SW, SW_old;
    bool   bounce_VRx = 0, bounce_VRy = 0, bounce_SW = 0; // антидребезговый флаг
    uint32_t past_VRx = 0, past_VRy = 0  , past_SW = 0   ;
  public:
    byte x, y   ; // положение надписи
    char * txt = NULL ; // указатель на надпись
    // указатель на следующий элемент
    Cl_aJoystick *pnt;
    // конструктора
    Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)(byte, byte));
    void setup() {
      pinMode(VRx_pin, INPUT)       ;// подключить вывод VRx
      pinMode(VRy_pin, INPUT)       ;// подключить вывод VRy
      pinMode(SW_pin , INPUT_PULLUP);// подключить вывод SW с подтяжкой
      VRx = analogRead (VRx_pin);
      x = map( VRx, 0, 1023, 0, 83);
      VRy = analogRead (VRy_pin);
      y = map( VRy, 0, 1023, 0, 47);
      SW = digitalRead(SW_pin) ;
    }
    // setup()
    void loop() {
      // проверяем аналог канал х
      int analog = analogRead (VRx_pin);
      if (! bounce_VRx && (VRx < analog - delta || VRx > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRx = 1;                    // выставить флаг
        past_VRx = millis();               // сделать временую засветку
      } else if ( bounce_VRx && millis() - past_VRx >= 5 ) { // если прошло антидребезговое время
        bounce_VRx = 0;      // то снять флаг
        VRx_old = VRx ;
        VRx = analog ; // прочитать реальное значение на выводе
        x = map( VRx, 0, 1023, 0, 83);

      }
      // проверяем аналог канал y
      analog = analogRead (VRy_pin);
      if (! bounce_VRy && (VRy < analog - delta || VRy > analog + delta)) { // если прошел фронт изм на выводн
        bounce_VRy = 1;                    // выставить флаг
        past_VRy = millis();               // сделать временую засветку
      } else if ( bounce_VRy && millis() - past_VRy >= 5 ) { // если прошло антидребезговое время
        bounce_VRy = 0;      // то снять флаг
        VRy_old = VRy ;
        VRy = analog ; // прочитать реальное значение на выводе
        y = map( VRy, 0, 1023, 0, 47);
      }
      // проверяем кнопку SW
      if (! bounce_SW && SW != digitalRead(SW_pin)) { // если прошел фронт изм на выводн
        bounce_SW = 1;                    // выставить флаг
        past_SW = millis();               // сделать временую засветку
      } else if ( bounce_SW && millis() - past_SW >= 5 ) { // если прошло антидребезговое время
        bounce_SW = 0;      // то снять флаг
        SW_old = SW ;
        SW = digitalRead(SW_pin) ; // прочитать реальное значение на выводе
        if (! SW_old && SW)  Do_SW(x, y);
      }
    }
    int VRx ; // значение на канале X
    int VRy ; // значение на канале Y
};
//-----Cl_Label-------------------------------------------------------------
class Cl_Label {
  public:
    byte x, y, w, h; // геомет размеры поз x,y w-ширина h-высота
    char *txt = NULL;
    // указатель на следующий элемент
    Cl_Label *pnt;
    // конструктора
    Cl_Label(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt);
    void setup() {
    }
    // setup()
    void loop() {
    }
};
//-----Cl_Btn-------------------------------------------------------------
class Cl_Btn {
  public:
    void (* Do)(); // указатель на обработчик клик
    byte x, y, w, h; // геомет размеры поз x,y w-ширина h-высота
    char *txt = NULL;
    // указатель на следующий элемент
    Cl_Btn *pnt;
    // конструктора
    Cl_Btn(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt, void (* _Do)());
    void setup() {
    }
    // setup()
    void loop() {
    }
};
//-----Cl_Sys----------------------------------------------------------------
class Cl_Sys {
    uint32_t past = 0;
  public:
    Cl_aJoystick *Start_aJoystick = NULL;
    Cl_Label     *Start_Label     = NULL;
    Cl_Btn       *Start_Btn       = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      display.begin();              // Инициализация дисплея
      display.setContrast(60);      // Устанавливаем контраст
      display.setTextColor(BLACK);  // Устанавливаем цвет текста
      display.setTextSize(1);       // Устанавливаем размер текста
      display.clearDisplay();       // Очищаем дисплей
      display.display();
      for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->setup();
      for (Cl_Label     *i = Start_Label    ; i != NULL; i = i->pnt) i->setup();
      for (Cl_Btn       *i = Start_Btn      ; i != NULL; i = i->pnt) i->setup();
    }
    // loop()
    void loop() {
      for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) i->loop();
      for (Cl_Label     *i = Start_Label    ; i != NULL; i = i->pnt) i->loop();
      for (Cl_Btn       *i = Start_Btn      ; i != NULL; i = i->pnt) i->loop();
      // вывод обновленой информации раз в 0.5 сек
      if (millis() - past >= 100) {
        past = millis();
        display.clearDisplay();       // Очищаем дисплей
        // вывод Label
        for (Cl_Label *i = Start_Label; i != NULL; i = i->pnt) {
          display.setCursor(i->x + 2, i-> y + 2);
          display.print(i->txt);
          display.drawRect(i->x, i->y, i->w, i->h, BLACK);
        }
        // вывод Btn
        for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) {
          display.setCursor(i->x + 2, i-> y + 2);
          display.print(i->txt);
          display.drawRect(i->x, i->y, i->w, i->h, BLACK);
        }
        // вывод джойстика
        for (Cl_aJoystick *i = Start_aJoystick; i != NULL; i = i->pnt) {
          display.setCursor(i->x, i-> y);
          display.print(i->txt);
          display.display();
        }
      }
    }
    void onClick(byte onClickX, byte onClickY) {
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt)
        if (i->x <= onClickX && onClickX < (i->x + i->w) && i->y <= onClickY && onClickY < (i->y + i->h))i->Do();
    }
} Sys;
//---------описание классов------------
Cl_aJoystick::Cl_aJoystick(Cl_Sys *Sys, byte _1pin, byte _2pin, byte _3pin, void (* _Do_SW)(byte, byte))
  :                              VRx_pin(_1pin), VRy_pin(_2pin), SW_pin(_3pin), Do_SW(_Do_SW) {
  x = 0; y = 0; txt = "^";
  pnt = Sys->Start_aJoystick;
  Sys->Start_aJoystick = this;
}
Cl_Label::Cl_Label(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt)
  :                                 x(_x), y(_y), w(_w), h(_h), txt(_txt) {
  pnt = Sys->Start_Label;
  Sys->Start_Label = this;
}
Cl_Btn::Cl_Btn(Cl_Sys *Sys, byte _x, byte _y, byte _w, byte _h, char *_txt, void (* _Do)())
  :                           x(_x),   y(_y),   w(_w),   h(_h),   txt(_txt) ,    Do(_Do) {
  pnt = Sys->Start_Btn;
  Sys->Start_Btn = this;
}
//----------Компоновка---------------------
void Do_SW(byte onClickX, byte onClickY) {
  Sys.onClick(onClickX, onClickY);
}
Cl_aJoystick *aJoystick = new Cl_aJoystick(&Sys,/*VRx*/A0,/*VRy*/A1,/*SW*/A2,/*обработчик наж SW*/Do_SW); // создать aJoystick_1
Cl_Label     *Label     = new Cl_Label    (&Sys,/*x*/0 ,/*y*/0 ,/*w*/48,/*h*/11,/*текст*/"Label 1"); // создать Label_1
void Do_Btn1() {
  Label->txt = "Do_Btn1";
}
void Do_Btn2() {
  Label->txt = "Do_Btn2";
}
void Do_Btn3() {
  Label->txt = "Do_Btn3";
}
Cl_Btn  *Btnl = new Cl_Btn(&Sys,/*x*/0 ,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn1",/*обработчик^\_*/Do_Btn1);// создать кнопку 1
Cl_Btn  *Btn2 = new Cl_Btn(&Sys,/*x*/28,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn2",/*обработчик^\_*/Do_Btn2);// создать кнопку 2
Cl_Btn  *Btn3 = new Cl_Btn(&Sys,/*x*/56,/*y*/36,/*w*/27,/*h*/11,/*текст*/"Btn3",/*обработчик^\_*/Do_Btn3);// создать кнопку 3
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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