ESP32: ovládání modulu JQ6500 přes UART
V předchozích článcích jsme se seznámili s několika běžně používanými komunikačními rozhraními pro mikrokontroléry. Ať už to bylo SPI, které je velmi rychlé a vhodné pro komunikaci s pamětmi, displeji nebo jinými zařízeními s vysokými nároky na přenos dat, nebo sběrnice I²C, jež díky své jednoduchosti a možnosti připojit více zařízení na dvojici komunikačních vodičů nachází uplatnění u řady senzorů, RTC čipů nebo expandérů.
Přesto jsme dosud poněkud opomíjeli jedno z nejstarších a nejzákladnějších sériových rozhraní – UART.
Je tedy na čase to napravit!
Dnes si UART nejen představíme, ale rovnou si ukážeme jeho praktické použití na konkrétním příkladu – ovládání modulu JQ6500, což je malý, levný, ale překvapivě schopný přehrávač zvukových souborů, který se ovládá právě přes UART.
UART
UART (Universal Asynchronous Receiver/Transmitter) nebo také SCI (Serial Communication Interface) je jedno z nejjednodušších rozhraní pro přenos dat mezi dvěma zařízeními. Najdeme ho prakticky ve všech mikrokontrolérech, nejen u ESP32, ale i u Arduina, STM32, Raspberry Pi a dalších. UART používají i různé moduly, například GPS přijímače, moduly pro komunikaci přes GSM, některé RFID čtečky nebo právě zvukové přehrávače, jako je JQ6500.
Vlastnosti UART:
- Asynchronní:Vzhledem k tomu, že není potřeba sdílený hodinový signál, přenos je řízen pouze startovacím a stopovacím bitem. Tento způsob je ideální pro jednoduché a flexibilní přenosy.
- Full duplex: UART je schopný současně vysílat a přijímat data (to znamená, že dvě zařízení mohou komunikovat obousměrně bez vzájemného čekání).
- Sériový přenos: Data jsou přenášena bit po bitu na jednom vodiči, což znamená, že místo paralelního přenosu (kde je potřeba více vodičů) stačí pouze dvě linky:
TX
(vysílání) aRX
(přijímání).
Sběrnice UART je ideální pro jednoduchou a rychlou obousměrnou komunikaci mezi dvěma zařízeními. I když má oproti novějším rozhraním některá omezení (např. jen dvě zařízení na jedné lince), právě jeho jednoduchost z něj dělá stále velmi praktický nástroj pro řadu aplikací.
Pokud budeme chtít ve svém programu použít komunikaci přes UART, je třeba při konfiguraci této sběrnice nastavit několik základních parametrů:
- Baudrate (rychlost přenosu): Udává, jak rychle budou data odesílána, obvykle v bps (bits per second). Například 9600 bps znamená 9600 bitů za sekundu.
- Data bits: Obvykle 8 bitů, což znamená, že každý přenášený bajt obsahuje 8 bitů informací. (Toto nastavení vypadá trochu nelogicky, ale vězte, že existují zařízení, u kterých se informace přenáší kupříkladu jen pomocí 7 bitů.)
- Stop bits: Obvykle 1 stop bit (někdy mohou být 2), který indikuje konec datového rámce.
- Parity bit: Tento bit slouží k detekci chyb. Někdy se nepoužívá (je volitelný), což znamená, že přenos není kontrolován. V takovém případě je parametr Parity bit nastaven na
None
.
Přenos dat přes UART
Při přenosu jednoho bajtu dat přes UART je celý rámec tvořen těmito základními částmi:
Start bit |
Data bits |
Parity bit (volitelný) |
Stop bit |
Příklad přenosu:
Pokud bychom chtěli přenést hodnotu 0xA0
(v binární podobě 10100000
) bez nastaveného kontrolního paritního bitu, přenos by vypadal takto:
0 (Start) |
10100000 (Data) |
1 (Stop) |
- Start bit: Označuje začátek přenosu (vždy 0).
- Data bits: 8 bitů dat, které přenášíme.
- Stop bit: Ukončuje přenos (vždy 1).
Bližší práci se sběrnicí UART na modulu ESP32 si ukážeme dále při odesílání konkrétních příkazů pro zvukový modulu JQ6500.
Modul JQ6500
JQ6500 je populární čip, který slouží jako jednoduchý MP3/WAV přehrávač pro různé projekty. Je vybaven interní pamětí (flash nebo SD), do které můžeme nahrát vlastní zvukové soubory, a následně je přehrávat. Kromě jiného lze modul ovládat pomocí jednoduchých sériových příkazů.


Proč si vybrat JQ6500?
- Nízká cena: Tento modul je cenově velmi dostupný (obvykle stojí méně než 100 Kč), což z něj činí ideální volbu pro DIY projekty.
- Jednoduché ovládání: JQ6500 nevyžaduje složité programování. Přenos zvukových souborů a jejich následné ovládání je snadné.
- Různorodé aplikace: Díky své jednoduchosti a malým rozměrům je tento modul je ideální pro zvukové efekty, mluvící zařízení nebo automatizované hlášení.
Jak vidíme, JQ6500 je ideální volbou pro naši dnešní praktickou demonstraci – přehrávač zvukových souborů ve formátu MP3/WAV, který budeme ovládat přes sériovou linku. A za tu cenu!? Ale není to jen o nízké ceně, ale hlavně o zábavě (a poučení) při práci s tímto modulem. 😊 Kdo z nás by si nechtěl postavit zařízení, které vydává zvuky lepší než pouhá sterilní pípání? Můžeme postavit mluvící budík, zařízení se zvukovým upozorněním na stav jiného zařízení, nebo dokonce přidat unikátní zvukové efekty do interaktivní hračky… Možnosti jsou omezené pouze fantazií bastlíře (a někdy také i velikostí paměti modulu JQ6500!).
Hlavní vlastnosti modulu JQ6500
- Ukládání zvukových souborů: Námi používaný typ modulu má vestavěnou flash paměť, obvykle o kapacitě 4 MB nebo 8 MB. Do této paměti si můžete uložit vlastní zvukové soubory ve formátu MP3 nebo WAV.
- Ovládání přes UART: Pro přehrávání souborů a ovládání modulu budeme používat sériovou linku UART. To znamená, že jakýkoli mikrořadič nebo počítač, který má UART, může tento modul ovládat (například ESP32, Arduino apod.).
- Jednoduché ovládání: Příkazy k přehrávání, pauzování, přechodu na další skladbu nebo změně hlasitosti jsou opravdu jednoduché (viz tabulka dále). Modul přijímá příkazy ve formátu sériového přenosu (UART) a podle nich přehrává zvukové soubory, které byly dříve nahrány do paměti.
Verze modulů JQ6500:
Modul JQ6500 se vyrábí, jak již bylo naznačeno, v několika variantách. Některé moduly mají USB konektor, díky kterému můžete snadno nahrát zvukové soubory přímo z počítače. Jiné verze, které nemají USB port, obsahují pouze piny pro připojení k mikrokontroléru a vyžadují přenos souborů prostřednictvím jiných metod, například pomocí SD karty nebo jiných externích zařízení. V hobby elektronice je oblíbenou variantou modulu JQ6500 zejména verze s vestavěnou flash pamětí.
Pojďme se podívat na jeho pinout této verze a postupně si probereme, jak tento modul můžeme ovládat.

