Посмотрите/Оцените/Покритикуйте/Похвалите (класс для светодиода)
- Войдите на сайт для отправки комментариев
Пт, 04/01/2019 - 18:59
Доброго времени суток и с наступившим НГ. Решил делать свой первый самостоятельный проект на ардуинке. Среди прочего потребуется "помигать светодиодами" (почему бы и нет :) ). По классике в первой версии 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(); }
Ах да, забыл написать, что можно делать. Можно включить светодиод. Можно выключить светодиод. Можно включить автоматическое моргание с заданными интервалами горения и не горения...
Осталось вам освоить автоматное программирование и можете писать программы посложнее.
Ну и так далее http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov
Осталось вам освоить автоматное программирование и можете писать программы посложнее.
Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?
Ну я нутром чуял, что велосипед изобретаю :)
Велосипед уже есть, титановый :-)
Евжений, а что должна сделать функция abs() с аргументом типа unsigned long? Что-то Вы там с миллис намудрили по-моему.
Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?
Ну, для начала, очень неплохо. Разве что строчка N48 лишняя. Но на библиотеку, пока, не тянет. Начинайте использовать в своих проектах. По мере добавления функционала, может и дорастет до библиотеки.
Ну я нутром чуял, что велосипед изобретаю :) Ну зато потренировался. Я так понимаю из конструктивной критики у меня только setup() и loop()? или еще что то?
Евжений, сколько Вам лет?
Это я к тому, чтобы понять как с Вами разговаривать.
Ну да, с abs и unsigned я погорячился :) Спасибо.
Лет мне 40. Программирую я давно. Вот с ардуино у меня "первая любовь"... Да и c++ не мой фаворит :)
Рассматривайте мою тему не как эталон, или "классику". Просто я раньше вас начал копать в этом направлении. И эта тема это "часть моих изысканий" . И если бы я сейчас писал этот класс, то писал так.
А конструктивно это или нет решайте сами.
Ну, если давно программируете, то ... держите :))) То что подростку списалось бы ...
Про abs не буду ибо уже боян. А про остальное, поехали...
Давайте разбираться почему
Про дальнейшую экономию я говорить не буду, т.к. это уже паранойя, хотя там есть ещё куда расти, но то, о чём написано выше – абсолютно ничем не оправданный расход памяти
1. Про память - согласен полностью... Не поспоришь :)
2. а вот тут поспорю. Тут конечно и ваша правда есть, но мне ничего не мешает написать так:
Переопределить параметры "моргания", а в следующий раз просто вызвать led.autoBlink(true); Что как бы и не запрещено. Параметр есть - надо отработать.
3. На сколько я проникса классами - в привате описываются внутренние параметры, которые не должны переопределяться из-вне, так сказать. Я уже понял, что на захват мира не тянет. А для разового проэкта - даже слишком хорошо.
з.ы. А вообще я разочаровался :( Не не в ардуинке... В результате который я получил. Раньше у меня был delay()... ну фиг с ним 2-3 раза, что замедляло скорость работы проекта, но на функционал не влияло. Сейчас в погоне за красивым кодом запилил класс, который не замедляет выполнение, что привело к тому, что работать задумка перестала. В итоге ее надо теперь замедлить принудительно. Если писать delay () - то перестает работать корректно моргание. т.е. надо теперь хитрую "замедлялку"... опять небось класс. в итоге проэкт в котором всего было 50 строк разматывается в нечто очень большое и ужасное.
Что бы не было лишних вопросов - что поломалось: фоторезистор снимает показания. маленькие колебания мне не нужны и плавное изменение в течении длительного времени (аля восход и закат солнца), а надо было отследить именно резкое изменение освещенности - включение/выключение света. А лампа с которой я тут эксперементирую с диммером. И получается, что пока я кручу диммер показания плавно растут... и фильтруются.
qwone, дайте ссылку уже, где почитать. Гуглил, но хотелось бы прям шоб носом ткнули :)
2. а вот тут поспорю. Тут конечно и ваша правда есть, но мне ничего не мешает написать так:
Переопределить параметры "моргания", а в следующий раз просто вызвать led.autoBlink(true); Что как бы и не запрещено. Параметр есть - надо отработать.
напрасно спорите. Вы не до конца разобрались с языком. Вызов led.autoBlink(false); абсолютно идентичен вызову led.autoBlink(false, 1000, 1000); Нет никакой разницы от слова совсем.
Так что, поверьте, здесь спорить неочем. Если Вы не согласны - перечитайте описание языка и читайте пока не поймёте. Эти два присваивания у Вас выполнятся ВСЕГДА, т.е. при выключении они - лишние.
3. На сколько я проникса классами - в привате описываются внутренние параметры, которые не должны переопределяться из-вне, так сказать.
Почитайте ещё и про protected и попытйтесь понять разницу.
Сейчас в погоне за красивым кодом запилил класс, который не замедляет выполнение, что привело к тому, что работать задумка перестала. В итоге ее надо теперь замедлить принудительно. Если писать delay () - то перестает работать корректно моргание. т.е. надо теперь хитрую "замедлялку"... опять небось класс. в итоге проэкт в котором всего было 50 строк разматывается в нечто очень большое и ужасное.
Что бы не было лишних вопросов - что поломалось: фоторезистор снимает показания. маленькие колебания мне не нужны и плавное изменение в течении длительного времени (аля восход и закат солнца), а надо было отследить именно резкое изменение освещенности - включение/выключение света. А лампа с которой я тут эксперементирую с диммером. И получается, что пока я кручу диммер показания плавно растут... и фильтруются.
Ничего не понял, но если Вам нужно фильтровать значения, так фильруйте, а не замедляйте программу. Напишите фильтр и пусть фильтрует :)
напрасно спорите. Вы не до конца разобрались с языком. Вызов led.autoBlink(false); абсолютно идентичен вызову led.autoBlink(false, 1000, 1000); Нет никакой разницы от слова совсем.
Так что, поверьте, здесь спорить неочем. Если Вы не согласны - перечитайте описание языка и читайте пока не поймёте. Эти два присваивания у Вас выполнятся ВСЕГДА, т.е. при выключении они - лишние.
Ничего не понял, но если Вам нужно фильтровать значения, так фильруйте, а не замедляйте программу. Напишите фильтр и пусть фильтрует :)
Так вот в том то и дело. Было кода мало - все работало. Дописал еще чуть-чуть... теперь надо еще дописывать... Хотя блин все уже работало и без класса. Вот в чем спич.
qwone, дайте ссылку уже, где почитать. Гуглил, но хотелось бы прям шоб носом ткнули :)
Но скорее Вам надо что-то виде автомата Пуха. Но такой темы нет. Не написал. Так что почитайте это #27 и #26
Может поможет. Да и не пугайтесь объема кода и текста исходника . Главное что бы вы в этом объеме не потерялись.
Мне вот интересно, неужели никто из кодописателей никогда не управлял яркостью светодиода посредством ШИМ?
Или никогда не подключал светодиоды через 595 регистр?
Если для включения/выключения светодиода всегда используется digitalWrite(), то класс здесь совершенно не нужен, т.к. явно избыточен. А вот если необходимо единообразно работать с двумя-тремя сотнями светодиодов, часть из которых подключены непосредственно к Ардуине, а часть - к регистрам (или внешнему ШИМ-контроллеру), то ради такой унификации может иметь смысл и написать класс.
Должен же класс иметь хоть какой-то практический смысл кроме чисто учебного.
и еще, тут никто не сказал, счас у тебя светодиод зажигается высоким уровнем, а это не всегда так. Иногда устройство, а светодиод это именно исполнительное устройство, управляется нулем, а не единицей. Как это отразить в классе?
Каким боком? У Вас есть метод без параметров? Нет. А значит при следующем включении Вы снова передадите параметры, и они снова будут присваиваться, а Ваше "заранешнее определение" будет выброшено на помойку. Если Вы хотите передавать для следующего, то это надо было так и писать.
Так вот в том то и дело. Было кода мало - все работало. Дописал еще чуть-чуть... теперь надо еще дописывать... Хотя блин все уже работало и без класса. Вот в чем спич.
Если использовать классы там, где они не нужны и так, что они перестают быть объктами ООП, то от них никогда толку не бывает. Это тот самый случай. Очень удачный пример.
Спасибо за оценку. Постараюсь все учесть.
qwone, автомат получился у меня? Или так же как и класс (я его подправил. попытку на "универсальность" выкинул - он под конкретную задачу теперь)... На сколько я понял - нам надо пройти по цепочке - никуда не сворачивая, вополняя каждое действие (исключения возможны конечно, но не в данном случае). Итак, автоматический освежитель воздуха. Ну да... захотелось :) Ждем включения света, ждем выключения света, пшикаем, пауза (1 минута - что бы ребенок щелкающий светом не устроил газовую камеру). После паузы - опять ждем включения света. Вроде можно просто сразу ждать выключения... Но мне с включением больше нравится.
Евжений, зря Вы выбросили метод stand(). Эта функция очень сильно упрощает код и читаемость текста. Имеено с нее я и перешел на автоматное программирование в среде Ардуино.
Для пшикалки надо 3 состояния Ready,ON,Wait - готовность , пшик, и пауза блокирования. А а внутри метода inject - вспрыск проверять состояние Ready и stand(ON) если автомат в этом состоянии и газововой атаки нет.
А это, вообще, что? :)))
Может, нормально написать?
Метод класса bool state() не изменяет данные класса, по этому должен быть декларирован как bool state() const;
иначе использовать этот метод в константном методе другого класса не получится (если не указан -fpermissive).
Для отладочных плат на ядре авр в платформ.тхт любят злоупотреблять этой опцией, и когда с авра переключаемся на другую плату, например на esp8266 неожиданно начинаем получать ошибку
И чего он (compiller) хочет от нас??? не давно же всё собиралось.
Метод класса stand() для внутренего использования внутри класса. Так что он всегда private или protected . Для внешнего всегда должны присутсвовать обертки. Так что const тут по желанию и не больше.
A вот state это свойство. Оно не должно быть константным . Потому что автомат.
Евжений, А вот структура скетча должна по моему мнению такой
Метод класса stand() для внутренего использования внутри класса. Так что он всегда private или protected . Для внешнего всегда должны присутсвовать обертки. Так что const тут по желанию и не больше.
A вот state это свойство. Оно не должно быть константным . Потому что автомат.
а не о enum actions { act_WAITON, act_WAITOFF, act_FRESH, act_PAUSE } state;
В классе A инкапсулирован экземпляр класса LED и у этого экземпляра вызывается метод state() и вызов выполняется из константного метода класса A.
Тот скетч не мой. Так почему я не скажу. Вот мой скетч