Посмотрите/Оцените/Покритикуйте/Похвалите (класс для светодиода)

Евжений
Offline
Зарегистрирован: 04.01.2019

Доброго времени суток и с наступившим НГ. Решил делать свой первый самостоятельный проект на ардуинке. Среди прочего потребуется "помигать светодиодами" (почему бы и нет :) ). По классике в первой версии delay()... Но потом понял что это не хорошо, да и неудобно. Погуглил, но ничего особо не нашел (да и не особо старался, если честно). Попробовал написать класс самостоятельно. Оно вроде работает, но все же прошу оценить/подсказать, ежели что не так.

И на сколько такой класс может быть востребован? Есть идея доделать его до уровня библиотеки. Стоит ли продолжать, так сказать.


class LED {
  public:
    LED(byte ledPin = LED_BUILTIN);
    void ON();
    void OFF();
    void autoBlink(bool state, word delayON = 1000, word delayOFF = 1000);
    bool autoBlink() {return _autoBlink; };
    bool state() { return _state; } ;
    void update();
  private:
    byte _ledPin;
    bool _state = false;
    bool _autoBlink = false;
    word _delayON, _delayOFF;
    unsigned long interval, cMillis, pMillis;
};

LED::LED(byte ledPin) {
  _ledPin = ledPin;
  pinMode(ledPin, OUTPUT);
}

void LED::ON() {
  _state = true;
  digitalWrite(_ledPin, HIGH);
}

void LED::OFF() {
  _state = false;
  digitalWrite(_ledPin, LOW);
}

void LED::autoBlink(bool state, word delayON, word delayOFF) {
  _autoBlink = state;
  _delayON = delayON;
  _delayOFF = delayOFF;

  if (state) 
    pMillis = millis();

}

void LED::update() {

  if (_autoBlink) {
    cMillis = millis();
    interval = cMillis - pMillis;
    interval = abs(interval);
  
    if (!_state && interval >= _delayOFF) {
      pMillis = cMillis;
      ON();
    }
    else if (_state && interval >= _delayON) {
      pMillis = cMillis;
      OFF();
    }
  }
  
}

LED led;

void setup() {
  led.autoBlink(true, 100, 2000);
}

void loop() {
  led.update();
}

 

Евжений
Offline
Зарегистрирован: 04.01.2019

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

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

Евжений пишет:
И на сколько такой класс может быть востребован? Есть идея доделать его до уровня библиотеки. Стоит ли продолжать, так сказать.
Ну и так далее http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

Осталось вам освоить автоматное программирование и можете писать программы посложнее.

Евжений
Offline
Зарегистрирован: 04.01.2019

qwone пишет:

Ну и так далее http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

Осталось вам освоить автоматное программирование и можете писать программы посложнее.

Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?

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

Евжений пишет:

Ну я нутром чуял, что велосипед изобретаю :) 

Велосипед уже есть, титановый :-)

kalapanga
Offline
Зарегистрирован: 23.10.2016

Евжений, а что должна сделать функция abs() с аргументом типа unsigned long? Что-то Вы там с миллис намудрили по-моему.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Евжений пишет:

Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?

 

Ну, для начала, очень неплохо. Разве что строчка N48 лишняя. Но на библиотеку, пока, не тянет. Начинайте использовать в своих проектах. По мере добавления функционала, может и дорастет до библиотеки.

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

Евжений пишет:

Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?

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

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

Евжений, сколько Вам лет?

Это я к тому, чтобы понять как с Вами разговаривать.

Евжений
Offline
Зарегистрирован: 04.01.2019

Ну да, с abs и unsigned я погорячился :) Спасибо.

Лет мне 40. Программирую я давно. Вот с ардуино у меня "первая любовь"... Да и c++ не мой фаворит :)

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

Рассматривайте мою тему не как эталон, или "классику". Просто я раньше вас начал копать в этом направлении. И эта тема это "часть моих изысканий" . И если бы я сейчас писал этот класс, то писал так.

