Как заставить серву добавлять или убирать 5-10 градусов по нажатию двух кнопок.

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017
История такая: обьект двигается, при достижении цели запускается серво и поворачивается на 45 градусов.
 
После чего оператор должен иметь возможность изменить этот угол в + или -.
шаг 5 градусов и есть ограничение в максимальном значении 30 градусов и 65.
 
Никак не могу понять как это сделать (((
ардурино только осваиваю...
 
Только недавно понял как вообще заставить программу "подождать" до нажатия на кнопку что бы по кругу все не крутилось))  сделал это с помощью while.
Кстати как еще можно затормозить исполнение ?
 
 
 
 
#include <Servo.h>
//моторы
const int en1 = 11;//Двигатель
const int in2 = 7;
const int in6 = 6;
 
int button2 = 2; //КНОПКА2
int buttom4= 4; //КНОПКА4
int i;
int b;
 
//серво
Servo myservo;
Servo myservo2;
 
void setup()
{
  digitalWrite (in2,LOW);
  digitalWrite (in6,HIGH);
  analogWrite (en1, 255);
  myservo.attach(9);
  myservo2.attach(10);
  Serial.begin (9600);
  pinMode (buttom4, OUTPUT);
  pinMode (button2, OUTPUT);
 
}
 
 
 
void loop()
  
{
    int RESULT;
  myservo.write (45);//серва которая поворачивает
  
  while (digitalRead(button2) != HIGH)//цикл который не дает программе завериться и в нем планировалось дать возможность оператору менять угол.
  {
    delay (250);
    i= myservo.read();
   
    if (digitalRead (buttom4) == HIGH)//наращиваем угол
    {
      
     ++i;
     myservo.write (i);
      
    Serial.print(i); 
    Serial.println();
    if   (i>55) //вроде как ограничение угла
    {
    i=56;
    }
    }
  }
}
 
 
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А у меня это гранаты не той системы. Блин оговорился код не такой.

/*Cl_Btn.ino
  серво 1    --> 4
  серво 2    --> 5
  кнопка '+' --> 2
  кнопка '-' --> 3
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//-----Cl_Servo-----------------
#include <Servo.h>
class Cl_Servo {
    byte pin;// нога на которой сидит серва
    Servo *motor;
    int angl;
    byte step;
  public:
    //
    // указатель на следующий элемент
    Cl_Servo *pnt;
    // конструктора
    Cl_Servo(Cl_Sys *Sys, byte _pin, int _angl, byte _step);
    void setup() {
      motor = new Servo;
      motor->attach(pin);
      write(angl);
    }
    // setup()
    void loop() {
    }
    // write();
    void write(int _angl) {
      if (_angl > 180)_angl = 180;
      if (_angl < 0)  _angl = 0;
      motor->write(angl = _angl);
    }
    //
    void plus() {
      write(angl + step);
    }
    //
    void minus() {
      write(angl - step);
    }
};
//-----Cl_Btn-----------------
class Cl_Btn {
    byte pin; // номер ноги на кнопке
    void (* Do)();// указатель на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_Btn *pnt = NULL;
    // конструктора
    Cl_Btn() {}
    Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)());
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    // setup()
    void loop() {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ;                   // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do();
      }
    }
};
//-----Cl_Sys-----------------
class Cl_Sys {
  public:
    Cl_Btn   *Start_Btn   = NULL;
    Cl_Servo *Start_Servo = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      for (Cl_Servo *i = Start_Servo; i != NULL; i = i->pnt) i->setup();
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->setup();
    }
    void loop() {
      for (Cl_Servo *i = Start_Servo; i != NULL; i = i->pnt) i->loop();
      for (Cl_Btn *i = Start_Btn; i != NULL; i = i->pnt) i->loop();
    }
} Sys;
//---------описание классов------------
Cl_Servo::Cl_Servo(Cl_Sys *Sys, byte _pin, int _angl, byte _step): pin(_pin), angl(_angl), step(_step) {
  pnt = Sys->Start_Servo;
  Sys->Start_Servo = this;
}
Cl_Btn::Cl_Btn(Cl_Sys *Sys, byte _pin, void (* _Do)()): pin(_pin), Do(_Do) {
  pnt = Sys->Start_Btn;
  Sys->Start_Btn = this;
}
//----------Компоновка---------------------
Cl_Servo *myServo  = new Cl_Servo(&Sys,/*пин*/4,/*нач угол */45,/*шаг поворота*/5); // создать Servo_1
Cl_Servo *myServo1 = new Cl_Servo(&Sys,/*пин*/5,/*нач угол */90,/*шаг поворота*/5); // создать Servo_2
void Do_Btn1() {
  myServo ->plus();
  myServo1->plus();
}
void Do_Btn2() {
  myServo ->minus();
  myServo1->minus();
}
Cl_Btn *Btn_1 = new Cl_Btn(&Sys,/*пин*/2,/*обработчик*/Do_Btn1); // создать кнопку Btn_1
Cl_Btn *Btn_2 = new Cl_Btn(&Sys,/*пин*/3,/*обработчик*/Do_Btn2); // создать кнопку Btn_2
//-----------Main()-----------------------
void setup() {
  Sys.setup();
}

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

 

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

