• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
PWM - Sygnały przesunięte w fazie
#1
Witam,

Chciałbym poprosić o pomoc w napisaniu programu generującego sygnał PWM wysokiej częstotliwości (rzędu 20kHz) o tym samym wypełnieniu na dwóch pinach, jednak oba te sygnały mają być przesunięte względem siebie w fazie o 180 stopni. Udało mi się wygenerować jeden sygnał o zbliżonej częstotliwości przy użyciu funkcji analogWrite oraz modyfikacji danych w rejestrze TCCRnB, jednak nie wiem jak wygenerować analogiczny sygnał, który byłby przesunięty w fazie.

Z góry dziękuję za każdą podpowiedź i poradę.
 
Odpowiedź
#2
180 stopni czyli zanegowany. Użyj trybu komplementarnego. Na wyjściu OCxx masz sygnał prosty na /OCxx zanegowany.

PS
20kHz do wysoka częstotliwość?
 
Odpowiedź
#3
O czestotluwosci napisałem "wysoka" poniewaz jest ona sporo wyższa od domyślnej częstotliwości PWM w Uno którego używam, choć rzeczywiście nie jest to jakaś szczególnie duża wartość.

Jeśli chodzi o Twoją propozycję, nie za bardzo wiem jak miałbym to zapisać w IDE. Mógłbym prosić o dokładniejsze wyjaśnienie?
Inna kwestia która mnie zastanawia, czy zanegowanie o którym wspominasz nie zadziała tak, że gdy na jednym pinie będę miał wartość wypełnienia 10% to na drugim pojawi się 90%? W moim projekcie konieczne jest zachowanie tego samego stopnia wypełnienia na obu pinach
 
Odpowiedź
#4
(17-07-2018, 06:37)akudom napisał(a): czy zanegowanie o którym wspominasz nie zadziała tak, że gdy na jednym pinie będę miał wartość wypełnienia 10% to na drugim pojawi się 90%? W moim projekcie konieczne jest zachowanie tego samego stopnia wypełnienia na obu pinach

Dokładnie tak zadziała. Narysuj jak te przebiegi mają wyglądać, pewnie coś w rodzaju sygnału na wyjściu kodera sterującego serwomechanizmami. Jeśli tak, to musisz wyzwalać jeden timerem drugim. W ARm nie ma problemu, natomiast w AVR nie pamiętam czy jest możliwość wyzwalania jednego timera innym. Wydaje mi się, że tak, trzeba zerknąć do noty katalogowej.
 
Odpowiedź
#5
W załączniku pokazałem przykładowy przebieg dla PWM 10% (stopień wypełnienia będzie regulowany, ale to już odrębna kwestia)

Problem którego nie potrafię rozwiązać to przesunięcie tego drugiego sygnału w fazie, czyli w zasadzie przesunięcie rozpoczęcia sygnału o połowę okresu, nie mam pomysłu jak możnaby to zapisać