/**/
class Cl_Led {
  protected:
    byte pin;
    unsigned long past, time;
    enum state_t {sOFF = 0, sON, sOFF_Blink, sON_Blink} state;
    void stand(state_t s) {
      state = s;
      past = millis();
      switch (state) {
        case sOFF:
          digitalWrite(pin, LOW);
          break;
        case sON:
          digitalWrite(pin, HIGH);
          break;
        case sOFF_Blink:
          digitalWrite(pin, LOW);
          break;
        case sON_Blink:
          digitalWrite(pin, HIGH);
          break;
      }
    }
  public:
    Cl_Led(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      stand(sOFF);
    }
    void run() {
      switch (state) {
        case sOFF:
          break;
        case sON:
          break;
        case sOFF_Blink:
          if (millis() - past >= time) stand(sON_Blink);
          break;
        case sON_Blink:
          if (millis() - past >= time) stand(sOFF_Blink);
          break;
      }
    }
    void ON() {
      stand(sON);
    }
    void OFF() {
      stand(sOFF);
    }
    void blink(unsigned long t = 1000) {
      time = t;
      stand(sON_Blink);
    }
};
//-----компоновка---------------------------
Cl_Led Led(/*пин*/13);
//-----main()---------------------------
void setup() {
  Led.init();
  Led.blink(200);
}
void loop() {
  Led.run();
}
/**/

А конструктивно это или нет решайте сами.

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

Ну, если давно программируете, то ... держите :))) То что подростку списалось бы ...

Про abs не буду ибо уже боян. А про остальное, поехали...

  1. Экземпляр Вашего класса занимает 19 (девятнадцать!!!) байтов памяти. Учитывая, что всего их (байтов) в той же UNO всего 2k (я уж молчу про тиньки). Не многовато для одного светодиода?
    Давайте разбираться почему
    1. Переменные interval и cMillis испольуются только в одном методе update(). Причём в этом методе они сразу получают значения, т.е. сохранять значения между вызовами метода им не нужно. Так почему они не описаны локально? Какого хрена они делают в классе? А я Вам скажу, что они делают – они абсолютно впустую отжирают 8 байтов памяти.
    2. pMillis формально используется в двух методах, но если самую малость перестроить код, то можно спокойно обойтись без её использования в методе autoBlink, и тогда к ней будет применимо всё, сказанное выше. Ещё 4 байта
    3. Зачем нужна переменная state? Пин сам знает своё состояние и умеет его возвращать. Ещё 1 байт.
    4. Итого уже 13 из 19 байтов – лишние

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

  1. Правильно ли я понимаю, что первый параметр метода autoBlink означает «включить» мигание или выключить? Если так, то нафига он в случае «выключить» запоминает значения _delayON и _delayOFF? Контроллеру больше нечем заниматься?
  2. Зачем использовать столь жёсткое ограничение, как private? Вы напрочь лишаете себя возможность создания производных классов (например, для RG или RGB светодиода). Вообще класс без возможности наследования является классом только «по пачпорту», а главная идея ООП в нём убита. Зачем?
  3. (хотел написать, но забыл, дописываю) После выключения мигания светодиод остаётеся в неопределённом состоянии. Конечно, его можно принудительно перевестив нужное дополнительным вызовом ON или OFF, но считаю это архитектурной ошибкой.
Евжений
Offline
Зарегистрирован: 04.01.2019

1. Про память - согласен полностью... Не поспоришь :) 

2. а вот тут поспорю. Тут конечно и ваша правда есть, но мне ничего не мешает написать так:

led.autoBlink(false, 1000, 1000);

Переопределить параметры "моргания", а в следующий раз просто вызвать led.autoBlink(true); Что как бы и не запрещено. Параметр есть - надо отработать.

3. На сколько я проникса классами - в привате описываются внутренние параметры, которые не должны переопределяться из-вне, так сказать. Я уже понял, что на захват мира не тянет. А для разового проэкта - даже слишком хорошо.

