Библиотека DRY

Тема в разделе "Arduino & Shields", создана пользователем acos, 31 май 2015.

  1. acos

    acos Официальный гик Администратор

    Всем привет. У меня тут идея)
    Я по работе пишу много кода под Arduino. Часто случается так, что какая-то часть кода постоянно повторяется из проекта в проект. Не смотря на то, что есть библиотеки, в них совсем не все)
    Вот например. Заметил, что слишком часто стал использовать конструкцию для неблокирующих временных задержек. Типа такой:

    Код (C++):
    unsigned long time=0;
    void setup() {
      // put your setup code here, to run once:
    }
    void loop() {
      // put your main code here, to run repeatedly:
      bool buttonState;
      if (millis() - time > 200) // вроде писать не много, но каждый раз
      {
        time = millis();  // а вот это я часто забываю написать
        buttonState = digitalRead(10); // это просто для примера
      }
    }
    Чет так достало, что решил запилить уже наконец вот такой класс неблокирующей задержки,
    чтоб не писать одну и ту же логику по сто раз

    Код (C++):
    class TimeOut
    {
      public:
        bool timeOut(unsigned long time)
        {
          unsigned long currentTime = millis();
          bool result = (currentTime - _time >= time);
          if (result)
          {
            _time = currentTime;
          }
          return result;
        }
      private:
        unsigned long _time = 0;
    };

    // Использование

    TimeOut button; // объявляем таймаут

    void setup() {
      // put your setup code here, to run once:
    }

    void loop() {
      // put your main code here, to run repeatedly:
      bool buttonState;
      if (button.timeOut(50)) // используем
      {
        buttonState = digitalRead(10);
      }
    }
    Потом подумал, а наверняка же не у меня одного есть какие-то такие потребности. Дай думаю запилю библиотечку, куда буду со временем пихать по потребности вот такие помогалки-сокращалки. Библиотечку назвал Amp_ino и начал реализацию с такого таймаута) Библиотечку залил на гитхаб, буду развивать потихоньку
    Вот пример использования
    Код (C++):
    #include <Amp_ino.h>

    #define LED 13

    TimeOut led;

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(LED, OUTPUT);
    }

    void loop() {
      // put your main code here, to run repeatedly:
    Serial.println(millis());

      if (led.timeOut(1000))
      {
        digitalWrite(LED, !digitalRead(LED));
      }
    }
    Уважаемые форумчане, наверняка вы так же сталкиваетесь с необходимостью писать одни и те же куски кода каждый раз. Поделитесь мыслями - написание каких кусков кода вам уже набило оскомину? Я мог бы добавить сокращалку для них в эту же библиотечку. А после мы могли бы всё что туда добавим совместно использовать к общему удовольствию. Ну и если окажется, что я изобретаю велосипед, дайте знать. С удовольствием глянул бы на похожие проекты.
    Ну а если у вас есть похожие наработки и сокращалки кода - буду благодарен, если поделитесь)
     
  2. Vad33

    Vad33 Капитан-оригинал

    Раз уж есть временная задержка, то можно добавить процедуру:

    - подачу digitalWrite(x,HIGH) на определенный контакт x,
    - задержка,
    - подача digitalWrite(x,LOW).

    И тоже самое с ШИМ - analogWrite....

    Постоянно что то приходится включать и выключать. :)
    Что бы все было упаковано в одну процедуру с параметрами:
    номер ноги и задержка(для ШИМ еще и скважность).
     
    Последнее редактирование: 31 май 2015
  3. X-Dron

    X-Dron Гик

    Вот это точно не надо, тем более, что предложенный вариант задержки не подойдет.
    У меня есть такая самописная либа
    https://yadi.sk/d/hGQy8xu1fZNks
    Объекты:
    Универсальный таймер. см. описание и временные диаграммы в либе
    Обработка дискретных входов на антидребезг (чем-то аналог debounce)
    Меандр для мигания.
    До 5 дискретных входов на аналоговый вход.
    Так же дописывал либу к SHIELD-LCD16x2
    https://www.olimex.com/Products/Duino/Shields/SHIELD-LCD16x2/open-source-hardware
    :)
     
    ИгорьК и acos нравится это.
  4. Vad33

    Vad33 Капитан-оригинал

    Почему - "не надо"? И кому "не пойдет"?
     
  5. X-Dron

    X-Dron Гик

    потому что
    Это типичная реализация с delay(), а у acos типичная задержка без его использования.
    Негоже в классы пихать delay(), которые тормозят всю программу. Только в случае крайней необходимости.
    Например, если делать антидребезг с помощью delay(10), то на обработку 14 кнопок уйдет 140мс, пр этом программа просто ничего не делает. А потом возникают вопросы, почему прога тормозит, откуда стробы берутся, почему нажатия пропускаются, почему беспроводные приемники не работают.
    А текст класса скрыт в библиотеке и далеко не все полезут копаться в описание методов класса.
    Можно сделать фильтрацию антидребезга без delay()? Можно. Можно упаковать это в вызов 2-3 функций? можно. А можно, чтобы это еще и в цикле делалось? Можно.
    http://forum.amperka.ru/threads/помогите-немного-с-кодом-для-кнопочной-клавиатуры.5022/#post-40057
     
  6. DrProg

    DrProg Вечный нерд

    Для 14 кнопок только аппаратное подавление дребезга, иначе в любом случае тормозить будет.
     
  7. X-Dron

    X-Dron Гик

    ссылка выше - рабочий код без тормозов.
     
  8. Vad33

    Vad33 Капитан-оригинал

    А я где то писал про delay() ?
     
  9. X-Dron

    X-Dron Гик

    Третий раз процитировать?
    Да, действительно можно обойтись без delay() каждый раз написав
    Код (Text):
    {
        uint16_t start = (uint16_t)micros();

        while (ms > 0) {
            yield();
            if (((uint16_t)micros() - start) >= 1000) {
                ms--;
                start += 1000;
            }
        }
    }
    Но,
    во первых это противоречит изначальной идее ТС.
    во вторых это исходник delay(), см arduino\hardware\arduino\avr\cores\arduino\wiring.c
    Код (Text):
    void delay(unsigned long ms)
    {
        uint16_t start = (uint16_t)micros();

        while (ms > 0) {
            yield();
            if (((uint16_t)micros() - start) >= 1000) {
                ms--;
                start += 1000;
            }
        }
    }
     
  10. Vad33

    Vad33 Капитан-оригинал

    Еще раз, как напишет ТС это его дело, не стоит за него все решать.
    Я лишь сообщил о том, что часто пишу.

    Даже в том же вашем примере не тупо крутить yield(), а выполнять более
    осмысленные действия применительно к данному МК в зависимости от
    фантазии и параметров.
    Или еще например навскидку:
    две процедуры PinHIGH(<numPin>) и PinLOW(<numPin>, <Dealy>)
    Одна включает в высокое состояние и запоминает момент включения,
    другая проверяет наступление момента выключения и выключает и
    все без блокировок и все проверки упрятаны вовнутрь.
    А между ними можно вставлять другие куски кода (без фанатизма, конечно)
     
  11. DrProg

    DrProg Вечный нерд

    А вот интересно, компилятор из библиотеки перекодирует все что там есть или только то что берется в работу? Не получится огромного кода ради пары функций? И вообще, не проще ли создать базу таких функций в текстовом виде, нужные копипастятся в скетч и все.
     
  12. acos

    acos Официальный гик Администратор

    @X-Dron , а это всё ваши библиотеки? Извините за любопытство, а почему вы не пользуетесь гитхабом? Хотя наверное это я уже избаловался) По крайней мере просмотр кода в том же гитхабе сделан великолепно.
    Библиотека прикольная, попробую с ней поработать.

    @DrProg компилятор должен вырезать всё, что не используется. Хотя это смотря как написать. Если это маленькие изолированные классы, то так. Если это один супергигантский класс на все случаи жизни, то вот тут уже не уверен.

    @Vad33 ШИМ кастомный проще всего сделать из готовых библиотек. Например тот же TimerOne и TimerThree http://playground.arduino.cc/Code/Timer1
    По поводу поднять и через какое-то время опустить ножку - тут надо подумать, как это сделать. По идее, если мы говорим о библиотеке,позволяющей просто не повторять одно и то же каждый раз, то вполне уместно добавить и delay() сюда, ибо иначе мы в конкретном месте программы всё-равно бы написали delay(). Другое дело, что такую библиотекку уже никому не дашь просто так, иначе будет то, о чем предупреждал @X-Dron : "Чего оно тупит? Плохая либа!!!". Неблокирующая реализация такого действия потребует определённой организации кода (например так сделано в SoftwareServo - http://playground.arduino.cc/ComponentLib/Servo / Там нужно вызывать write() не реже чем раз в 20 мс). Нужно подумать, как сделать правильно
     
  13. X-Dron

    X-Dron Гик

    @acos
    Да эти библиотеки мои. Начинал с этого поста
    http://forum.amperka.ru/threads/Таймеры-и-программный-антидребезг-входов.4280/#post-34041
    Будут вопросы по применению - обращайтесь с удовольствием помогу. Можно сделать достаточно сложные вещи парой строчек. Например ядро кодового замка на азбуке Морзе
    http://forum.amperka.ru/threads/кодовый-замок.4758/#post-37807
    Еще пример - часы с подводкой времени с кнопок.
    http://forum.amperka.ru/threads/rtc1307-добавить-настройку-кнопками.4742/#post-37869
    При длительном нажатии выполняется автоперебор значений.
    Гитхабом пользуюсь https://github.com/X-Dron/X-Dron_lib
    И это был первоначальный хостинг библиотеки.
    На гитхабе удобно вести отслеживание версий и отслеживать изменения. Но скорость скачивания оттуда, особенно при наличии видео оставляет желать лучшего. К тому же с гитхабом нужно синхронизироваться вручную (использую родное приложение).
    Нашел на сайте совет, который мне показался шикарным: настроить рабочую папку IDE локальную папку Я-диска. И все наработки, которые делаю, все библиотеки и проекты автоматически синхронизируются с серверной папкой. В итоге на любом компе могу получить доступ ко всему с чем когда-либо работал в актуальной версии. Соответственно, если я шарю папку на доступ это гарантия, что я предоставляю актуальную версию файлов, те же что и сам использую.
    Яркий пример тормозной библиотеки - это заводская либа DallasTemperature.h для DS18S20.
     
    DrProg нравится это.
  14. Megakoteyka

    Megakoteyka Оракул Модератор

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

    ИгорьК Гуру

    ... но понимаешь это очень долго. Для начинающего это одна из "засадных" библиотек, помнится.
     
  16. Megakoteyka

    Megakoteyka Оракул Модератор

    Многие начинающие считают библиотеки чем-то незыблемым и им даже в голову не приходит, что нужную последовательность сигналов можно сформировать как-то иначе, чем это сделано в библиотеке. Новичок чаще всего не имеет представления о том, что такое алгоритм и как его можно придумать самостоятельно. Он может выучить операторы языка, но не знает, как их применить.
    Это обратная сторона легкости погружения в Ардуино. Новоиспеченный ардуинщик делает несколько скетчей с использованием готовых библиотек и впадает в ступор, если для очередной задачи нет готовой библиотеки или она работает не так, как хотелось бы.
    Пока писал, вспомнилась картинка:
    C++21day.jpg
     
  17. DrProg

    DrProg Вечный нерд

    Я вот начинающий ардуинщик и вопреки традиционному протоколу наоборот чем дальше тем больше разочаровываюсь в библиотеках и даже в некоторых встроенных функциях, о чем создавал соответствующие ветки форума. Потому особенно внимательно слежу за альтернативными возможностями работы, например с модулем времени, температурного датчика и цифрового дисплея. Ну и остальное тоже.
     
  18. X-Dron

    X-Dron Гик

    А может Вы не умеете их готовить? По крайней мере плохо изучаете материалы сайта?
    http://forum.amperka.ru/threads/rtc1307-добавить-настройку-кнопками.4742/#post-41719
    Готовые либы, естественно, не догма. Если внимательно посмотреть, то в моих ссылках в этом топике можно насчитать 4 правленые библиотеки, заточенные под свои нужду. Исправления в одной отослал разработчику, и он принял результаты.
    Но увлекаться не стоит. Может лучше посидеть и подумать: "А возможно существуют другие методы"
    http://arduino.ru/forum/programmirovanie/stepper-v-massive
     
    MESS нравится это.