Как контролировать частоту дискретизации??

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

  1. portnoj

    portnoj Нуб

    Люди помогите плиз, чисто теоретический вопрос... Разбираюсь с ПИД -регулятором. Для себя уяснил что смертельно важно опрашивать состояние системы через равные промежутки времени...А теперь вопрос №1"лайтовый"? Как понять как часто уно опрашивает датчик или как частота будет зависеть от количества кода, и вообще как оценить время выполнения программы??? и ВОПРОС №2 "ГЛАВНЫЙ" - как задать желаемую частоту опроса датчика? например хочу чтоб опрашивал с частотой 100 ГЦ как сделать не пойму? Всем заранее спасибо если что изв за нубство как обычно:)
     
  2. portnoj

    portnoj Нуб

    случайно возникла идея- не связан ли мой вопрос№2 с прерыванием по таймеру?
     
  3. ИгорьК

    ИгорьК Гуру

    Контролировать частоту дискретизации очень просто - каждый раз после опроса датчика указываете новое время его проверки и делаете такую проверку после того, как текущее время превысило контрольное.
    Код (Text):
    если mills() > контрольное время {
        контрольное время = millis() + интервал;
        проверить датчик;
    }
    Что касается прерываний, то все зависит от того, что делает система в целом.
    Например, если Вы печатаете биткоины, а параллельно управляете отопителем, то, безусловно, все надо завешивать на прерывание.
    Однако, если Вы ничего особо тяжелого не делаете, то прерывания скорее вредны и вот почему.
    Вы, конечно, можете проверить датчик в прерывании, но Вы должны, кроме того, как-то отреагировать на проверку - рассчитать необходимую реакцию, дать команду исполнительному устройству. Все это действо обязано уложиться в промежуток, между проверками, иначе реакция будет в ответ на уже несуществующее показание датчика. И что это за ПИД-управление тогда?
    В общем, если расчетов много, проверок много - надо брать более мощный процессор, а не заниматься прерываниями. ИМХО.
    Посмотрите эту тему, может чем-то поможет.
     
  4. DrProg

    DrProg Вечный нерд

    Правильнее всего именно так и сделать, с прерыванием по таймеру. Можно еще по millis() в цикле, проще но не тру.
     
    Последнее редактирование: 11 сен 2015
    ИгорьК нравится это.
  5. ИгорьК

    ИгорьК Гуру

    Пруф?
     
  6. Alex19

    Alex19 Гуру

    Все зависит от того, для чего нужно контролировать частоту.

    Предположим нужно формировать сигнал ШИМ, PPM (или как там его называют, сигнал управления сервомашинками) или требуется формировать другие сигналы где требуется 100% соблюдение временных периодов, тогда без варианта - прерывания.

    Кроме формирования сигналов иногда могут появится другие причины, где требуется точное соблюдение временных интервалов.

    Когда происходит прерывание, работа loop будет прервана и управление будет передано обработчику прерывания, после того как обработчик прерывания будет выполнен, управление вернется в loop, в то место где работа loop была прервана прерыванием.

    Сами прерывания очень мощный инструмент, но их неправильное использование таит в себе больше проблем, чем плюсов.

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

    Но нужно учитывать, что вариант на mills(), зависит от Вашего кода.

    К примеру (пример из BlinkwithoutDelay) какой-то код 1 выполняется 234 миллисекунды, какой-то код 2 выполняется 136 миллисекунды, интервал 1000.
    Код (Text):

    /* Blink without Delay

    */

    // constants won't change. Used here to
    // set pin numbers:
    const int ledPin =  13;      // the number of the LED pin

    // Variables will change:
    int ledState = LOW;             // ledState used to set the LED
    long previousMillis = 0;        // will store last time LED was updated

    // the follow variables is a long because the time, measured in miliseconds,
    // will quickly become a bigger number than can be stored in an int.
    long interval = 1000;           // interval at which to blink (milliseconds)

    void setup() {
      // set the digital pin as output:
      pinMode(ledPin, OUTPUT);
    }

    void loop()
    {
      // here is where you'd put code that needs to be running all the time.

      // check to see if it's time to blink the LED; that is, if the
      // difference between the current time and last time you blinked
      // the LED is bigger than the interval at which you want to
      // blink the LED.
      unsigned long currentMillis = millis();

      /* Какой-то код 1 */

      if(currentMillis - previousMillis > interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;

        // if the LED is off turn it on and vice-versa:
        if (ledState == LOW)
          ledState = HIGH;
        else
          ledState = LOW;

        // set the LED with the ledState of the variable:
        digitalWrite(ledPin, ledState);
      }
      /* Какой-то код 2 */
    }
     
    Первый раз мы включили светодиод, к следующей поверки мы подошли разницей значений 370 (код 2 и код 1 = 136 + 234) выключать рано, доходим до следующей (370+ 136 + 234 = 740) выключать рано, идем до следующей (740 + 136 + 234 = 1110) , пора включать. Ошибка для данного примера в вакууме составила - 110 миллисекунд. Именно по этому все проверки на millis сравниваются на больше (в идеале больше или равно).

    Все значения были взяты с потолка, просто чтобы описать работу. Для микроконтролера значение в 100 миллисекунд если не вечность, то близка к ней.

    Для ПИД регулирования, в большинстве случаев достаточно и millis().
     
    Последнее редактирование: 11 сен 2015