Вопрос по функции tone

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

  1. Orrca

    Orrca Нуб

    Добрый день.
    Почему нижеследующий код приводит к коротким щелчкам с периодичностью в секунду вместо того, чтобы играть сигнал в течение секунды, потом секунда тишины и снова? Помогите советом, плз.

    #define BUZZER_PIN 3

    void setup()
    {
    pinMode(BUZZER_PIN, OUTPUT);
    }

    void loop()
    {
    tone(BUZZER_PIN, 200, 1000);
    noTone(BUZZER_PIN);
    delay (1000);
    }
     
  2. alex-prog

    alex-prog Гик

    Попробуйте, после tone(BUZZER_PIN, 200, 1000); добавить delay(1000);
     
  3. Orrca

    Orrca Нуб

    Спасибо, я так потом и сделал. Однако вопрос остался. Почему функция tone не приняла третий аргумент - длительность сигнала 1000 мс?
     
  4. alex-prog

    alex-prog Гик

    Попробуйте:
    Код (C++):

    void loop()
    {
    tone(BUZZER_PIN, 200, 5000);
    delay(1000);
    }
    По идее, звук должен быть 5 сек, затем пауза в 1 секунду.

    noTone вроде нужно вызывать, когда задержка в tone не указана, может поэтому он и отключает Ваш звуковой сигнал некорректно...

    Кстати, частота 200 Герц не слишком маленькая для динамика?
     
    Последнее редактирование: 3 авг 2016
  5. Orrca

    Orrca Нуб

    Все, разобрался. Помогли на ардуино.ру. Короче так, Ардуино, получив команду "tone(BUZZER_PIN, 200, 1000);" не ждет, как я полагал, 1000 мс, чтобы потом передать управление на команду noTone(BUZZER_PIN);, а делает это сразу! Потому и слышен лишь щелчок. Если сделать так, как предлагаете Вы (и я уже попробовал), то будет так. Ардуино дает команду на динамик звучать 5000 мс и сразу переходит к delay(1000); Замирает в таком состоянии только на 1000 мс, а не на 5000 мс и снова возвращается к началу цикла. Результат - постоянное звучание без каких либо внятных пауз. Странная логика, надо просто запомнить.
     
  6. alex-prog

    alex-prog Гик

    То есть, при коде, который я написал выше, паузы в звучании нет? :confused:
     
  7. Orrca

    Orrca Нуб

    Проверил, паузы нет. Но если сделать наоборот:
    void loop()
    {
    tone(BUZZER_PIN, 200, 1000);
    delay(5000);
    }
    то это будет работать так. 1000 мс из 5000 мс задержки динамик звучит, потом остаток 4000 мс - молчит и снова в начало цикла.
     
  8. alex-prog

    alex-prog Гик

    Интересная логика :) Жаль на форуме специалистов по Arduino сейчас нет, подсказали бы, почему так происходит...
     
  9. Orrca

    Orrca Нуб

    Частота 200 Гц норм для пьезожужжалки, выше - противнее звучит. А по поводу логики, то теперь понимаю, что она обычная. Если простыми словами, то Ардуино не ждет пока закончится выполнение функции, а начинает выполнять следующую за ней параллельно. Как раз иначе было бы странно. Например отдали бы мы команду динамику звучать 1000 мс. И что, пока он бы не закончил звучать не могли бы выполнить никакую другую команду? Как раз это было бы неудобно. А что до спецов, то они, очевидно, вечером набегут :)
     
  10. alex-prog

    alex-prog Гик

    У меня логика была в том, что там delay используется, то есть, пока пауза не закончится, ничего выполняться не будет, а так получается там другой процесс для паузы - многопоточный видимо, поэтому он и идёт вместе с delay в один момент. Но всё же, уточнить принцип хотелось бы, как там tone на Arduino реализовали...
     
  11. DIYMan

    DIYMan Guest

    tone, емнип, юзает таймер, поэтому работает вне зависимости от delay. Логика там простая - последним параметром передаём, через какой промежуток tone заткнётся, вот и всё. noTone надо вызывать только тогда, когда нужный промежуток времени уже прошёл. Поскольку функция tone неблокирующая, то вызов noTone сразу за вызовом tone приведёт к тому, что ничего пищать не будет.
     
    alex-prog нравится это.
  12. alex-prog

    alex-prog Гик

    DIYMan, примерно так и думал :)
     
  13. DIYMan

    DIYMan Guest

    Когда сомневаетесь - не лишним будет поглядывать в исходники ардуино, это вообще полезно на предмет "потихоньку разбираться в кишочках и низком уровне".

    Найдите файл Tone.cpp, он лежит в папке установки Arduino, в подпапке hardware/arduino/avr/cores/arduino - и там сразу будет видно, что юзается таймер, причём - не один, в зависимости от директив условной компиляции они могут юзаться разные ;)
     
  14. alex-prog

    alex-prog Гик

    DIYMan, когда до компьютера доберусь, посмотрю ;)