Мелодия на ардуино без «delay»

Тема в разделе "Arduino & Shields", создана пользователем SDV, 3 янв 2019.

  1. SDV

    SDV Нерд

    Доброго времени суток. Подскажите пожалуйста как можно написать скетч, что бы проигрывалась мелодия при достижении определенного уровня, без DELAY???
    Код (C++):

    #include <hcsr04.h>
    #define TRIG_PIN 7
    #define ECHO_PIN 8
    HCSR04 hcsr04(TRIG_PIN, ECHO_PIN, 20, 4000);
    int level_water; // уровень воды в мм.
    int stop_level = 35; // уровень при которотом срабатывает звуковой сигнал
    int volume_now; // переменная текущего уровня жидкости с датчика
    int volume_ratio = 2; // коэфициент объема жидкости, переводит уровень в объем (мл)
    int p = 9;
    const byte COUNT_NOTES = 39;

    int frequences [COUNT_NOTES] = {
      392, 392, 392, 311, 466, 392, 311, 466, 392,
      587, 587, 587, 622, 466, 369, 311, 466, 392,
      784, 392, 392, 784, 739, 698, 659, 622, 659,
      415, 554, 523, 493, 466, 440, 466,
      311, 369, 311, 466, 392
    };
    int durations [COUNT_NOTES] = {
      350, 350, 350, 250, 100, 350, 250, 100, 700,
      350, 350, 350, 250, 100, 350, 250, 100, 700,
      350, 250, 100, 350, 250, 100, 100, 100, 450,
      150, 350, 250, 100, 100, 100, 450,
      150, 350, 250, 100, 750
    };

    void setup () {
      pinMode (p, OUTPUT);
      Serial.begin(9600);
    }

    void loop() {
      hc_sdr ();
      if (level_water <= stop_level) {
        sound ();
      }
    }

    void hc_sdr () { // функция замера уровня жидкости
      level_water = hcsr04.distanceInMillimeters();
      volume_now = (level_water_max - level_water) * volume_ratio;
      Serial.println(level_water);
    }

    void sound () {
      for (int i = 0; i <= COUNT_NOTES; i++) {
        tone(p, frequences[i], durations[i] * 2);
        delay (durations[i] * 2);
        noTone(p);
      }
    }

     
     
    Последнее редактирование: 3 янв 2019
  2. Airbus

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

    А чем delay не угодил?Именно в этом коде?
     
  3. SDV

    SDV Нерд

    Программу тормозит. Это часть другого кода.
     
  4. Airbus

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

    Во время проигрывания мелодии выполняется ещё одна программа?
     
  5. SDV

    SDV Нерд

    Да.
     
  6. parovoZZ

    parovoZZ Гуру

    А если всё тоже самое, но только по-русски и с правильной расстановкой знаков препинания? Я ничего не понял.
    Играть мелодию надо с помощью таймера в режиме ШИМ. Из кода будет только требоваться запись регистра цифрового компаратора (OCRxA/B). Это всего одна команда.
     
    Un_ka и Daniil нравится это.
  7. Daniil

    Daniil Гуру

    Для каждого "звука" должна быть длительность.
    Каждый раз когда "звук" начинается засекается момент времени.
    В лупе каждый раз проверяется сколько времени прошло с начала воспроизведения "звука". Если время "звука" вышло, то нужно менять "звук" на следующий и, соответственно, засекать новое время начала.
    Но в таком случае будет проблема:
    если исполняемый код между проверками времени будет выполняться долго (по отношению к длительности "звука"), то могут (зависит от того что и как вы запрограммируете) появиться слышимые искажения мелодии.
    Чтобы свести к минимуму такие искажения, я бы советовал изучить прерывания таймера.