Не могу понять поведение таймера.

Nimrok94
Offline
Зарегистрирован: 01.06.2018

   Здравствуйте, пытаюсь наладить работу пьезодинамика с микроконтроллером. Сейчас работаю в Ардуино и по некоторым причинам пробую сделать это в обход библиотеки tone(на самом деле пробовал и брать код из tone.cpp, и писать свой, и постоянно терплю фиаско). Написал простой тестовый код с использованием 8-битного t2 таймера: 

#include <avr/interrupt.h>
#include <avr/io.h>

#define F_CPU 16000000L  
#define buzzer 6

unsigned long tcount = 0;
char ocr = 100;

ISR(TIMER2_COMPA_vect)    //раз в 100*(1/16 000 000) секунд
{
    if (tcount > 1000)                  //раз в 0,006 25с
    {
      PORTD ^= (1 << PD6);      //за 0,0125с ножка дергается внизвверх
      tcount = 0;                          //в секунду ножка дергается внизвверх 80 раз
    }
    tcount++;                              //тикает раз в 0,000 006 25с
}

void setup() 
{
  pinMode(buzzer, OUTPUT);
  digitalWrite(buzzer, LOW);
  TCCR2A |= (1 << WGM21);   //СТС режим
  TCCR2B |= (1 << CS20);       //без предделителя
  OCR2A  = ocr;
  TIMSK2 |= (1 << OCIE2A);
}

void loop() 
{
  delay(5);
}

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

По эффективности и правильности вопросов нет - это только проверка таймера и пьезодинамика.

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В строках №№ 24-27 замените |= на присваивания.

Таймер уже настроен средой ардуино (прескэйлер и много чего), а Вы сохраняете все их биты, взводя только свои. Вам же нужно установить все биты как Вам надо - какие-то взвести, а какие-то сбросить.

P.S. Зачем делать так сложно мне непонятно, но работать-то, конечно, должно.

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Действительно, спасибо. Я добавил перед взводом регистров их обнуление, еще в loop вставил: delay(500); TIMSK2 ^=(1 << OCIE2A); и здесь нарвался на старую свою проблему с пьезодинамиком и таймерами.

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

Такое поведение уже я замечал и на отдельной atmega328 с ардуиновскими фьюзами и кварцем 16МГц.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так первая проблема решилась? Мы переходим ко второй? Правильно?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Nimrok94, не очень понятно зачем заставлять срабатывать прерывания в 1000 раз чаще, чем нужно. Вот то-же самое, но элегантнее:

#define buzzer 6
char ocr = 100;

ISR(TIMER2_COMPA_vect){
static uint8_t n;
if (n <77) {PORTD ^= (1 << PD6);} 
n<128? n++ : n=0;
}

void setup() {
pinMode(buzzer, OUTPUT);
TCCR2A = (1 << WGM21);   //СТС режим
TCCR2B = (1 << CS20)|(1 << CS21)|(1 << CS22); //div1024
OCR2A  = ocr;
TIMSK2 = (1 << OCIE2A);
}

void loop() {}

Без участия лупа получаются прерывистые гудки.

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Да, так и есть. Нужно создать новую тему? Не будет ли это подобием спама? Я раньше не писал на специализированных форумах, слышал тут довольно строгие правила.

Первая проблема действительно решилась. Но я неожиданно понял, что новая имеет для меня более важное значение, так как она давно мешается. Как-то мне нужно было сделать звуковое сопровождение на устройстве, которое общалось пакетами в ~30 байт по uart (rs 232, rs485). На Ардуино столкнулся с тем, что функция tone просто переставала работать после получения одного сообщения по Serial, тогда перешел на си и появилось это: после отработки нужных частот динамик время от времени начинал высоко пищать, когда обработка прерываний была уже отключена и должна была быть мертвая тишина. Пищать он так может до следующего срабатывания нужных частот и, в дальнейшем, до бесконечности. 

Я все это отложил на длительный срок, а сейчас, столкнувшись с проблемой, не выдержал и, наконец, написал сюда :) 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1. Посмотрите, что Вам написал dimax, он оказался менее ленивым, чем я. Я то ограничился замечанием, что не понимаю зачем такие сложности.

Теперь о второй проблеме

