Классы Ардуино по qwone для чайников.

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

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

nik182 пишет:

200 кнопок для контроллера?

нет - для суперкомпьютера

Да, у них как-то ваще кнопок негусто - у многих ни одной нет:)

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

ЕвгенийП пишет:
Вы хотели сказать "14"? А то уж скоро стандарт 17 выйдет.
Да и это тоже. Вот только туговато у меня получается с теорией как писать программы на Си++, с применением ООП ,Абстрактного класса и Абстракного типа данных. Это как электрический ток . Вроде все ясно, но в все равно окончательного ответа не получается.

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

Вот еще задание от сюда http://arduino.ru/forum/programmirovanie/morganie-svetodioda-nuzhnoe-kolichestvo-raz

Foster312 пишет:
Приветствую,можно ли привести пример простенькой программки для nano ,чтобы светодиод моргал сначала 1 раз,потом 2,3 и так далее до бесконечности.Заранее -Спасибо.

решение через delay

/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
//-------main()----------------------------
void setup() {
  pinMode(pin, OUTPUT);
  for (int n = 1;; ++n) {
    for (int i = 0; i < n; ++i) {
      digitalWrite(pin, HIGH);
      delay(/*время вкл*/200);
      digitalWrite(pin, LOW);
      delay(/*время выкл*/200);
    }
    delay(/*пауза между сериями*/500);
  }
}
void loop() {
}
/*Скетч использует 968 байт (3%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/

Промежуточная разметка 

/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
//-------main()----------------------------
void setup() {
  pinMode(pin, OUTPUT);
  for (int n = 1;; ++n) {
    for (int i = 0; i < n; ++i) { // stat =0
      digitalWrite(pin, HIGH);    // stat =1
      delay(/*время вкл*/200);    // stat =2
      digitalWrite(pin, LOW);
      delay(/*время выкл*/200);    // stat =3
    }                              // stat =4
    delay(/*пауза между сериями*/500); // stat =5
  }
}
void loop() {
}
/*Скетч использует 968 байт (3%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/

Ну и перевод в millis()

/**/
//-------компоновка----------------------------
const byte pin =/*пин*/13;
int stat = 0, n = 1, i;
uint32_t mill, past;
//-------main()----------------------------
void setup() {
  pinMode(pin, OUTPUT);
}
void loop() {
  mill = millis();
  if (stat == 0) {  // 0
    stat = 1;
    i = 1;
  }
  if (stat == 1) {  // 1
    stat = 2;
    digitalWrite(pin, HIGH);
    past = mill;
  }
  if (stat == 2 && mill - past >=/*время вкл*/200) {  // 2
    stat = 3;
    digitalWrite(pin, LOW);
    past = mill;
  }
  if (stat == 3 && mill - past >=/*время выкл*/200) {   // 3
    stat = 4;
    digitalWrite(pin, LOW);
    past = mill;
  }
  if (stat == 4) { // 4
    if (i < n) {
      stat = 1;
      ++i;
    }
    else stat = 5;
  }
  if (stat == 5 && mill - past >=/*пауза между сериями*/500) {  // 5
    stat = 0;
    past = mill;
    ++n;
  }
}
/*Скетч использует 1268 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 23 байт (1%) динамической памяти, оставляя 2025 байт для локальных переменных. Максимум: 2048 байт.
*/

А теперь упакован код в класс

/**/
uint32_t mill;//millis()
//-----------------------------------------------------
class Cl_Led {
    const byte pin ;
    int stat = 0, n = 1, i;
    uint32_t  past;
  public:
    Cl_Led(byte _pin): pin(_pin) {}
    void setup() {
      pinMode(pin, OUTPUT);
      stat = 0;
    }
    void loop() {
      if (stat == 0) {  // 0
        stat = 1;
        i = 1;
      }
      if (stat == 1) {  // 1
        stat = 2;
        digitalWrite(pin, HIGH);
        past = mill;
      }
      if (stat == 2 && mill - past >=/*время вкл*/200) {  // 2
        stat = 3;
        digitalWrite(pin, LOW);
        past = mill;
      }
      if (stat == 3 && mill - past >=/*время выкл*/200) {   // 3
        stat = 4;
        digitalWrite(pin, LOW);
        past = mill;
      }
      if (stat == 4) { // 4
        if (i < n) {
          stat = 1;
          ++i;
        }
        else stat = 5;
      }
      if (stat == 5 && mill - past >=/*пауза между сериями*/500) {  // 5
        stat = 0;
        past = mill;
        ++n;
      }
    }
};
//-------компоновка----------------------------
Cl_Led Led(/*пин*/13);
//-------main()----------------------------
void setup() {
  Led.setup();
}

void loop() {
  mill = millis();
  Led.loop();
}
/*Скетч использует 1340 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 24 байт (1%) динамической памяти, оставляя 2024 байт для локальных переменных. Максимум: 2048 байт.
*/

ПС: Тут скорее появился вопрос: Зачем? delay компактнее. Ответ. delay просто съедает ресурсы производительности процессора. А без этих ресурсов сэкономленая флеш и Озу память бесполезна для будущей модернизации программы.

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

Вариант связки классов через статическую переменную и статические функции класса

/**/
//--------Cl_AAA----------------------------
// эскиз связки класса в блок через статическиую переменную и статические функции класса
class Cl_AAA {
    Cl_AAA *next; // <-- указатель на след элемент
  public:
    static Cl_AAA *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_AAA *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    static void loop() {
      for (Cl_AAA *ii = start; ii != NULL; ii = ii->next)ii->run();
    }
    Cl_AAA() { // <-- конструктор
      this->next = start ;
      start = this;
    }
    void init() {}
    void run() {}
};
Cl_AAA *Cl_AAA::start = NULL;
//---------Компановка---------------------------
Cl_AAA AAA1;//<-- объявление объекта AAA1
Cl_AAA AAA2;//<-- объявление объекта AAA2
//----------main()--------------------------
void setup() {
  Cl_AAA::setup();
}

void loop() {
  Cl_AAA::loop();
}
/*Скетч использует 564 байт (1%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

qwone пишет:

Вариант связки классов 

Каких классов? В скетче, вроде, один всего класс.

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

Ну можно так 

/**/
uint32_t mill;// переменная под millis()
//--------Cl_Led----------------------------
//  класс светодиод
class Cl_Led {
    Cl_Led *next; // <-- указатель на след элемент
    const byte pin;
    const bool inv;
    bool led;
  public:
    static Cl_Led *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    Cl_Led(byte _pin, bool _inv)  // <-- конструктор
      : pin(_pin), inv(_inv) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, OUTPUT);
      OFF();
    }
    void ON() {
      led = 1;
      digitalWrite(pin, led ^ inv);
    }
    void OFF() {
      led = 0;
      digitalWrite(pin, led ^ inv);
    }
};
Cl_Led *Cl_Led::start = NULL;
//------Cl_Btn------------------------------------------
// класс кнопка
class Cl_Btn {
    Cl_Btn *next; // <-- указатель на след элемент
    const byte pin;
    void (*Do1)(), (*Do2)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    static Cl_Btn *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    static void loop() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next) {
        ii->run();
      }
    }
    Cl_Btn(byte _pin, void (*_Do1)(), void (*_Do2)())
      : pin(_pin), Do1(_Do1), Do2(_Do2) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, INPUT_PULLUP);
      btn_old = digitalRead(pin);
    }
    void run() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do1();
        if (!btn_old && btn) Do2();
      }
    }
};
Cl_Btn *Cl_Btn::start = NULL;
//---------Компановка---------------------------
Cl_Led Led(/*пин*/13,/*инв*/0);
void Do1_Btn() {
  Led.ON();
}
void Do2_Btn() {
  Led.OFF();
}
Cl_Btn Btn(/*пин*/2,/*обраб наж*/Do1_Btn,/*обраб отж*/Do2_Btn);
//----------main()--------------------------
void setup() {
  Cl_Led::setup();
  Cl_Btn::setup();
}

void loop() {
  mill = millis();
  Cl_Btn::loop();
}
/*Скетч использует 1368 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 36 байт (1%) динамической памяти, оставляя 2012 байт для локальных переменных. Максимум: 2048 байт.
*/

Или так

/**/
uint32_t mill;// переменная под millis()
//--------Cl_Led----------------------------
//  класс светодиод
class Cl_Led {
    Cl_Led *next; // <-- указатель на след элемент
    const byte pin;
    const bool inv;
    bool led;
  public:
    static Cl_Led *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    Cl_Led(byte _pin, bool _inv)  // <-- конструктор
      : pin(_pin), inv(_inv) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, OUTPUT);
      OFF();
    }
    void ON() {
      led = 1;
      digitalWrite(pin, led ^ inv);
    }
    void OFF() {
      led = 0;
      digitalWrite(pin, led ^ inv);
    }
};
Cl_Led *Cl_Led::start = NULL;
//------Cl_Btn------------------------------------------
// класс кнопка
class Cl_Btn {
    Cl_Btn *next; // <-- указатель на след элемент
    const byte pin;
    void (*Do1)(), (*Do2)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    static Cl_Btn *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    static void loop() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next) {
        ii->run();
      }
    }
    Cl_Btn(byte _pin, void (*_Do1)(), void (*_Do2)())
      : pin(_pin), Do1(_Do1), Do2(_Do2) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, INPUT_PULLUP);
      btn_old = digitalRead(pin);
    }
    void run() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do1();
        if (!btn_old && btn) Do2();
      }
    }
};
Cl_Btn *Cl_Btn::start = NULL;
//---------Компановка---------------------------
Cl_Led Led1(/*пин*/13,/*инв*/0);
Cl_Led Led2(/*пин*/12,/*инв*/0);
void Do1_Btn1() {
  Led1.ON();
}
void Do2_Btn1() {
  Led1.OFF();
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do1_Btn1,/*обраб отж*/Do2_Btn1);
void Do1_Btn2() {
  Led2.ON();
}
void Do2_Btn2() {
  Led2.OFF();
}
Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do1_Btn2,/*обраб отж*/Do2_Btn2);
//----------main()--------------------------
void setup() {
  Cl_Led::setup();
  Cl_Btn::setup();
}