з.ы. А вообще я разочаровался :( Не не в ардуинке... В результате который я получил. Раньше у меня был delay()... ну фиг с ним 2-3 раза, что замедляло скорость работы проекта, но на функционал не влияло. Сейчас в погоне за красивым кодом запилил класс, который не замедляет выполнение, что привело к тому, что работать задумка перестала. В итоге ее надо теперь замедлить принудительно. Если писать delay () - то перестает работать корректно моргание. т.е. надо теперь хитрую "замедлялку"... опять небось класс. в итоге проэкт в котором всего было 50 строк разматывается в нечто очень большое и ужасное.

Что бы не было лишних вопросов - что поломалось: фоторезистор снимает показания. маленькие колебания мне не нужны и плавное изменение в течении длительного времени (аля восход и закат солнца), а надо было отследить именно резкое изменение освещенности - включение/выключение света. А лампа с которой я тут эксперементирую с диммером. И получается, что пока я кручу диммер показания плавно растут... и фильтруются.

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

Евжений пишет:
з.ы. А вообще я разочаровался :( Не не в ардуинке... В результате который я получил. Раньше у меня был delay()... ну фиг с ним 2-3 раза, что замедляло скорость работы проекта, но на функционал не влияло. Сейчас в погоне за красивым кодом запилил класс, который не замедляет выполнение, что привело к тому, что работать задумка перестала. В итоге ее надо теперь замедлить принудительно. Если писать delay () - то перестает работать корректно моргание. т.е. надо теперь хитрую "замедлялку"... опять небось класс. в итоге проэкт в котором всего было 50 строк разматывается в нечто очень большое и ужасное.
Рецепт лекарства автоматное программирование.

Евжений
Offline
Зарегистрирован: 04.01.2019

qwone, дайте ссылку уже, где почитать. Гуглил, но хотелось бы прям шоб носом ткнули :)

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

Евжений пишет:

2. а вот тут поспорю. Тут конечно и ваша правда есть, но мне ничего не мешает написать так:

led.autoBlink(false, 1000, 1000);

Переопределить параметры "моргания", а в следующий раз просто вызвать led.autoBlink(true); Что как бы и не запрещено. Параметр есть - надо отработать.

напрасно спорите. Вы не до конца разобрались с языком. Вызов led.autoBlink(false); абсолютно идентичен вызову led.autoBlink(false, 1000, 1000); Нет никакой разницы от слова совсем.

Так что, поверьте, здесь спорить неочем. Если Вы не согласны - перечитайте описание языка и читайте пока не поймёте. Эти два присваивания у Вас выполнятся ВСЕГДА, т.е. при выключении они -  лишние.

Евжений пишет:

3. На сколько я проникса классами - в привате описываются внутренние параметры, которые не должны переопределяться из-вне, так сказать. 

Почитайте ещё и про protected и попытйтесь понять разницу.

Евжений пишет:

Сейчас в погоне за красивым кодом запилил класс, который не замедляет выполнение, что привело к тому, что работать задумка перестала. В итоге ее надо теперь замедлить принудительно. Если писать delay () - то перестает работать корректно моргание. т.е. надо теперь хитрую "замедлялку"... опять небось класс. в итоге проэкт в котором всего было 50 строк разматывается в нечто очень большое и ужасное.

Что бы не было лишних вопросов - что поломалось: фоторезистор снимает показания. маленькие колебания мне не нужны и плавное изменение в течении длительного времени (аля восход и закат солнца), а надо было отследить именно резкое изменение освещенности - включение/выключение света. А лампа с которой я тут эксперементирую с диммером. И получается, что пока я кручу диммер показания плавно растут... и фильтруются.

Ничего не понял, но если Вам нужно фильтровать значения, так фильруйте, а не замедляйте программу. Напишите фильтр и пусть фильтрует :)

Евжений
Offline
Зарегистрирован: 04.01.2019

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

напрасно спорите. Вы не до конца разобрались с языком. Вызов led.autoBlink(false); абсолютно идентичен вызову led.autoBlink(false, 1000, 1000); Нет никакой разницы от слова совсем.

Так что, поверьте, здесь спорить неочем. Если Вы не согласны - перечитайте описание языка и читайте пока не поймёте. Эти два присваивания у Вас выполнятся ВСЕГДА, т.е. при выключении они -  лишние.