Я только пару недель как осваиваю arduino и с программированием только знакомлюсь. Спасибо за ответ, пока для меня ваш код не четабелен :) пойду книжки почитаю. 

Кстати если написать банальный код аля:

Он имеет право на жизнь?:)

 while (digitalRead(button2) != HIGH)//цикл который не дает программе завериться и в нем планировалось дать возможность оператору менять угол.
  {
 if (digitalRead (buttom2HI) == HIGH || i==1) //кнопка +1 к углу при i==1
{
++i;
}

 if (digitalRead (buttom2HI) == HIGH || i==2)
{
++i;
}

if (digitalRead (buttom1LOW) == HIGH || i==1) //кнопка -1 к углу при i==1
{
--i;
}

if (digitalRead (buttom1LOW) == HIGH || i==2)
{
--i;
}
}

 

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

Андрей PV пишет:
Он имеет право на жизнь?:)

Попробуй поймешь. Пронраммирование это наука практическая. Не важно, что вам могут наговорить, зальете код и вам станет ясно. И да , маленькое замечание. Легкая планка входа в Ардуину ведет в никуда, топтание на месте. Так что если хотите пользы от Ардуины, берите серьезные книги, а не лабуду от Джереми Блюма и прочих.

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

Спасибо за ценный совет! Я почти сразу заподозрил неладное, вы мои сомнения подтвердили.

Если не сложно посоветуйте книгу для начинающих.

 

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

Андрей PV пишет:
Если не сложно посоветуйте книгу для начинающих.

Не считайте это за издевку. Но начинайте с этого. http://cpp.com.ru/ И да ссылку кидайте в закладки. Потому что это справочный материал, а не прочитал и выкинул. Сам регулярно откровения там нахожу.

Сразу изучайте указатели всех видов.

ПС: 

