Глупый блинкер робко прячет ... наш delay в пещере тёмной

Тема в разделе "Arduino & Shields", создана пользователем DIYMan, 2 авг 2016.

  1. Benny_Ray

    Benny_Ray Нерд

    в чем потеряна логика?
    при передаче
    Код (C++):
    Blink(13, 1000);
    мы передаем функции значение пина = 13, и таймера равное 1000мс, из этого получаем что активируется пин с № 13, элемент массива с № 13 и таймер = 1000 мс.
    Передав
    Код (C++):
    Blink(10, 500);
    мы передаем функции значение пина = 10, и таймера равное 500мс, из этого получаем что активируется пин с № 10, элемент массива с № 10 и таймер = 500 мс

    т.е. в первом случае функция будет отсчитывать 1000мс а во втором 500 мс, это никак не должно мешать.
     
  2. alex-prog

    alex-prog Гик

    Не знаю, мне код DIYMan'а проще понять, и проверить работоспособность в голове. Теперь вроде Ваш код тоже понятен, и по-моему, тоже работоспособный :)

    Update: возможно поспешил, ledState, это же не глобальная переменная у Вас, то есть, она определяется только в процедуре Blink?
     
  3. Benny_Ray

    Benny_Ray Нерд


    кстати да, спасибо что подсказали, эту переменную тоже нужно убрать из функции (процедуры) и добавить в раздел void setup массивом так же как и long previousMillis

    правильный код будет чтото типа вот этого

    Код (C++):
    void Setup() {
        for (i=0; i<=13; i++) {                     // i = количеству пинов
            long previousMillis[i] = 0;                    //массив с элементами таймеров
            int ledState[i] = LOW;                    //массив с элементами статуса пина
        }
    }


    //функция мигания (передаются переменные номер пина и таймер мигания

    void Blink(int ledPin, long Timer) {

        unsigned long currentMillis = millis();

        if (currentMillis - previousMillis[ledPin] > Timer) {
            previousMillis[ledPin] = currentMillis;
            if (ledState[ledPin] == LOW)
                ledState[ledPin] = HIGH;
            else
                ledState[ledPin] == LOW;

            digitalWrite(ledPin, ledState);
        }
    }


    void loop() {

        Blink(pinNumber, timer); // функции передаются значения конкретного пина и таймера, которые можно получить выполняя различные условия для переменных pinNumber и timer

    }

    на 100% правильность не претендую, в настоящий момент проверить могу только мозгом. Можно еще чтото придумать и с массивом для переменной timer, но пока что считаю что в данном случае это избыточно.
     
    Последнее редактирование: 2 авг 2016
  4. alex-prog

    alex-prog Гик

    Вот так, автор и пришел к выводу, что лучше класс сделать... Вам хотя бы структуру выделить blinkLED, чтобы хранить в ней, вместе, и номер пина, и интервал задержки, а потом, на её основе, можно и массив создать...
     
  5. Benny_Ray

    Benny_Ray Нерд

    Мое мнение что класс всетаки лишнее хотя бы по тому что в моем коде 15 строк, а в коде автора 20 строк + 2 процедуры на 17 и 34 строки, а функциональность по факту одинакова )))) но свой код писал только мозгом, проверить не могу поэтому согласен на то что я могу быть не прав.

    но даже если всю мою процедуру вынести в класс то код больше не станет даже в сумме с классом, а без него уменьшится до 7 строк )))
     
  6. alex-prog

    alex-prog Гик

    Benny_Ray, будет альтернативное решение ;) Я только про введение структуры советую, чтобы код был более грамотным...
     
  7. Benny_Ray

    Benny_Ray Нерд

    всетаки забыл в функцию (процедуру) добавить в начало одну строку

    Код (C++):
    pinMode(ledPin, OUTPUT);
    :rolleyes:

    и тут собственно главный вопрос, умеет ли ардуинка динамически менять состояние порта на вход/выход
     
  8. DIYMan

    DIYMan Guest

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

    Код прежде всего должен быть понятен человеку, а потом уже - компилятору. Не надо гнаться за компактностью самого исходного кода - лучше гонитесь за его лаконичностью и красотой ;) Поверьте на слово - компилятор лучше нас с вами соптимизирует ;)
     
  9. Benny_Ray

    Benny_Ray Нерд

    Своим кодом я, как и Вы, отвечал на эти положения

    По поводу массивов я так и не понял что Вы хотели сказать словами "городить кучу массивов" т.к. в моем коде 2 одномерных массива, в вашем 1 двумерный, разницы по факту никакой



    и да, Вы сами написали )))

    Кстати на мой вопрос по поводу if - elseif в случае подсчета нажатий одной кнопки Вы так и не ответили )))

    P.S. Вообще раньше не писал ничего профессионально поэтому нуб и учусь.
     
  10. DIYMan

    DIYMan Guest

    Это очень хорошо, что так. Именно на подобных примерах стоит учиться. По поводу остального, типа массивов и пр. - вот смотрите: я оперирую объектами, вы - двумя массивами. Да, у меня объекты запрятаны в одномерный (к слову, он одномерный, а не двумерный) массив - но это только для примера. Теперь представим, что я ввёл понятие "диспетчер" - это класс, который рулит светодиодами. В моём случае код станет выглядеть вот так:
    Код (C++):
    void setup()
    {
       dispatcher.init();
    }

    void loop()
    {
      dispatcher.update();
    }
    вне зависимости от кол-ва светодиодов. Далее: допустим, светодиод у нас один. В вашем случае - всё равно две переменных (массива с размерностью 1, если хотите), в моём:

    Код (C++):
    DiodeBlink blinker;

    blinker.on();
    blinker.off();
    blinker.toggle();
    // и т.д.
    Т.е. прозрачность понимания остаётся при любом раскладе. Я не говорю, что мой подход единственно верный, но мы ведь с вами обсуждаем различные способы, не так ли? И раз уж вы учитесь - считаю, что в этом случае надо быть открытым и изучать, как устроено то или иное. Ещё раз подчеркну - можно написать тысячей способом, но для меня, как для программиста, на первом месте - это лёгкость поддержки кода. И тут, к слову, в программировании МК ооочень большая проблема, в отличие от программирования больших компьютеров: как правило, никто не заморачивается на читаемость, напишут вроде:

    Код (C++):
    TIMSK1 = 1 << TOIE1;
    И ломай потом голову, даже комментарии не помогут. Вот что стоило эти константы обозвать более человечно? Какой-то пещерный подход, в двадцать-первом веке-то. В общем, это лирика.

    Вам лично - респект, что учитесь на примерах, это очень хорошо ;)
     
  11. alex-prog

    alex-prog Гик

    DIYMan, кстати по поводу:

    При программировании AVR микроконтроллера это можно, насколько я помню, а как у Arduino?
     
  12. DIYMan

    DIYMan Guest

    Если средствами ардуино - то в любой момент вызываете pinMode - вот вам и перевод порта на вход/выход. Можно напрямую DDR-портами рулить, если хотите.
     
    alex-prog нравится это.
  13. Benny_Ray

    Benny_Ray Нерд

    добрался до ардуины правда удаленно и только с выводом данных в компорт но все же проверил и доработал немного файл получился вот такой монстр

    Код (C++):
    #define SUMM_PINS 14

    int ledState[SUMM_PINS];
    unsigned long previousMillis[SUMM_PINS];
    long interval[SUMM_PINS];
    int item = 0;

    void setup() {
      for(int i=0; i<SUMM_PINS; i++){
        ledState[i] = LOW;
        previousMillis[i] = 0;
      }
    }

    void loop() {
      usedPins(13, 2000, 1);
      usedPins(12, 1000, 2);
    }

    void usedPins(int usedPin, long interval, int item) {

      unsigned long currentMillis = millis();

      if (currentMillis - previousMillis[usedPin] >= interval) {

        previousMillis[usedPin] = currentMillis;

        if (item == 1){
          pinMode(usedPin, OUTPUT);

          if (ledState[usedPin] == LOW) {
            ledState[usedPin] = HIGH;
          }
          else {
            ledState[usedPin] = LOW;
          }
          digitalWrite(usedPin, ledState[usedPin]);
        }

        if (item == 2){
          pinMode(usedPin, INPUT);
          //любой код чтения датчиков
        }
      }
    }
    Но теперь если вызвать "usedPins(PIN, TIMER, 1);" то пин открывается для передачи данных, а если отправить "usedPins(PIN, TIMER, 2);" то пин откроется для приема данных, итого если к 13 пину подключен свевтодиод а к 10 подключен например датчик движения то с ними можно работать отправляя запросы таким образом. Вот по этому коду можите закидывать какашками )))
     
    Последнее редактирование: 3 авг 2016
  14. DIYMan

    DIYMan Guest

    Точно готовы? :D

    Тут дело в том, что вы смешиваете мух с котлетами: на практике крайне редко надо менять режим работы пина, т.к. к небу обычно жёстко приколошмачена та или иная железка. Это, что называется, раз.

    Два: попробуйте взглянуть на свой код со стороны, как бы. И вы увидите, что код совершенно неочевидным образом как-то манипулирует с режимом работы пина, отследить это где-то со стороны потом - очень неочевидно и сложно.

    Я не наезжаю, правда. Я просто добиваюсь, чтобы вы начали смотреть немного иначе, а именно - архитектурно. Для того, чтобы это получилось, надо попробовать мыслить абстракциями, например: вот представьте, что идёт стройка, строится многоэтажный дом. Прораб - рулит рабочими, крича им - это туда неси, а вот это - закапывай здесь. Кран - подаёт материалы на этажи, причём может это делать как по факту наличия привезённой паллеты с материалом, так и по требованию прораба, вне очереди, что называется. Рабочие - одни штукатурят, другие - кладут кирпич, при этом все отвлекаются на требования прораба сбегать за пузырём (у нас правильный прораб :D).

    Вот это и есть - архитектура. Не в смысле, что стройка - а в том смысле, как это всё меж собой взаимодействует.

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

    Абстракция в нашем понимании - это некая самодостаточная единица, имеющая своё "я" и хранящее в себе свои умения. Её можно всегда дёрнуть за умения, даже не представляя, как этот навык устроен изнутри: можно попросить рабочего поштукатурить, и он будет штукатурить, вот только вы не знаете, как он штукатурит - вручную или при помощи штукатурной машины. Тем не менее - вы уверены в результате.

    Это я о чём всё? О красивости, о ней, родимой. Давайте возьмём следующий кусок псевдокода:

    Код (C++):

    рабочий.Штукатурить();

    прораб.неПропуститьСобытие("пришли материалы", поФактуСделать()
    {

      заорать("Пришёл материал, разгружать!");

      шестёрка = матюгальник.Крикнуть("Вася, иди сюда!");
      ждать(пока нет шестёрки);

      шестёрка.обойтиКаждого(поФактуСделать(рабочий)
    {
        рабочий.Передать("Босс сказал, что яйки оторвёт, если щас же не явишься!");
    }

    });
     
    Ну и т.д. Подобные уровни абстракций позволяют, не глядя на конкретную реализацию, легко поддерживать и расширять существующий функционал. Вот вы же - юзаете библиотеки в Arduino? По факту - это набор классов, таких вот абстракций. И когда вы пишите:
    Код (C++):
    while(Serial.available())
    {
      char c = Serial.read();
    }
    вам совершенно пофигу, как там этот Serial устроен внутри. Не отказывайтесь от изучения возможностей С++, вы всё равно плотно на нём сидите, юзая ардуину. А если почитаете про инкапсуляцию, наследование, полиморфизм - то ещё больше понравится мощь языка ;)
     
    Vetrinus нравится это.
  15. Benny_Ray

    Benny_Ray Нерд

    К этому всегда готов.

    А вот тут да, изучать можно но вот сколько раз раньше когда было свободное время пытался взяться за "плюсы" так и не въехал в язык, хотя азы некоторых остальных давались без особых проблем.
     
  16. DIYMan

    DIYMan Guest

    Главное - чтобы от процесса штырило, что называется. Тогда всё пойдёт как по маслу. В любом случае, если у вас есть желание изучить - изУчите рано или поздно.

    А если что - поможем, главное, пытаться понять самому и если уж совсем не получается - не стесняться спрашивать ;) У вас, я верю, всё будет отлично, мне импонирует ваш пытливый подход ;)
     
  17. Benny_Ray

    Benny_Ray Нерд

    Сейчас вот никак не могу сообразить как мне в processing'e прицепить такую вещь как Yandex Speech API точнее даже как
    сделать запись с микрофона,
    отправить яндексу,
    получить ответ
    разобрать его на составляющие.
     
  18. alex-prog

    alex-prog Гик

    Benny_Ray, может перенести в отдельную тему? ;)

    А то итак тему DIYMan раздули, и отвели её от первичной темы, из-за которой автор её создал...
     
  19. Benny_Ray

    Benny_Ray Нерд

    Да это просто к слову сообщение было а по остальному помоему все обсуждение ка краз в пределах темы ТС было ))) Хотя решать ему, можно вообще все лишнее потереть )))
     
    alex-prog нравится это.
  20. Vetrinus

    Vetrinus Гик

    Смеялся долго и со вкусом))) @DIYMan , вы случайно на 1С не писали?)