Ovládáme servo modulem ESP32
- UPOZORNĚNÍ
- Následující článek byl již upraven pro jádro Arduino ESP32 verze 3.x.
Dnes se podíváme na další základní úkol domácí automatizace – tedy na ovládání servomotoru (opět pomocí vývojové desky s modulem ESP32). Nejdříve se podíváme na základy ovládání servomotoru, protože abychom porozuměli propojovacímu obvodu a řídicímu programu, musíme nejprve porozumět jeho základnímu fungování.
Servomotor (zkráceně servo) je motor pro pohony, u kterých lze na rozdíl od běžného motoru nastavit přesnou polohu natočení osy. Ovládají se jím například posuvy CNC strojů, nastavení čtecí hlavičky u pevného disku, RC modely používají modelářská serva pro své ovládání… apod.
Servomotor je řízen sérií pulzů na ovládacím pinu. Téměř všechna serva používaná pro hobby projekty pracují na základní frekvenci 50 Hz (doba mezi dvěma pulzy 20 ms). Poloha hřídele je určena šířkou řídicího signálu, tzv. PWM signálu (Pulse Width Modulation – Pulzně šířková modulace), jehož šířka se pohybuje v rozmezí 1 ms pro krajní levou polohu do 2 ms pro krajní pravou polohu (1,5 ms odpovídá střední poloze). Servo se obvykle může otáčet od 0 do 180 stupňů, níže uvedený obrázek č. 1 ilustruje vztah mezi PWM signálem a polohou hřídele:
Připojení serva k modulu ESP32
O generování řídicího signálu se při použití modulu ESP32 vlastně nebudeme muset příliš starat, protože pro řízení serva použijeme knihovnu Servo
(speciálně pro ESP32!!!), takže se nyní nejdříve zaměříme na elektrické připojení serva k modulu ESP32.
Připojovací kabel servomotoru je tvořen třemi vodiči: (viz obrázek č. 2)
- Napájecí vodič Ucc (obvykle červená barva),
- Zemnící vodič GND (obvykle černý nebo hnědý),
- Řídicí PWM signál (obvykle má oranžovou, žlutou nebo bílou barvu).
A zase ta elektřina…
Před samotným připojením k modulu ESP32 se musíme ujistit, jak velký elektrický proud je nutný pro provoz zvoleného servomotoru. (Na trhu jsou k dispozici různé servomotory.) Pokud používáme servomotor s malým výkonem, jako jsou modelářská serva typu S0009, SG90, SG92R…, můžeme jej přímo připojit k desce ESP32. Pokud však chceme s modulem ESP32 používat výkonnější servomotor, musíte použít proudově posilující ovladač motoru, jako je např. UNL2003. Obdobně pokud bychom chtěli s ESP32 používat více serv, musíme též použít servo „driver“ (např. PCA9685 – viz dále) nebo nějak jinak vyřešit externí napájení.
Na většině internetových stránek, které se zabývají připojením serva k modulu ESP32 najdeme následující nebo obdobné zapojení (lišící se v použitém řídicím GPIO pinu) – viz následující obrázek č. 3
Ve schématu je použita vývojová deska ESP32 DOIT DEVKIT ve své 30pinové verzi, ale je možné použít i 36pinovou verzi nebo jinou desku ESP32. Servo je napájeno napětím 5 V, je tedy připojeno na desce ESP32 k pinu Vin a GND. Řídicí pin je připojen k libovolnému výstupnímu GPIO pinu, který podporuje PWN výstup – zde kupříkladu pin GPIO 13.
A máme zde opět problém spojení dvou zařízení, kdy jedno pracuje na 5 V (servo) a druhé na 3,3 V (ESP32). Již jsme v předešlých článcích viděli, někdy to může být problém, jindy ne. Také jsme již viděli, že na internetu můžeme najít několik zapojení, která jsou chybná a svým provozem ohrožují modul ESP32.
Bude tomu i v případě řízení servomotoru?
Opět se musíme obrátit k elektronickému schématu. V tomto případě jsme se zaměřili na servo SG90. V případě jiného typu je nutné si sehnat schéma řídicí elektroniky daného typu serva. Následující obrázek č. 4 ukazuje schéma řídicí elektroniky serva SG90, která je postavena na obvodu AA51880. Jedná se téměř o katalogové zapojení (červeně jsou vyznačeny změny oproti katalogovému zapojení).
Z tohoto zapojení však není jasné, zda se na řídicím pinu (14) neobjevuje napájecí napětí 5 V. Tuto otázku nám bohužel nezodpoví ani další informace plynoucí z katalogového listu tohoto obvodu. Nezbývá nám tedy nic jiného, než připojit na tento pin voltmetr a změřit, jaké je na něm napětí proti zemi. Při našem měření se ukázalo, že tento pin je asi skutečně čistě vstupní (žádný pull-up rezistor proti napájecímu napětí a podobně), protože je normálně na tomto pinu napětí 0 V – viz obrázek č. 5 ukazující měření.
Na základě tohoto zjištění lze tedy říci, že „třívoltový“ modul ESP32 je možné schématu z internetu věřit a tedy lze bezproblémově připojit k pětivoltovému servu SG90.
Pokud Vám připadá náš přístup poněkud opatrný (až paranoidní), přečtěte si příspěvky o připojení I²C LCD displeje, sonarového čidla nebo čidla BMP180. 😉
TAK: Víme-li, jak lze servo připojit ke zvolené vývojové desce s modulem ESP32, můžeme se vrhnout na programování.
Program pro ovládání serva modulem ESP32 (v prostředí Arduino IDE)
Jak jsme uvedli v úvodu, pro řízení serva použijeme ovládací knihovnu. Pro milovníky něčeho, co bychom mohli v nadsázce nazvat „RAW programování“, zde ale máme i ukázku řídicího kódu bez použití této knihovny. Proč si nezkusit ověřit, zda to povídání o PWM signálu (ne)byla skutečně pravda! 😎 Využijeme vhodné nastavení PWM kanálu, který se spíše používá pro PWM regulaci svitu LED. Ale to nám přece nemusí vadit! Nastavíme frekvenci PWM kanálu na 50 Hz a začneme měnit šířku pulzů v rozmezí 1–2 ms. Výhoda modulu ESP32 (např. oproti modulu Arduino) je to, že lze měnit frekvenci generovaného PWM výstupu. Následující kód znázorňuje řízení serva bez obslužné knihovny (princip je vysvětlen v kometářích kódu).
/* SERVO kyva sem-tam */
const int servoPin = 13; // servo pripojeno na GPIO13
int dutyCycle = 0;
/* Nastaveni PWM vlastnosti */
const int PWMFreq = 50; // frekvence PWM signalu
const int PWMResolution = 8; // rozliseni vstupni hodnoty (0-256);
// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
ledcAttach(servoPin, PWMFreq, PWMResolution); // nastaveni PWM vystupu
}
// funkce LOOP bezi stale dokola.
void loop() {
for(dutyCycle = 5; dutyCycle <= 32; dutyCycle++) { // nataceni vpravo
ledcWrite(servoPin, dutyCycle); // nastaveni vystupni hodnoty na vystup
delay(100);
}
for(dutyCycle = 32; dutyCycle >= 5; dutyCycle--) { // nataceni vlevo
ledcWrite(servoPin, dutyCycle); // nastaveni vystupni hodnoty na vystup
delay(100);
}
}
Všimněme si, že natočení serva zcela vlevo odpovídá hodnotě 5 v proměnné dutyCycle
, naopak maximální výchylka vpravo odpovídá hodnotě 32. Pokud bychom chtěli zadávat natočení serva ve stupních (například pomocí proměnné vstupni_uhel
), musí se „přemapovat“ interval vstupních hodnot 0–180 (stupňů) na interval hodnot 5–32. To bychom provedli následujícím příkazem:
Takže ono to občas asi jde i bez knihoven, ale my se dále odebereme do pohodlí, které nám ovládací knihovna poskytne.
Knihovna Servo
pro ESP32
- Poznámka:
- Knihovna
Servo
určená pro modul Arduino NELZE POUŽÍT pro modul ESP32! Je třeba nainstalovat knihovnu primárně určenou pro modul ESP32.
Pro řízení serva modulem ESP32 lze použít hned několik knihoven. Důležitým aspektem použití dané knihovny je aktuální kompatibilita s&jádrem Arduino ESP32. Od verze 3 došlo ke změně ovládání PWM výstupů, což se pro ovládání serva v knihovnách používá. Je tedy třeba použím knihovnu, která má aktuální poslední verzi tak z poloviny roku 2024. Použití starší verze knihovny by při použití jádra Arduino ESP32 ver. 3 mohlo při kompilaci kódu končit chybou.
V tuto chvíli lze doporučit knihovnu pro servo a modul ESP32 jménem ESP32Servo
, od autorů Kevina Harringtona a Johna Bennetta. Knihovnu lze najít přímo v manažeru knihoven prostředí Arduino IDE.
Následující příklad je obdobou předešlého kódu, který byl ale vytvořen bez obslužné knihovny.
Programový kód: (otáčení serva „sem a tam“)
/* SERVO kyva sem-tam (knihovna Servo) */
#include <ESP32Servo.h> // POZOR nejedna se o knihovnu Servo.h pro Arduino!!!
static const int servoPin = 13; // servo pripojeno na GPIO13
Servo servo1; // vytvoreni objektu pro servo
// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
servo1.attach(servoPin); // propojeni GPIO pinu s objektem servo
}
// funkce LOOP bezi stale dokola.
void loop() {
for(int posDegrees = 0; posDegrees <= 180; posDegrees++) { // nataceni od 0 do 180 stupnu
servo1.write(posDegrees); // nastaveni vystupu serva
delay(100);
}
for(int posDegrees = 180; posDegrees >= 0; posDegrees--) { // nataceni od 180 do 0 stupnu
servo1.write(posDegrees); // nastaveni PWM signalu na servo
delay(100);
}
}
Natáční dle polohy potenciometru
Další kód pak ukazuje natáčení serva dle natočení potenciometru. Toto zapojení zde uvádíme nejen kvůli kódu, ale především kvůli schématu zapojení (viz obr. 6).
Všimněme si, že servo je zapojeno na napájecí napětí 5 V, ale potenciometr je zapojen mezi napěťové piny 3V3 a GND. Hodnota napětí na jezdci potenciometru se tedy bude měnit v rozmezí 0–3,3 V. To je důležité! (Vzpomeňme si na povolené maximální napětí na pinech modulu ESP32!)
Na internetu lze najít i zapojení, kde je potenciometr zapojen mezi vodiče napájecího napětí serva, tedy mezi GND a 5 V. Pětivoltové napětí však při natočení potenciometru do maximální polohy zničí analogový vstup modulu ESP32. V případě třívoltového serva společné spojení potenciometru s napájením serva pochopitelně nevadí. Ale pokud budeme používat pětivoltové servo, musíme napájení serva (5 V) a maximální napětí na potenciometru (3,3 V) jasně oddělit!
Tato chyba patrně vznikla převzetím schématu pro případ serva napájeného napětím 3,3 V a jeho nepromyšleným použitím na případ serva pětivoltového.
Pokud máme potenciometr a servo správně připojené, můžeme použít následující kód:
Programový kód: (natáčení serva dle polohy potenciometru)
/* SERVO kyva podle potenciometru */
#include <ESP32Servo.h> // POZOR nejedna se o knihovnu Servo.h pro Arduino!!!
static const int servoPin = 13; // servo pripojeno na GPIO13
static const int potentiometerPin = 32; // potenciometr na GPIO32
Servo servo1; // vytvoreni objektu pro servo
// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
servo1.attach(servoPin); // propojeni GPIO pinu s objektem servo
}
// funkce LOOP bezi stale dokola.
void loop() {
int servoPosition = map(analogRead(potentiometerPin), 0, 4096, 0, 180); // nacteni a namapovani analogového vstupu (0-4096) na hodnoty 0-180
servo1.write(servoPosition); // nastaveni PWM signalu na servo
delay(100);
}
16kanálový PWM modul PCA9685
PCA96845 je 16kanálový modul PWM řadiče, který lze použít se servomotory, LED diodami a vším, co můžete ovládat pomocí PWM pulzů. Modul je I²C zařízením (o sběrnici I²C jsme si povídali v člálnku Rozhraní I²C a displej LCD s ESP32), takže veškerá práce s nastavením a generováním PWM signálů se provádí v modulu PCA96845, tím se řídicí zařízení (v našem případě modul ESP32) „osvobodí“ od nutnosti se provozem PWM signálu zabývat.
Modul PCA96845 má šest volitelných adresových bitů, takže je lze vytvořit až 26 = 64 různých adres. Díky tomu, že každý modul ovládá až 16 PWM „spotřebičů“ můžeme na jediné sběrnici I²C ovládat až 64·16 = 1024 servomotorů! A to nám asi stačí, ne? 😉
Modul PCA96845 ukazuje obrázek č. 7. Vidíme, že na modulu PCA9685 jsou duplicitní ovládací piny (na obou koncích), což usnadňuje připojení řídicího modulu nebo řetězení více modulů různé adresy (např. pomocí pravoúhlých konektorů Dupont samec a samice).
Zapojení PCA9685 k ESP32
PCA9685 je I²C zařízení a může pracovat s 3,3 V nebo 5 V logikou a napájením. Při připojení k modulu ESP32 budeme používat 3,3voltovou logiku a modul budeme napájet přímo z ESP32.
Připojení I²C k ESP32 je následující: (viz obrázek 8)
- SDA – GPIO 21
- SCL – GPIO 22
Ve skutečnosti můžete použít libovolné dva piny na ESP32 pro vaše připojení I²C a definovat je v programu, ale piny GPIO 21 a 22 jsou výchozí, tak je využijeme.
V některých zapojeních, která můžeme najít na internetu, jsou vodiče SDA a SCL ještě připojeny pomocí externích pull-up rezistorů k napájení 3,3 V. Myslíme si, že je to zbytečné, protože, jak ukazuje schéma z dokumentace modulu PCA9685, tento I²C modulu již pull-up rezistory obsahuje (červeně vyznačeno v obrázku č. 9)
Připojit servomotor nebo více servomotorů lze ke kterémukoliv z výstupních kanálů. Když se podíváme na programový kód (viz dále), uvidíte tam, jak připojení (servo)motoru definovat a jak (servo)motor adresovat.
Pro napájení PWM spotřebiče (v našem případě serva) je třeba využít napájecí svorkovnice v horní části modulu PCA9685. Třívoltové napětí z modulu ESP (připojeno na postranní konektor) a napájecí napětí serva jsou odděleny (kromě společné země), takže lze použít téměř jakýkoliv PWM spotřebič a nehrozí poškození modulu ESP32. Koneckonců k tomuto účelu byl asi modul PCA9685 vymyšlen! 😉
My si ukážeme připojení jednoho serva typu SG90, ale už víme, že jeden modul PCA9685 nám umožní připojit takových serv šestnáct.
Kód ovládání modulu PCA9685 pomocí ESP32
Modul PCA9685 pochází od společnosti Adafruit. Kdo zná společnost Adafruit a její výrobky, jistě ví, že nejenže neprodávají nic bez rozsáhlé dokumentace, ale především i bez podpůrných knihoven. Takže je jasné, že pro ovládání modulu PCA9685 využijeme knihovnu Adafruit PWM Servo Driver
od Adafruit, která funguje jak s modulem Arduinem, tak s modulem ESP32.
Knihovnu Adafruit pro PCA9685 Adafruit PWM Servo Driver
můžeme získat přímo v manažéru knihoven v prostředí Arduino IDE, stejně jako knihovnu Wire
, což je knihovna pro práci s I²C. Jak bylo zmíněno dříve, způsob, jak stáhnout v prostředí Arduino IDE knihovnu pomocí manažéru knihoven je popsán v předešlých článcích, proto to ani zde to již neuvádíme.
Následující program je ukázkou řízení serva připojeného na kanálu 0 modulu PCA9685. (Schéma je obrázku č. 9)
/* ESP32 a PCA9685 (Servo Control) */
#include <Wire.h> // vlozeni knihovny pro I2C komunikaci
#include <Adafruit_PWMServoDriver.h> // vlozeni knihovny modul PCA9685
Adafruit_PWMServoDriver pca9685 = Adafruit_PWMServoDriver(0x40); // objekt pro PCA9685 (vychozi adresa)
// Definice maximalni a minimalni sirky PWM pro servomotory (celkovy rozsah 0-4095)
// hodnota 80 je pro 1ms, 600 je pro sirku pulzu 2ms
#define SERVOMIN 80 // Minimalni hodnota
#define SERVOMAX 600 // Maximalni hodnota
// Definice pripojeni servomotoru (pro vice serv lze rozsirit)
#define SER0 0 // Servo0 pripojene na vystupnim kanalu 0
int pwm0; // Promenna pro polohu Serva 0
// funkce SETUP se spusti jednou pri stisknuti tlacitka reset nebo pri zapnuti desky.
void setup() {
pca9685.begin(); // Inicializace PCA9685
pca9685.setPWMFreq(50); // Nastaveni frekvence PWM na 50 Hz
}
// funkce LOOP bezi stale dokola.
void loop() {
for (int posDegrees = 0; posDegrees <= 180; posDegrees++) { // Natoceni Serva0 z 0 na 180 stupnu
pwm0 = map(posDegrees, 0, 180, SERVOMIN, SERVOMAX); // Prevod stupnu na sirku pulzu PWM
pca9685.setPWM(SER0, 0, pwm0); // zapis na modul PCA9685
delay(100);
}
for (int posDegrees = 180; posDegrees >= 0; posDegrees--) { // Natoceni Serva0 z 180 na 0 stupnu
pwm0 = map(posDegrees, 0, 180, SERVOMIN, SERVOMAX); // Prevod stupnu na sirku pulzu PWM
pca9685.setPWM(SER0, 0, pwm0); // zapis na modul PCA9685
delay(100);
}
}
V kódu si všimněme nastavení konstant SERVOMIN
a SERVOMAX
, které určují maximální a minimální šířku generovaného PWM pulzu.
Tyto hodnoty vycházení z následující úvahy:
- Na modulu PCA9685 je určena základní frekvenci pulzů (v našem případě stanoveno na 50 Hz). Každý úsek mezi začátky následujících pulzů je rozdělen na 4096 úseků. Příkazem
pca9685.
nastavíme počet těchto časových úseků, určující délku PWM pulzu (tj. po které bude výstup ve stavu HIGH).setPWM() - Například, aby měl generovaný PWM pulz 50% délku pracovního cyklu, nastavíme hodnotu 2048 (2048 úseků bude na úrovni HIGH a zbylých 2048 úseků bude na úrovni LOW).
- Pro 25% délku pracovního cyklu zapíšeme jen hodnotu 1024.
- Konstanty
SERVOMIN
aSERVOMAX
tedy představují počet úseků pro minimální a maximální šířku pulzu. Na tyto hodnoty se pak „přemapovává“ hodnota krajních poloh zadaných ve stupních – tedy 0 až 180 stupňů.
Závěr
Opět jsme si ukázali další periférii, kterou můžeme připojit k některé z vývojových desek s modulem ESP32. Vysvětlili jsme si princip řízení servomotoru, ukázali jsme si jeho možné připojení k desce ESP32. Ovládání jsme si ukázali pomocí PWM kanálu, nebo pomocí obslužné knihovny.
V druhé části článku jsme si představili zajímavý modul PCA9685, který je určen pro PWM řízení. My jste to zde využili pro řízení serva. V některém z následujících článků bychom se k tomuto modulu ještě rádi vrátili a ukázali si jeho použití pro řízení DC motorů, což se dá například použít pro řízení ovládání robotického podvozku.
Do budoucna bychom chtěli Vám začít přinášet i některé ukázky konkrétních projektů, takže se jistě s připojením serva k modulu ESP32 nevidíme naposledy.