/*.ino
  реле на вентилятор 1 -->2 (Fan1_pin)
  реле на вентилятор 2 -->3 (Fan2_pin)
  lcd1602_I2C
  таймер обратного счета
  светодиод 1          -->8  (Led1_pin)
  светодиод 2          -->9  (Led2_pin)
  светодиод 3          -->10 (Led3_pin)
  светодиод 4          -->A0 (Led4_pin)
  светодиод 5          -->A1 (Led5_pin)
  светодиод 6          -->A2 (Led6_pin)
  светодиод 7          -->13 (Led7_pin)
  кнопка 1             -->4 (btn1_pin)  кнопка смена режима /режим 10мин,20минут 40минут
  кнопка 2             -->5 (btn2_pin)  кнопка смена режима / режим 1,режим2,режим3
  кнопка 3             -->6 (btn3_pin)  кнопка старт
  кнопка 4             -->7 (btn4_pin)  кнопка стоп
  Принцип кода: Кнопкой btn1 меняется режим 10мин,20минут 40минут
                Кнопкой btn2 меняется режим вид работы
                Кнопкой btn3 меняется запуск
                Кнопкой btn4 меняется стоп
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//------------------------ Cl_back_timer ----------------------------------
// класс  таймер
class Cl_back_timer {
    uint32_t mill;
    bool stat;// 0 стоит /1 обратный счет
    void (* Do1)(), (* Do2)();
    uint32_t time ;
    void convert_time() {
      minute = time / 60000;
      sec = time / 1000 - minute * 60;
    }
    const uint32_t interval = 1000;// цикл обновления показаний
    uint32_t past = 0;
    uint32_t past_end;
  public:
    // указатель на следующий элемент
    Cl_back_timer *pnt;
    // конструктор
    Cl_back_timer(Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      mill = millis();
      if (stat && mill - past >= interval) {
        past = mill;
        if (time > interval) {
          time -= interval;
          convert_time();
          Do1();
        } else {
          stat = 0;
          Do2();
        }
      }
    }
    void Start() {
      stat = 1;
      past = millis();
      time = time_start;
    }
    void Stop() {
      stat = 0;
    }
    byte sec;
    byte minute;
    uint32_t time_start = 10000;
};
// ------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 1 обработчиком
class Cl_do_btn {
    byte pin ; // нога
    bool inv; // инверсия
    void (*Do)();
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    // указатель на следующий элемент
    Cl_do_btn *pnt;
    // конструктор
    Cl_do_btn(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)());
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без внут подтяжки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin) ; // прочитать реальное значение на выводе
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce_btn && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce_btn = 1;                                 // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_btn = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) Do()  ;
      }
    }
};
//------------------------ Cl_do_btn_3mode ----------------------------------
// класс  кнопка с 3 выборами
#include <EEPROM.h>
class Cl_do_btn_3mode {
    int adrEEPROM;
    byte pin ;// нога
    bool inv; // инверсия
    void (*Do1)(), (*Do2)() , ( *Do3)();
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
    byte mode;// 0,1,2 режим
  public:
    // указатель на следующий элемент
    Cl_do_btn_3mode *pnt;
    // конструктор
    Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      //pinMode(pin, INPUT);// подключить кнопку 1 без подтязки
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      bounce = 0 ;
      btn_old = 1 ;
      btn = digitalRead(pin)^inv ; // прочитать реальное значение на выводе
      byte _mode = EEPROM.read(adrEEPROM);
      if (_mode == 0 || _mode == 1 || _mode == 2  )mode = _mode;
      else mode = 0;
      EEPROM.update(adrEEPROM, mode);
      if (mode == 0) Do1();
      else if (mode == 1) Do2();
      else Do3();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (! bounce && btn != (digitalRead(pin)^  inv)) { // если прошел фронт изм на выводн
        bounce = 1;                                      // выставить флаг
        past = millis();                                 // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin)^  inv ; // прочитать реальное значение на выводе
        if (btn_old && ! btn) {
          (mode >= 2) ? mode = 0 : mode++;
          if (mode == 0) Do1();
          if (mode == 1) Do2();
          if (mode == 2) Do3();
        }
      }
    }
    // поставить в нужный режим
    void Set_mode(int _mode) {
      switch (_mode) {
        case 0:
          mode = 0;
          Do1();
          break;
        case 1:
          mode = 1;
          Do2();
          break;
        case 2:
          mode = 2;
          Do3();
          break;
      }
    }
};
//------------------------ Cl_fan ----------------------------------
// класс  вентилятор
class Cl_fan {
    uint32_t time_work_old; //время работы 10 минут
    uint32_t time_pulse_old; //время полного импульса 1 минута
    uint32_t time_pulse_ON_old; //время работы в течении импульса 0,5 нинут
    byte pin; // нога
    bool inv; // инверсия
    bool stat;
    bool work;
    uint32_t past_pulse;
    uint32_t past_work;
  public:
    // указатель на следующий элемент
    Cl_fan *pnt;
    // конструктор
    Cl_fan(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
      pinMode(pin, OUTPUT);
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (work && millis() - past_pulse >= time_pulse_old) {
        past_pulse = millis();
        stat = 1;
        digitalWrite(pin, stat ^ inv);
      }
      if (stat && millis() - past_pulse >= time_pulse_ON_old) {
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
      if (work && millis() - past_work >= time_work_old) {
        work = 0;
        stat = 0;
        digitalWrite(pin, stat ^ inv);
      }
    }
    void ON() {
      time_work_old = time_work;
      time_pulse_old = time_pulse;
      time_pulse_ON_old = time_pulse_ON;
      past_work = millis();
      work = 1;
      past_pulse = millis();
      stat = 1;
      digitalWrite(pin, stat ^ inv);
    }
    void OFF() {
      work = 0;
      stat = 0;
      digitalWrite(pin, stat ^ inv);
    }
    uint32_t time_work = 600000; //время работы 10 минут
    uint32_t time_pulse = 60000; //время полного импульса 1 минута
    uint32_t time_pulse_ON = 30000; //время работы в течении импульса 0,5 нинут
};
//------------------------ Cl_led ----------------------------------
// класс  светодиод
class Cl_led {
    byte pin ;// нога
    bool inv; // инверсия вывода
    bool led;// 0 откл / 1 вкл
    bool stat_blink;// 1 мигает/0 нет
    uint32_t past = 0;
    uint32_t time_blink = 500;
  public:
    // указатель на следующий элемент
    Cl_led *pnt;
    // конструктор
    Cl_led(Cl_Sys *Sys, byte _pin, bool _inv);
    // setup()
    void setup() {
      if (this->pnt != NULL) this->pnt->setup();
      pinMode(pin, OUTPUT);// подключить светодиод
      OFF();
    }
    // loop()
    void loop() {
      if (this->pnt != NULL) this->pnt->loop();
      if (stat_blink && millis() - past >= time_blink) {
        past = millis();
        digitalWrite(pin, led = ! led) ;
      }
    }
    // включить
    void ON() {
      stat_blink = 0;
      digitalWrite(pin, led = 1 ^ inv) ; // зажечь
    }
    // выключить
    void OFF() {
      stat_blink = 0;
      digitalWrite(pin, led = 0 ^ inv) ; // погасить
    }
    // начать мигать
    void blink() {
      stat_blink = 1;
      past = millis();
    }
    // начать мигать с опред полупериодом
    void blink(uint32_t time) {
      time_blink = time;
      stat_blink = 1;
      past = millis();
    }
};
//-----------------class Cl_sys---------------------------
class Cl_Sys {
  public:
    Cl_back_timer    *Start_back_timer   = NULL;
    Cl_do_btn        *Start_do_btn       = NULL;
    Cl_do_btn_3mode  *Start_do_btn_3mode = NULL;
    Cl_fan           *Start_fan          = NULL;
    Cl_led           *Start_led          = NULL;
    Cl_Sys() {}
    // setup()
    void setup() {
      Start_back_timer  ->setup();
      Start_do_btn      ->setup();
      Start_do_btn_3mode->setup();
      Start_fan         ->setup();
      Start_led         ->setup();
    }
    // loop()
    void loop() {
      Start_back_timer  ->loop();
      Start_do_btn      ->loop();
      Start_do_btn_3mode->loop();
      Start_fan         ->loop();
      Start_led         ->loop();
    }
} Sys;
//---------описание классов------------
Cl_back_timer  ::Cl_back_timer  (Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()): Do1(_Do1), Do2(_Do2), pnt(NULL) {}
Cl_do_btn      ::Cl_do_btn      (Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)()): pin(_pin), inv(_inv), Do(_Do), pnt(NULL) {}
Cl_do_btn_3mode::Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM)
  :                                            pin(_pin), inv(_inv),    Do1(_Do1),       Do2(_Do2),       Do3(_Do3), adrEEPROM(_adrEEPROM), pnt(NULL) {}
Cl_fan         ::Cl_fan         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
Cl_led         ::Cl_led         (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {}
//----------Компоновка---------------------
const uint32_t time_20sec =   20000; //время 20 секунд
const uint32_t time_30sec =   30000; //время 30 секунд
const uint32_t time_1min  =   60000; //время 1 минуты
const uint32_t time_3min  =  180000; //время 3 минуты
const uint32_t time_10min =  600000; //время работы 10 нинут
const uint32_t time_20min = 1200000; //время работы 20 нинут
const uint32_t time_40min = 2400000; //время работы 40 нинут
// вентилятор
Cl_fan *Fan1 = new Cl_fan(&Sys,/*пин*/2,/*инверсия*/0);// подключить реле вентилятора на выв 2, вкл если на выв 1
Cl_fan *Fan2 = new Cl_fan(&Sys,/*пин*/3,/*инверсия*/0);// подключить реле вентилятора на выв 3, вкл если на выв 1
// таймер обратного счета
void Do1_Back_timer();
void Do2_Back_timer();
Cl_back_timer *Back_timer = new Cl_back_timer(&Sys,/*обработчик*/ Do1_Back_timer, /*обработчик*/ Do2_Back_timer );
void Do1_Back_timer() {  // отправить текущие показания
  lcd.setCursor(6, 0);
  if (Back_timer->minute < 10)lcd.print("0");
  lcd.print(Back_timer->minute);
  lcd.print(":");
  if (Back_timer->sec < 10)lcd.print("0");
  lcd.print(Back_timer->sec);
}
void Do2_Back_timer() { // отправить последнее сообщение
  lcd.setCursor(6, 0);
  lcd.print(" END ");
}
// светодиоды для 1 выбора режима
Cl_led *Led1 = new Cl_led(&Sys,/*пин*/8 ,/*инверсия*/ 0);// подключить светодиод на выв 8 , горит если на выв 0
Cl_led *Led2 = new Cl_led(&Sys,/*пин*/9 ,/*инверсия*/ 0);// подключить светодиод на выв 9 , горит если на выв 0
Cl_led *Led3 = new Cl_led(&Sys,/*пин*/10,/*инверсия*/0);// подключить светодиод на выв 10, горит если на выв 0
// светодиоды для 2 выбора режима
Cl_led *Led4 = new Cl_led(&Sys,/*пин*/A0,/*инверсия*/0);// подключить светодиод на выв A0, горит если на выв 0
Cl_led *Led5 = new Cl_led(&Sys,/*пин*/A1,/*инверсия*/0);// подключить светодиод на выв A1, горит если на выв 0
Cl_led *Led6 = new Cl_led(&Sys,/*пин*/A2,/*инверсия*/0);// подключить светодиод на выв A2, горит если на выв 0
// индикатор работа
Cl_led *Led7 = new Cl_led(&Sys,/*пин*/13,/*инверсия*/0);// подключить светодиод на выв 13, горит если на выв 0
// кнопка 1
void Do1_Btn1() {
  Fan1->time_work = time_10min;
  Fan2->time_work = time_10min;
  Back_timer->time_start = time_10min;
  Led3->OFF();
  Led1->ON();
  lcd.setCursor(0, 0);
  lcd.print("10min");
}
void Do2_Btn1() {
  Fan1->time_work = time_20min;
  Fan2->time_work = time_20min;
  Back_timer->time_start = time_20min;
  Led1->OFF();
  Led2->ON();
  lcd.setCursor(0, 0);
  lcd.print("20min");
}
void Do3_Btn1() {
  Fan1->time_work = time_40min;
  Fan2->time_work = time_40min;
  Back_timer->time_start = time_40min;
  Led2->OFF();
  Led3->ON();
  lcd.setCursor(0, 0);
  lcd.print("40min");
}
Cl_do_btn_3mode *Btn1 = new Cl_do_btn_3mode(&Sys,/*пин*/4,/*инверсия*/ 0,/*обработчик*/ Do1_Btn1, /*обработчик*/ Do2_Btn1, /*обработчик*/ Do3_Btn1,/*adrEEPROM*/0x00);
//Кнопка 2
void Do1_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_1min;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led6->OFF();
  Led4->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=ON    2=1m/30");
}
void Do2_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_30sec;
  Fan2->time_pulse = time_1min;
  Fan2->time_pulse_ON = time_30sec;
  Led4->OFF();
  Led5->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/30 2=1m/30");
}
void Do3_Btn2() {
  Fan1->time_pulse = time_1min;
  Fan1->time_pulse_ON = time_20sec;
  Fan2->time_pulse = time_3min;
  Fan2->time_pulse_ON = time_30sec;
  Led5->OFF();
  Led6->ON();
  lcd.setCursor(0, 1);
  lcd.print("1=1m/20 2=3m/30");
}
Cl_do_btn_3mode *Btn2 = new Cl_do_btn_3mode(&Sys,/*пин*/5,/*инверсия*/ 0,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*обработчик*/ Do3_Btn2,/*adrEEPROM*/0x01);
//Кнопка 3 Пуск
void Do_Btn3() {
  Fan1->ON();
  Fan2->ON();
  Back_timer->Start();
  Led7->blink();
  lcd.setCursor(13, 0);
  lcd.print("ON ");
}
Cl_do_btn *Btn3 = new Cl_do_btn(&Sys,/*пин*/6,/*инверсия*/0,/*обработчик*/ Do_Btn3);
//Кнопка 4 Стоп
void Do_Btn4() {
  Fan1->OFF();
  Fan2->OFF();
  Back_timer->Stop();
  Led7->ON();
  lcd.setCursor(13, 0);
  lcd.print("OFF ");
}
Cl_do_btn *Btn4 = new Cl_do_btn(&Sys,/*пин*/7,/*инверсия*/ 0,/*обработчик*/Do_Btn4);
//-----------Main()-----------------------
void setup() {
  lcd.init();
  lcd.backlight();
  Sys.setup();
}
void loop() {
  Sys.loop();
}

 

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