void loop() {
  mill = millis();
  Cl_Btn::loop();
}
/*Скетч использует 1484 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 55 байт (2%) динамической памяти, оставляя 1993 байт для локальных переменных. Максимум: 2048 байт.
*/

А можно так 

/**/
uint32_t mill;// переменная под millis()
//--------Cl_Led----------------------------
//  класс светодиод
class Cl_Led {
    Cl_Led *next; // <-- указатель на след элемент
    const byte pin;
    const bool inv;
    bool led;
    bool stat;// 1 мигает 0 нет
    uint32_t past, time;
  public:
    static Cl_Led *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    static void loop() {
      for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->run();
    }
    Cl_Led(byte _pin, bool _inv)  // <-- конструктор
      : pin(_pin), inv(_inv) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, OUTPUT);
      OFF();
    }
    void ON() {
      led = 1;
      digitalWrite(pin, led ^ inv);
      stat = 0;
    }
    void OFF() {
      led = 0;
      digitalWrite(pin, led ^ inv);
      stat = 0;
    }
    void blink(uint32_t _time = 500) {
      time = _time;
      past = mill;
      stat = 1;
      led = 1;
      digitalWrite(pin, led ^ inv);
    }
    void run() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        led = !led;
        digitalWrite(pin, led ^ inv);
      }
    }
};
Cl_Led *Cl_Led::start = NULL;
//------Cl_Btn------------------------------------------
// класс кнопка
class Cl_Btn {
    Cl_Btn *next; // <-- указатель на след элемент
    const byte pin;
    void (*Do1)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    static Cl_Btn *start; //<-- статический указатель  на начало списка
    static void setup() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next)ii->init();
    }
    static void loop() {
      for (Cl_Btn *ii = start; ii != NULL; ii = ii->next) {
        ii->run();
      }
    }
    Cl_Btn(byte _pin, void (*_Do1)())
      : pin(_pin), Do1(_Do1) {
      this->next = start ;
      start = this;
    }
    void init() {
      pinMode(pin, INPUT_PULLUP);
      btn_old = digitalRead(pin);
    }
    void run() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do1();
      }
    }
};
Cl_Btn *Cl_Btn::start = NULL;
//---------Компановка---------------------------
Cl_Led Led1(/*пин*/13,/*инв*/0);
void Do_Btn1() {
  Led1.ON();
}
void Do_Btn2() {
  Led1.OFF();
}
void Do_Btn3() {
  Led1.blink(200);
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do_Btn1);
Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do_Btn2);
Cl_Btn Btn3(/*пин*/4,/*обраб наж*/Do_Btn3);
//----------main()--------------------------
void setup() {
  Cl_Led::setup();
  Cl_Btn::setup();
}

void loop() {
  mill = millis();
  Cl_Led::loop();
  Cl_Btn::loop();
}
/*Скетч использует 1614 байт (5%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 67 байт (3%) динамической памяти, оставляя 1981 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Всем известна программа Blink с delay()

/**/
void setup() {
  pinMode(13, OUTPUT);
}
void loop() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
}
/*Скетч использует 928 байт (2%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/

Вот вариант с классом .заменил pinMode и digitalWrite

/*
*/
//---------Cl_led----------------------------------
//класс светодиод
class Cl_led {
    uint8_t bit ;// номер бита
    uint8_t port ; // номер порта
    volatile uint8_t *reg, *out;
  public:
    Cl_led(uint8_t pin) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin);
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      SREG = oldSREG;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      *out |= bit;
      SREG = oldSREG;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      *out &= ~bit;
      SREG = oldSREG;
    }
};
//-------------------------------------------
Cl_led led(13);
//-------------------------------------------
void setup() {
  led.setup();
}

void loop() {
  led.ON();
  delay(200);
  led.OFF();
  delay(200);
}
/*Скетч использует 874 байт (2%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.
*/

Ужался код немного.

Добавил в класс инвесию 

/*
*/
//---------Cl_led----------------------------------
//класс светодиод
class Cl_led {
    uint8_t bit ;// номер бита
    uint8_t port ; // номер порта
    volatile uint8_t *reg, *out;
    bool led; // состояние светодиода
    bool inv;// состояние бита инверсии
  public:
    Cl_led(uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin);
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      led = 0;
      if (led ^ inv == 0) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      led = 1;
      if (led ^ inv == 0) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      led = 0;
      if (led ^ inv == 0) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
    }
};
//-------------------------------------------
Cl_led led(/*пин*/13,/*инверсия*/0);
//-------------------------------------------
void setup() {
  led.setup();
}

void loop() {
  led.ON();
  delay(200);
  led.OFF();
  delay(200);
}
/*Скетч использует 958 байт (2%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 17 байт (0%) динамической памяти, оставляя 2031 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Странная у Вас инверсия. Для  того, чтобы инвертировать пин, достаточно прописать 1 в соответствующий бит регистра PINx.

Например для третьего пина:

PIND |= (1 << 3);

и это странслируется в одну единственную машинную команду

sbi 9,3

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
// а вы уверены что так?
PIND |= (1 << 3);
// а может так
*out ^=bit&inv;
// а то у Метров такие мелочи не волнуют

 

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

qwone пишет:

// а вы уверены что так?
PIND |= (1 << 3);
// а может так
*out ^=bit&inv;
// а то у Метров такие мелочи не волнуют

Вопрос не понятен. Я написал "Например для третьего пина". Так вот, для тертьего пина - это действительно так, я уверен (и даташит тоже). А как Вам это перевести в Ваш класс и сделать универсально для любого пина - это Ваша забота.

Только не забывайте. так как я написал - это ОДНА машинная команда и НОЛЬ байтов дополнительной памяти данных. Вы же зачем-то пытаетесь помнить какую-то переменную и выполнять логику с нею. Зачем? Для инвертирования пина, как я Вам писал, достаточно записать 1 в нужный бит PINx (и неважно. что там было раньше - запишете единицу ещё раз - инвертируется ещё раз). Попробуйте.

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

Третий скетч отсюда #109

Получился таким.

/*
*/
//---------Cl_led----------------------------------
//класс светодиод
class Cl_led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
  public:
    Cl_led(uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
    }
};
//-----Компоновка----------------------------------
Cl_led led(/*пин*/13,/*инверсия*/1);
//-----main()--------------------------------------
void setup() {
  led.setup();
}

void loop() {
  led.ON();
  delay(200);
  led.OFF();
  delay(200);
}
/*Скетч использует 940 байт (2%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт.
*/

Такой же в работе код, но уже на millis()

/*
*/
unsigned long mill = 0; // переменная millis()
//---------Cl_led----------------------------------
//класс светодиод
class Cl_led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    Cl_led(uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//-----Компоновка----------------------------------
Cl_led led(/*пин*/13,/*инверсия*/1);
//-----main()--------------------------------------
void setup() {
  led.setup();
  led.blink(1000);// мигать 1сек горит+1сек нет
}

void loop() {
  mill = millis();
  led.loop();
}
/*Скетч использует 896 байт (2%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 28 байт (1%) динамической памяти, оставляя 2020 байт для локальных переменных. Максимум: 2048 байт.
*/

Код на 3 кнопки и светодиод с миганием на таком же принципе

/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    Cl_Led   (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр выхода порта
    uint8_t port; // номер порта на выводе
    const byte pin;
    void (*Do)();
    bool btn, btn_old, btn_new;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    Cl_Btn(byte pin, void (*_Do)()):  Do(_Do) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      //pinMode(pin, INPUT_PULLUP);
      uint8_t oldSREG = SREG;
      cli();
      *reg &= ~bit; //INPUT_PULLUP
      *out |= bit;
      SREG = oldSREG;
      btn_old = (*portInputRegister(port) & bit) == 0;
    }
    void loop() {
      btn_new = (*portInputRegister(port) & bit) == 0;
      if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = btn_new ;  // прочитать реальное значение на выводе
        if (btn_old && ! btn)(*Do)();
      }
    }
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do_Btn1() {
  Led1.ON();
}
void Do_Btn2() {
  Led1.OFF();
}
void Do_Btn3() {
  Led1.blink(200);
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do_Btn1);
Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do_Btn2);
Cl_Btn Btn3(/*пин*/4,/*обраб наж*/Do_Btn3);
//-------------main()-----------------------------------
void setup() {
  Led1.setup();
  Btn1.setup();
  Btn2.setup();
  Btn3.setup();
}

void loop() {
  mill = millis();
  Led1.loop();
  Btn1.loop();
  Btn2.loop();
  Btn3.loop();
}
/*Скетч использует 1472 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 79 байт (3%) динамической памяти, оставляя 1969 байт для локальных переменных. Максимум: 2048 байт.
*/

Последний скетч немного оптимизировал

/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    Cl_Led   (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
    uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
    uint8_t port; // номер порта на выводе
    void (*Do)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    Cl_Btn(byte pin, void (*_Do)()):  Do(_Do) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin); // получить номер порта
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      volatile uint8_t *reg = portModeRegister(port);
      volatile uint8_t *out = portOutputRegister(port);
      *reg &= ~bit; //INPUT
      *out |= bit; //_PULLUP
      SREG = oldSREG;
      btn_old = (*portInputRegister(port) & bit) == 0;
    }
    void loop() {
      bool btn_new = (*portInputRegister(port) & bit) == 0;
      if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = btn_new ;  // прочитать реальное значение на выводе
        if (btn_old && ! btn)(*Do)();
      }
    }
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do_Btn1() {
  Led1.ON();
}
void Do_Btn2() {
  Led1.OFF();
}
void Do_Btn3() {
  Led1.blink(200);
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do_Btn1);
Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do_Btn2);
Cl_Btn Btn3(/*пин*/4,/*обраб наж*/Do_Btn3);
//-------------main()-----------------------------------
void setup() {
  Led1.setup();
  Btn1.setup();
  Btn2.setup();
  Btn3.setup();
}

void loop() {
  mill = millis();
  Led1.loop();
  Btn1.loop();
  Btn2.loop();
  Btn3.loop();
}
/*Скетч использует 1502 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 61 байт (2%) динамической памяти, оставляя 1987 байт для локальных переменных. Максимум: 2048 байт.
*/

А эта версия если кнопки или датчики у вас без дребезга 

/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    Cl_Led   (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//------Cl_Btn------------------------------------------
// класс кнопка на бездребезговый выход
class Cl_Btn {
    uint8_t bit ; // номер бита в виде 00010000,1 находится там где выход
    uint8_t port; // номер порта на выводе
    void (*Do)();
    bool btn, btn_old;
  public:
    Cl_Btn(byte pin, void (*_Do)()):  Do(_Do) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin); // получить номер порта
    }
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      volatile uint8_t *reg = portModeRegister(port);
      volatile uint8_t *out = portOutputRegister(port);
      *reg &= ~bit; //INPUT
      SREG = oldSREG;
      btn = (*portInputRegister(port) & bit) == 0;
    }
    void loop() {
      btn_old = btn;
      btn = (*portInputRegister(port) & bit) == 0;
      if (!btn_old && btn)(*Do)();
    }
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do_Btn1() {
  Led1.ON();
}
void Do_Btn2() {
  Led1.OFF();
}
void Do_Btn3() {
  Led1.blink(200);
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do_Btn1);
Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do_Btn2);
Cl_Btn Btn3(/*пин*/4,/*обраб наж*/Do_Btn3);
//-------------main()-----------------------------------
void setup() {
  Led1.setup();
  Btn1.setup();
  Btn2.setup();
  Btn3.setup();
}

void loop() {
  mill = millis();
  Led1.loop();
  Btn1.loop();
  Btn2.loop();
  Btn3.loop();
}
/*Скетч использует 1314 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 46 байт (2%) динамической памяти, оставляя 2002 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Уроки программирования Ардуино.  http://mypractic.ru/uroki-programmirovaniya-arduino-navigaciya-po-urokam

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    /*
      конструктор Cl_Led
      Описание создает класс
      Ввод     pin: подключение к ноге
             inv: бит инвертирования 0 нет / 1 инверсия
      Вывод    нет
    */
    Cl_Led   (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    /*
      Функция  setup
      Описание иницирование класса
      Ввод     нет
      Вывод    нет
    */
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  OFF
      Описание выключить светодиод
      Ввод     нет
      Вывод    нет
    */
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  ON
      Описание включить светодиод
      Ввод     нет
      Вывод    нет
    */
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  blink
      Описание мигать светодиодои
      Ввод     _time  - полупериод мигания
      Вывод    нет
    */
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    /*
      Функция  loop
      Описание для нормальной работе разместить в loop программы
      Ввод     нет
      Вывод    нет
    */
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр выхода порта
    uint8_t port; // номер порта на выводе
    const byte pin;
    void (*Do1)(), (*Do2)();
    bool btn, btn_old, btn_new;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    /*
      конструктор Cl_Btn
      Описание создает класс
      Ввод     pin: подключение к ноге
             _Do1: фунция обработчик нажатия кнопки
             _Do2: фунция обработчик отжатия кнопки
      Вывод    нет
    */
    Cl_Btn(byte pin, void (*_Do1)(), void (*_Do2)()):  Do1(_Do1), Do2(_Do2) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    /*
      Функция  setup
      Описание иницирование класса
      Ввод     нет
      Вывод    нет
    */
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg &= ~bit; //INPUT
      *out |= bit; //PULLUP
      SREG = oldSREG;
      btn_old = (*portInputRegister(port) & bit) == 0;
    }
    /*
      Функция  loop
      Описание для нормальной работе разместить в loop программы
      Ввод     нет
      Вывод    нет
    */
    void loop() {
      btn_new = (*portInputRegister(port) & bit) == 0;
      if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = btn_new ;  // прочитать реальное значение на выводе
        if (btn_old && ! btn)(*Do1)();
        if (!btn_old && btn)(*Do2)();
      }
    }
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do1_Btn1() {
  Led1.ON();
}
void Do2_Btn1() {
  Led1.OFF();
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do1_Btn1,/*обраб отж*/Do2_Btn1);
//-------------main()-----------------------------------
void setup() {
  Led1.setup();
  Btn1.setup();
}

void loop() {
  mill = millis();
  Led1.loop();
  Btn1.loop();
}
/*Скетч использует 1308 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 47 байт (2%) динамической памяти, оставляя 2001 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Послушайте, qwone,

Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?

Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!

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

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

Послушайте, qwone,

Вы хотя бы компилировать свои опусы пробуете (я уж не говорю запускать)? Или вот как в голову пришло, так публикуете?

Ваш код элементарно не компилируется потому, что Вы в 108 строку засунули константый член класса, которым нигде и никогда не пользуетесь (главное - не инициализируете)!

Ну компилируется вы же видели это /*  */  И работает. Ну да остались рудименты. Так компилятор это и опускает. Умный блин однако, это я про компилятор. const byte pin все же загружаемая переменная, но только с конструктора.

ПС: хотя да без нее на один байт в программе меньше.

/**/
uint32_t mill;// переменная под millis()
//---------Cl_Led----------------------------------
//класс светодиод
class Cl_Led {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр входа порта
    bool inv;// состояние бита инверсии выхода
    bool stat;// 1 мигать / 0 нет
    unsigned long past, time;
  public:
    /*
      конструктор Cl_Led
      Описание создает класс
      Ввод     pin: подключение к ноге
             inv: бит инвертирования 0 нет / 1 инверсия
      Вывод    нет
    */
    Cl_Led   (uint8_t pin, uint8_t _inv = 0): inv(_inv) {
      bit  = digitalPinToBitMask(pin);
      uint8_t port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    /*
      Функция  setup
      Описание иницирование класса
      Ввод     нет
      Вывод    нет
    */
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg |= bit;
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  OFF
      Описание выключить светодиод
      Ввод     нет
      Вывод    нет
    */
    void OFF() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out &= ~bit;
      else *out |= bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  ON
      Описание включить светодиод
      Ввод     нет
      Вывод    нет
    */
    void ON() {
      uint8_t oldSREG = SREG;
      cli();
      if (inv) *out |= bit;
      else *out &= ~bit;
      SREG = oldSREG;
      stat = 0;
    }
    /*
      Функция  blink
      Описание мигать светодиодои
      Ввод     _time  - полупериод мигания
      Вывод    нет
    */
    void blink(unsigned long _time = 500) {
      time = _time;
      stat = 1;
      past = mill;
      uint8_t oldSREG = SREG;
      cli();
      *out ^= bit;
      SREG = oldSREG;
    }
    /*
      Функция  loop
      Описание для нормальной работе разместить в loop программы
      Ввод     нет
      Вывод    нет
    */
    void loop() {
      if (!stat) return;
      if (mill - past >= time) {
        past = mill;
        uint8_t oldSREG = SREG;
        cli();
        *out ^= bit;
        SREG = oldSREG;
      }
    }
};
//------Cl_Btn------------------------------------------
// класс кнопка c програмной подтяжкой
class Cl_Btn {
    uint8_t bit ;  // номер бита в виде 00010000,1 находится там где выход
    volatile uint8_t *reg; // указатель на регистр настройки порта
    volatile uint8_t *out; // указатель на регистр выхода порта
    uint8_t port; // номер порта на выводе
    void (*Do1)(), (*Do2)();
    bool btn, btn_old, btn_new;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    /*
      конструктор Cl_Btn
      Описание создает класс
      Ввод     pin: подключение к ноге
             _Do1: фунция обработчик нажатия кнопки
             _Do2: фунция обработчик отжатия кнопки
      Вывод    нет
    */
    Cl_Btn(byte pin, void (*_Do1)(), void (*_Do2)()):  Do1(_Do1), Do2(_Do2) {
      bit  = digitalPinToBitMask(pin);
      port = digitalPinToPort(pin); // получить номер порта
      reg  = portModeRegister(port);
      out  = portOutputRegister(port);
    }
    /*
      Функция  setup
      Описание иницирование класса
      Ввод     нет
      Вывод    нет
    */
    void setup() {
      uint8_t oldSREG = SREG;
      cli();
      *reg &= ~bit; //INPUT
      *out |= bit; //PULLUP
      SREG = oldSREG;
      btn_old = (*portInputRegister(port) & bit) == 0;
    }
    /*
      Функция  loop
      Описание для нормальной работе разместить в loop программы
      Ввод     нет
      Вывод    нет
    */
    void loop() {
      btn_new = (*portInputRegister(port) & bit) == 0;
      if (! bounce && btn != btn_new) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = mill;                         // сделать временую засветку
      }
      else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = btn_new ;  // прочитать реальное значение на выводе
        if (btn_old && ! btn)(*Do1)();
        if (!btn_old && btn)(*Do2)();
      }
    }
};
//-------------компоновка-----------------------------------
Cl_Led Led1(/*пин*/13,/*инв*/1);
void Do1_Btn1() {
  Led1.ON();
}
void Do2_Btn1() {
  Led1.OFF();
}
Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do1_Btn1,/*обраб отж*/Do2_Btn1);
//-------------main()-----------------------------------
void setup() {
  Led1.setup();
  Btn1.setup();
}

void loop() {
  mill = millis();
  Led1.loop();
  Btn1.loop();
}
/*Скетч использует 1308 байт (4%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 46 байт (2%) динамической памяти, оставляя 2002 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

qwone, ну реально какой-то поток сознания - нахрена это всё?

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

qwone пишет:

Ну компилируется вы же видели это /*  */  И работает. 

Я вставил в IDE. И ни хрена не компилируется. Как и следовало ожидать выдаёт сообщение

abc.ino: In constructor 'Cl_Btn::Cl_Btn(byte, void (*)(), void (*)())':
abc:122: error: uninitialized member 'Cl_Btn::pin' with 'const' type 'const byte {aka const unsigned char}' [-fpermissive]
uninitialized member 'Cl_Btn::pin' with 'const' type 'const byte {aka const unsigned char}' [-fpermissive]
 
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

так  у меня Ардуино 1.8.0 . Заходит нормально.

Клапауций 112 пишет:
qwone, ну реально какой-то поток сознания - нахрена это всё?
Да так смотрю как программа выглядил на форуме с такими комментариями. Всегда найдутся люди со строны и увидят что-то не так.

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

qwone пишет:

Да так смотрю как программа выглядил на форуме с такими комментариями. Всегда найдутся люди со строны и увидят что-то не так.

ок а, тема как называется?

я сюда захожу, что бы научиться чему-то новому.

и, что я вижу - бред сумасшедшего.

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

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

Клапауций 112 пишет:
и, что я вижу - бред сумасшедшего.
Так развитие науки идет с сумашедших идей. Замечу не с идиотских. Идиотские идеи идут от консерваторов.

class Cl_AAA {
    const byte aaa;//<--- нормально так работает
  public:
    Cl_AAA(byte _aaa): aaa(_aaa) {}
};
Cl_AAA AAA(/*константа*/1);
void setup() {
}

void loop() {
}
/*Скетч использует 488 байт (1%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 10 байт (0%) динамической памяти, оставляя 2038 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

//<--- нормально так работает

почему не должно работать?

 

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

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

//<--- нормально так работает

почему не должно работать?

Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.

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

qwone пишет:

так  у меня Ардуино 1.8.0 . Заходит нормально.

1.8.1 - выдаёт не ошибку, но предупреждение (в отличие от 1.6.5 и 1.6.12 - те выдают ошибку - опции разные)

Вот предупреждение 1.8.1

C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino: In constructor 'Cl_Btn::Cl_Btn(byte, void (*)(), void (*)())':
 
C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino:122:5: warning: uninitialized const member in 'const byte {aka const unsigned char}' [-fpermissive]
 
C:\Users\Admin\Google Диск\Soft\Kaka\Kaka0\Kaka0.ino:108:16: note: 'const byte Cl_Btn::pin' should be initialized
 
-------------------
 
Вы же понимаете, что неинициализировать константу неправильно? Так исправьте, чего спорить-то, проще же просто исправить ошибку чем докуазывать недоказуемое.
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:

Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.

Не в том дело кто может менять, а кто  - нет.

Если в классе объявлена константа, конструктор обязан её инициализировать. Вы этого не сделали, вот и ругается.

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

ЕвгенийП пишет:
Если в классе объявлена константа, конструктор обязан её инициализировать. Вы этого не сделали, вот и ругается.

 Ну зеванул. Точнее мне захотелось посмотреть код где убран pinMode(),digitalWrite(),digitalRead(). Точнее их раскрыл уже внутри класса. Затем убрал лишние куски, что бы не мешались. Но мой компилятор не предупредил, хотя программа загрузилась и работала. Значит все нормально. Вот даже переменая pin - нога не понадобилась. И да если компилятор чистит код, то глобальные переменые оставляет. Даже если это глобально внутри класса. Этого не знал.

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

qwone пишет:

мой компилятор не предупредил

Посмотрите в настройках IDE "Compiler warnings". По умолчанию "из коробки" там стоит "None". Поставьте "All" - для разработчика это более адекватно.

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

qwone пишет:

Считается если объявлена константа, то ее изменять нельзя. Потому что это константа. Но конструктор может, так как он создает класс. Но видно для новичков Ардуино это убрали в некоторых версиях среды.

ну, так и попробуй изменить...

class Cl_AAA {
    public:
    const byte aaa;//<--- нормально так работает
    Cl_AAA(byte _aaa): aaa(_aaa) {}
};
Cl_AAA AAA(/*константа*/1);
void setup() {
AAA.aaa = 5;
}

void loop() {}


sketch_aug13a:8: error: assignment of read-only member 'Cl_AAA::aaa'

 AAA.aaa = 5;

 

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

Код