Не удачный пример привел... Просто я забыл, что у меня 1000 в дефолте стоит. Не суть. Я имею в виду, что могу при отключении определять параметры мигания для следующего включения. Вот. И это имеет право на жизнь. Все зависит от задачи.

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

Почитайте ещё и про protected и попытйтесь понять разницу.

Инкапсуляция... Наследование... Полиморфизм... protected... virtual... abstract... там голова треснет :) Я все это когда то учил. Только давно это было :) Так сказать, как смог - вспомнил.

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

Ничего не понял, но если Вам нужно фильтровать значения, так фильруйте, а не замедляйте программу. Напишите фильтр и пусть фильтрует :)

Так вот в том то и дело. Было кода мало - все работало. Дописал еще чуть-чуть... теперь надо еще дописывать... Хотя блин все уже работало и без класса. Вот в чем спич.

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

Евжений пишет:

qwone, дайте ссылку уже, где почитать. Гуглил, но хотелось бы прям шоб носом ткнули :)

ТАк просто не выйдет.http://arduino.ru/forum/otvlechennye-temy/private-property-no-trespassing

Но скорее Вам надо что-то виде автомата Пуха. Но такой темы нет. Не написал. Так что почитайте это #27 и #26

Может поможет. Да и не пугайтесь объема кода и текста исходника . Главное что бы вы в этом объеме не потерялись.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Мне вот интересно, неужели никто из кодописателей никогда не управлял яркостью светодиода посредством ШИМ?

Или никогда не подключал светодиоды через 595 регистр?

Если для включения/выключения светодиода всегда используется digitalWrite(), то класс здесь совершенно не нужен, т.к. явно избыточен. А вот если необходимо единообразно работать с двумя-тремя сотнями светодиодов, часть из которых подключены непосредственно к Ардуине, а часть - к регистрам (или внешнему ШИМ-контроллеру), то ради такой унификации может иметь смысл и написать класс.

Должен же класс иметь хоть какой-то практический смысл кроме чисто учебного.

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

и еще, тут никто не сказал, счас у тебя светодиод зажигается высоким уровнем, а это не всегда так.  Иногда устройство, а светодиод это именно исполнительное устройство, управляется нулем, а не единицей.  Как это отразить в классе?

 

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

Евжений пишет:

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

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

Евжений пишет:

Так вот в том то и дело. Было кода мало - все работало. Дописал еще чуть-чуть... теперь надо еще дописывать... Хотя блин все уже работало и без класса. Вот в чем спич.

Если использовать классы там, где они не нужны и так, что они перестают быть объктами ООП, то от них никогда толку не бывает. Это тот самый случай. Очень удачный пример.

Евжений
Offline
Зарегистрирован: 04.01.2019

Спасибо за оценку. Постараюсь все учесть.

qwone, автомат получился у меня? Или так же как и класс (я его подправил. попытку на "универсальность" выкинул - он под конкретную задачу теперь)... На сколько я понял - нам надо пройти по цепочке - никуда не сворачивая, вополняя каждое действие (исключения возможны конечно, но не в данном случае). Итак, автоматический освежитель воздуха. Ну да... захотелось :) Ждем включения света, ждем выключения света, пшикаем, пауза (1 минута - что бы ребенок щелкающий светом не устроил газовую камеру). После паузы - опять ждем включения света. Вроде можно просто сразу ждать выключения... Но мне с включением больше нравится.

#define diffLight 200
#define pinLight  A0

unsigned long pMillis = 0;
int lastLight = - 1;
bool activateFresh = false;
bool pause = false;
enum actions { act_WAITON, act_WAITOFF, act_FRESH, act_PAUSE } state;

class LED {
  protected:
    bool blink = false;
    word delayON, delayOFF;
  public:
    LED() { pinMode(LED_BUILTIN, OUTPUT); };
    bool state() { return digitalRead(LED_BUILTIN); };
    void ON (bool disableBlink = true) { if (disableBlink) LED::blink = false; digitalWrite(LED_BUILTIN, HIGH); };
    void OFF(bool disableBlink = true) { if (disableBlink) LED::blink = false; digitalWrite(LED_BUILTIN, LOW);  };
    void autoBlink(word delayON = 100, word delayOFF = 2000) { if (!blink) { LED::blink = true; LED::delayON = delayON; LED::delayOFF = delayOFF; } };
    void update() {
      if ( LED::blink ) {
        if (!LED::state() && millis() - LED::pMillis >= LED::delayOFF ) { LED::pMillis = millis(); LED::ON (false);  }
        if ( LED::state() && millis() - LED::pMillis >= LED::delayON  ) { LED::pMillis = millis(); LED::OFF(false); }
      } 
    };
  private:
    unsigned long pMillis;
};

LED led;

void setup() {
  Serial.begin(9600);
}

void loop() {

  led.update();

  switch (state) { 

    case act_WAITON:
      led.autoBlink();
      if (millis() - pMillis >= 3000) { 
        pMillis = millis();
        if (lightON()) 
          state = act_WAITOFF; 
      }
      break;
 
    case act_WAITOFF:
      led.ON();
      if (millis() - pMillis >= 3000) { 
        pMillis = millis();
        if (lightOFF()) 
          state = act_FRESH; 
      }
      break;
 
    case act_FRESH:
      state = act_PAUSE;
      fresh();
      break;

    case act_PAUSE:
      led.OFF();
      if (millis() - pMillis >= 60000) 
        state = act_WAITON;
      break;
 
    default:
      pMillis = millis();
      state = act_WAITON;
  }

}

bool lightON() {
  int diff = difference();
  if (diff > 0 && diff > diffLight) return true; else return false;
}

bool lightOFF() {
  int diff = difference();
  if (diff < 0 && -diff > diffLight) return true; else return false;
}

// Вык - Вкл +
int difference() {
  int result;
  int currentLight = analogRead(pinLight);
  if ( lastLight < 0 ) result = 0; else result = currentLight - lastLight;

  Serial.print("result: "); Serial.print(result); Serial.print(" = "); Serial.print(lastLight); Serial.print(" - "); Serial.println(currentLight);
  
  lastLight = currentLight;
  return result;
}

void fresh() {

  Serial.println();  
  Serial.println("!!! FRESH !!!");  
  Serial.println();  

}

 

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

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

Для пшикалки надо 3 состояния Ready,ON,Wait - готовность , пшик, и пауза блокирования. А а внутри метода inject - вспрыск проверять состояние Ready и stand(ON) если автомат в этом состоянии и газововой атаки нет.

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

А это, вообще, что? :)))

if (diff > 0 && diff > diffLight) return true; else return false;

Может, нормально написать?

return diff > 0 && diff > diffLight;

 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Метод класса bool state() не изменяет данные класса, по этому должен быть декларирован как bool state() const;
иначе использовать этот метод в константном методе другого класса не получится (если не указан -fpermissive).
Для отладочных плат на ядре авр в платформ.тхт любят злоупотреблять этой опцией, и когда с авра переключаемся на другую плату, например на esp8266 неожиданно начинаем получать ошибку

class A {
  public:
  bool my_led_state() const {
    return this->led.state();
  }
  LED led;
};

/opt/arduino-1.8.7/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/bin/xtensa-lx106-elf-g++ -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ -I/opt/arduino-1.8.7/hardware/esp8266com/esp8266/tools/sdk/include -I/opt/arduino-1.8.7/hardware/esp8266com/esp8266/tools/sdk/lwip2/include -I/opt/arduino-1.8.7/hardware/esp8266com/esp8266/tools/sdk/libc/xtensa-lx106-elf/include -I/tmp/arduino_build_760268/core -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections -DF_CPU=80000000L -DLWIP_OPEN_SRC -DTCP_MSS=536 -DARDUINO=10807 -DARDUINO_ESP8266_NODEMCU -DARDUINO_ARCH_ESP8266 "-DARDUINO_BOARD=\"ESP8266_NODEMCU\"" -DESP8266 -I/opt/arduino-1.8.7/hardware/esp8266com/esp8266/cores/esp8266 -I/opt/arduino-1.8.7/hardware/esp8266com/esp8266/variants/nodemcu /tmp/arduino_build_760268/sketch/sketch_jan06a.ino.cpp -o /tmp/arduino_build_760268/sketch/sketch_jan06a.ino.cpp.o
/tmp/arduino_modified_sketch_643936/sketch_jan06a.ino: In member function 'bool A::my_led_state() const':
sketch_jan06a:110:30: error: passing 'const LED' as 'this' argument of 'bool LED::state()' discards qualifiers [-fpermissive]
       return this->led.state();
                              ^
exit status 1
passing 'const LED' as 'this' argument of 'bool LED::state()' discards qualifiers [-fpermissive]

И чего он (compiller) хочет от нас??? не давно же всё собиралось.

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

Метод класса stand() для внутренего использования внутри класса. Так что он всегда private или protected . Для внешнего всегда должны присутсвовать обертки. Так что const тут по желанию и не больше.

 A вот  state это свойство. Оно не должно быть константным . Потому что автомат.

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

Евжений, А вот структура скетча должна по моему мнению такой

/**/
class Cl_Fresher {
  protected:
  public:
    void init() {}
    void run() {}
    void fresh() {}
};
//-------Компоновка-------------
const int diffLight = 200;
const byte LightPin = /*пин*/A0;
enum state1_t {sNoLight, sLight} state1;
Cl_Fresher Fresher;
//-------------------------
void setup() {
  state1 = sNoLight;
  Fresher.init();
}

void loop() {
  int tmp = analogRead(LightPin);
  switch (state1) {
    case sNoLight:
      if (tmp <= diffLight) {
        state1 = sLight;
        Fresher.fresh();
      }
      break;
    case sLight:
      if (tmp > diffLight+20) {
        state1 = sNoLight;
      }
      break;
  }
  Fresher.run();
}

 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

qwone пишет:

Метод класса stand() для внутренего использования внутри класса. Так что он всегда private или protected . Для внешнего всегда должны присутсвовать обертки. Так что const тут по желанию и не больше.

 A вот  state это свойство. Оно не должно быть константным . Потому что автомат.

Я об этом методе bool state() { return digitalRead(LED_BUILTIN); }; класса LED
а не о enum actions { act_WAITON, act_WAITOFF, act_FRESH, act_PAUSE } state;
В классе A инкапсулирован экземпляр класса LED и у этого экземпляра вызывается метод state() и вызов выполняется из константного метода класса A.

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

Тот скетч не мой. Так почему я не скажу. Вот мой скетч 

/**/
class Cl_Fresher {
  protected:
    byte pin;
    unsigned long past;
    const unsigned long timeFresh = 1000; /*время пшика*/
    const unsigned long timeWait = 2000; /*время паузы после пшика*/
    enum state_t {sReady, sFresh, sWait} state;
    void stand(state_t s) {
      state = s;
      past = millis();
      switch (state) {
        case sReady:
          break;
        case sFresh:
          digitalWrite(pin, HIGH);
          break;
        case sWait:
          digitalWrite(pin, LOW);
          break;
      }
    }
  public:
    Cl_Fresher(byte p): pin(p) {}
    void init() {
      pinMode(pin, OUTPUT);
      stand(sWait);
    }
    void run() {
      switch (state) {
        case sReady:
          break;
        case sFresh:
          if (millis() - past >= timeFresh)stand(sWait);
          break;
        case sWait:
          if (millis() - past >= timeWait)stand(sReady);
          break;
      }
    }
    void fresh() {
      if (state == sReady)stand(sFresh);
    }
};
//-------Компоновка-------------
const int diffLight = 200;
const byte LightPin = /*пин*/A0;
enum state1_t {sNoLight, sLight} state1;
Cl_Fresher Fresher(/*пин*/13);
//-------------------------
void setup() {
  state1 = sNoLight;
  Fresher.init();
}

void loop() {
  int tmp = analogRead(LightPin);
  switch (state1) {
    case sNoLight:
      if (tmp <= diffLight) {
        state1 = sLight;
        Fresher.fresh();
      }
      break;
    case sLight:
      if (tmp > diffLight + 20) {
        state1 = sNoLight;
      }
      break;
  }
  Fresher.run();
}