Skocz do zawartości

[C] Programowy PWM na 50 Hz


Jechbeat

Pomocna odpowiedź

Witam

Już od dawna zajmuję sie programowaniem, lecz komputerów (c++, c#).

Natomiast zacząłem uczyć się C i programowania Atmeg (Tu konkretnie Atmega 128).

Teraz siedzę nad line followerem, i mam problem z PWM, płytka poszła już do druku 🙂, a wyprowadzenia do Mostka H, które powinny nadawać sygnał PWM, zostały podłączone ze zwykłych I/0.

Dlatego jedyne rozwiązanie to programowe PWM.

Dodatkowo jest jeszcze turbina podpięta przez regulator też do zwykłego portu.

Z tego co wiem regulator wymaga sygnału PWM o częstotliwości 50 Hz (20 ms), gdzie sygnał rozruchowy to 1 ms, a potem pomiędzy 1,5 a 2 ms (min , max mocy).

I teraz powiem jak wykombinowałem ale nie wiem czy tak to działa.

Początkowo deklaracja zmiennych odpowiedzialnych za wypełnienie

volatile uint8_t pwm1,pwm2,pwm3;

Chce ogólnie na timerze2 uzyskac 50 Hz, czyli zrobiłem tak:

 TCCR2 |= (1<<WGM21);   //tryb CTC
  TCCR2 |= (1<<CS21);    //Preskaler 8
  OCR2 = 10; //dodatkowy podział cześtotliowści przez 10
  TIMSK |= (1<<OCIE2); // zewolenie na przerwanie CompareMatch

Czestowtliwosc procka dobrałem 1024000 Hz.

I teraz timer2 jest 8-bitowy, wiec przechowuje do 256.

To 1024000/8/10/256 = 50

Tak sobie dobralem zeby przerwanie otrzymywac 50 razy na sekundę. (czyli jakby 50 Hz tego PWM).

Więc teraz:

ISR( TIMER2_COMP_vect )   //Zegar pracuje w czestotliwosci 12800 Hz, wysyła przerwania 50 razy na s, 
{
static uint8_t cnt; ///definicja naszego licznika PWM

//bezpośrednie sterowanie wyjściami kanałow PWM

if(cnt<pwm1) ENG_0_ON; else ENG_0_OFF;

if(cnt<pwm2) ENG_1_ON; else ENG_1_OFF;

if(cnt<pwm3) TUR_ON; else TUR_OFF;

cnt++; //zwiększenie licznika o 1
if(cnt > 50)cnt = 0;
}

Ale teraz nawet jak to by było dobrze, dochodziłby problem.

Jak wysyłać sygnal inicjujący 1 ms na te 20 ms, przeciez to jest 2.5 raza na 50, jak to rozwiązać.

Bardzo proszę o pomoc, i mam nadzieję że chociaż część jednak rozumiem 🙂.

Pozdrawiam i dziękuje za przeczytanie.

Edit: Czy ewentulanie moge zmiejszyć dzielnik OCR2 na 5, żeby uzyskac 100 Hz i wtedy po prostu dwa wieksze dac liczby, wtedy nie było by problemu i zamiast 2.5 miał bym pełną liczbę 5

Link do komentarza
Share on other sites

wiem ze strasznie malo, ale wyczytalem ze jak sie robi pwm programowo to wtedy mozna to pwm miec na kazdej nozce, ale za to wszystkie pracuja na jednym zegarze, a przecierz regulator musi miec 50 Hz. No chyba ze zrobie z 10-20k Hz aw przerwaniu na silniki bede w kazdej petli wysylal, a do regulatora np co te 200 przerwan

Link do komentarza
Share on other sites

Zmień timer na 16 bitowy.

W Atmedze 128 są takie 2 więc jeden wykorzystasz do kół, drugi do turbiny bo chyba ją chcesz uruchamiać i sterować takimi sygnałami.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Moim zdaniem, to powinieneś mimo wszystko tak przerobić płytkę, by dało się wykorzystać sprzętowe generatory PWM. Druty na płytce? Nie pierwsze i pewnie nie ostatnie. Jeśli to Twój pierwszy projekt (a sądząc z rodzaju błędu to chyba tylko raz można tak sobie strzelić w kolano) to żaden wstyd, ścieżki pod nóż i do roboty. I tak jesteś w dobrej sytuacji, bo nie musisz wylutowywać scalaków w TQFP czy BGA. Na gołej płytce takie zmiany to pewnie godzina-dwie i po bólu.

Gdybyś jednak był skrajnym estetą i brzydził się kableków na PCB, to programowy PWM daje sie oczywiście robić. Jest to duże obciążenie dla procesora (nie na darmo zrobiono to w sprzęcie timera) szczególnie, jeśli częstotliwość powtarzania zaczyna być duża.

Ja bym tematów impulsów PPM i PWM dla silnika nie łączył w jedną funkcję. Każdy z nich ma w Twoim przypadku inne wymagania. Sterowanie turbinką jest dużo prostsze a o generacji PPM napisano już wiele.

Poświęć na to jeden krótki timer a w obsłudze jego przerwania zbuduj sobie prostą funkcję, która w zależności od flagi odwracanej za każdym razem będzie albo ustawiała albo zerowała wyjście. Teraz już tylko wystarczy napisać linijkę kodu wymyślającą za jaki czas ma nastąpić kolejne przerwanie i odpowiednio przeładowującą sam timer albo jeszcze lepiej jego rejestr OCRn. Np. jeśli puścisz timer "wolno" z zegarem dajmy na to 10kHz to zakres czasu jaki możesz odliczyć będzie zawierał się w zakresie od 100us do 25.6ms i to wystarcza, prawda? Teraz robisz tak:

1. W inicjalizacji odblokowujesz przerwania od komparacji z rejestrem OCR tego timera i ustawiasz sobie stan zmiennej np. ppm_time określającej długość impulsu PPM (liczoną w okresach timera = 100us) np. na 10, czyli ma być impuls 1ms. Zawartośc timera jest nieistotna, rejestru OCR również.

2. Obsługa przerwania od komparacji timera z OCR:

Jeśli znacznik był ustawiony to:

{

zerujesz wyjście

OCR += (200-ppm_time)

}

else

{

ustawiasz wyjście

OCR += ppm_time

}

i za każdym razem odwracasz stan znacznika

Dzięki temu rejestr OCR zawsze pokazuje na przyszłą chwilę w czasie, do której timer musi doliczyć. Teraz wystarczy, by program wpisywał do zmiennej ppm_time żadaną długość impulsu a prawidłowy ciąg PPM będzie się generował z okresem 20ms na wyjściu. To daje tylko dwie obsługi przerwania na każdy okres PPM a to nie jest dużo. Oczywiście dla innej szybkości timera liczbę 200 (okres impulsów PPM wyrażony w "cyknięciach" timera) musisz zastąpić inną stałą ale idea będzie taka sama.

W przypadku sterowania mostkiem H starałbym się zmaksymalizować częstotliwość PWM i ta funkcja będzie niestety obciążąła procesor dużo bardziej niż PPM. Skorzystaj z innego timera, też może być krótki 8-bitowy, bo nic oprócz zgłaszania przerwań nie jest nam potrzebne. Musisz też sobie odpowiedzieć jakiej rozdzielczości PWM potrzebujesz. Może nie ma sensu robić 8 bitów czyli 256 stopni wysterowania gdy wystarczy np. 16? W najprostszym przypadku zgłaszający w trybie CTC przerwania timer wyznacza Ci najmniejszy "skok" PWM. Dalej wiadomo, programowo "obracasz" jakimś licznikiem i porównujesz jego zawartość z żądanym wysterowaniem danego kanału (lub z dwoma różnymi, gdy kanały masz dwa). Gdy licznik jest mniejszy od wysterowania, odpowiednie wyjście zerujesz. Gdy większy lub równy, ustawiasz w stan wysoki. Taki sposób oznacza, że musisz obsłużyć np. 16 przerwań w każdym okresie PWM. Dla powiedzmy 1kHz to już się robi 16kHz - ATmega jeszcze da radę ale na pewno nie z zegarem 1MHz. Musisz tu podkręcić ją do tego, co fabryka dała. Przecież oprócz robienia PWM ma jeszcze sensownie "myśleć" dokąd ma jechać.

Możesz też użyć metody pokazanej w poprzednim akapicie - planowania i generowania przerwań tylko wtedy, gdy coś ma się stać ale musisz mieć świadomość, że to jedynie odciąży procesor od bezproduktrywnie mielonych przerwań ale nie pozwoli na zwiększenie częstotliwości PWM. Krytycznym jest tu czas obsługi przerwania i musi on być krótszy niż "skok" PWM o jeden stopień wysterowania.

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.