Modul JQ6500 pro hlasový výstup má 16 pinů, jejichž funkce jsou vysvětleny v následující tabulce.
Pin | Popis pinu | Pin | Popis pinu |
---|---|---|---|
RX | Sériový vstup dat UART | BUSY | Indikátor přehrávání |
TX | Sériový výstup dat UART | ADKEY | AD port (řízení pomocí vstupního napětí) |
GND | Zem | SGND | Zem (signálová) |
VCC | Napájení 3,5V–5V (optimum 4,2 V) |
K5 | Přehrávání zvuku 5 |
ADC_R | Sluchátka/zesilovač (pravý kanál) |
K4 | Přehrávání zvuku 4 |
ADC_L | Sluchátka/zesilovač (levý kanál) |
K3 | Přehrávání zvuku 3 |
SPK– | Reproduktor – (8 Ω) |
K2 | Přehrávání zvuku 2 |
SPK+ | Reproduktor + (8 Ω) |
K1 | Přehrávání zvuku 1 |
Ovládání tlačítky
Modul JQ6500 podporuje ovládání pomocí fyzických tlačítek, což je užitečné pro projekty, kde chcete přehrávač ovládat manuálně bez nutnosti použití mikrokontroléru. Modul nabízí piny, které umožňují připojení tlačítek (proti zemi) pro spouštění jednotlivých skladeb (piny K1–K5). Dále je k dispozici tlačítko ADKEY
, které umožňuje funkce jako play/pause, přechod na další/předchozí stopu, zvýšení/snížení hlasitosti a další.
Pokud využijete pin ADKEY
, je nutné připojit ovládací tlačítka přes odporové děliče, která pak nastavijí různé napětí na pinu ADKEY
. Různá napětí na tomto pinu jsou pak pro modul reprezentována jako různé příkazy. I když je toto řešení zajímavé, je třeba ale říci, že je náchylné na elektromagnetické rušení, což může ovlivnit spolehlivost tohoto ovládání.
Bylo by možné vytvořit zapojení, ve kterém by mikrokontrolér simuloval tlačítka K1–K5 nebo měnil napěťovou úroveň na analogovém vstupu ADKEY
. Avšak pro náš dnešní projekt zvolíme jiný a sofistikovanější způsob ovládání.
Ovládání UART
Piny RX
a TX
slouží ke komunikaci modulu JQ6500 s připojeným mikrokontrolérem. Modul JQ6500 má jasně definovaný formát zasílaných příkazů. Některé příkazy řídí stav modulu (přehrávání, pauza…) a jeho parametry (např. nastavení hlasitosti, typ ekvalizéru…), jiné příkazy požadují od modulu JQ6500 odpovědi (např. délka přehrávaného souboru). Jednotlivé příkazy si za chvíli vysvětlíme při přípravě programu pro komunikaci mezi modulem ESP32 a JQ6500.
Zajímavostí UART komunikace modulu JQ6500 je jeho napěťová úroveň. I když je modul napájen napětím až 5 V, napěťová úroveň jeho komunikačních linek (RX, TX) je 3,3 V. To je ideální pro připojení k modulu ESP32, který používá právě tuto napěťovou úroveň. V případě použití mikrokontroléru s 5 V logikou (např. Arduino) je třeba si na to dát pozor a nezapomenout na řešení této rozdílné napěťové úrovně.
Integrovaný zesilovač a výstupy
Jednou z velkých výhod modulu JQ6500 je, že na něj můžete rovnou připojit reproduktor, protože modul má integrovaný zesilovač pro přímý výstup. Tento výstup je sice pouze mono a výkonově se pohybuje mezi 1–3 W (v závislosti na typu modulu), ale pokud potřebujete jednoduchý projekt s jedním reproduktorem, není nutné přidávat žádný externí zesilovač. Stačí připojit reproduktor k výstupu a modul je připraven přehrávat zvukové soubory.
Jestliže je požadován kvalitnější zvuk nebo stereo efekt, je to také možné. Modul JQ6500 nabízí stereo výstup, ale pro tento výstup je již nutné připojit externí zesilovač.
Napájení a napěťové úrovně
Jak jsme již zmínili, napájení modulu JQ6500 je na úrovni 5 V (doporučené napětí je 4,2 V), což je běžné pro tento typ zařízení. Nicméně, logika sběrnice UART je v tomto případě na úrovni 3,3 V, což je plně kompatibilní s modulem ESP32.
Nahrávání MP3 souborů do JQ6500
Pokud používáte modul JQ6500 s USB konektorem, proces nahrávání souborů je velmi jednoduchý. Modul se chová „tak trochu“ jako USB flash disk, takže po připojení k počítači je automaticky detekován jako běžný diskový prostor. Tento prostor je sice určen pro ukládání zvukových souborů, ale nepočítejte s tím, že na něj budete soubory ve formátech MP3 nebo WAV kopírovat například v Průzkumníku nebo Total Commanderu.
Postup při nahrávání souborů (modul s USB konektorem):
- Připojení modulu JQ6500 k počítači:
Po připojení modulu JQ6500 k počítači pomocí USB kabelu se modul automaticky připojí jako USB flash disk. V počítači se objeví nové zařízení, které bude vypadat jako obyčejný pevný disk.
- Otevření nástroje JQ6500 Music Download Tool:
Jakmile se pokusíme modul otevřít (např. poklikáním v Průzkumníku), automaticky se spustí nástroj JQ6500 Music Download Tool, který usnadní celý proces nahrávání souborů. Tento nástroj je v modulu JQ6500 k dispozici ve verzi pro OS Windows.

- Poznámka:
- Nástroj JQ6500 Music Download Tool je na modulu k dispozici v čínštině, což může být pro většinu uživatelů trochu problematické. Ale ovládání je poměrně jednoduché a intuitivní, že se to dá zápis zvukových souborů zvládnout. Nicméně existují i alternativy v angličtině (viz níže).
- Nahrání souborů do paměti:
Otevřeme nástroj JQ6500 Music Download Tool a na první záložce si můžete vybrat zvukové soubory (např. 01.mp3, 02.mp3, atd.), které chcete nahrát. Výběr souborů potvrďte tlačítkem vedle okna.

Po výběru souborů se vrátíme na první záložku a jednoduše klikneme na tlačítko pro nahrání. Program začne kopírovat soubory do flash paměti modulu JQ6500.

- Odpojení modulu:
Po dokončení nahrávání můžete modul bezpečně odpojit od počítače. Soubory jsou nyní uloženy v paměti modulu a připraveny pro přehrávání.
Nástroj v angličtině
Pro uživatele, kteří nechtějí používat verzi v čínštině, existují upravené verze nástroje v angličtině, které byly zveřejněny na komunitních webech. Tato verze je mnohem uživatelsky přívětivější, neboť nevyžaduje interakci s čínským rozhraním. Další výhodou je, že lze tento nástroj spustit rovnou ve svém počítači. Jednu z možných anglických alternativ lze stáhnout ze stránek: https://


- Poznámka:
- Pokud máme modul JQ6500 bez USB konektoru, jde většinou o typ se slotem pro SD kartu. V takovém případě stačí soubory MP3 nakopírovat na tuto kartu pomocí čtečky TF karet a následně ji vložit do slotu zvukového modulu.
Pojmenování souborů
Obecně se uvádí, že (bez ohledu na způsob přenosu souborů do modulu JQ6500) je velmi důležité soubory správně pojmenovat. Každý soubor by měl mít číselný název, který odpovídá pořadí skladby. Například:
- 01.mp3 pro první skladbu
- 02.mp3 pro druhou skladbu
- a tak dál.
Je však třeba upozornit, že pojmenování souborů neudává pořadí, ve kterém budou soubory přehrávány. O pořadí souborů rozhoduje jejich pořadí ve FAT tabulce modulu JQ6500. Použití očíslování souborů nám tedy pomůže při jejich načítání do nástroje Music Download Tool, tím určí pořadí jejich uložení do modulu (a tedy i pořadí zápisu do FAT). Soubor 01.mp3 bude následně odpovídat prvnímu souboru a bude možné jej přehrát příkazem pro přehrávání konkrétní skladby.
Pokud možno se vyvarujme používání dlouhých názvů nebo diakritiky (a mezer) v názvech souborů. Po jednom takovém pokusu náš modul JQ6500 začal „zlobit“ a občas začne přehrávat sekvence ze souboru, který už v něm dávno neměl být. Pravděpodobně došlo k poškození FAT tabulky.
Jak připojit JQ6500 k ESP32
Pokud jsme již „naplnili“ modul JQ6500 požadovanými MP3 soubory, můžeme přistoupit k připojení modulu k řídicímu mikrokontroléru ESP32 a začneme ho řídit přes UART – pochopitelně v MicroPythonu.
Modul ESP32 má obvykle tři UART rozhraní (UART0
, UART1
, UART2
). Každý z těchto UART portů je nezávisle konfigurovatelný a umožňuje komunikaci přes sériovou linku. Ve výchozím nastavení je UART0
obvykle vyhrazen pro sériovou komunikaci s počítačem během nahrávání a ladění programu, zatímco UART1
a UART2
jsou volné pro uživatelské aplikace.
V našem případě použijeme UART2
(výchozí piny TX
= GPIO17
, RX
= GPIO16
). Propojení mezi ESP32 a JQ6500 zobrazuje následující obrázek a tabulka:

