![]() |
| 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ń