Регистры таймера (кроме OCR2A и OCR2B) не имеют двойной буферизации, потому, возможно, Вы просто невовремя в них пишете и всё идёт вразнос. Попробуйте

1. запретить прерывания на время выполнения очистки бита в TIMSK2.

2. Одновременно с очисткой бита, сбрасывайте бит запроса прерывания OCF2A

3. Если не поможет, заодно обнуляйте TCNT2 там же.

Но, если есть такая возможность, я бы просто останавливал таймер - это "неэстетично, зато дешево, надёжно и практично".

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Первым делом, как проснулся, попробовал код dimax'а - по таймингу, конечно, работает, но вот переход в писк, когда должен молчать, динамик продолжает. Получается нечто такое: /(звук)(писк)\-/(звук)(тишина)\-/(звук)(писк)\-/(звук)(тишина)\-

Пробовал также cli(), sei(), отключать таймер занулением CS2 битов вместе со всем регистром TCCR2B и другие регистры обнулял. Что-то изменил только cli() на первую половину периода - писка нет, только постоянный звук без пауз.

Может быть проблема аппаратная, но в некоторых примерах динамик соединяют с мк вообще без обвязки и никаких сбоев не ловят. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите, если Вы спец, то не обижайтесь, но тут у нас такое бывает ... Что у Вас за динамик? Не активный случаем? Дайте-ка ссылочку, пожалуйста (хотя китайцы могут и наврать - нарывался), но всё равно, дайте-ка.

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Спец это точно не про меня)

Пьезодинамик вроде самый обыкновенный: 

Подключен вот по такой схеме:

VCC брал как внешние 12В, так и 5В со стабилизатора ардуины. И ведь функция tone работает хорошо, а как пытаюсь руками все настроить так пищит. Но у tone была своя проблема, как писал выше. Я думал может кто-то сталкивался с таким и сейчас опишет свой опыт) Единственное, что во всех случаях я работал с atmega328 на 16МГц с ардуиновским бутлоадером и набором фьюзов, может это решает. В любом случае буду пробовать дальше. Спасибо вам за помощь)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Попробуйте подать на него просто 5В, соблюдая полярность. Никаких tone, никаких шимов - вообще ничего, просто 5В подайте питание, соблюдая нарисованную полярность..

Если запищит, то это активный динамик, а судя по наклейке (её плохо видно, но всё же) - это так и есть.

Если активный, то все Ваши проблемы имеют простые объяснения. Проверьте и скажите. И если он от простых 5В запищит, то я смогу полностью объяснить его поведение, во всех описанных Вами случаях.

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Трудно передать словами, что я почувствовал, когда подал на него напряжение) Я даже не помню где покупал этот черный цилиндр с двумя ножками и вот оказалось, что это вполне самодостаточная пищалка! И даже в голову не пришло при таких симптомах провести самую простую проверку..

Еще раз спасибо за ваш свежий взгляд)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Nimrok94 пишет:

Пьезодинамик

Это - сразу в перлы. 

Вы уж что ли Википедию бы почитали, что такое громкоговоритель

https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%BE%D0%BC%D0%BA%D0%BE%D0%B3...

и каких видов они бывают

 https://ru.wikipedia.org/wiki/%D0%9F%D1%8C%D0%B5%D0%B7%D0%BE%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%B8%D0%B7%D0%BB%D1%83%D1%87%D0%B0%D1%82%D0%B5%D0%BB%D1%8C

https://ru.wikipedia.org/wiki/%D0%AD%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%BE...

 

Nimrok94
Offline
Зарегистрирован: 01.06.2018

Кстати, действительно столкнулся с вопросом - как называть эту пищащую штуку, и в дальнейшем запросы в интернете слова пьезодинамик давали свои результаты) Вот например- http://wiki.amperka.ru/%D0%BA%D0%BE%D0%BD%D1%81%D0%BF%D0%B5%D0%BA%D1%82-arduino:%D0%BF%D1%8C%D0%B5%D0%B7%D0%BE%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D0%BA

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну, значит, это не Ваш перл.

Хотя, надо отметить, техника развивается быстрее, чем успевает устаканиться терминология. Например, использованный глубокоуважаемым Евгением термин "активный динамик" уже занят совершанно другим устройством.