Спасибо!

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

Спустя месяц понял что такое функции, классы и массивы.

Стал лучше вчитываться в код.

Вас спасибо большое за совет учить с++ а не "простой код на ардуино"! :)

Но вот ваш код пока прочитать все равно не могу... 

    void (* Do)();// указатель на обработчик
 

 

    void (* Do1)(), (* Do2)();
 

 я так понимаю пустая функция получает данные от указателей на класс ?

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
// Вот смотрите
int a; // это переменая
a = 10; // это присвоение перемненной

void (*func)(); // это тоже "переменая" но с типом - может быть записан адресс функции void aaa(void)
// попробуем присвоить этой "переменной" "значение"
void aaa() {  // считайте что это "константа"
}
//тогда
func=aaa;// вот "присвоение"
// ну или так 
func=&aaa;// присвоить переменной func адресс функции aaa()
// ну дальше попробуем
func(); // вот запустилась функция aaa
// преимущество. Можно организовать готовые рабочие модули. А в нужный момент менять их по своему усмотрению, не трогая рабочий код

 

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

А по какой причине два разных указателя могут иметь один адрес в оперативной памяти.

Сегодня пытался вытащить несколько значений из функции с помощью  указателя и почему то они имеют один адрес в оперативке соответственно и значение одно.

Так и не понял в чем дело((

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

Андрей PV пишет:

А по какой причине два разных указателя могут иметь один адрес в оперативной памяти.

О чем вы?
void (* Do1)(), (* Do2)();
это тоже самое что и
void (* Do1)();
void (* Do2)();
просто Си допускает и такую запись.
Вот у вас класс кнопка. При нажатии сделать одну функцию, при отжатии другую. Вот их и вносят в константы представителя класса при инициализации


 

Вот пример кнопка 1 но первое нажатие сделать это 2 это и 3 это.

/* Cl_Mech_BTN_3mode.ino
  кнопка1    ардуина
  пин 1 <==> пин 2 программная подтяжка
  пин 2 <==> GND
*/
class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему
//----------------Cl_Mech_BTN_3mode------------------------------------------------------------
// класс на механич кнопку выбирающую 3 варианта последовательно и записыв в памяти
#include <EEPROM.h>
class Cl_Mech_BTN_3mode {
    int adrEEPROM;
    byte pin; // номер ноги на кнопке
    bool inv; // инверсия вывода
    void (*Do1)(), (*Do2)() , ( *Do3)();// указатели на обработчик
    bool btn, btn_old;
    bool bounce = 0; // антидребезговый флаг
    uint32_t past = 0 ;
    byte mode;// 0,1,2 режим
  public:
    //указатель на следующий компонент
    Cl_Mech_BTN_3mode *pnt_Mech_BTN_3mode;
    //конструктор
    Cl_Mech_BTN_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM);
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin)^inv; // прочитать реальное значение на выводе};
      byte _mode = EEPROM.read(adrEEPROM);
      if (_mode == 0 || _mode == 1 || _mode == 2 )mode = _mode;
      else mode = 0;
      EEPROM.update(adrEEPROM, mode);
      if (mode == 0) Do1();
      else if (mode == 1) Do2();
      else Do3();
    }
    void loop () {
      if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce = 1;                              // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce = 0;                                // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin)^inv ;                   // прочитать реальное значение на выводе
        if (btn_old && !btn) {
          byte _mode = EEPROM.read(adrEEPROM);
          ++_mode;
          if (_mode == 0 || _mode == 1 || _mode == 2 )mode = _mode;
          else mode = 0;
          EEPROM.update(adrEEPROM, mode);
          if (mode == 0) Do1();
          else if (mode == 1) Do2();
          else Do3();
        }
      }
    }
};
//----------------Cl_Sys------------------------------------------------------------
class Cl_Sys {
  public:
    // указатели на блоки однотипных классов в системе
    Cl_Mech_BTN_3mode * Start_Mech_BTN_3mode = NULL;
    void setup() {
      for (Cl_Mech_BTN_3mode *i = Start_Mech_BTN_3mode; i != NULL; i = i->pnt_Mech_BTN_3mode) i->setup();
    }
    void loop () {
      for (Cl_Mech_BTN_3mode *i = Start_Mech_BTN_3mode; i != NULL; i = i->pnt_Mech_BTN_3mode)  i->loop ();
    }
};
//-----------------конструкторы классов входящих в систему-------------------------------
Cl_Mech_BTN_3mode::Cl_Mech_BTN_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM)
  :                                                pin(_pin), inv(_inv),    Do1(_Do1),       Do2(_Do2),       Do3(_Do3), adrEEPROM(_adrEEPROM) {
  pnt_Mech_BTN_3mode = Sys->Start_Mech_BTN_3mode;
  Sys->Start_Mech_BTN_3mode = this;
}
//------------------компоновка-------------------------------------------------------
Cl_Sys *Sys = new Cl_Sys();
void Do1_BTN1() {
  Serial.println("Do1_BTN1");
}
void Do2_BTN1() {
  Serial.println("Do2_BTN1");
}
void Do3_BTN1() {
  Serial.println("Do3_BTN1");
}
Cl_Mech_BTN_3mode *BTN1 = new Cl_Mech_BTN_3mode(Sys,/*пин*/2,/*инверсия*/0,/*обработчик1*/Do1_BTN1,/*обработчик2*/Do2_BTN1, /*обработчик3*/Do3_BTN1,/*adrEEPROM*/0x00);// создать кнопку BTN1
//------------------ main()----------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Sys->setup();
}

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

}

 

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

Если вам сложен этот код скачайте и запустите эту папку https://yadi.sk/d/OhKUoDQ93FuSL3

Головной файл выкладываю 

/* Class_do_btn.ino 
  #1 кнопка ->2
  #2 кнопка ->3
  #3 кнопка ->4
  Принцип кода:нажал на кнопку , отправилось сообщение в сериал
*/
//#1 кнопка 1
#include "Cl_do_btn.h"
const byte btn1_pin = A2;
void Do_Btn1() {
  Serial.println("Press Bottom 1");
}
Cl_do_btn Btn1(btn1_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn1   );  // какую функцию надо сделать
//#2 кнопка 2
const byte btn2_pin = 3;
void Do_Btn2() {
  Serial.println("Press Bottom 2");
}
Cl_do_btn Btn2(btn2_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn2   );  // какую функцию надо сделать
//#3 кнопка 3
const byte btn3_pin = 4;
void Do_Btn3() {
  Serial.println("Press Bottom 3");
}
Cl_do_btn Btn3(btn3_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn3   );  // какую функцию надо сделать
void setup() {
  Serial.begin(9600);
  Btn1.setup();
  Btn2.setup();
  Btn3.setup();
}
void loop() {
  Btn1.loop();
  Btn2.loop();
  Btn3.loop();
}

 

Андрей PV
Андрей PV аватар
Offline
Зарегистрирован: 30.05.2017

Спасибо буду тестить :)

Кстати если вдруг нужно что-нибудь для ардуино, у меня свое рекламное произвоство и есть лазер.

Могу вырезать что-нибудь бесплатно )

Я вот для себя наделал разные полочки и подставки для работы с ардуинкой.