Załączone pliki Miniatury
   
 
Odpowiedź
#6
Łatwo nie będzie, nie widzę możliwości aby zrealizować to sprzętowo na AVR Mega, to nie ARM.
Jedyna opcja jak przychodzi mi do głowy, to użyć przerwania od porównania i w przerwaniu "wachować" GPIO.
Jednego PWM realizujesz standardowo np na OCRxA, drugi na przerwaniach od OCRxB (ustawianie GPIO) i OCRxC (zerowanie GPIO.
 
Odpowiedź
#7
Pokaż jaki masz kod i napisz czy procek ma robić coś jeszcze.
Jak masz DUE to tu jest przykład:
http://forum.arduino.cc/index.php?topic=...msg3096824.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#8
Jeśli chodzi o kod, na ten moment nie ma tam nic poza generowaniem jednego sygnału PWM z wykorzystaniem analogWrite i zmiany częstotliwości po modyfikacji danych z rejestru TCCRnB.
Co do samej płytki, posiadam klon Arduino Uno. Poza wygenerowaniem dwóch PWM chciałbym aby mikrokontroler zbierał sygnał prądowy i napięciowy a na ich podstawie regulował stopień wypełnienia PWM
 
Odpowiedź
#9
Jeśli chodzi o efekt jak tu: 

   
to faktycznie udałoby się może coś tylko około 4kHz w Arduino Uno. Pewnie millis bruździ, ale może Pan es2 wymyśli coś w assemblerze, C lub jadąc po rejestrach. 
Ewentualnie można dobrać odpowiednio długi przewód, policzyć jakie ma być opóźnienie, uwzględnić Einsteina, itp. wysłać sygnał jednym końcem i odczytywać drugim. 
Może jeszcze sprawdzę czy można zmniejszyć preskaler z 8, ale to i tak nie trafi w 20kHz, jak nawet zadziała to wyjdzie koło 30kHz.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#10
(19-07-2018, 03:30)kaczakat napisał(a): Może jeszcze sprawdzę czy można zmniejszyć preskaler z 8, ale to i tak nie trafi w 20kHz, jak nawet zadziała to wyjdzie koło 30kHz.

Można dość dokładnie uzyskać 20kHz. Wystarczy wybrać tryb timera, w którym przeładowanie następuje nie przy wartości TOP a jest określane przez rejestr, OCRxA.
Proste?

(19-07-2018, 03:30)kaczakat napisał(a): wymyśli coś w assemblerze, C lub jadąc po rejestrach.
ASM do tak banalnej sprawy?
Ponadto, łącząc program C z ASM trzeba wiedzieć jak poinformować kompilator o tym, jakie się rejestry użyło, do woli można bowiem używac tylko R0 i R1. Trzeba wiedzieć jak C przekazuje parametry do funkcji, jak je zwracać. Jak używać zmiennych z C w ASM. Jak nie musze to w takie rzeczy się nie bawiem, bo to strata czasu, aby zapisać dwa rejestry timera w ASM.
Do tego wystarczy C, bo co niby zyskam używając Asm? Szybkość kodu? Nie! Oszczędność pamięci? Nie! Komplikację programu, dłuższy czas jego pisania/uruchamiania? TAAAAAAK.

Biblioteki Arduino nie sa przygotowane do wszystkiego. Trzeba wziąć notę katalogową uC i zrobić co trzeba na rejestrach. Można też szukać (pewnie baaaaardo długo) kodu napisanego przez kogoś innego, który realizuje wymaganą funkcjonalność.

Zanim zabierze się za robotę nad samodzielnym napisaniem kodu trzeba pamiętać o:
- Czasie wejścia w przerwanie (czas reakcji sprzętu i czas odłożenia rejestrów na stosie). Robiąc wstawki ASM i korzystając z ISR_NAKED można zejść poniżej 1us, bez tego, może być różnie, nawet do 3us. Do tych 3us trzeba doliczyć czas realizacji algorytmu w przerwaniu, który ustawi GPIO. W 15us to raczej na pewno da się wyrobić a myślę, że będzie poniżej 5us. Trzeba się więc liczyć z jtter-em na takim poziomie o ile nie przeszkodzą inne przerwania! AVR nie ma priorytetowego systemu przerwań, więc ów jtter będzie większy. w AVR problemem są przerwania odbiorcze od USART, których nie można zadeklarować jako nie blokowalne (ISR_NOBLOKC czy INTERRUPT). W ich przypadku trzeba się namęczyć aby zezwolić na przerwanie w przerwaniu odpowiednio szybko. Mnie udało się zejść do 4 czy 5 rozkazów co przekłada sie na ok 7 cykli.
- Obciążenie CPU. Realizując licznik częstotliwości i czasu, max jaki uzyskałem (bez asm) to był pomiar czasu około 4,8ms czyli ok 20kHz. Fakt, że tam w przerwaniu było przeprowadzane dużo obliczeń. W przypadku PWM obliczeń nie będzie, więc tu raczej problemów nie widzę.

Podsumowując:
Da się zrobić.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości