Niniejszy projekt to nic odkrywczego, ale może się komuś przyda.
Czasem potrzebujemy wygenerować sygnał PWM dla większej ilości kanałów a akurat nie mamy pod ręką dedykowanego układu - tak było w moim przypadku gdy robiłem mały projekt z oświetleniem i wentylatorami przy "modowaniu PC" - tak to się pisze? To nie mój PC
Oczekiwanie na dedykowany układ z Chin nie miało sensu a i ceny takich układów nie były zachęcające. Postanowiłem poradzić sobie z tym co akurat było w szufladzie. A w niej na szczęście mam zazwyczaj sporo różnych uC. W obroty wziąłem attiny2313.
Po kilku godzinach pisania powstał prosty generator PWM sterowany przez port szeregowy (UART) za pomocą prostego protokołu tekstowego więc bez trudu można sterować układem z portu szeregowego PC.
Układ można konfigurować na kilka sposobów:
- można określać ilość wykorzystywanych kanałów;
- można określać rozdzielczość/głębokość PWM wartości od 0 do 255;
- można określić wypełnienie PWM dla każdego kanału osobno (w zakresie ustalonej głębokości);
Ustalona konfiguracja zapisywane jest w wewnętrznej pamięci EEPROM więc po ponownym uruchomieniu układ działa z ostatnio przesłanymi parametrami.
Myślę, że układ może być ciekawą i tanią alternatywą w wielu zastosowaniach tym bardziej, że cena układu atTiny jest bardzo niska a czasem niższa od dedykowanych generatorów PWM.
Rozwiązanie ma swoje ograniczenia ale jak wspomniałem powstało z potrzeby chwili zapewne można to zrobić inaczej i lepiej jednak do sterowania kolorowymi diodami i 4 wentylatorami w PC sprawdziło się doskonale.
W zależności od konfiguracji głębokości modulacji oraz ilości aktywnych kanałów zmieniają się maksymalne częstotliwości generowanego sygnału PWM a przedstawia je poniższa tabela oraz załącznik xls.
Wartości skrajne oraz przykładowe to:
- 476kHz dla 1 kanału i głębokości PWM = 4;
- 2,5kHz dla 8 kanałów i głębokości PWM = 255;
- 25,5kHz dla 8 kanałów i głębokości PWM = 26;
- 25,5kHz dla 8 kanałów i głębokości PWM = 26;
- 10,0kHz dla 8 kanałów i głębokości PWM = 64;
- 102kHz dla 4 kanałów i głębokości PWM = 10;
* Wartości podane dla kwarcu 20Mhz.
Na obrazku wybrane wartości częstotliwości PWM w zależności od ilości kanałów i głębokości (w załączniku xls pełne dane):
Opis protokołu:
/*
Opis protokołu komunikacji:
Ramki przychodzące:
-------------------
Programowanie wypełnienia PWM wybranego kanału:
bajt 0 : numer kanału w ascii ( wartości : '0', '1', '2', '3', '4', '5', '6', '7' )
bajt 1 : starsze 4 bity wypełnienia PWM jako HEX ( '0' .. 'F' )
bajt 2 : młodsze 4 bity wypełnienia PWM jako HEX ( '0' .. 'F' )
bajt 3 : 'X' zakończenie ramki
Zmiana ilości kanałów:
bajt 0 : 'C'
bajt 1 : starsze 4 bity ilości kanałów zawsze = '0'
bajt 2 : młodsze 4 bity ilości kanałów jako HEX ( '0' .. '8' )
bajt 3 : 'X' zakończenie ramki
Zmiana rozdzielczości PWM :
bajt 0 : 'R'
bajt 1 : starsze 4 bity rozdzielczości PWM ( '0' .. 'F' )
bajt 2 : młodsze 4 bity rozdzielczości PWM ( '0' .. 'F' )
bajt 3 : 'X' zakończenie ramki
Prośba o status :
bajt 0 : 'G'
bajt 1 : cokolwiek
bajt 2 : cokolwiek
bajt 3 : 'X' zakończenie ramki
Odpowiedzi:
-----------
- przyjęcie ramki potwierdzane jest znakiem '#' ;
- błąd w interpretacji ramki sygnalizowany jest znakiem '!' ;
Przykład użycia:
----------------
C04X ( ustaw 4 kanały )
# ( potwierdzenie od sterownika )
RFFX ( ustaw rozdzielczość PWM na 255 )
# ( potwierdzenie od sterownika )
366X ( ustaw wypełnienie PWM kanału 3 na 0x66 )
# ( potwierdzenie od sterownika )
223X ( ustaw wypełnienie PWM kanału 2 na 0x23 )
# ( potwierdzenie od sterownika )
*/
Kod źródłowy:
Uwagę zwrócą zapewne powtórzone pętle... Zastosowałem ich kilka ze względu na optymalizację i chęć uzyskania jak najwyższych częstotliwości. Tak samo wstawka assemblerowa ma na celu optymalizację przebiegu każdej pętli o 1 takt (kompilator nie chciał tego zoptymalizować po mojej myśli).
Kod: C / C++
W załączniku kod źródłowy oraz pliki HEX (uwaga, HEX dla kwarcu 11.059Mhz).
Fajne? Ranking DIY