ESP32 Pin | JQ6500 Pin |
---|---|
GPIO17 (TX) | RX |
GPIO16 (RX) | TX |
GND | GND |
5V | VCC |
- Poznámka:
- Pokud pozorného čtenáře překvapilo, že na pin
RX
modulu JQ6500 je připojen pin modulu ESP32, který odpovídá linceTX
, nejedná se o chybu tisku! Co je pro jeden modul vysílání (TX
), to musí být pro druhý modul přijímání (RX
). - Linky sběrnice UART jsou tedy překřížené, což je ale zcela běžná praxe.
Pro inicializaci UART v MicroPythonu použijeme třídu UART
z modulu machine
. Nejprve je třeba importovat tento modul a následně vytvořit instanci UART s požadovanými parametry. Tyto parametry obvykle zahrnují číslo UART, rychlost přenosu (baud rate) a piny pro RX
a TX
.
Následující kód ukazuje, jak inicializovat UART2
s rychlostí 9600 baudů a piny GPIO16
a GPIO17
pro RX
a TX
. V ukázce hned vidíme použití metod pro zápis a čtení informací na sběrnici UART:
from machine import UART, Pin
import time
# Inicializace UART2
uart = UART(2, baudrate=9600, tx=Pin(16), rx=Pin(17))
# Malé zpoždění po inicializaci
time.sleep(1)
# Zápis dat
uart.write("Hello, ESP32!")
# Čtení dat
data = uart.read()
if data:
print("Received:", data.decode())
Odesílání příkazů do JQ6500:
Komunikační formát
Modul JQ6500 při komunikaci přes UART očekává následující základní parametry sériového rozhraní:
- Rychlost (Baud Rate): 9600 baudů (standardní)
- Datové bity: 8
- Parita: Žádná
- Stop bity: 1
Příkazy se posílají jako bajty dat, a to jak pro ovládání modulu, tak pro přijímání odpovědí. Každá komunikace začíná start bajtem 0x7E
, následující bajt určuje počet bajtů zprávy (délka zprávy je počet bajtů mezi startovním a koncovým bajtem), následuje bajt specifikující příkaz. Poté následuje jeden nebo dva bajty parametrů příkazu (dle konkrétního příkazu). Celá zpráva je pak
ukončena koncovým bajtem 0xEF
(viz následující schéma struktury rámce):
[0x7E] [length] [command] [param1] [param2] [0xEF]
Pokud například chceme spustit přehrávání prvního souboru, musíme odeslat následující komunikační rámec:
0x7E 0x04 0x03 0x00 0x01 0xEF
kde struktura rámce je následující:
- Start bajt →
0x7E
- Délka paketu → 1 + 1 + délka dat, tedy: [délka (1) + příkaz (1) + data (2)] =
0x04
- Příkaz →
0x03
(kód pro příkaz „Přehrát soubor podle indexového čísla“) - Data →
0x00
a0x01
(číslo souboru – v pořadí horní osmice (0x00
), pak dolní osmice bitů (0x01
), zde tedy skladba číslo 1) - End bajt →
0xEF
Víme-li jak soubory odesílat do modulu JQ6500, pojďme se podívat na přehled všech příkazů pro modul JQ6500 – tak jak je uvádí čínský datový list.
Přehled příkazů modulu JQ6500:
Kód příkazu | Popis funkce | Rámec příkazu |
---|---|---|
0x01 | Následující skladba (Next) | 7E 02 01 EF |
0x02 | Předchozí skladba (Prev) | 7E 02 02 EF |
0x03 | Přehrát soubor podle indexového čísla, pro SD (1–65535), FLASH (0–200) | 7E 04 03 00 01 EF Červeně je číslo skladby Argument 1 = horních 8 bitů indexového čísla, Argument 2 = dolních 8 bitů indexového čísla. |
0x04 | Zvýšení hlasitosti | 7E 02 04 EF |
0x05 | Snížení hlasitosti | 7E 02 05 EF |
0x06 | Nastavení hlasitosti (0–30) | 7E 03 06 15 EF Červená hodnota označuje rozsah hlasitosti od 00 do 1E |
0x07 | Nastavení ekvalizéru Normální/Pop/Rock/Jazz/Classic/Base (0/1/2/3/4/5) |
7E 03 07 01 EF Červená hodnota lze změnit od 0 do 5 |
0x09 | Nastavení zdroje U/TF/AUX/SLEEP/FLASH (0/1/2/3/4) |
7E 03 09 01 EF Červená hodnota lze změnit od 0 do 4 1 = 0x01 pro kartu SD kartu,4 = 0x04 pro paměť flash na desce |
0x0A | Přejděte do režimu spánku – nízká spotřeba energie | 7E 02 0A EF Pozastaví přehrávání |
0x0C | Resetování čipu | 7E 02 0C EF Po odeslání je vhodné počkat 500 ms |
0x0D | Přehrávání (Play) | 7E 02 0D EF |
0x0E | Pauza (Pause) | 7E 02 0E EF |
0x0F | Přepínání mezi složkami (0/1) Názvy složek na disku U a kartě SD musí být 01, 02,…99 (na flash nejsou složky podporované) |
7E 03 0F 00 EF Červená hodnota lze změnit od 0 do 1 1 – Další složka0 – Předchozí složka |
0x11 | Přehrávání ve smyčce ALL/FOL/ONE/RAM/ONE_STOP (0/1/2/3/4) |
7E 03 11 00 EF Červená hodnota odpovídá odpovídajícímu režimu, 00 znamená plnou smyčku,01 znamená jednu smyčku;Například: Chcete-li přehrát druhou skladbu ve smyčce, nejprve odešlete 7E 03 11 01 EF a poté odešlete 7E 04 03 00 02 EF |
0x12 | Zadejte soubor ze složky, který chcete přehrát Názvy složek na disku U a kartě SD musí být 01, 02,…99 (na flash nejsou složky podporované) |
7E 04 12 01 02 EF 01 označuje složku02 vzadu označuje souborTo znamená, že přehrajete soubor 2 ve složce 1 |
Příkazy pro získání odpovědi
Kód příkazu | Popis funkce | Formát příkazu |
---|---|---|
0x40 | Chyba vrácení, požadavek na opětovné odeslání | 7E 02 42 EF |
0x42 | Dotaz na aktuální stav | 7E 02 42 EF Odpověď celé číslo jako šestnáctkové znaky ascii) 0/1/2 pro Stopped/Playing/Paused. Vestavěná paměť se nikdy po přehrání skladby „nezastaví“, pouze se „pozastaví“. Při přehrávání se občas objeví chybná odpověď „Paused“, je třeba několikrát dotázat, aby bylo jasno. |
0x43 | Dotaz na aktuální hlasitost | 7E 02 43 EF Odpověď je celé číslo (jako hexadecimální ascii znaky) od 0 do 30 |
0x44 | Dotaz na nastavení ekvalizéru | 7E 02 44 EF Odpověď je celé číslo (jako hexadecimální ascii znaky) od 0 do 5 (definice viz výše). |
0x45 | Dotaz na aktuální režim přehrávání | 7E 02 45 EF Odpověď je celé číslo (jako hexadecimální ascii znaky) od 0 do 4 (definice viz výše). |
0x46 | Dotaz na aktuální verzi softwaru | 7E 02 46 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x47 | Dotaz na celkový počet souborů na SD kartě | 7E 02 47 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x48 | Dotaz na celkový počet souborů v UDISK (Co je UDISK?) |
7E 02 48 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x49 | Dotaz na celkový počet souborů FLASH | 7E 02 49 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x4B | Zjištění indexového čísla (tabulka FAT) aktuálního souboru na kartě SD. | 7E 02 4B EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x4C | Zjištění indexového čísla (tabulka FAT) aktuálního souboru na UDISK. | 7E 02 4C EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x4D | Zjištění indexového čísla (tabulka FAT) aktuálního souboru na kartě FLASH. | 7E 02 4D EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x50 | Získání pozice aktuálního přehrávaného souboru v sekundách. | 7E 02 50 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x51 | Celková délka aktuálně přehrávaného souboru v sekundách. | 7E 02 51 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
0x52 | Zjištění názvu aktuálního souboru na kartě SD (FLASH není podporována) | 7E 02 52 EF Odpověď ASCII znaky. Pamatujte, že se vrátí název, i když se soubor nepřehrává, i když se přehrává soubor z vnitřní paměti, i když byla SD karta vyjmuta…! Ve skutečnosti to také není název souboru, chybí mu oddělovač přípony a má pravděpodobně maximální délku [8-nazev][3-pripona] |
0x53 | Celkový počet složek v aktuální složce, na kterou se dotazuje | 7E 02 52 EF Odpověď je celé číslo (jako hexadecimální ascii znaky). |
Příklady příkazů
Přehrání první skladby
Příkazový rámec pro přehrání první skladby jsme si již ukazovali výše, takže se nyní podíváme, jak tento příkaz pomocí MicroPythonu odeslat přes UART sběrnici do modulu JQ6500.
from machine import UART, Pin
# Inicializace UART
uart = UART(2, baudrate=9600, tx=Pin(17), rx=Pin(16))
cmd = bytearray([0x7E, 0x04, 0x03, 0x00, 0x01, 0xEF])
uart.write(cmd)
Nastavení hlasitosti
Pokud bychom chtěli odeslat příkaz pro nastavení hlasitosti na zadanou úroveň, mohli bychom vytvořit funkci nazvanou set_volume
: (všimněte si způsobu vložení obsahu proměnné level do odesílané struktury)
from machine import UART, Pin
# Inicializace UART
uart = UART(2, baudrate=9600, tx=Pin(17), rx=Pin(16))
def set_volume(level):
level = max(0, min(31, level)) # omezíme hodnotu
cmd = bytearray([0x7E, 0x03, 0xA7, level, 0xEF])
uart.write(cmd)
set_volume(20)
Program ovládání modulu JQ6500
Jelikož velká část rámce příkazů zůstává stejná, pokusíme se vytvořit „univerzální“ funkci send_command
, kterou následně využijeme pro vytvoření specifických funkcí pro ovládání modulu JQ6500.
Zároveň připravíme kód na příjem možné odpovědi od modulu JQ6500. Ještě předtím, ale vytvoříme metodu flush()
, která bude čistit buffer odpovědí od případných předchozích příkazů.
from machine import UART, Pin
from time import sleep
# Inicializace UART
uart = UART(2, baudrate=9600, tx=Pin(17), rx=Pin(16))
# Vyčištění příp. odpovědí
def flush():
# Vyprázdní přijímací buffer UARTu, pokud je v něm něco z předchozích komunikací
while uart.any(): # pokud je k dispozici nějaký znak v bufferu
uart.read() # přečte a zahodí
sleep(0.01) # krátká pauza pro stabilitu čtení uart.read()
def send_command(cmd, data=[]):
# Sestaví a odešle příkaz podle protokolu modulu JQ6500
length = 2 + len(data) # délka paketu = 1 + délka + 1 bajt příkaz + data
body = [cmd] + data # hlavní část zprávy
message = [0x7E, length] + body + [0xEF] # kompletní paket s hlavičkou a patičkou
flush() # před odesláním vyčistí buffer
uart.write(bytes(message)) # pošle paket na UART
# TEST našich funkcí
# --- hlavní program ---
# Odešli PLAY příkaz
send_command(0x0D)
print("Příkaz PLAY odeslán.")
# Pauza a čtení odpovědi (volitelné, může být None)
sleep(0.2)
resp = uart.read()
print("Odpověď:", resp)
V načítání odpovědi modulu JQ6500 je však skrytý problém! Co se stane, když modul neodpoví? Opravdu musí modul JQ6500 na každý příkaz odeslat nějakou odpověď.
Zatím si ve výše uvedeném programy myslíme, že ano. Ale, co když ne? V takovém případě program uvízne při čekání na odpověď, která ale nikdy nepřijde. To rozhodně není ideální. Pro zpracování odpovědi od modulu JQ6500 si tedy vytvoříme vlastní funkci read_response
, která bude obsahovat timeout
. Pokud během určité doby neobdržíme odpověď, funkce čekání na načtení dat z modulu JQ6500 ukončí.
from time import ticks_ms, ticks_diff
def read_response(timeout_ms=500):
# Čeká na odpověď modulu po dobu timeoutu (v ms) a vrací přijatá data nebo None
start = ticks_ms() # čas začátku čekání
buffer = b'' # prázdný buffer pro ukládání příchozích dat
while ticks_diff(ticks_ms(), start) < timeout_ms:
if uart.any(): # pokud jsou data v UART bufferu
buffer += uart.read() # načte je a přidá do bufferu
sleep(0.01) # krátká pauza, aby CPU nebyl přetížen
if buffer:
return buffer
else:
return None # pokud nic nepřišlo, vrátí None
Máme-li připravenou funkci pro odeslání příkazů a načtení jejich odpovědí, můžeme začít psát funkce pro jednotlivé příkazy:
Reset modulu:
def reset():
# Resetuje modul příkazem 0x0C a čeká na odpověď (max 3 sekundy)
send_command(0x0C)
return read_response(1000) # čeká na odpověď max 1s
Volba zdroje MP3 souborů:
def set_source(source=4):
# Nastaví zdroj přehrávání (např. 4 = interní paměť, 1 = SD karta)
send_command(0x09, [source])
return read_response()
Nastavení hlasitosti:
def set_volume(level):
# Nastaví hlasitost na hodnotu mezi 0 a 30
level = max(0, min(level, 30)) # omezí hodnotu do povoleného rozsahu
send_command(0x06, [level])
return read_response()
Přehrání souboru zadaného indexu:
def play_index(index):
# Přehrání skladby podle indexu (čísla skladby)
hi = (index >> 8) & 0xFF # vyšší bajt indexu (pro případ víc jak 255 skladeb)
lo = index & 0xFF # nižší bajt indexu
send_command(0x03, [hi, lo])
return read_response()
Zastavení aktuálního souboru:
def pause():
# zastaví aktuální přehrávání.
send_command(0x0E) # Příkaz pro pauzu/stop
return read_response()
Získání délky aktuální skladby:
def get_length():
# Zjistí délku aktuálně přehrávané skladby v sekundách
send_command(0x51)
resp = read_response()
if resp:
try:
# Odpověď modulu je ASCII hex (např. b'000b' => 11 sekund)
length_sec = int(resp.decode('ascii'), 16)
return length_sec
except Exception:
return None
return None
Obdobně bychom mohli zakomponovat další příkazy podle výše uvedeného přehledu funkcí.
Neuvádíme zde všechny příkazy, protože je běžně asi uživatel stejně všechny nepotřebuje. A navíc, už dlouho jsme nezadali zvídavému čtenáři domácí úkol. Tak proč by to nemohlo být právě tohle? 😉
- Upozornění:
- Je nutné zmínit, že některé funkce fungují pouze u modelu JQ6500 s SD kartou! (Řada z nich byla již zmíněna v tabulce příkazů.) Překvapivě mezi takové příkazy patří i příkaz Stop. Pokud budeme chtít některou skladbu předčasně ukončit, u modelu s flash pamětí musíme použít příkaz Pause. Po příkazu Pause (který je v podstatě ekvivalentem příkazu Stop) není možné skladbu z flash paměti znovu spustit od stejného místa. Zkrátka, Pause je Stop, a příkaz Pause na modulu s flash pamětí prostě nefunguje! 😒
Než uvedeme celý ukázkový program, který předvede komunikaci mezi modulem ESP32 a JQ6500, ukážeme si, jak bude vypadat hlavní část programu při použití výše definovaných funkcí.
print('Iniciuji modul JQ6500')
reset()
sleep(0.5)
print('Nastavuji hlasitost')
set_volume(20)
print('Nastavuji vnitrni pamet jako zdroj MP3')
set_source(4)
print('Spouštím 1. skladbu')
play_index(1)
delka = get_length()
print(f'delka je {delka} sec.')
sleep(delka) # cekani, nez skladba skonci
Úkol našeho ukázkového programu je poměrně jednoduchý. Iniciuje modul JQ6500, nastaví se mu hlasitost, zvolí se zdroj načítání MP3 souborů z paměti flash a spustí se první skladba. Dále se načte délka skladby a následuje stejně dlouhá čekací smyčka, protože modul ESP32 „odstartuje“ zvukový modul JQ6500, a tím je pro něj hotovo. ESP32 už nečeká na nic dalšího – modul JQ6500 totiž přehrává skladbu zcela autonomně. Program v modulu ESP32 by tedy klidně běžel dál, může dělat cokoliv – třeba i spouštět další a další skladby, to ale určitě nechceme. Proto, jakmile skladbu spustíme a nemáme nic dalšího na práci, počkáme do na skončení skladby.
Zde je možná příležitost zamyslet se nad využitím pinu BUSY
modulu JQ6500, který je aktivní po dobu přehrávání skladby. Tento problém jsme ale v našem případě neřešili hardwarově. Místo toho se teď spolehneme na informaci o délce skladby, která se načte z modulu. V některých zdrojích se uvádí, že modul JQ6500 může mít problém s určením délky některých MP3 souborů. My jsme se s tímto problémem nesetkali, možná je to způsobeno jiným nastavením některých MP3 souborů – přeci jen, není MP3 jako MP3.
import machine
from machine import UART, Pin
from time import sleep, ticks_ms, ticks_diff
# Inicializace UART
uart = UART(2, baudrate=9600, tx=Pin(17), rx=Pin(16))
# Vyčištění příp. odpovědí
def flush():
# Vyprázdní přijímací buffer UARTu, pokud je v něm něco z předchozích komunikací
while uart.any(): # pokud je k dispozici nějaký znak v bufferu
uart.read() # přečte a zahodí
sleep(0.01) # krátká pauza pro stabilitu čtení uart.read()
def send_command(cmd, data=[]):
# Sestaví a odešle příkaz podle protokolu modulu JQ6500
length = 2 + len(data) # délka paketu = 1 + d0lka + 1 bajt příkaz + data
body = [cmd] + data # hlavní část zprávy
message = [0x7E, length] + body + [0xEF] # kompletní paket s hlavičkou a patičkou
flush() # před odesláním vyčistí buffer
uart.write(bytes(message)) # pošle paket na UART
def read_response(timeout_ms=500):
# Čeká na odpověď modulu po dobu timeoutu (v ms) a vrací přijatá data nebo None
start = ticks_ms() # čas začátku čekání
buffer = b'' # prázdný buffer pro ukládání příchozích dat
while ticks_diff(ticks_ms(), start) < timeout_ms:
if uart.any(): # pokud jsou data v UART bufferu
buffer += uart.read() # načte je a přidá do bufferu
sleep(0.01) # krátká pauza, aby CPU nebyl přetížen
if buffer:
return buffer
else:
return None # pokud nic nepřišlo, vrátí None
def reset():
# Resetuje modul příkazem 0x0C a čeká na odpověď (max 3 sekundy)
send_command(0x0C)
return read_response(1000) # čeká na odpověď max 1s
def set_source(source=4):
# Nastaví zdroj přehrávání (např. 4 = interní paměť, 1 = SD karta)
send_command(0x09, [source])
return read_response()
def set_volume(level):
# Nastaví hlasitost na hodnotu mezi 0 a 30
level = max(0, min(level, 30)) # omezí hodnotu do povoleného rozsahu
send_command(0x06, [level])
return read_response()
def play_index(index):
# Přehrání skladby podle indexu (čísla skladby)
hi = (index >> 8) & 0xFF # vyšší bajt indexu
lo = index & 0xFF # nižší bajt indexu
send_command(0x03, [hi, lo])
return read_response()
def pause():
# zastaví aktuální přehrávání.
send_command(0x0E) # Příkaz pro pauzu/stop
return read_response()
def get_length():
# Zjistí délku aktuálně přehrávané skladby v sekundách
send_command(0x51)
resp = read_response()
if resp:
try:
# Odpověď modulu je ASCII hex
length_sec = int(resp.decode('ascii'), 16)
return length_sec
except Exception:
return None
return None
# ===== hlavní program =====
print('Iniciuji modul JQ6500')
reset()
sleep(0.5)
print('Nastavuji hlasitost')
set_volume(20)
print('Nastavuji vnitrni pamet jako zdroj MP3')
set_source(4)
print('Spouštím 1. skladbu')
play_index(1)
delka = get_length()
print(f'delka je {delka} sec.')
sleep(delka) # cekani, nez skladba skonci
print('KONEC')
Trochu dlouhý program na přehrání jediného souboru, že?
Ale uvědomme si, že definované funkce v tomto programu dokáží mnohem více. Je skoro škoda mít tyto funkce v programu takto samostatně. Co kdybychom je dali do své první vlastní knihovny (nebo, jak říkají správní „pythoňáci“, do modulu)? 😉

