Sterownik PWM PCA9685 |
Specyfikacja
- 16 niezależnych kanałów PWM
- 12 bitowa rozdzielczość generowania sygnałów PWM
- interfejs I2C
- domyślny adres 0x40 (konfigurowalny za pomocą zworek na wyprowadzonych punktach lutowniczych)
- zasilanie 3,3 - 5V
- 6 zworek do ustawiania adresu modułu na magistrali I2C
- regulacja częstotliwości PWM w przedziale 24Hz - 1526Hz (taka sama dla wszystkich kanałów). Domyślnie 200Hz.
- wbudowane rezystory 220Om chroniące wyjścia, dzięki czemu można bezpośrednio podłączać LED-y
- konfiguracja wszystkich wyjść jako push-pull lub open-drain. Domyślnie push-pull (dokładnie nazywa się to totem pole od charakterystycznego układu wyjścia układów TTL).
- dopuszczalny prąd na wyjściu każdego z kanałów (dla zasilania 5V) wynosi 25mA (przy prądzie wpływającym - current sink) lub 10mA (przy prądzie wypływającym - current source)
- łańcuchowy projekt płytki - komplementarna para pinów sterowania i zasilania umożliwia podłączenie kolejnego modułu
- dodatkowe zasilanie V+ napięciem max. 6V (o jego funkcji będzie poniżej) podłączane pod pin V+ lub pod złącze ARK (z dodanym zabezpieczeniem chroniącym przed odwrotną polaryzacją)
- miejsce na dodatkowy kondensator elektrolityczny, którego pojemność wylicza się wg. wzoru n * 100uF, gdzie n to ilość podpiętych serw (6)
Sterownik w akcji |
Uwagi
- Opcja zasilania dodatkowym napięciem V+ jest przydatna jeśli zasilamy moduł niskim napięciem, np 3,3V a chcielibyśmy móc sterować LED-ami wysokimi napięciami przewodzenia - kolor świecenia biały i niebieski. Wtedy LED wpina się między piny V+ i PWM, podłączając anodę do V+.
Podobnie ma się rzecz z zasilaniem serw - z V+ zasilane jest serwo, a do jego sterowania powinno wystarczyć 3,3V podawane na pinie PWM. - Stosowanie serw wymusza ustawienie częstotliwości 50Hz.
Stosowana biblioteka Adafruit-PWM-Servo-Driver-Library dostarcza m.in. poniższe funkcje:
Funkcja | Opis |
---|---|
Adafruit_PWMServoDriver(addr) | Konstruktor - ustawia adres modułu (domyślnie 0x40) |
begin() | Inicjalizacja komunikacji z modułem |
setPWMFreq(freq) | Ustawia częstotliwość pracy modułu freq. Wartość z przedziału 40 - 1000 |
setPWM(num, on, off) | Ustawia wartość PWM dla kanału o numerze num. On wyznacza początek pojawienia się impulsu (zmianę stanu z niskiego na wysoki), a off jego koniec (zmiana stanu z wysokiego na niski). On i off przyjmują wartości z przedziału 0 - 4095 |
setPin(num, val, invert); | Ustawia stan niski 0 lub wysoki 4095 dla kanału num. Opcjonalny parametr invert odwraca impuls (domyślna wartość to false) |
Piny
Pin(y) | Opis |
---|---|
VCC, GND | Zasilanie 3,3V lub 5V |
SDA, SCL | Piny dla podłączenia magistrali I2C (domyślnie dla aruduino uno łączą się odpowienio z pinami A4, A5) |
V+ | Dodatkowe napięcie zasilania, max +6V |
OE | Odłączenie wyjść po podaniu stanu wysokiego |
ARK (V+) | Dodatkowe napięcie zasilania, max +6V z zabezpieczeniem przed odwróconą polaryzacją |
Uruchomienie
Układ uruchomieniowy, będący przymiarką do realizacji "samochodu robota", zasilany jest w sumie trzema napięciami:
- 5V (1) - napięcie brane z arudino zasilające "logikę" modułów: PCA9685 i mostka H L298N
- 5V (2) - napięcie z zasilacza zasilające wyjście V+ PCA9685 (zasilania serw, ewentualnie diod LED). Zasilanie jest oddzielne z racji na możliwy znacznie większy pobierany prąd, niż ma to miejsce dla części "logicznej"
- 8,2V (3) - dwa akumulatory Li-ion 18650 zasilające silniki podłączone do mostka H. To samo co wyżej odnośnie prądu. Poza tym silniki mogą wymagać większego napięcia (użyte przeze mnie tego wymagały).
Schemat połączeń |
Diody LED wpięte są pod piny V+ (anoda) i PWM (katoda), co pozwala na użycie większego prądu, maksymalnie do 25mA. Zmierzona wartość prądu dla użytej diody LED świecącej na czerwono przy rezystorze 220Om i zasilaniu 5V wyniosła ok. 16mA. To oznacza, że dość łatwo może być przekroczona dopuszczalna wartość 10mA przy wpięciu LED między piny PWM i GND. Tym bardziej, że rezystory zabezpieczające wyjścia mają własnie po 220 Om.
Podpięcie serwa SG90 wymusza jeszcze jedną istotną rzecz w konfiguracji modułu PCA9685. Chodzi o częstotliwość pracy wszystkich kanałów PWM, która zgodnie z dokumentacją serwa wynosi 50Hz.
Zastosowanie modułu daje jeszcze jeszcze tę zaletę, że mamy wyższą rozdzielczość regulacji sygnału PWM (4096 stopni)
Test działania modułu |
Test działania modułu |
Oryginalnie w przykładzie do modułu dotyczącym serwa SERVOMIN i SERVOMAX przyjmują odpowiednio wartości: 150 i 600. Ja musiałem je zmniejszyć z racji na problem z serwem opisany na końcu postu. Dzięki temu dla wartości 170, 280, 400 mam odpowiednio kąty obrotu serwa: 0, 90, 180 stopni.
Może nie jest to najprostszy możliwy układ uruchomieniowy, ale jakby nie patrzeć, cztery LEDy, jedno serwo i mostek H "pochłaniają" aż 10 kanałów/pinów PWM opisywanego modułu. To obrazuje, w jakim stopniu opisywany moduł "odciąża" Arduino.
#include <Wire.h> #include <Adafruit_PWMServoDriver.h> //stałe dla pozycji serwa #define SERVOMIN 170 //minimalna długość pulsu (z 4096) #define SERVOMAX 400 //maksymalna długość pulsu (z 4096) #define SERVMIDDLE 280 //długość pulsu dla pozycji środkowej //piny LED-ów const int LED_FRONT_RIGHT = 0; const int LED_FRONT_LEFT = 1; const int LED_BACK_RIGHT = 2; const int LED_BACK_LEFT = 3; //piny mostka const int ENA = 4; const int ENB = 5; const int IN1 = 6; const int IN2 = 7; const int IN3 = 8; const int IN4 = 9; //piny serwo const int SERVO = 10; //utworzenie obiektu sterownika //funkcja przyjmuje jako wartość adres modułu (domyślnie 0x40) Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); //stany niski i wysoki na potrzeby sterowania mostkiem const int SD_LOW = LOW; const int SD_HIGH = 4095; //przechowuje pozycję serwa (kąt obrotu) int pos = 0; //odpowiada za jednorazowe wykonanie kodu w loop() boolean run; void setup() { pwm.begin(); pwm.setPWMFreq(50); //białe LED-y pwm.setPWM(LED_FRONT_RIGHT, 0, 0); pwm.setPWM(LED_FRONT_LEFT, 0, 0); //czerwone LED-y - normalne światło (tj. nie stop) pwm.setPWM(LED_BACK_RIGHT, 0, 3500); pwm.setPWM(LED_BACK_LEFT, 0, 3500); //mostek H pwm.setPin(ENA, 0); pwm.setPin(ENB, 0); run = true; } void loop() { if (run) { //czerwone LED-y - światło stop (większa jasność) pwm.setPWM(LED_BACK_RIGHT, 0, 0); pwm.setPWM(LED_BACK_LEFT, 0, 0); delay(2000); //czerwone LED-y (nie stop) pwm.setPWM(LED_BACK_RIGHT, 0, 3500); pwm.setPWM(LED_BACK_LEFT, 0, 3500); //serwo - obrót od 0 do 180 stopni i z powrotem for (pos = SERVOMIN; pos <= SERVOMAX; pos += 1) { pwm.setPWM(SERVO, 0, pos); delay(15); } for (pos = SERVOMAX; pos >= SERVOMIN; pos -= 1) { pwm.setPWM(SERVO, 0, pos); delay(15); } //operacje na silnikach (przód, tył, obrót w lewo i prawo) motorForward(4095); delay(2000); motorFastBrake(); delay(2000); motorBackward(4095); delay(2000); motorFastBrake(); delay(2000); motorLeft(2000); delay(2000); motorRight(2000); delay(2000); motorFastBrake(); run = false; } } //ruch silników do przodu void motorForward(int speed) { pwm.setPWM(ENA, 0, speed); pwm.setPWM(ENB, 0, speed); pwm.setPin(IN1, SD_LOW); pwm.setPin(IN2, SD_HIGH); pwm.setPin(IN3, SD_LOW); pwm.setPin(IN4, SD_HIGH); } //ruch silników do tyłu void motorBackward(int speed) { pwm.setPWM(ENA, 0, speed); pwm.setPWM(ENB, 0, speed); pwm.setPin(IN1, SD_HIGH); pwm.setPin(IN2, SD_LOW); pwm.setPin(IN3, SD_HIGH); pwm.setPin(IN4, SD_LOW); } //skręt w lewo void motorLeft(int speed) { pwm.setPWM(ENA, 0, speed); pwm.setPWM(ENB, 0, speed); pwm.setPin(IN1, SD_LOW); pwm.setPin(IN2, SD_HIGH); pwm.setPin(IN3, SD_HIGH); pwm.setPin(IN4, SD_LOW); } //skręt w prawo void motorRight(int speed) { pwm.setPWM(ENA, 0, speed); pwm.setPWM(ENB, 0, speed); pwm.setPin(IN1, SD_HIGH); pwm.setPin(IN2, SD_LOW); pwm.setPin(IN3, SD_LOW); pwm.setPin(IN4, SD_HIGH); } //zatrzymanie silników void motorFastBrake() { pwm.setPWM(ENA, 0, SD_HIGH); pwm.setPWM(ENB, 0, SD_HIGH); pwm.setPin(IN1, SD_HIGH); pwm.setPin(IN2, SD_HIGH); pwm.setPin(IN3, SD_HIGH); pwm.setPin(IN4, SD_HIGH); delay(500); }
Źródła
1) Schemat elektryczny modułu
2) Opis i specyfikacja na stronie Adafruit
3) Dokumentacja układu PCA9685
4) Biblioteka sterująca modułem (Adafruit-PWM-Servo-Driver-Library)
5) Dokumentacja do biblioteki Adafruit-PWM-Servo-Driver-Library
6) Podpinanie serwa
Dziękuję !
OdpowiedzUsuń