Cześć, Mam problem z PWM sterowanym z timera1 używanym do sterowania on buzzerem. Działa to tak, że timer2 odlicza konkretny czas, aby zmienić częstotliwość dla PWM. W tablicy mam zapisane kilka zestawów częstotliwości, na które po kolei ma się przestawiać PWM, co daje w efekcie krótką melodyjkę. Na potrzeby testów zmieniłem program, żeby po wywołaniu funkcji Play wywoływał na przemian tylko dwie częstotliwości i ku memu zdumieniu działa to bardzo losowo. Np. 30 sekund gra tak jak powinien, następnie zawieszą się i przez sekundę w ogóle nie wydaje dźwięku albo nie działa jeden z tonów i efekt jest taki, że na przemian gra i cichnie. Pomierzyłem oscyloskopem i wygląda na to, że winnym jest PWM, licznik timer2 wywołuje się prawidłowo - regularnie, natomiast zachowanie PWM jest totalnie losowe. Poniżej załączam kod obsługujący buzzer oraz krótki film z obrazem z oscyloskopu oraz dźwiękiem buzzera (przyciąłem tak, żeby było widać przejście, ale dzieję się tak za każdym razem inaczej i po kolejnym losowym czasie zestaw sam znowu wraca do tonu z początku). Męczę się już z tym jakiś czas i nie mam pojęcia co tam się może dziać. Funkcja Play jest wywoływana z raspberry pi pi I2C. Ogólnie komunikacja z Atmegą działa i jej inne zadania również, więc wnioskuje, że nie zawiesza (resetuje) się cały procesor, a jedynie PWM.
Dzięki za szybkie odpowiedzi. Dopiero jutro sprawdzę jak zachowa mi się kontroler z proponowanymi zmianami, jednak mam pytanie co do rady o volatile. Samo scheme_buffer nie jest volatile, a tylko zmienna prescaler_time. Wydawało mi się, że skoro inkrementuje ją przerwanie oraz resetuje funkcja Play, to jednak trzeba użyć volatile.
Przez chwilę myślałem, że źródłem problememu jest zbyt duża częstotliwość modyfikowania rejestrów OCR1B oraz ICR1. Rozumiem, że skoro mogę to teoretycznie zmieniać przy każdym przepełnieniu timera1, to moja teoria raczej odpada?
Dodam, że wykonałem jeszcze jeden test, a mianowicie zmieniłem w przerwaniu timera2, żeby set_frequency nie było wywoływane co 20 przerwań, a co 100 i wtedy problem nie występował przez kilka minut ciągłej pracy.
Przez chwilę myślałem, że źródłem problememu jest zbyt duża częstotliwość modyfikowania rejestrów OCR1B oraz ICR1. Rozumiem, że skoro mogę to teoretycznie zmieniać przy każdym przepełnieniu timera1, to moja teoria raczej odpada?
Raczej nie częstotliwość tu decyduje, a przypadkowość momentu zmiany wartości ICR1. Podejrzewam, że problem będzie podobnej natury jak w tym wątku: http://forum.atnel.pl/topic15630.html#p162736 tylko w Twoim przypadku wartość TOP znajduje się w ICR1. Rozwiązanie, które zaproponowałem, polega na tym, że w momencie zmiany ICR1 wartość TCNT1 będzie zawsze bardzo niska, więc ICR1 zawsze będzie większe. W tej chwili moment ten jest dosyć przypadkowy, bo timery 1 i 2 nie pracują synchronicznie, to znaczy mają inne interwały czasowe, które nie są prawdopodobnie podzielne przez siebie bez reszty, tym bardziej, że przecież okres zliczania timera 1 zmienia się po zmianie ICR1.
stefan_bak napisał(a):
Dodam, że wykonałem jeszcze jeden test, a mianowicie zmieniłem w przerwaniu timera2, żeby set_frequency nie było wywoływane co 20 przerwań, a co 100 i wtedy problem nie występował przez kilka minut ciągłej pracy.
Podejrzewam, że zmniejszenie częstotliwości wywołania funkcji set_frequency() to tylko zmniejszenie prawdopodobieństwa, a problem prędzej czy później i tak wystąpi. Chwila, w której to będzie następować może być zależna od melodii, czyli od wartości ICR1 z tablicy.
Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 2 gości
Nie możesz rozpoczynać nowych wątków Nie możesz odpowiadać w wątkach Nie możesz edytować swoich postów Nie możesz usuwać swoich postów Nie możesz dodawać załączników