Подскажите как правильно расположить блоки програмы

Тема в разделе "Arduino & Shields", создана пользователем MontiMonolitov, 21 дек 2017.

  1. MontiMonolitov

    MontiMonolitov Нерд

    Образно все выглядит вот так:
    Код (C++):
    void setup() {
      // put your setup code here, to run once:

    }

    void loop() {
      buttonState();
      blinck();
      timer();
    }
    void buttonState(){
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    }

    void blinck(){
      YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
    }

    void timer(){
      ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
    }
    Каждый блок по отдельности работает как надо, вопрос как правильно их объединить. Блоки "buttonState" и "blinck" по такой схеме то же работают, но как только добавляю "timer" (он около 30 мин), блоки кнопок и светилок перестают работать. Если я правильно понимаю пока не отработает таймер остальные блоки не прочитаются. Как расположить чтоб во время работы таймера можно было вносить изменения в "buttonState"
     
  2. DIYMan

    DIYMan Guest

    Избавляться от delay.
     
    NikitOS нравится это.
  3. b707

    b707 Гуру

    "А вы друзья, как ни садитесь...." (с) Дедушка Крылов

    Дело не в расположении блоков, а в их содержании. Ни один блок не должен захватывать исполнение надолго. Чтобы программа нормально работала, в ней ни в коем случае не должно быть блоков. исполняющихся дольше, чем 50-100мс. А лучше, чтобы все время цикла loop() (в вашем коде - это сумма длительности всех трех блоков) не превышало 1-5мс.
     
    NikitOS и Tomasina нравится это.
  4. Tomasina

    Tomasina Сушитель лампочек Модератор

    Расположение блоков в скетче не зависит от их очередности вызовов в программе.
    К слову, loop() лучше переместить в конец скетча, ибо новые версии IDE более строго относятся к размещению блоков в скетче.
     
  5. MontiMonolitov

    MontiMonolitov Нерд

    Выходит программу "timer" посадить на отдельную минидуину и пусть работают две в одном корпусе
     
  6. Airbus

    Airbus Радиохулиган Модератор

    Зачем?Пусть тикает millis отмеряя нужные интервалы.И для этого не надл отдельную программу "timer". Если же хотите чтобы устройство наглухо блокировалось на конкретный промежуток времени и исключить аппаратную отсебятину можно использовать delay-но только в этом случае.
     
  7. b707

    b707 Гуру

    Нет. неправильно. Легко можно обойтись одним контроллером. Но нужно процедуру timer переписать так, чтобы она не блокировала loop() больше чем на несколько микросекунд.
    Вы не приводите код, поэтому я не знаю, что происходит внутри timer(). Однако можно догадаться, что большую часть из этих 30 минут компьютер просто ждет, когда истечет время.
    Теперь подумайте, как вы сами поступаете в таких ситуациях. Предположим, вам через 2 часа нужно совершить важный звонок. Вы же не будете 2 часа сидеть перед телефоном и смотреть на него? - нет, вы заметите время и 2 часа будете заниматься другими делами, поглядывая на часы.
    Правильный отсчет интервалов в программе делается точно так же - нужно заметить время и регулярно его проверять, выполняя между проверками другие задачи. Практический пример смотрите в статье "Блинк без delay"
     
    Airbus нравится это.
  8. MontiMonolitov

    MontiMonolitov Нерд

    Спасибо за совет, буду пробовать
     
  9. MontiMonolitov

    MontiMonolitov Нерд

    а таймер вот
    Код (C++):
    #include "TM1637.h" //
    #define CLK A0 // CLK
    #define DIO A1 // DIO
    int ledPin = A2; //
    int ledState = LOW; //
    TM1637 tm1637(CLK,DIO); //

    int currentInterval =0; //
    int intervals[]={1800,300}; //длина интервалов в секундах, в массиве
    long startInterval =0; //время начала текущего интервала
    int currentTime =0; // прошедшее время с начала текущего интервала в секундах

    unsigned long previousMillis = 0;
    long OnTime = 10; //
    long OffTime = 10; //



    void setup() {
      tm1637.init(); // Сброс дисплея
       tm1637.set(BRIGHT_TYPICAL); // Уровень яркости
       // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2;
       tm1637.point(POINT_ON); // Активация точки посредине
       delay(1000); // Задержка 1 секунда

    }

    void loop() {
      currentTime =(millis()- startInterval)/1000;
       while(currentTime < intervals[currentInterval]){
       if(currentInterval % 2 == 0){
          tm1637.clearDisplay();//
       int showingTime = intervals[currentInterval] - currentTime;
       int seconds = showingTime % 60; //
       int mins = showingTime / 60; //
          tm1637.display(3,seconds%10);
       if(seconds > 9)
          tm1637.display(2,seconds/10);
       if(mins > 0)
          tm1637.display(1,mins%10);
       if(mins > 9)
          tm1637.display(0,mins/10);
             }
       currentTime =(millis()- startInterval)/1000;
       delay(200);
       }
      tm1637.clearDisplay(); //
      currentInterval =(currentInterval + 1 == sizeof(intervals)/sizeof(int)) ? 0 : currentInterval +1;
      startInterval = millis();

    }
     
  10. b707

    b707 Гуру

    чтобы этот таймер нормально работал с другими частями программы. надо всего лишь раскрыть цикл while. Общий принцип - сейчас у вас исполнение крутится в цикле while до конца текущего интервала, не выходя в основную программу. Поэтому в программе ничего больше не работает.
    А вам просто нужно сделать так, чтобы контроллер, пройдя код таймера один раз, потом возвращался в основную программу, исполнял процедуры buttonState() и blinck() - и снова шел в таймер. И так по кругу
     
  11. ostrov

    ostrov Гуру

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

    Еще есть прерывания, но это другая сказка.
     
    Последнее редактирование: 22 дек 2017
    Kamikadze нравится это.