/**/
//------qwString---------------------------
//класс стринг
class qwString {
    char *buffer;
    unsigned len;// длина строки боз последнего \0
    /*функция  destroy
      описание очистить кучу
      ввод     нет
      вывод    нет
    */
    void destroy() {
      if (buffer)
        delete[] buffer;
    }
  public:
    /*конструктор  qwString
      описание конструктор по умолчанию
      ввод     *data:строка
      вывод    нет
    */
    qwString (): len(0) {
      buffer = new char;
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание конструктор копирования
      ввод     data:строка
      вывод    нет
    */
    qwString (qwString & obj) {
      len = obj.len;
      buffer = new char[len + 1];
      strcpy(buffer, obj.buffer);
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание перенести данные во вновь создаваемый объект
      ввод     &&tmp:другой компонент
      вывод    нет
    */
    qwString(qwString&& tmp)
      :   len(tmp.len), buffer(tmp.buffer) {
      tmp.buffer = NULL;
    }
    /*конструктор  qwString
      описание создать класс со строкой в 1 символ
      ввод     data:строка
      вывод    нет
    */
    qwString (char data) {
      len = 1;
      buffer = new char[2];
      buffer[0] = data;
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание создать класс со значением строки
      ввод     *data:строка
      вывод    нет
    */
    qwString (char *data) {
      len = strlen(data);
      buffer = new char[len + 1];
      strcpy(buffer, data);
      buffer[len] = 0;
    }
    /*функция  operator=
      описание организовать присвоение
      ввод     other:другой компонент
      вывод    нет
    */
    qwString& operator=(const qwString& other) {
      destroy();
      len = other.len;
      buffer = new char[len + 1];
      strcpy(buffer, other.buffer);
      buffer[len] = 0;
      return *this;
    }
    /*функция  operator=
       описание организовать присвоение c переносом
       ввод     &&tmp:другой компонент
       вывод    нет
    */
    qwString& operator=(qwString&& tmp) {
      destroy();
      len = tmp.len;
      buffer = tmp.buffer;
      tmp.buffer = NULL;
      return *this;
    }
    /*деструктор  qwString
      описание удалить класс
      ввод     нет
      вывод    нет
    */
    ~qwString () {
      destroy();
    }
    /*функция  viev
      описание показать значение
      ввод     нет
      вывод    нет
    */
    void viev() {
      Serial.print(len);
      Serial.print("  ");
      Serial.print(buffer);
      Serial.println();
    }
};
/*функция для проверки перехвата конечного результата функции*/
qwString Create(char *const data) {
  qwString _data(data);
  return _data;
}
//-------Компоновка----------------------------
//------main()----------------------
void setup() {
  Serial.begin(9600);
  qwString AAA1 = Create("123"); // срабатывает конструктор перемещения
  AAA1.viev();
  qwString AAA2 = AAA1;          // срабатывает конструктор копирования
  AAA2.viev();
  AAA2 = Create("456");          // срабатывает конструктор перемещения, затем оператор перемещения
  AAA2.viev();
  AAA2 = AAA1;                   // срабатывает оператор присваивания
  AAA2.viev();
}

void loop() {
}
/*Скетч использует 2618 байт (8%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 206 байт (10%) динамической памяти, оставляя 1842 байт для локальных переменных. Максимум: 2048 байт.
*/

ПС: как работает не спрашивайте. Вроде понимаю, но похоже не очень твердо.

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

увековечил в железобетоне #48

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

qwone пишет:

Код

/**/
//------qwString---------------------------
//класс стринг
class qwString {
    char *buffer;
    unsigned len;// длина строки боз последнего \0
    /*функция  destroy
      описание очистить кучу
      ввод     нет
      вывод    нет
    */
    void destroy() {
      if (buffer)
        delete[] buffer;
    }
  public:
    /*конструктор  qwString
      описание конструктор по умолчанию
      ввод     *data:строка
      вывод    нет
    */
    qwString (): len(0) {
      buffer = new char;
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание конструктор копирования
      ввод     data:строка
      вывод    нет
    */
    qwString (qwString & obj) {
      len = obj.len;
      buffer = new char[len + 1];
      strcpy(buffer, obj.buffer);
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание перенести данные во вновь создаваемый объект
      ввод     &&tmp:другой компонент
      вывод    нет
    */
    qwString(qwString&& tmp)
      :   len(tmp.len), buffer(tmp.buffer) {
      tmp.buffer = NULL;
    }
    /*конструктор  qwString
      описание создать класс со строкой в 1 символ
      ввод     data:строка
      вывод    нет
    */
    qwString (char data) {
      len = 1;
      buffer = new char[2];
      buffer[0] = data;
      buffer[len] = 0;
    }
    /*конструктор  qwString
      описание создать класс со значением строки
      ввод     *data:строка
      вывод    нет
    */
    qwString (char *data) {
      len = strlen(data);
      buffer = new char[len + 1];
      strcpy(buffer, data);
      buffer[len] = 0;
    }
    /*функция  operator=
      описание организовать присвоение
      ввод     other:другой компонент
      вывод    нет
    */
    qwString& operator=(const qwString& other) {
      destroy();
      len = other.len;
      buffer = new char[len + 1];
      strcpy(buffer, other.buffer);
      buffer[len] = 0;
      return *this;
    }
    /*функция  operator=
       описание организовать присвоение c переносом
       ввод     &&tmp:другой компонент
       вывод    нет
    */
    qwString& operator=(qwString&& tmp) {
      destroy();
      len = tmp.len;
      buffer = tmp.buffer;
      tmp.buffer = NULL;
      return *this;
    }
    /*деструктор  qwString
      описание удалить класс
      ввод     нет
      вывод    нет
    */
    ~qwString () {
      destroy();
    }
    /*функция  viev
      описание показать значение
      ввод     нет
      вывод    нет
    */
    void viev() {
      Serial.print(len);
      Serial.print("  ");
      Serial.print(buffer);
      Serial.println();
    }
};
/*функция для проверки перехвата конечного результата функции*/
qwString Create(char *const data) {
  qwString _data(data);
  return _data;
}
//-------Компоновка----------------------------
//------main()----------------------
void setup() {
  Serial.begin(9600);
  qwString AAA1 = Create("123"); // срабатывает конструктор перемещения
  AAA1.viev();
  qwString AAA2 = AAA1;          // срабатывает конструктор копирования
  AAA2.viev();
  AAA2 = Create("456");          // срабатывает конструктор перемещения, затем оператор перемещения
  AAA2.viev();
  AAA2 = AAA1;                   // срабатывает оператор присваивания
  AAA2.viev();
}

void loop() {
}
/*Скетч использует 2618 байт (8%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 206 байт (10%) динамической памяти, оставляя 1842 байт для локальных переменных. Максимум: 2048 байт.
*/

Строки 73-80 (а также 86-92) - тпипчная ошибка реализации оператора присваивания. При такой реализации присваивание объекта класса самому себе непредсказуемо.

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

Класс qwStr строковая переменная(не полная буду наполнять)

/*qwStr.ino*/
//-----------qwStr--------------------------------------------
// класс строковая переменная
class qwStr {
  protected:
    char *str;
    unsigned int len;
    unsigned int size;
  public:
    /*конструктор  qwStr
      описание конструктор
      ввод     value:строка
      вывод    нет
    */
    qwStr (const char *value = "") {
      size = len = strlen(value);
      str = new char[len + 1];
      strncpy(str, value, len + 1);
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа char
      вывод    нет
    */
    explicit qwStr (const char value) {
      size = len = 1;
      str = new char[len + 1];
      str[0] = value;
      str[1] = 0;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа unsigned char
               base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(unsigned char value, unsigned char base = 10) {
      size = len = 8 * sizeof(unsigned char);
      char buf[len + 1];
      utoa(value, buf, base);
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа int
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(int value, unsigned char base = 10) {
      size = len = 8 * sizeof(unsigned char) + 1;
      char buf[len + 1];
      itoa(value, buf, base);
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа unsigned int
               base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(unsigned int value, unsigned char base = 10) {
      size = len = 8 * sizeof(unsigned char);
      char buf[len + 1];
      utoa(value, buf, base);
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа long
               base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(long  value, unsigned char base = 10) {
      size = len = 8 * sizeof(unsigned char) + 1;
      char buf[len + 1];
      ltoa(value, buf, base);
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа unsigned long
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(unsigned long  value, unsigned char base = 10) {
      size = len = 8 * sizeof(unsigned char) + 1;
      char buf[len + 1];
      ultoa(value, buf, base);
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа float
               base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(float value, unsigned char decimalPlaces = 2) {
      size = len = 32;
      char buf[len + 1];
      *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа unsigned char
        base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStr(double value, unsigned char decimalPlaces = 2) {
      size = len = 32;
      char buf[len + 1];
      *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     &value:строка
      вывод    нет
    */
    qwStr (const qwStr & value) {
      size = len = value.size;
      str = new char[len + 1];
      strncpy(str, value.str, len + 1);
    }
    /*конструктор  qwStr
      описание перенести данные во вновь создаваемый объект
      ввод     &&tmp:другой компонент
      вывод    нет
    */
    qwStr(qwStr&& tmp)
      : size(tmp.size), len(tmp.len), str(tmp.str) {
      tmp.str = NULL;
    }
    /*деструктор  qwStr
      описание деструктор
      ввод     нет
      вывод    нет
    */
    ~qwStr () {
      delete[] str;
    }
    /*функция  operator=
      описание организовать присвоение значений текущего от нового
      ввод     &tmp:новый компонент
      вывод    нет
    */
    qwStr& operator=(const qwStr &tmp) {
      if (this == &tmp) return *this;
      if (tmp.size > size) {
        delete[] str;
        size = len = tmp.size;
        str = new char[len + 1];
      }
      strncpy(str, tmp.str, len + 1);
      return *this;
    }
    /*функция  move
       описание перенести значение от нового к текущему с обнулением нового
       ввод     &tmp:новый компонент
       вывод    нет
    */
    void qwStr::move(qwStr &tmp) {
      if (str) { //если текущий буфер не пустой
        if (size >= tmp.len) { // и если емкость текущего больше длины нового
          strcpy(str, tmp.str); // то просто скопировать
          len = tmp.len;
          tmp.len = 0;
          return;              // и все
        } else delete[] str;
      }
      str  = tmp.str;// перенос значения нового текущему
      size = tmp.size;
      len  = tmp.len;
      tmp.str = NULL; // обнуление значений нового
      tmp.size = 0;
      tmp.len = 0;
    }
    /*функция  operator=
      описание организовать присвоение
      ввод     tmp:другой компонент
      вывод    нет
    */
    qwStr& operator=( qwStr &&tmp) {
      if (this != &tmp) move(tmp);
      return *this;
    }
    /*функция  viev
      описание показать значение в Serial
      ввод     нет
      вывод    нет
    */
    void viev() {
      Serial.print(len);
      Serial.print("  ");
      Serial.print(str);
      Serial.println();
    }
};
//-------------------------------------------------------
qwStr aaa1(1234, HEX);
qwStr aaa2(11.4);
qwStr aaa3 = aaa2;
qwStr aaa4(aaa1);
//-----main()--------------------------------------------------
void setup() {
  Serial.begin(9600);
  aaa1.viev();
  aaa2.viev();
  aaa3.viev();
  aaa4.viev();
}

void loop() {

}
/*Скетч использует 4640 байт (14%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 222 байт (10%) динамической памяти, оставляя 1826 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Не всё так просто. Вы используете конструкцию "if (this == &tmp)", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.

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

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

Не всё так просто. Вы используете конструкцию "if (this == &tmp)", но при этом оператор "==" у Вас не определён. Работать-то будет, но не всегда так, как Вы ожидаете - надеюсь, что Вы знаете, что делаете.

Разумеется. Там и кроме этого куча ошибок. Но пока не смогу сжевать этот кактус, то о дальнейшем изучении С++ и ОПП говорить бессмысленно.

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

Вот еще один вариант класса строковой переменных

/**/
//--------qwStrA-------------------
// класс строковая переменная qwStrA
class qwStrA {
  protected:
    char *str;
    unsigned int len;
    unsigned int size;
    //** внутрение функции для обработки
    /*функция init()
      описание инициализация
      ввод   нет
      вывод  нет
    */
    inline void init() {
      str = NULL;
      size = len =  0;
    }
    /*функция clear()
      описание очистка
      ввод   нет
      вывод  нет
    */
    inline void clear() {
      if (str) free(str);
      init();
    }
    /*функция reserve
      описание зарезервировать память
      ввод   _size:какое кол-во памяти надо выделить
      вывод  1 Ок/ 0 error
    */
    unsigned char reserve(unsigned int _size) {
      if (str && size >= _size) return 1;// выйти если памяти хватает
      if (changeSize(_size)) { // задать новый размер
        if (len == 0) str[0] = 0; // очистить содержимое
        return 1;
      }
      return 0;
    }
    /*функция changeSize
      описание изменить размер
      ввод   newSize:новый размер
      вывод  1 Ок/ 0 error
    */
    unsigned char changeSize(unsigned int newSize) {
      char *new_str = (char *)realloc(str, newSize + 1);
      if (new_str) {
        str = new_str;
        size = newSize;
        return 1;
      }
      return 0;
    }
    /*функция copy
      описание скопировать строку в класс
      ввод   _str:строка
             _len:длина копирования
      вывод  1 Ок/ 1 error
    */
    void copy(const char *_str, unsigned int _len) {
      if (!reserve(_len)) {
        clear();
        return *this;
      }
      len = _len;
      strcpy(str, _str);
      return *this;
    }
    /*функция  move
      описание перенести значение от нового к текущему с обнулением нового
      ввод     &obj:новый компонент
      вывод    нет
    */
    void move(qwStrA &obj) {
      if (str) { //если текущий буфер не пустой
        if (size >= obj.len) { // и если емкость текущего больше длины нового
          strcpy(str, obj.str); // то просто скопировать
          len = obj.len;
          obj.len = 0;
          return;              // и все
        } else delete[] str;
      }
      str  = obj.str;// перенос значения нового текущему
      size = obj.size;
      len  = obj.len;
      obj.str = NULL; // обнуление значений нового
      obj.size = 0;
      obj.len = 0;
    }
  public:

    //** конструкторы и деструктор
    /* конструктор  qwStrA
      описание создать объект по знач строковую перем
      ввод  *obj: указатель на строковую перем
      вывод нет
    */
    qwStrA(const char *obj = "") {
      init();
      if (obj) copy(obj, strlen(obj));
    }
    /* конструктор  qwStrA
      описание конструктор копирования
      ввод  *obj: указатель на  перем для копирования
      вывод нет
    */
    qwStrA(const qwStrA &obj) {
      init();
      *this = obj;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод  c: переменная char
      вывод нет
    */
    explicit qwStrA(char c) {
      init();
      char buf[2];
      buf[0] = c;
      buf[1] = 0;
      *this = buf;
    }
    /*конструктор  qwStr
      описание конструктор
      ввод     value:число типа unsigned char
               base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(unsigned char value, unsigned char base = 10) {
      init();
      char buf[1 + 8 * sizeof(unsigned char)];
      utoa(value, buf, base);
      *this = buf;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа int
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(int value, unsigned char base = 10) {
      init();
      char buf[2 + 8 * sizeof(int)];
      itoa(value, buf, base);
      *this = buf;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа unsigned int
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(unsigned int value, unsigned char base = 10) {
      init();
      char buf[1 + 8 * sizeof(unsigned int)];
      utoa(value, buf, base);
      *this = buf;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа long
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(long value, unsigned char base = 10) {
      init();
      char buf[2 + 8 * sizeof(long)];
      ltoa(value, buf, base);
      *this = buf;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа unsigned long
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(unsigned long value, unsigned char base = 10) {
      init();
      char buf[1 + 8 * sizeof(unsigned long)];
      ultoa(value, buf, base);
      *this = buf;
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа float
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(float value, unsigned char base = 2) {
      init();
      char buf[33];
      *this = dtostrf(value, base + 2, base, buf);
    }
    /* конструктор  qwStrA
      описание конструктор
      ввод     value:число типа double
                base:10 - вывести в 10-м виде
      вывод    нет
    */
    explicit qwStrA(double value, unsigned char base = 2) {
      init();
      char buf[33];
      *this = dtostrf(value, base + 2, base, buf);
    }
    /* деструктор ~qwStrA()
      описание уничтожить объект
      ввод  нет
      вывод нет
    */
    ~qwStrA() {
      free(str);
    }
    //** функция operator =
    /*функция  operator=
      описание организовать присвоение
      ввод     obj:другой компонент
      вывод    нет
    */
    qwStrA & operator = (qwStrA &&obj) {
      if (this != &obj) move(obj);
      return *this;
    }
    /*функция  operator=
      описание организовать присвоение значений текущего от нового
      ввод     &obj:новый компонент
      вывод    нет
    */
    qwStrA & operator=(const qwStrA &obj) {
      if (this == &obj) return *this;
      if (obj.size > size) {
        delete[] str;
        size = len = obj.size;
        str = new char[len + 1];
      }
      strncpy(str, obj.str, len + 1);
      return *this;
    }
    /*функция  operator=
      описание организовать присвоение значений текущего от нового
      ввод     &tmp:новое значение в *char
      вывод    нет
    */
    qwStrA & operator=(const char *obj) {
      if (obj) copy(obj, strlen(obj));
      else clear();
      return *this;
    }
    //** функции перевода значения в другой формат
    /*функция  toInt
      описание перевести значение в long
      ввод     нет
      вывод    результат:long
    */
    long toInt(void) const {
      if (str) return atol(str);
      return 0;
    }
    /*функция  toFloat
      описание перевести значение в float
      ввод     нет
      вывод    результат:float
    */
    float toFloat(void) const {
      return float(toDouble());
    }
    /*функция  toDouble
      описание перевести значение в double
      ввод     нет
      вывод    результат:double
    */
    double toDouble(void) const {
      if (str) return atof(str);
      return 0;
    }
    //** функции сравнения
    /*функция  compareTo
      описание сравнить с другим объектом
      ввод     *obj: другой объект
      вывод    1 - Верно / 0 - Неверно
    */
    int compareTo(const qwStrA &obj) const {
      if (!str || !obj.str) {
        if (obj.str && obj.len > 0) return 0 - *(unsigned char *)obj.str;
        if (str && len > 0) return *(unsigned char *)str;
        return 0;
      }
      return strcmp(str, obj.str);
    }
    /*функция  equals
      описание сравнить с другим объектом
      ввод     *obj: другой объект
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char equals(const qwStrA &obj) const {
      return (len == obj.len && compareTo(obj) == 0);
    }
    /*функция  equals
      описание сравнить со строчной переменной
      ввод     *obj: строчная переменная для сравнения
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char equals(const char *obj) const {
      if (len == 0) return (obj == NULL || *obj == 0);
      if (obj == NULL) return str[0] == 0;
      return strcmp(str, obj) == 0;
    }
    /*функция  operator ==
      описание сравнить со строчной переменной
      ввод     *obj: строчная переменная для сравнения
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char operator == (const qwStrA &obj) const {
      return equals(obj);
    }
    /*функция  operator ==
      описание сравнить со строчной переменной
      ввод     *obj: строчная переменная для сравнения
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char operator == (const char *obj) const {
      return equals(obj);
    }
    /*функция  operator !=
      описание сравнить со строчной переменной
      ввод     &obj: строчная переменная для сравнения
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char operator != (const qwStrA &obj) const {
      return !equals(obj);
    }
    /*функция  operator !=
      описание сравнить со строчной переменной
      ввод     *obj: строчная переменная для сравнения
      вывод    1 - Верно / 0 - Неверно
    */
    unsigned char operator != (const char *obj) const {
      return !equals(obj);
    }
    //** функции показ
    /*функция  viev
      описание показать значение в Serial
      ввод     нет
      вывод    нет
    */
    void viev() {
      Serial.print(len);
      Serial.print("  ");
      Serial.print(str);
      Serial.println();
    }
};
//--------Компоновка-------------------
qwStrA aaa1(123);
qwStrA aaa2 = "234";
//-----main()----------------------
void setup() {
  Serial.begin(9600);
  aaa1.viev();
  aaa2.viev();
  if (aaa1 == aaa2) Serial.println("TRUE");
  if (aaa1 != aaa2) Serial.println("FALSE");
}
void loop() {}
/*Скетч использует 3478 байт (10%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 226 байт (11%) динамической памяти, оставляя 1822 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Строки 64 и 68 выглядят странно, учитывая, что функция описана как void. Остальное не смотрел.

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

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

Строки 64 и 68 выглядят странно, учитывая, что функция описана как void. Остальное не смотрел.

 Ну да . В Ардуно вообще код идет такой 

String & String::copy(const char *cstr, unsigned int length)
{
	if (!reserve(length)) {
		invalidate();
		return *this;
	}
	len = length;
	strcpy(buffer, cstr);
	return *this;
}

Но метод protected:  и возвращаемое значение не используется в дальнейшем внутри класса

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

qwone пишет:

 Ну да . В Ардуно вообще код идет такой 

Этой фразы я не понял. Причём тут Ардуино? То, что разработчики IDE по умолчанию заткнули warning'и, так я Вам уже советовал включить - увидели бы сообщение.

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

Часто идет вопрос : Как заменить delay() на millis(). Две несхожые функции. Это как слона менять на коня. Попробую предложить свой вариант.

Вот есть код.

/**/
//------------------------------
//---Компановка-------------------
const byte led1 =/*пин 1 светодиода*/2;
const byte led2 =/*пин 1 светодиода*/3;
const byte led3 =/*пин 1 светодиода*/4;
void setupLeds() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
}
void runLeds() {
  digitalWrite(led1, HIGH);
  delay(200);
  digitalWrite(led1, LOW);
  digitalWrite(led2, HIGH);
  delay(200);
  digitalWrite(led2, LOW);
  digitalWrite(led3, HIGH);
  delay(200);
  digitalWrite(led3, LOW);
}
//----main--------------------------
void setup() {
  setupLeds();
  runLeds();
}

void loop() {
}
/*Скетч использует 1000 байт (3%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.
*/

Ну и результат обмена.

/**/
unsigned long mill;
//------------------------------
const byte led1 =/*пин 1 светодиода*/2;
const byte led2 =/*пин 2 светодиода*/3;
const byte led3 =/*пин 3 светодиода*/4;
void setupLeds() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
}
void runLeds(bool stat) {
  static unsigned long past;
  static byte step;
  if (stat) step = 0;
  switch (step) {
    case 0:
      digitalWrite(led1, HIGH);
      past = mill;
      step = 1;
      break;
    case 1:
      if (mill - past >= 200) { //  delay(200);
        digitalWrite(led1, LOW);
        digitalWrite(led2, HIGH);
        past = mill;
        step = 2;
      }
      break;
    case 2:
      if (mill - past >= 200) { //  delay(200);
        digitalWrite(led2, LOW);
        digitalWrite(led3, HIGH);
        past = mill;
        step = 3;
      }
      break;
    case 3:
      if (mill - past >= 200) { //  delay(200);
        digitalWrite(led3, LOW);
        step = 4;
      }
      break;
  }
}
//----main--------------------------
void setup() {
  setupLeds();
  runLeds(1);
}

void loop() {
  mill = millis();
  runLeds(0);
}
/*Скетч использует 1150 байт (3%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 18 байт (0%) динамической памяти, оставляя 2030 байт для локальных переменных. Максимум: 2048 байт.
*/

Понятно что код непривычен для тех кто мыслит процедурно. Одна и таже процедура(функция) запускается в версии с 1 и в версии с 0. И в setup() и в loop() За то не размазывается по программе как после фугасной бомбы

Alexandsvoi
Offline
Зарегистрирован: 11.07.2017

Человек просил помощи, а вы ему классы, не занимайтесь ерундой.

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

Alexandsvoi пишет:

Человек просил помощи, а вы ему классы, не занимайтесь ерундой.

Где вы видели там классы.Я ему метод, как решать такие проблемы. причем без классов. Знание методы банально упрощает решение задачи.

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

Ну классов там действительно нету, но ерунды достаточно. И наибольшая в том, что для решения банальнейшего вопроса выдается такой кривой код. А потом удивляемся, почему на форуме простыни кода забитого повторяющимися фрагментами и прочей ерундой. Дак их так учили здесь, примеры такие. Если уж Вы qwone, взялись за неимоверно тяжкую задачу убрать делеи, то предлагайте нормальное решение, а не то за которое будут чмырить позже. Публикуемый код должен быть образцем, а не пробой пера, пробу пера не обязательно людям показывать (за исключением случая когда надо чтоб код оценили и поругали), а тем более советовать как решение.  А то ж народ привыкнет так писать.

 Смотрю ваш код, нового и оригинального в нем ровно 0. А 3 минуты правки и 2 минуты на тест позволяют преобразовать его, сократив размер  скомпилированого на 10%. (с 1300 до 1070 байт)  Всего два момента легкой оптимизацией, а структура кода стала более явной, обработчики завершения временных интервалов каждый в своей функции, механизм легко маштабируем и т.д. Так что не публикуйте кривое и сырое, оставте это удовольствие велосипедостроителю ;)

/**/
byte mill;
//------------------------------
const byte led1 =/*пин 1 светодиода*/2;
const byte led2 =/*пин 2 светодиода*/3;
const byte led3 =/*пин 3 светодиода*/4;
void setupLeds() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
}

void FnLED0(void)
{
    digitalWrite(led1, HIGH);
}

void FnLED1(void)
{
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
}

void FnLED2(void)
{
   digitalWrite(led1, LOW);
   digitalWrite(led2, HIGH);
}

void FnLED3(void)
{
   digitalWrite(led3, LOW);
}


typedef void (*pFnLed)(void);
pFnLed arrLED[]={FnLED0, FnLED1, FnLED2, FnLED3};

void runLeds(bool stat) {
  static byte past;
  static byte step;
  if (stat) step = 0;
  
  if(((step) && ((byte)(mill - past) < 200)) ||
     (step>3))
    return;
   
  arrLED[step]();  
  past = mill;
 step++; 
}
//----main--------------------------
void setup() {
  setupLeds();
  runLeds(1);
}

void loop() {
  mill = millis();
  runLeds(0);
}
/*Скетч использует 1150 байт (3%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 18 байт (0%) динамической памяти, оставляя 2030 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Logik. Тот скетч я специально не пытался оптимизировать. Я просто показал как переходить с delay на millis хотя бы за счет простыней.

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

/*
пин 2 -> кнопка на землю
пин 8 -> динамик
*/
unsigned long mill;//переменая для millis()
//------------music----------------------------------------
const byte tonePin =/*пин*/8;
/* функция music
   описание проиграть мелодию
   ввод      num: 0-текучка / 1-старт/2-стоп
   вывод     нет

*/
void music(byte num) {
  static byte step = 66;
  static unsigned long past;
  if (num == 1) step = 0;
  if (num == 2) step = 66;
  if (step == 0) {
    step++;
    past = mill;
    tone(tonePin, 329, 338);

  }
  if (step == 1 && mill - past >= 417) {
    step++;
    past = mill;
    tone(tonePin, 329, 1012);
  }
  if (step == 2 && (millis() - past) >= 1250) {
    ++step;
    past = mill;
    tone(tonePin, 440, 169);
  }
  if (step == 3 && mill - past >= 207) {
    ++step;
    past = mill;
    tone(tonePin, 391, 169);
  }
  if (step == 4 && mill - past >= 209) {
    ++step;
    past = mill;
    tone(tonePin, 349, 675);
  }
  if (step == 5 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 293, 338);
  }
  if (step == 6 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 261, 338);
  }
  if (step == 7 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 246, 338);
  }
  if (step == 8 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 329, 675);
  }
  if (step == 9 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 293, 338);
  }
  if (step == 10 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 261, 338);
  }
  if (step == 11 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 220, 675);
  }
  if (step == 12 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 13 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 391, 506);
  }
  if (step == 14 && mill - past >= 625) {
    ++step;
    past = mill;
    tone(tonePin, 261, 506);
  }
  if (step == 15 && mill - past >= 625) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 16 && mill - past >= 625) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 17 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 523, 338);
  }
  if (step == 18 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 493, 338);
  }
  if (step == 19 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 20 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 415, 1350);
  }
  if (step == 21 && mill - past >= 2917) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 22 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 523, 675);
  }
  if (step == 23 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 493, 338);
  }
  if (step == 24 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 523, 338);
  }
  if (step == 25 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 493, 338);
  }
  if (step == 26 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 675);
  }
  if (step == 27 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 28 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 29 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 30 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 31 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 32 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 33 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 349, 675);
  }
  if (step == 34 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 349, 338);
  }
  if (step == 35 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 329, 675);
  }
  if (step == 36 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 37 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 349, 338);
  }
  if (step == 38 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 39 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 293, 338);
  }
  if (step == 40 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 261, 338);
  }
  if (step == 41 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 246, 338);
  }
  if (step == 42 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 220, 1350);
  }
  if (step == 43 && mill - past >= 2917) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 44 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 523, 675);
  }
  if (step == 45 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 493, 338);
  }
  if (step == 46 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 523, 338);
  }
  if (step == 47 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 493, 338);
  }
  if (step == 48 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 675);
  }
  if (step == 49 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 50 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 51 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 52 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 53 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 440, 338);
  }
  if (step == 54 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 55 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 349, 675);
  }
  if (step == 56 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 349, 338);
  }
  if (step == 57 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 329, 675);
  }
  if (step == 58 && mill - past >= 833) {
    ++step;
    past = mill;
    tone(tonePin, 391, 338);
  }
  if (step == 59 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 349, 338);
  }
  if (step == 60 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 329, 338);
  }
  if (step == 61 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 293, 338);
  }
  if (step == 62 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 261, 338);
  }
  if (step == 63 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 246, 338);
  }
  if (step == 64 && mill - past >= 417) {
    ++step;
    past = mill;
    tone(tonePin, 220, 1350);
  }
  if (step == 65 && mill - past >= 1500) {
    ++step;
  }
}
//---------Cl_Btn-------------------------------------------------
// класс кнопка
class Cl_Btn {
    const byte pin;
    void (*Do)();
    bool btn, oldBtn = 1;
    bool bounce = 0;
    unsigned long past;
  public:
    /*конструктор Cl_Btn
      описание    создать объект
      ввод        _pin: нога
                  _inv: инверсия выхода
      вывод       нет
    */
    Cl_Btn(byte _pin, void (_Do)()): pin(_pin), Do(_Do) {}
    /*функция     setup
      описание    иницилизация
      ввод        нет
      вывод       нет
    */
    void setup() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*функция     loop
      описание    для нормальной работы вставить в тело loop()
      ввод        нет
      вывод       нет
    */
    void loop() {
      bool newBtn = digitalRead(pin);
      if (bounce && newBtn != btn) {
        bounce = 1;
      }
      if (!bounce && mill - past >= 10) {
        past = mill;
        bounce = 0;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) (*Do)();
      }
    }
};
//----компановка------------------------------------------------
void Do_Btn() {
  music(1);// проиграть музыку
}
Cl_Btn Btn(/*пин*/2,/*обработчик*/Do_Btn);
//---mail()-------------------------------------------------
void setup() {
  Btn.setup();
}
void loop() {
  mill = millis();
  Btn.loop();
  music(0);
}
/*Скетч использует 9694 байт (30%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 50 байт (2%) динамической памяти, оставляя 1998 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Зачем мне эта грязная простыня? Вы ща как Клапауций, ныть будете "ну глянь, ну попробуй"? Так упреждаю. Я глянул раз, и у него и у Вас. Больше не стоит время терять. Глянул, сделал вывод изложил и даже проилюстрировал. А Ваш уровень писания кода - ваша проблема, плохо что другие на ваш код смотрят и себе так пишут. Хотя и это тоже вобщем не моя проблема ;)

Тема плавно переходит в сборище говнокода от qwone. Но зато наглядно видно что не в классах дело, ох не в классах.

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

Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной.  А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего. 

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

Logik пишет:

Вы ща как Клапауций, ныть будете "ну глянь, ну попробуй"? Так упреждаю. Я глянул раз, и у него и у Вас. Больше не стоит время терять. 

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

делов то.

или, смени ник на Дъартаньян.

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

qwone пишет:

Logik. Меня удивляет ,то что вы здесь пытаетесь найти для себя полезное. Вы ковыряетесь в Си++ больше меня. Это вы должны выкладывать код, а я искать что-то полезное. Но похоже я такой темы не наблюдаю. Может я плохо ищу, или в гугл вашу тему обходит стороной.  А то что тема исчерпала себя я давно знаю. Что мог то рассказал. А новое оно очень сырое. Вот у меня вопрос вываливать это новое сюда и слышать, что я говнокодю или работать в стол. Похоже последнее вернее всего. 

Первый раз открывая тему действительно допускал что чего толковоги и оригинального увижу. Иначе бы и не открывал разумеется. Мой код найти не можете? Странно, его здесь много есть, например из последнего http://arduino.ru/forum/apparatnye-voprosy/dtmf-gsm#comment-302080 . Захотите найти - найдете. Например по работе с модемом А8 большой и оч. интересный код публиковал. Так что упрек не по адресу.

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

Тема выдохлась. И скатилась в замену делея на милис. Напомню только про http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-ch.... Возможно это было бы интересней. И для Вас точно полезней, в ООП продвинулись бы. Например написали бы абстрактный класс реализующий вызов метода через интервалы времени,  а на его базе и свой пример последний музыкальный, описав мелодию масивом констант разумеется а не тем бредовым свичем. 

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

Logik пишет:
Например написали бы абстрактный класс реализующий вызов метода через интервалы времени,  а на его базе и свой пример последний музыкальный, описав мелодию масивом констант разумеется а не тем бредовым свичем.

 Про астрактный класс (данных или объекта обрабатывающие эти данные )могу сказать одно. Не все что хорошо в теории, хорошо ложится в код. В Гардвадской организации и небольшой памяти точно.  Опять я специально привел тот бредовый код , что бы выложить получше сейчас. Ведь пока не видишь разницы думаешь, что есть лучше.

/*
  пин 2 -> кнопка на землю
  пин 8 -> динамик
*/
unsigned long mill;//переменая для millis()
//------------music----------------------------------------
const byte tonePin =/*пин*/8;
const unsigned int melody[] = {
  // тон, длительность ноты ,полная длительность
  329, 338, 417
  , 329, 1012, 1250
  , 440, 169, 207
  , 391, 169, 209
  , 349, 675, 833
  , 293, 338, 417
  , 261, 338, 417
  , 246, 338, 417
  , 329, 675, 833
  , 293, 338, 417
  , 261, 338, 417
  , 220, 675, 833
  , 391, 338, 417
  , 391, 506, 625
  , 261, 506, 625
  , 329, 338, 625
  , 391, 338, 417
  , 523, 338, 417
  , 493, 338, 417
  , 440, 338, 417
  , 415, 1350, 2917
  , 329, 338, 417
  , 523, 675, 833
  , 493, 338, 417
  , 523, 338, 417
  , 493, 338, 417
  , 440, 675, 833
  , 329, 338, 417
  , 440, 338, 417
  , 440, 338, 417
  , 391, 338, 417
  , 440, 338, 417
  , 391, 338, 417
  , 349, 675, 833
  , 349, 338, 417
  , 329, 675, 833
  , 391, 338, 417
  , 349, 338, 417
  , 329, 338, 417
  , 293, 338, 417
  , 261, 338, 417
  , 246, 338, 417
  , 220, 1350, 2917
  , 329, 338, 417
  , 523, 675, 833
  , 493, 338, 417
  , 523, 338, 417
  , 493, 338, 417
  , 440, 675, 833
  , 329, 338, 417
  , 440, 338, 417
  , 440, 338, 417
  , 391, 338, 417
  , 440, 338, 417
  , 391, 338, 417
  , 349, 675, 833
  , 349, 338, 417
  , 329, 675, 833
  , 391, 338, 417
  , 349, 338, 417
  , 329, 338, 417
  , 293, 338, 417
  , 261, 338, 417
  , 246, 338, 417
  , 220, 1350, 1500
};
/* функция music
   описание проиграть мелодию
   ввод      num: 0-текучка / 1-старт/2-стоп
   вывод     нет
*/
void music(byte num) {
  const int temPlay = 2; // темр игры
  static byte step = 66;
  static byte stepEnd = 0 ;
  static unsigned long past, time;
  if (num == 1) {
    stepEnd = sizeof( melody) / sizeof(unsigned int) / 3;
    step = 0;
    tone(tonePin, melody[0], melody[1] / temPlay);
    time = melody[2] / temPlay;
    past = mill;
  }
  if (num == 2) step = 100;
  if (step <= stepEnd && mill - past >= time) {
    step++;
    past = mill;
    tone(tonePin, melody[step * 3], melody[step * 3 + 1] / temPlay);
    time = melody[step * 3 + 2] / temPlay;
  }
}
//---------Cl_Btn-------------------------------------------------
// класс кнопка
class Cl_Btn {
    const byte pin;
    void (*Do)();
    bool btn, oldBtn = 1;
    bool bounce = 0;
    unsigned long past;
  public:
    /*конструктор Cl_Btn
      описание    создать объект
      ввод        _pin: нога
                  _inv: инверсия выхода
      вывод       нет
    */
    Cl_Btn(byte _pin, void (_Do)()): pin(_pin), Do(_Do) {}
    /*функция     setup
      описание    иницилизация
      ввод        нет
      вывод       нет
    */
    void setup() {
      pinMode(pin, INPUT);
      btn = digitalRead(pin);
    }
    /*функция     loop
      описание    для нормальной работы вставить в тело loop()
      ввод        нет
      вывод       нет
    */
    void loop() {
      bool newBtn = digitalRead(pin);
      if (bounce && newBtn != btn) {
        bounce = 1;
      }
      if (!bounce && mill - past >= 10) {
        past = mill;
        bounce = 0;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) (*Do)();
      }
    }
};
//----компановка------------------------------------------------
void Do_Btn() {
  music(1);// проиграть музыку
}
Cl_Btn Btn(/*пин*/2,/*обработчик*/Do_Btn);
//---mail()-------------------------------------------------
void setup() {
  Btn.setup();
}
void loop() {
  mill = millis();
  Btn.loop();
  music(0);
}
/*Скетч использует 3558 байт (11%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 445 байт (21%) динамической памяти, оставляя 1603 байт для локальных переменных. Максимум: 2048 байт.
*/

 

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

Лучше. Только melody ну никак не массив интов. Массив должен состоять из однотипных величин, а у вас там вперемешку частоты и длительности (тот факт что они  инт влезли еще не означает их однотипность). Заведите соответствующую структуру и melody массив структур. Строки 88-91 и 96-98 подозрительно похожи, не так ли? Ну и void music(byte num) тоже полезно в класс, аналогичный Btn. А если бы они оба наследовали один базовый класс с абстрактным сетапом и лопом то все бы стало еще интересней.

Про архитектуру и как ложится - не переживайте, ляжет. Только напишите ;)  

 

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

Logik пишет:

один базовый класс с абстрактным сетапом и лопом

Про это ТС говорили ещё месяц назад, но, похоже, здесь принципиальное неприятие :)

b707
Онлайн
Зарегистрирован: 26.05.2017

qwone пишет:

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

согласен