Kontroluj częstotliwość PWM sprzętu

21

Używam sprzętowego wyjścia PWM z wiringpi. Zapewnia funkcję pwmSetClock, która powinna umożliwić zmianę częstotliwości. ( https://projects.drogon.net/raspberry-pi/wiringpi/functions/ ). Uważam, że ponieważ domyślnie jest to 200 MHz ustawienie dzielnika na 200000000 powinno sprawić, że dioda LED podłączy się do wyjściowej lampy błyskowej w widoczny sposób, ale tak nie jest.

Czy można to zmienić?

użytkownik1217949
źródło
1
Robię pewne testy ze sprzętowym PWM, i wydaje się, że nie ma on stałej częstotliwości. Zmieniało się w zależności od ustawionej szerokości impulsu pwmWrite(). Nie spodziewałbym się, że to się wydarzy
TheMeaningfulEngineer

Odpowiedzi:

25

Niedawno miałem jakiś powód, aby sam zacząć eksperymentować z PWM i odkryłem, że (jak wskazano w jednym z komentarzy) częstotliwość wydaje się zmieniać w zależności od cyklu pracy - bizzare, prawda? Okazuje się, że Broadcom wdrożył „zrównoważony” PWM, aby impulsy PWM były jak najbardziej równomiernie rozłożone. Podają opis algorytmu i trochę więcej dyskusji na stronie 139 swojego arkusza danych: http://www.element14.com/community/servlet/JiveServlet/downloadBody/43016-102-1-231518/Broadcom.Datasheet.pdf

Więc tak naprawdę chcesz przełączyć PWM w tryb znaczników, co da ci tradycyjny (i łatwo przewidywalny) PWM, którego szukasz:

pwmSetMode(PWM_MODE_MS);

Reszta odpowiedzi zakłada, że ​​jesteśmy w trybie znaczników.

Przeprowadziłem również eksperymenty z dopuszczalnym zakresem wartości dla pwmSetClock()i pwmSetRange(). Jak zauważono w jednej z pozostałych odpowiedzi, prawidłowy zakres pwmSetClock()wydaje się wynosić od 2 do 4095, podczas gdy prawidłowy zakres pwmSetRange()wynosi do 4096 (nie próbowałem znaleźć dolnej granicy).

Zasięg i zegar (lepsza nazwa to prawdopodobnie dzielnik) wpływają na częstotliwość. Zakres wpływa również na rozdzielczość, więc chociaż możliwe jest użycie bardzo niskich wartości, istnieje praktyczny limit tego, jak nisko prawdopodobnie będziesz chciał zejść. Na przykład, jeśli użyłeś zakresu 4, możesz osiągnąć wyższe częstotliwości, ale będziesz mógł ustawić cykl pracy tylko na 0/4, 1/4, 2/4, 3/4 lub 4/4.

Zegar Raspberry Pi PWM ma częstotliwość podstawową 19,2 MHz. Ta częstotliwość, podzielona przez argument to pwmSetClock(), jest częstotliwością, przy której licznik PWM jest zwiększany. Kiedy licznik osiągnie wartość równą podanemu zakresowi, resetuje się do zera. Podczas gdy licznik jest krótszy niż określony cykl pracy, wydajność jest wysoka, w przeciwnym razie wydajność jest niska.

Oznacza to, że jeśli chcesz ustawić PWM na określoną częstotliwość, możesz użyć następującej zależności:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange.

Jeśli użyjesz maksymalnych dopuszczalnych wartości dla pwmSetClock()i pwmSetRange(), uzyskasz minimalną możliwą do osiągnięcia częstotliwość sprzętową PWM ~ 1,14 Hz. To z pewnością spowoduje widoczne migotanie (naprawdę błysk), naprawdę diody LED. Potwierdziłem powyższe równanie za pomocą oscyloskopu i wydaje się, że tak jest. Na górną granicę częstotliwości wpłynie potrzebna rozdzielczość, jak opisano powyżej.

Kerry
źródło
Odnośnie dolnej granicy pwmRange: Z powodzeniem ustawiłem ją na 2 (aby uzyskać cykl roboczy 50%).
Ted Pudlik,
z jakiego źródła wiesz, że zegar PWM ma częstotliwość 19,2 MHz?
thggg
10

Zgodnie z tą formułą:

pwmFrequency in Hz = 19.2e6 Hz / pwmClock / pwmRange

Możemy ustawić pwmClock=1920i pwmRange=200uzyskać pwmFrequency=50Hz:

50 Hz = 19.2e6 Hz / 1920 / 200

Testuję to na alarmpi:

$ pacman -S wiringpi
$ gpio mode 1 pwm
$ gpio pwm-ms
$ gpio pwmc 1920
$ gpio pwmr 200     # 0.1 ms per unit
$ gpio pwm 1 15     # 1.5 ms (0º)
$ gpio pwm 1 20     # 2.0 ms (+90º)
$ gpio pwm 1 10     # 1.0 ms (-90º)

Uwaga: Moje serwo oczekuje sygnału 50 Hz .

kev
źródło
jak doszedłeś do: 'gpio pwmr 200 # 0,1 ms na jednostkę'
mxlian
50 Hz ---> 20 ms na cykl. 20ms / 200 jednostek = 0,1ms na jednostkę
MXLAN
5

To jest kod, którego używam. Próbuję zobaczyć, co się zmieni, gdy zmienię ustawienia.

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main (void)
{
  printf ("Raspberry Pi wiringPi test program\n") ;

  if (wiringPiSetupGpio() == -1)
    exit (1) ;

  pinMode(18,PWM_OUTPUT);
  pwmSetClock(2);
  pwmSetRange (10) ;
  pwmWrite (18, 5);

for (;;) delay (1000) ;
}

pwmSetClock (1); -> 2,342 kHz

pwmSetClock (2); -> 4,81 MHz

pwmSetClock (3); -> 3,19 MHz

pwmSetClock (4); -> 2,398 MHz

pwmSetClock (5); -> 1,919 MHz

pwmSetClock (6); -> 1,6 MHz

pwmSetClock (7); -> 1,3 MHz

pwmSetClock (8); -> 1,2 MHz

pwmSetClock (9); -> 1,067 MHz

pwmSetClock (10); -> 959 kHz

pwmSetClock (11); -> 871 kHz

pwmSetClock (20); -> 480 kHz

pwmSetClock (200); -> 48 kHz

pwmSetClock (500); -> 19kHz

pwmSetClock (1000); -> 9,59 kHz

pwmSetClock (2000); -> 4,802 kHz

pwmSetClock (4000); -> 2,401 kHz

pwmSetClock (5000); -> 10,58 kHz

Z tego, co przetestowałem, wydaje się, że dzielnik przechodzi z 2 do pewnej liczby mniejszej niż 5000. Sądzę, że ma to coś wspólnego z binarną reprezentacją liczb, które są bezpośrednio ustawione w rejestrze. Gdy binarna reprezentacja liczb ma więcej bitów, niż rejestr może przyjąć, bierze tylko pierwsze bity i interpretuje liczby w ten sposób. Właśnie dlatego dziwne zachowanie pojawia się przy przejściu z 4000 do 5000.

TheMeaningfulEngineer
źródło
1
Jak mam zmienić cykl pracy?
noufal
Jak zmierzyłeś częstotliwości?
Seanny123