вопрос по функции tone()
- Войдите на сайт для отправки комментариев
Втр, 22/04/2014 - 18:53
Попробовал в своем проектике, для озвучки нажатия кнопок такую конструкцию...
----------------
void beepKey()
{
tone (buzzerPin,5000,40); //это означает: на соответ. пине, частота 5000 Hz, длительность 40миллисекунд.
}
-----------------------
Все очень даже хорошо, но это привело к "утяжелению" при компиляции на 2.5 кБ. Меня это не устраивало.
Переделал на такой вариант, с импользованием Таймера
/* При отладке (экспериментальным путем установлено, что нужна функция вывода звука в буззер tone (buzzerPin,5000,40); Эта команда генерит звук с частотой 5000 Hz, длительностью 40 милисекунд Для генерации 5000 Hz, нужно соответствующий пин "инвертировать" 10000 раз в секунду Будем использовать таймер 2. Ставим предделитель 32. Значит 16000000/32=500000 раз в секунду будет срабатывать счетчик. И увеличивать свое значение. По достижении 255 (счетчик то у нас 8 битовый) вызывается процедура ISR(TIMER2_OVF_vect) Для получения частоты в 10000 нужно чтобы переполнение счетчика происходило 500000/10000=50 раз. Итого будем при каждом вызове "подсовывать значение" в TCNT2=(255-50)=205 И счетчик протикав всего-то 50 тиков опять переполниться. Теперь с длительностью. Заводим переменную времени звучания soundLenght. для получения длительности в 40 миллисекунд (при условии, что каждые 10000 будем увеличивать соответствующий счетчик) 1 сек=1000 миллисекунд = 10000 "прыжков" 40миллисекунд=400 "прыжков". Итого, как только достигаем этого (400) значения - выключаем прерывание. Получается, что для получения "звукового ПИК" нам нужно просто разрешить прерывание */ byte buzzerPin=11; int soundLenght=0; void setup(){ pinMode(buzzerPin,OUTPUT); TCCR2A = 0; //нормальный режим TCCR2B = 3; // 011 - fclk/32 (16000000/32=500000) // Предделитель таймера/счетчика TCNT2 = 205; // TIMSK2 |= (1 << TOIE2); // разрешаем прерывание таймера/счетчика 2 по переполнению } void loop(){ beepKey(); delay(2000); } ISR(TIMER2_OVF_vect) { soundLenght++; // digitalWrite(buzzerPin, !digitalRead(buzzerPin)); PORTB = PORTB ^ B00001000; //инвертируем третий бит порта TCNT2 = 205; //подсовываем в счетчик наше значение if (soundLenght>400){ TIMSK2 &= ~(1 << TOIE2); // если нужный период времени прошел, выключаем прерывание PORTB &= ~_BV(PORTB3); //ну и пишем 0 в порт // digitalWrite(buzzerPin,0); soundLenght=0 ; //и сбрасываем переменную счетчик времени } }//end ISR void beepKey() { TIMSK2 |= (1 << TOIE2); //просто разрешаем прерывание }
Вот в таком виде (отдельным скетчем), все более-менее работало. Однако при вставке всей "этой" конструкции в проект звук из биппера есть, но ТАКОЙ тихий!
В проекте использую еще и Таймер1. И прерывание от внешнего источника. Весь это участок в проекте выглядит так:
attachInterrupt(0, blink, CHANGE); <-- одна функция
вторая функция (вывод изображения на индикатор)
TCCR1A = 0; //нормальный режим
TCCR1B = 1;
TIMSK1 |= (1 << TOIE1); // разрешаем прерывание таймера/счетчика 1 по переполнению
и третья:
//для звука
TCCR2A = 0;
TCCR2B = 3;
TCNT2 = 205;
А теперь вопрос, могут ли в такой комбинации обработчики прерываний НАСТОЛЬКО мешать друг другу?
Товарищу не ответили.
Может мне кто-нибудь ответит или ткнёт носом (сам не нашел). Где найти подробное описание функции Tone() какая у неё минимальная частота? У меня получается, что Arduino Pro mini ниже 35Гц некорректно их выдаёт, частота получается гораздо больше.
Собственно необходимо сделать преобразователь частоты для датчика скорости мотоцикла, который выдаёт прямоугольные импульсы. Если бы не косяк с функцией tone() указаный выше проблема бы решалась, "в 2 строчки":
перепробывал кучу других вариантов начиная от использования delay до прерываний и использования библиотеки TimerOne. Может кому в голову придёт здравая идея буду благодарен, если поделитесь.
PS или опять всё упирается в 16MHz у pro mini?