Pojďme si napsat knihovnu v Pythonu!
Pokud se chceme v MicroPythonu posunout dál a napsat něco, co budeme moci opakovaně používat ve více projektech, je skvělé naučit se, jak vytvářet vlastní moduly. Modul (někdo tomu říká knihovna) je v podstatě soubor, který obsahuje funkce, třídy nebo proměnné, které můžete importovat do jiných skriptů a znovu použít. Tímto způsobem nemusíte každý kód psát znovu a znovu, což vám ušetří spoustu času a umožní psát čistější a přehlednější programy.
Například pokud potřebujete pracovat s LED diodami, můžete si napsat modul, který tyto LED diody ovládá, a poté tento modul použít ve více projektech.
Co je to třída a proč se používá?
Třída je v podstatě šablona pro vytváření objektů. Objekt je konkrétní instance třídy, která má své vlastní hodnoty a metody. Když chcete pracovat s nějakým druhem dat, který má více atributů a funkcí, je ideální použít třídu.
V Pythonu (a tedy i v MicroPythonu) jsou třídy definovány pomocí klíčového slova class
. To, co je pro třídy typické, je speciální metoda __init__()
, která je volána při vytvoření nové instance třídy. Tato metoda slouží k inicializaci objektu a k nastavení jeho počátečních hodnot.
Co znamená self
?
Klíčové slovo self
je v Pythonu (a MicroPythonu) speciální parametr, který odkazuje na aktuální instanci třídy. Je to něco jako „já“ pro daný objekt. Když v metodách třídy použijeme self
, odkazujeme na konkrétní objekt, na
kterém se metoda volá. To znamená, že každá instance třídy může mít vlastní hodnoty pro své atributy.
Příklad: Vytvoření vlastního modulu s třídou
Teď se podíváme na jednoduchý příklad. Vytvoříme modul, který bude obsahovat třídu pro práci s „osobou“ (vytvoříme třídu Osoba
). Tento modul bude mít metody pro nastavení jména a věku osoby a pro jejich zobrazení.
1. Vytvoření modulu
Nejprve si vytvoříme soubor, který bude náš modul reprezentovat. V tomto případě ho pojmenujeme osoba.py
. Tento soubor bude obsahovat naši třídu Osoba
.
# osoba.py
class Osoba:
# Konstruktor třídy (metoda __init__)
def __init__(self, jmeno, vek):
self.jmeno = jmeno # Atribut jméno
self.vek = vek # Atribut věk
# Metoda pro zobrazení informací o osobě
def zobraz_info(self):
print(f"Jméno: {self.jmeno}, Věk: {self.vek}")
2. Použití modulu
Nyní, když máme náš modul osoba.py
, můžeme ho použít v jiném skriptu. Použijeme import
, abychom si tento modul do našeho skriptu načetli a použili třídu Osoba
.
# hlavni.py
# Importujeme náš vlastní modul osoba
import osoba
# Vytvoření nové instance třídy Osoba
osoba1 = osoba.Osoba("Jan", 30)
# Zavoláme metodu pro zobrazení informací o osobě
osoba1.zobraz_info()
Vysvětlení kódu:
- Soubor
osoba.py
:- Třída
Osoba
má metodu__init__()
, která je automaticky zavolána při vytvoření nové instance třídy. Parametryjmeno
avek
se při vytvoření objektu předají a inicializují. Atributyself.jmeno
aself.vek
.self
jsou odkaz na konkrétní instanci třídy, takže každý objekt třídyOsoba
může mít své vlastní hodnoty projmeno
avek
. - Metoda
zobraz_info()
používá tyto atributy a vypíše informace o osobě.
- Třída
- Soubor
hlavni.py
:- Tento soubor importuje modul
osoba
a vytváří novou instanci třídyOsoba
s parametry "Jan" a 30. - Poté zavolá metodu
zobraz_info()
, která zobrazí (vypíše do výstupu) jméno a věk osoby.
- Tento soubor importuje modul
Tento příklad ukazuje, jak vytvořit velmi jednoduchý vlastní modul v MicroPythonu, jak definovat třídu, používat konstruktor __init__
a jak pracovat s objekty a metodami.
Není to jasné?
Tak to ještě více „zatemníme“ tím, že se právě nabyté informace pokusíme aplikovat na příklad vytvoření modulu pro ovládání modulu JQ6500.
V následujícím příkladu si ukážeme, jak převést množství funkcí pro komunikaci s audio modulem JQ6500 do jedné třídy a jak tuto novou třídu použít v praxi.
Vytvoření třídy pro JQ6500
Vytvoříme třídu JQ6500
, která bude obsahovat všechny potřebné metody pro ovládání tohoto modulu. Kromě samotných funkcí pro modul JQ6500 rovnou připojíme také příkazy pro komunikaci s UART do strukturovaného objektu.
Jak bude vypadat třída JQ6500 (soubor jq6500_FK.py
)
# jq6500_FK.py
from machine import Pin, UART
from time import sleep, ticks_ms, ticks_diff
class JQ6500:
# Konstanty pro zdroje přehrávání (interní paměť a SD karta)
SOURCE_INTERNAL_MEMORY = 4
SOURCE_SD_CARD = 1
def __init__(self, uart_id=2, tx_pin=17, rx_pin=16, baudrate=9600):
# Inicializace UARTu podle zadaných pinů a parametru uart_id
self.uart = UART(uart_id, baudrate=baudrate, tx=Pin(tx_pin), rx=Pin(rx_pin))
def flush(self):
# Vyprázdní přijímací buffer UARTu
while self.uart.any():
self.uart.read()
sleep(0.01)
def send_command(self, cmd, data=[]):
# Sestavení a odeslání příkazu na modul
length = 2 + len(data)
body = [cmd] + data
message = [0x7E, length] + body + [0xEF]
self.flush()
self.uart.write(bytes(message))
def set_source(self, source=SOURCE_INTERNAL_MEMORY):
# Nastaví zdroj přehrávání
self.send_command(0x09, [source])
return self.read_response()
atd…
Metoda __init__()
je nyní využita jako konstruktor, který inicializuje UART a připojení k pinům pro přenos dat. Jakmile tedy vytvoříme nějakou instanci této třídy, bude v rámci jejích metod zajištěno i propojení přes UART. Všimněme si, že v rámci třídy jsme vytvořili i konstanty, které pak mohou svým názvem lépe reprezentovat hodnoty, které zastupují.
Použití třídy v hlavním programu
Nyní, když máme třídu, můžeme ji použít v hlavním programu. Vytvoření instance třídy je snadné, stačí pouze specifikovat UART port a piny pro přenos a příjem dat. Náš dříve uvedený ukázkový program, pak můžeme nyní přepsat do následující podoby:
# hlavní.py
from machine import Pin
from jq6500_FK import JQ6500
# Vytvoření instance třídy JQ6500 s nastavením UART
mp3 = JQ6500(uart_id=2, tx_pin=17, rx_pin=16)
# Iniciace modulu JQ6500
print('Iniciuji modul JQ6500')
mp3.reset()
# Nastavení hlasitosti
print('Nastavuji hlasitost')
mp3.set_volume(20)
# Nastavení zdroje přehrávání na interní paměť
print('Nastavuji vnitrni pamet jako zdroj MP3')
mp3.set_source(JQ6500.SOURCE_INTERNAL_MEMORY)
# Spuštění první skladby
print('Spoustím 1. skladbu')
mp3.play_index(1)
# Zjištění délky skladby
delka = mp3.get_length()
print(f'Délka skladby: {delka} sekundy.')
# Počkej, než skladba skončí
sleep(delka)
print('KONEC')
Vytvoření objektu třídy JQ6500 je základním krokem pro práci s tímto modulem v našem programu. Objekt je vlastně konkrétní instance třídy, která má k dispozici všechny metody a vlastnosti definované v třídě. V tomto případě bude objekt mp3
obsahovat všechno, co je potřeba pro komunikaci s audio modulem JQ6500, a umožní nám snadno přistupovat k různým funkcím, jako je přehrávání skladeb, nastavování hlasitosti nebo kontrola délky aktuální skladby.
K vytvoření objektu mp3
použijeme následující zápis:
mp3 = JQ6500(uart_id=2, tx_pin=17, rx_pin=16)
V tomto příkladu předáváme do konstruktoru třídy JQ6500
tři argumenty:
uart_id=2
: Tento parametr určuje, který UART port bude použit pro komunikaci s modulem.tx_pin=17
: Tento parametr určuje pin na desce, který bude použit pro odesílání dat na modul (transmit pin) – v našem případě je to pinGPIO17
.rx_pin=16
: Tento parametr určuje pin pro příjem dat z modulu (receive pin) – v našem případě je to pin GPIO16.
Tato tři nastavení (UART port a piny pro TX a RX) jsou zásadní pro správnou komunikaci mezi naším mikrořadičem (například ESP32) a audio modulem JQ6500. Po vytvoření objektu mp3
je tento objekt připraven přijímat a odesílat data na těchto specifikovaných pinech, což nám umožňuje ovládat modul JQ6500 pomocí metod, které jsme definovali v třídě JQ6500.
„Tahák“ pro tvorbu tříd a knihoven
Pokud se rozhodnete organizovat svůj kód do tříd a knihoven, může to být skvělý způsob, jak zjednodušit práci s hardwarem a celkově zpřehlednit váš kód. Abychom vám tento proces co nejvíce usnadnili, připravili jsme pro vás stručný průvodce („tahák“), který vám krok za krokem ukáže, jak na to.
Tato tabulka vám poskytne jasné pokyny, jak vytvořit třídu, jak ji použít v hlavním programu a jak ji následně transformovat do samostatného modulu, který budete moci opakovaně využívat ve více projektech. Postupujte podle jednotlivých kroků a nikdy nezapomeňte, že každá třída, kterou vytvoříte, je vlastně nástrojem, který vám pomůže efektivněji komunikovat s vaším hardwarem, šetřit čas a zjednodušit údržbu kódu.
Krok | Popis | Příklad |
---|---|---|
1. Definice třídy | Začneme definováním třídy pomocí klíčového slova class . Třída bude obsahovat atributy (proměnné) a metody (funkce), které souvisejí s konkrétním objektem nebo zařízením. |
class JQ6500:
|
2. Inicializační metoda __init__() |
Metoda __init__() je konstruktor třídy, který se volá při vytvoření nové instance třídy. Nastavujeme zde počáteční hodnoty atributů třídy. |
def __init__(self, uart_id, tx_pin, rx_pin):
|
3. Definice metod třídy | Vytváříme metody, které budou reprezentovat funkce související s objektem. Tyto metody mohou přijímat parametry a manipulovat s atributy třídy. |
def send_command(self, cmd, data=[]):
|
4. Vytvoření objektu (instance třídy) | Pro použití třídy musíme vytvořit její instanci (objekt). Při vytváření objektu předáváme parametry konstruktoru třídy. |
mp3 = JQ6500(uart_id=2, tx_pin=17, rx_pin=16)
|
5. Použití metod objektu | Po vytvoření objektu můžeme volat metody, které jsme definovali ve třídě, k provádění různých operací (např. posílání příkazů, nastavování hodnot, apod.). |
mp3.reset()
|
6. Vytvoření samostatného modulu | Pokud chceme třídu používat v několika projektech, můžeme ji uložit do samostatného souboru (modulu). Tento soubor pak jednoduše importujeme v hlavním programu. | Uložte třídu do souboru jq6500.py .V hlavním programu použijte:
from jq6500 import JQ6500
|
7. Import a použití knihovny | Když máme svou třídu jako samostatný modul, můžeme ji importovat a používat v jiných projektech, aniž bychom museli kopírovat kód. |
from jq6500 import JQ6500
|
Tipy pro tvorbu knihovny v (Micro)Pythonu:
- Modularita: Knihovnu rozdělte na menší, přehledné soubory, pokud obsahuje mnoho funkcí, tříd nebo souvisejících částí. Například můžete mít jednu třídu pro UART komunikaci a jinou pro samotné ovládání zařízení.
- Dokumentace: Každou třídu, metodu a funkci vždy dokumentujte, aby bylo jasné, co daný kód dělá. Používejte docstringy (např. """ Popis funkce """).
- Znovupoužitelnost: Při vytváření knihovny mějte na paměti, že ji budete moci použít v dalších projektech. Snažte se, aby byla co nejvíce univerzální a flexibilní – například tím, že umožníte nastavení různých parametrů (např. UART porty, piny apod.).
- Testování: Před použitím knihovny v hlavním programu ji otestujte na malých příkladech, abyste se ujistili, že vše funguje, jak má. To zahrnuje kontrolu komunikace s hardwarem nebo testování metod, které manipulují s daty.
Na závěr tohoto článku uvedeme celou ukázkovou knihovnu jq6500_FK.py
pro základní práci s modulem JQ6500. I když je tato knihovna mírně rozšířena o další
metody (oproti výše uvedeným příkladům), musíme zmínit, že neobsahuje všechny příkazy pro modul JQ6500. Jsou zde vybrané pouze ty, které nám přišly pro tento článek zajímavé a důležité.
from machine import Pin, UART
from time import sleep, ticks_ms, ticks_diff
class JQ6500:
# Příkazy
CMD_RESET = 0x0C
CMD_SET_SOURCE = 0x09
CMD_SET_VOLUME = 0x06
CMD_PLAY_INDEX = 0x03
CMD_NEXT_TRACK = 0x01
CMD_PREV_TRACK = 0x02
CMD_GET_LENGTH = 0x51
CMD_PAUSE = 0x0E
CMD_GET_FILE_COUNT = 0x49
CMD_GET_PLAYER_STATUS = 0x42
CMD_SET_EQUALIZER = 0x07
CMD_GET_EQUALIZER = 0x44
# Konstanty pro zdroje přehrávání
SOURCE_INTERNAL_MEMORY = 4 # Interní paměť modulu
SOURCE_SD_CARD = 1 # SD karta
# Přidání konstant pro stavy přehrávače
STATUS_STOPPED = 0x00
STATUS_PLAYING = 0x01
STATUS_PAUSED = 0x02
# Režimy ekvalizéru
EQ_NORMAL = 0
EQ_POP = 1
EQ_ROCK = 2
EQ_JAZZ = 3
EQ_CLASSIC = 4
EQ_BASS = 5
def __init__(self, uart_id=2, tx_pin=17, rx_pin=16, baudrate=9600):
"""
Inicializuje instanci třídy JQ6500.
Nastaví UART pro komunikaci s modulem JQ6500 a provede základní nastavení.
:param uart_id: ID UART portu, výchozí hodnota je 2.
:param tx_pin: Pin pro odesílání dat (TX), výchozí hodnota je 17.
:param rx_pin: Pin pro příjem dat (RX), výchozí hodnota je 16.
:param baudrate: Baudrate pro UART, výchozí hodnota je 9600.
"""
self.uart = UART(uart_id, baudrate=baudrate, tx=Pin(tx_pin), rx=Pin(rx_pin))
sleep(0.01) # krátká pauza, aby se UART stabilizoval
self.flush() # vyčistí UART buffer, aby nezůstaly staré data
def flush(self):
"""
Vyprázdní přijímací buffer UARTu.
Pokud je v bufferu něco z předchozích komunikací, tento příkaz to odstraní.
Tento krok je důležitý pro zajištění, že následující data budou čistá.
"""
while self.uart.any(): # pokud je k dispozici nějaký znak v bufferu
self.uart.read() # přečte a zahodí
sleep(0.01) # krátká pauza pro stabilitu čtení
def send_command(self, cmd, data=[]):
"""
Sestaví a odešle příkaz podle protokolu modulu JQ6500.
Příkaz je sestaven z hlavičky, délky, příkazu a dat, a následně odeslán na UART.
:param cmd: Příkaz, který se má odeslat (např. reset, nastavení hlasitosti).
:param data: Seznam dat, která se mají připojit k příkazu.
"""
length = 2 + len(data) # délka paketu = 1 + délka + 1 bajt příkaz + data
body = [cmd] + data # hlavní část zprávy
message = [0x7E, length] + body + [0xEF] # kompletní paket s hlavičkou a patičkou
self.flush() # před odesláním vyčistí buffer
self.uart.write(bytes(message)) # pošle paket na UART
def read_response(self, timeout_ms=500):
"""
Čeká na odpověď modulu a vrací přijatá data nebo None.
Čekání probíhá po dobu stanoveného timeoutu v milisekundách. Pokud žádná odpověď
nepřijde, vrátí funkce hodnotu None.
:param timeout_ms: Doba čekání na odpověď v milisekundách.
:return: Přijatá data nebo None, pokud není odpověď.
"""
start = ticks_ms() # čas začátku čekání
buffer = b'' # prázdný buffer pro ukládání příchozích dat
while ticks_diff(ticks_ms(), start) < timeout_ms:
if self.uart.any(): # pokud jsou data v UART bufferu
buffer += self.uart.read() # načte je a přidá do bufferu
sleep(0.01) # krátká pauza, aby CPU nebylo přetížené
if buffer:
return buffer
else:
return None # pokud nic nepřišlo, vrátí None
def reset(self):
"""
Resetuje modul JQ6500.
Pošle resetovací příkaz modulu a čeká na odpověď po dobu maximálně 1 sekundy.
:return: Odpověď modulu nebo None, pokud žádná odpověď nepřijde.
"""
self.send_command(self.CMD_RESET)
return self.read_response(1000)
def set_source(self, source=4):
"""
Nastaví zdroj přehrávání.
Může to být interní paměť modulu nebo SD karta.
:param source: Zvolený zdroj přehrávání (např. 4 pro interní paměť, 1 pro SD kartu).
:return: Odpověď modulu.
"""
self.send_command(self.CMD_SET_SOURCE, [source])
return self.read_response()
def set_volume(self, level):
"""
Nastaví hlasitost přehrávače na požadovanou úroveň.
Hlasitost je omezena na hodnoty mezi 0 a 30.
:param level: Úroveň hlasitosti (0-30).
:return: Odpověď modulu.
"""
level = max(0, min(level, 30)) # omezí hodnotu do povoleného rozsahu
self.send_command(self.CMD_SET_VOLUME, [level])
return self.read_response()
def play_index(self, index):
"""
Přehrává skladbu na základě indexu (čísla skladby).
Funkce převádí index na dvě hodnoty (vyšší a nižší bajt) a pošle příkaz pro přehrání.
:param index: Index skladby (např. 1 pro první skladbu).
:return: Odpověď modulu.
"""
hi = (index >> 8) & 0xFF # vyšší bajt indexu (pro případ víc jak 255 skladeb)
lo = index & 0xFF # nižší bajt indexu
self.send_command(self.CMD_PLAY_INDEX, [hi, lo])
resp = self.read_response()
return resp
def next_track(self):
"""
Přehraje další skladbu v seznamu.
Pošle příkaz pro přehrání další skladby.
:return: Odpověď modulu.
"""
self.send_command(self.CMD_NEXT_TRACK)
return self.read_response()
def prev_track(self):
"""
Přehraje předchozí skladbu v seznamu.
Pošle příkaz pro přehrání předchozí skladby.
:return: Odpověď modulu.
"""
self.send_command(self.CMD_PREV_TRACK)
return self.read_response()
def get_length(self):
"""
Zjistí délku aktuálně přehrávané skladby v sekundách.
Pošle příkaz pro získání délky skladby a vrátí ji jako celé číslo v sekundách.
:return: Délka skladby v sekundách nebo None, pokud došlo k chybě.
"""
self.send_command(self.CMD_GET_LENGTH)
resp = self.read_response()
if resp:
try:
# Odpověď modulu je ASCII hex (např. b'000b' => 11 sekund)
length_sec = int(resp.decode('ascii'), 16)
return length_sec
except Exception:
return None
return None
def pause(self):
"""
Zastaví aktuální přehrávání skladby.
Pošle příkaz pro pauzu, aby se přehrávání zastavilo.
:return: Odpověď modulu.
"""
self.send_command(self.CMD_PAUSE) # Příkaz pro pauzu
return self.read_response()
def get_file_count(self):
"""
Získá počet souborů na interní paměti modulu JQ6500.
Pošle příkaz pro získání počtu souborů a vrátí výsledek jako celé číslo.
:return: Počet souborů na paměti nebo None, pokud došlo k chybě.
"""
self.send_command(self.CMD_GET_FILE_COUNT)
response = self.read_response()
if response:
try:
file_count = int(response.decode('ascii'), 16)
return file_count
except Exception:
return None
else:
return None
def get_player_status(self):
"""
Získá aktuální stav přehrávače (Stop, Playing, Pause).
Pošle příkaz pro zjištění stavu přehrávače a vrátí jeden z následujících stavů:
- 'STOPPED' pro 0x00
- 'PLAYING' pro 0x01
- 'PAUSED' pro 0x02
:return: Stav přehrávače jako řetězec ('STOPPED', 'PLAYING', 'PAUSED', nebo 'ERROR').
"""
self.send_command(self.CMD_GET_PLAYER_STATUS)
resp = self.read_response(1000)
if resp:
try:
status = int(resp.decode('ascii'), 16)
if status == self.STATUS_STOPPED:
return 'STOPPED'
elif status == self.STATUS_PLAYING:
return 'PLAYING'
elif status == self.STATUS_PAUSED:
return 'PAUSED'
else:
return 'UNKNOWN'
except Exception:
return 'ERROR'
else:
return 'NO RESPONSE'
def set_equalizer(self, mode):
"""
Nastaví ekvalizér podle zvoleného režimu.
Možné režimy:
0 = Normal
1 = Pop
2 = Rock
3 = Jazz
4 = Classic
5 = Bass
:param mode: Režim ekvalizéru (hodnota mezi 0 a 5).
:return: Odpověď modulu.
"""
if mode not in [self.EQ_NORMAL, self.EQ_POP, self.EQ_ROCK, self.EQ_JAZZ, self.EQ_CLASSIC, self.EQ_BASS]:
mode = 0
self.send_command(self.CMD_SET_EQUALIZER, [mode])
return self.read_response(1000)
def get_equalizer(self):
"""
Získá aktuální režim ekvalizéru.
Pošle příkaz pro získání aktuálního režimu ekvalizéru a vrátí hodnotu mezi 0 a 5.
:return: Aktuální režim ekvalizéru (0-5) nebo "ERROR", pokud došlo k chybě.
"""
self.send_command(self.CMD_GET_EQUALIZER)
resp = self.read_response(1000)
if resp:
try:
eq_mode = int(resp.decode('ascii'), 16)
if eq_mode in range(6):
return eq_mode
else:
return "ERROR"
except Exception:
return "ERROR"
else:
return "ERROR"
Abychom mohli ukázat použití modulu JQ6500_FK
v praxi, vytvoříme jednoduchý program. Tento program bude komunikovat s modulem JQ65000 pomocí naší knihovny jq6500_FK.py
a různým způsobem přehrávat skladby uložené v modulu.
Předpokládáme, že v modulu JQ6500 jsou nahrány alespoň 4 soubory MP3 a že bude použit standardní pinout pro UART komunikaci.
from jq6500_FK import JQ6500 # Import třídy JQ6500 z knihovny
mp3 = JQ6500(uart_id=2, tx_pin=17, rx_pin=16) # vytvoření instance třídy JQ6500 s nastavenými piny
print('Iniciuji modul JQ6500')
mp3.reset() # reset modulu na výchozí stav
print('Nastavuji vnitrni pamet jako zdroj MP3')
mp3.set_source(JQ6500.SOURCE_INTERNAL_MEMORY) # Nastaví interní paměť jako zdroj
# mp3.set_source(JQ6500.SOURCE_SD_CARD) # Nastaví SD kartu jako zdroj
print('Nastavuji hlasitost')
mp3.set_volume(25) # nastaví hlasitost na úroveň 25 (max 30)
print("Nastavuji ekvalizér na Bass...")
mp3.set_equalizer(JQ6500.EQ_BASS)
# Získání aktuálního režimu ekvalizéru
print("Zjišťuji aktuální režim ekvalizéru...")
current_eq = mp3.get_equalizer()
print(f"Aktuální režim ekvalizéru: {current_eq}")
# Získání stavu přehrávače
status = mp3.get_player_status()
print(f'Aktuální stav přehrávače: {status}')
print('Získávám počet souborů v paměti...')
if file_count is not None:
print(f'Počet souborů na interní paměti: {file_count}')
else:
print('Nepodařilo se získat počet souborů.')
print()
# Smyčka pro přehrání skladeb 1 až 5
for i in range(1, file_count+1):
print(f'Spouštím skladbu {i} ... ', end='')
mp3.play_index(i) # přehraje skladbu s indexem i
delka = mp3.get_length()
print(f'delka je {delka} sec.')
sleep(delka)
print(f'Dokončeno přehrávání {file_count} skladeb.')
sleep(3)
print('\nTed prehraji skladbu č. 3')
mp3.play_index(3)
delka = mp3.get_length()
sleep(delka)
print('\nTed prehraji nasledujici skladbu')
mp3.next_track()
sleep(2.6)
# Zkontroluje aktuální stav přehrávače
status = mp3.get_player_status()
print(f"Aktuální stav přehrávače: {status}")
# Pokusí se zastavit přehrávač, pokud je v režimu přehrávání nebo pauzy
print('Ted jsem to zastavil...')
mp3.pause()
status = mp3.get_player_status()
print(f"Aktuální stav po pokusu o zastavení: {status}")
Co program dělá?
Program nejdříve resetuje modul JQ6500, nastaví zdroj MP3 souborů (flash paměť) a nastaví výchozí hlasitost. Poté program nastaví styl ekvalizéru na hodnotu BASS
a okamžitě se dotáže toto nastavení. Návratová hodnota ukazuje, zda nastavení proběhlo správně (návratová hodnota 5
odpovídá nastavení BASS
).
Dále se vypíše stav přehrávače. Pokud jej pouštíte poprvé, bude STOPPED
, jinak pak již PAUSED
.
Konečně nastává přehrávání. Zjistí se počet skladeb v paměti modulu a následně se všechny popořadě přehrají. U každé skladby se zjistí a vypíše její délka v sekundách. Zároveň program vždy čeká po dobu délky skladby, aby další skladbu nespustil předčasně.
V závěrečné části programu se nejdříve spustí skladba se zadanou absolutní pozicí, pak relativní (přehraj další). Zároveň se vypíše stav přehrávače při přehrávání skladby. Daná skladba je pak okamžitě zastavena a opět je vypásá dotaz na stav přehrávače. Protože byla skladba ukončena příkazem Pauza, je i stav zastaveného přehrávače PAUSED
.
Na následujícím obrázku vidíme výpis výstupu programu při použití pěti zvukových souborů v modulu JQ6500.

Závěr
A je to! Teď už byste měli mít solidní základy pro ovládání modulu JQ6500 pomocí modulu ESP32 v MicroPythonu. Prošli jsme si vše od nastavení UART komunikace, přes vytváření třídy pro JQ6500 až po praktické použití ve svém vlastním kódu.
Pokud jste se při čtení občas zastavili, popřemýšleli a možná i provedli „lehký restart“, nic se neděje? To k tomu prostě patří. Naučili jsme se, jak správně komunikovat s hardwarem a jak napsat knihovnu, která nám pomůže ušetřit čas při budoucích projektech. Ať už budete chtít přehrávat na modulu JQ6500 MP3 soubory, upravovat hlasitost nebo zjišťovat délku skladby, teď máte nástroje k tomu, abyste to zvládli s přehledem.
Ať už se rozhodnete tento základní projekt vylepšit o vlastní funkce, nebo si vytvoříte úplně nový, věřte, že možnosti jsou neomezené. Pokud vás čekají nové výzvy, ať už na poli automatizace, zvukových projektů nebo jiných, nezapomeňte – takto postavený základ je skvělým odrazovým můstkem pro další rozvoj.
Takže hurá do dalších projektů! Ať už se pustíte do přehrávání dalších zvukových souborů, nebo se rozhodnete ovládnout jinou další hardwarové komponenty, teď víte, jak na to. A kdo ví, třeba se pod vašima rukama zrodí projekt, který místo pouhého přehrávání MP3 bude rovnou streamovat audio z oblíbených streamovacích služeb – ale to už je na vás, jak si své bastlířské sny naplníte. 😊
S mikrokotrolérem ESP32 a MicroPythonem máte v rukou velmi silný nástroj, který vás s tím pomůže a podrží vás na každém kroku.