Как-то решил для более удобной работы с цифровыми выходами/входами ардуино написать классы. Первый это DigOut (ссылка постоянная) для работы с выходами. Для его использования его необходимо установить его в среду ардуино как библиотеку. Объявление Объявление экземпляра класса DigOut MyPinName(pin,state); Объявление нескольких экземпляров DigOut led1(13), led2(3), relay(4,1), relay2(5,0), pomp(12); MyPinName - имя присваиваемое цифровому выходу (например Relay_1) pin - номер цифрового выхода state - состояние при объявлении (1-высокий уровень, 0-низкий уровень если не указывать то по умолчанию низкий уровень) При объявлении выхода через класс не требуется прописывать в секции setup режим выхода pinMode(pin,OUPUT); На данный момент класс имеет следующие методы: MyPinName.HI() - устанавливает высокий уровень на выходе MyPinName.LO() - устанавливает низкий уровень на выходе MyPinName.invert() - инвертирует выход MyPinName.state() - возвращает состояние выхода (0 или 1) MyPinName.blink(period, impuls) - этот метод организует медленный ШИМ на выходе. period - период ШИМ impuls - длина импульса (но не более длительности периода) это по сути blink без delay. Работу основной программы в loop не останавливает. Применение в качестве медленного ШИМ для управления мощностью нагревателя Код (C++): #include <DigOut.h>//класс дискретного выхода DigOut ten(13);//нагреватель на 13 пине #define t_pwm 1000//период медленного ШИМ`а //для симистора или твердотельного реле от 1000мс (для реле не менее 60000мс) void setup(){} void loop() { //где-то в loop рассчитывается необходимая мощность power //выдаем рассчитанную мощность ten.blink(t_pwm,(t_pwm/100)*power); //(t_pwm/100)*power) - перевод рассчитанной мощности (0-100%) в продолжительность импульса } Состояния экземпляров класса можно приравнивать друг другу (MyPinName1 = MyPinName2) или писать выражения типа MyPinName = 1; Планирую добавить методы afterHi - установить высокий уровень через заданное время и afterLo - установить низкий уровень через заданное время. Класс DigIn (ссылка постоянная) создан для удобной работы с цифровым входом, включает в себя анти дребезг. Объявление Объявление экземпляра класса DigIn MyPinName(pin,pullup,debounce); MyPinName - имя присваиваемое цифровому входу (например Button_Ok) pin - номер цифрового входу pullup - включение встроенного подтягивающего резистора (1-pullup on, 0-pullup off можно не указывать, тогда подтяжка установится автоматически) debounce - период времени ожидания окончания дребезга контактов (можно не указывать по умолчанию 50ms). При объявлении входа через класс не требуется прописывать в секции setup режим входа pinMode(pin,INPUT); На данный момент класс имеет следующие методы: MyPynName.valid(currentMillis) - возвращает 1 если вход действительно замкнут на землю и дребезг прекратился, по сути это тот же digitalRead(pin) только со встроенным антидребезгом. В метод необходимо передавать текущий millis() - но это я постараюсь решить, дабы избавить пользователя от лишней рутины. Пример использования. Код (C++): #include <DigIn.h>//https://yadi.sk/d/7tGp_zlVsBt7s #include <DigOut.h>//https://yadi.sk/d/NM4S6HmFrTRu6 //объявляем дискретные входы DigIn button_ON(2), button_OFF(3);//кнопка ON на 2 пине, кнопка OFF на 3 пине /*или так DigIn button_ON(2,1);//кнопка ON на 2 пине, встроенная подтяжка вкл DigIn button_OFF(3,1);//кнопка OFF на 3 пине,встроенная подтяжка вкл */ //объявляем дискретный выход DigOut led(13,0);//светодиод led на 13 пине, отключен unsigned long currentMillis=millis();//для хранения текущего времени void setup() { //прерывание от таймера 0 для опроса millis() не чаще 1 раза/мс OCR0A = 0xAF;//http://robotosha.ru/arduino/multitasking-and-interrupts-arduino.html TIMSK0 |= _BV(OCIE0A); } void loop() { // currentMillis=millis();//сохраняем текущее время if(button_ON.valid(currentMillis))//если ON действительно нажата { led.HI();//включаем светодиод } if(button_OFF.valid(currentMillis))//если OFF действительно нажата { led.LO();//выключаем светодиод } } //по прерыванию таймера получаем текущий millis //чтобы постоянно в loop не запрашивать millis SIGNAL(TIMER0_COMPA_vect) { currentMillis = millis(); } //yul-i-an@mail.ru 06.2016 - Я/Д 41001603404940 Пример блинка Код (C++): #include <DigOut.h>//https://yadi.sk/d/NM4S6HmFrTRu6 DigOut led(13,0);//светодиод led на 13 пине, отключен //можно и так DigOut led(13); низкий уровень установится по умолчанию void setup(){} void loop() { led.blink(1000,500);//мигаем с периодом 1с и продолжительностью 0,5с //не тормозя основной цикл }
MyPinName.State(); Код (C++): bool state(void) const { return digitalRead(_pin); } Порт настроен на выход, а вы его считываете. сделайте поле в котором хранится состояние, а потов возвращайте из функции.
Код (C++): #define _setL(port,bit) do { port &= ~(1 << bit); } while(0) #define _setH(port,bit) do { port |= (1 << bit); } while(0) #define _clrL(port,bit) do { port |= (1 << bit); } while(0) #define _clrH(port,bit) do { port &= ~(1 << bit); } while(0) #define _bitL(port,bit) (!(port & (1 << bit))) #define _bitH(port,bit) (port & (1 << bit)) #define _cpl(port,bit,val) do {port ^= (1 << bit); } while(0)
В класс DigOut (ссылка постоянная) добавил функцию lpwm(period, fill) - аналог функции blink(period, impuls) из этого же класса, но в отличие от неё вместо продолжительности импульса (impuls) задается процент заполнения (fill от 0 до 100%). Что дает. Раньше в коде когда нужен был медленный ШИМ писал так Код (C++): ten.blink(t_pwm,(setPower*(t_pwm/100)));//медленный ШИМ на тен Теперь так Код (C++): ten.lpwm(t_pwm, setPower);//медленный ШИМ на тен
Вопросы: для чего? Зачем надстройка над надстройкой, по сути? Чем отличается digitalWrite(13,!digitalRead(13)); от объявления переменной класса, чтобы только позвать метод invert? Которая (переменная класса) к тому же занимает лишнюю оперативку, будучи объявлена глобальной, например. Далее: просмотрел код - он не совсем хороший: Код (C++): DigOut (const int8_t pin=13, const bool state=0) Во-первых, в квалификаторах const тут смысла нет, от слова совсем, во-вторых - у нас номером пина может быть отрицательное число, оказывается? int8_t - знаковый тип, диапазоном -128 ... 127. Код (C++): void DW(const bool state) const const bool також не несёт никакого смысла, достаточно было просто bool. Код (C++): digitalWrite(_pin, state); Расходимся, ребята, нас обманули Код (C++): if(cms<impuls+preMillis){//если время высокого уровня не прошло HI(); } else//иначе { LO(); } Зачем каждый раз дёргать с бешеной частотой HI() и LO()? Установили один раз - и всё, когда надо - установили другой уровень, МК не дурак - уровни держит между вызовами. Код (C++): void blink (unsigned long period, int impuls) Что будет, если я в impuls передам отрицательное значение (int - знаковый тип)? И вот смотрите, что мы получаем в итоге: во-первых, плохой код. Во-вторых - из-за сомнительного удобства имеем 5 байт в оперативе на 1 пин, не дай бог держать такой объект глобально, что называется. Прошу воспринять мою критику адекватно, считаю, что развиваться надо, но категорически против того, чтобы выкладывать подобные практические занятия под видом "библиотеки".
Ну... я на это же пытался намекнуть. Обычно для работы с пинами идут по пути ускорения и уж точно не утяжеления. Но с другой стороны, товарищ просто тренируется в написании библиотек, что тоже неплохо
Изначально планировалось прямое управление пинами. Потом решил не заморачиватся, т.к. какаянибудь библиотека ЛСД или DS18B20 всё равно использует DigitalWrite. К чему эта гонка за скоростью. Если мне будет нужно для какой-нибудь динамической индикации скорость я её реализую на прямом управление портами. А класс написан для удобства (это крем для пирога Ардуино). Идеология Ардуино подразумевает упрощение написания кода без вникания в работу железа. Я же не навязываю. Кому надо пусть прямой доступ используют.
Ну так и я про то же. Давайте рассмотрим на примере invert: Код (C++): #define LED 10 pinMode(LED,OUTPUT); digitalWrite(LED,!digitalRead(LED)); и ваш: Код (C++): #define LED 10 DigOut pin(LED); pin.invert(); Где упрощение то? Ткните пальцем, плз. Вижу только жирную надстройку над жирной надстройкой.
Без класса Код (C++): #define LED 10 //даем внятное имя пину void setup(){ pinMode(LED,OUTPUT);//настраиваем пин как выход } void loop(){ digitalWrite(LED,!digitalRead(LED));//нвертируем пин } С классом Код (C++): #include <DigOut.h> DigOut LED(10);//даем внятное имя пину void setup(){} void loop(){ LED.invert();//нвертируем пин } И вообще эта функция сама напрашивалась чтобы запись короче была и понятней. Вы лучше DigOut.blink() сравните... По поводу Код (C++): if(cms<impuls+preMillis){//если время высокого уровня не прошло HI(); } else//иначе { LO(); } Оно быстрее работает чем выставлять флаги (тоже память занимают) и проверять их.
С чем сравнивать? Я уже писал, что код blink написан безграмотно, мне повторить? Зачем дёргать постоянно digitalWrite, если достаточно только один раз при смене состояний? У вас МК занят бессмысленным перемешиванием бессмысленной каши.