如何基于ESP32和MicroPython構(gòu)建一個RFID控制的MP3播放器
有一段時間了,我有一個圣誕節(jié)抽獎與射頻識別標(biāo)簽為ESP32編程。貢獻用語音輸出的測量結(jié)果回來。我用手機記錄下了這些零碎的語言,并將其傳輸?shù)絊D卡上?,F(xiàn)在你當(dāng)然也可以把音樂保存在SD卡上,并通過射頻識別標(biāo)簽調(diào)用——一個具有擴展?jié)摿Φ腗P3播放器已經(jīng)準(zhǔn)備好了。我嘗試了各種編程方法。最初看起來很有希望和有趣的線程方法,最終不得不放棄,轉(zhuǎn)而支持傳統(tǒng)編程,因為性能不符合我的想法。我現(xiàn)在用這個系列的新文章向你介紹這個解決方案
ESP32和ESP8266上的Micropython
今天:
帶RFID的MP3播放器
嚴(yán)格來說,我是通過關(guān)于ESP32/ESP8266 dem Raspberry Pi Pico和那臺PC上的串行接口的文章產(chǎn)生了這篇文章的想法。我想展示RS232端口上的其他一些應(yīng)用程序。這里使用的DFPlayer Mini是通過串行接口控制的。由于使用了雙向數(shù)據(jù)交換,因此只需一個ESP32或Raspberry Pi Pico作為控制器。PC也可以通過RS232 TTL轉(zhuǎn)換器直接與DFPlayer Mini進行對話,但我將其省略。
兩個迷你斷路器上的組件通過許多跳線電纜查看鳥類游戲。畢竟,使用了四個接口,SPI (RFID讀取器),I2C (OLED顯示器),RS232 (DFPlayer Mini)和ADC (Poti)。
圖1:MP3播放器的結(jié)構(gòu)與SH1106
有幾件事需要考慮。DFPlayer Mini必須提供5V。因此,具有5V電平的脈沖也在他的PIN TX上,因為是忙碌引腳。由于ESP32只能承受3.3V到其gpio,電平必須通過電壓分壓器降低。我選擇了1kΩ和2.2kΩ。您還可以采用其他比例為1:2的值。相反,RX輸入端的DFPlayer可以很好地處理ESP32的3.3V信號。
如果揚聲器用黑線放在GND上,則5V圈的電流約為。450馬!這是因為連接SP1和SP2引線為5V電平。因此,只將兩個揚聲器連接到SP1和SP2,不要連接到GND。即使您只使用一個揚聲器,它的線路也屬于SP1和SP2(圖2中黃色部分)。否則你必須通過ELKO連接揚聲器。
圖2:帶有4gb SD卡的DFPlayer Mini
ESP32上的ADC輸入可以處理高達(dá)2.4V的張力。然而,電位器是3.3V。因此,我通過計算2.2kΩ的電阻來降低失調(diào)電壓。因此,電位器可以放在面包板上,我提供了一個5針筆帶的連接。
圖3:面包板蒙太奇的波蒂與筆條
你必須特別小心上面提到的顯示。SDA和SCK的連接是一致的,但是+VCC和GND的引腳與96“模塊(上面的筆條)在1.3”模塊(下面的筆條)中相互交換。我在圖4的電路中使用了一個1.3“模塊。
圖4:運行中的SH1106
圖5:MP3播放器-電路
為了自主操作,我為16850的鋰離子電池提供了一個電池所有者。它可以通過封閉的電纜直接連接到ESP32,然后接管其他模塊的供應(yīng)。
圖6:電池所有者18650
連接圖可能有助于將電路放在一起。
圖7:連接計劃
一架ESP32接管了主要位置。為了使用它,需要兩個面包板,它們連接到中間的電源導(dǎo)軌上,這樣你就可以用引腳排的間隔到達(dá)那里,也可以在邊緣插入電纜。
ESP32的小兄弟,ESP8266,不適合我們的目的,因為它不能提供第二個,完整的接口,我們需要它來控制DFPlayer。
Uart是通用異步接收器/發(fā)射器的縮寫。我們還從tony的終端與控制器討論了這樣一個接口。ESP32 /ESP8266通過USB線纜與PC相連,主控板上的USB- rs232 - ttl轉(zhuǎn)換器將數(shù)據(jù)流量傳輸?shù)娇刂破鞯腢ART0接口。這反過來又提供給數(shù)據(jù)流sys.stdin。輸入命令從這個文件對象提供。sys。stdout通過UART0將輸出數(shù)據(jù)發(fā)送到tony的終端。因此,我們不能使用UART0向mini-MP3播放器發(fā)送命令并從中接收數(shù)據(jù)。一個UART接口只能有一個對應(yīng)物。ESP8266有第二個UART接口,但實際上只有一半,因為只有一條TXD線(傳輸線),沒有RXD線(接收管理)可用。但也會有一個樹莓派Pico (W),它有兩個免費提供的組件。程序是一樣的,只是pin分配不同。
Micropython -語言-模塊和程序
要安裝托尼,你會在這里找到一個詳細(xì)的說明(英文版)。還有一個關(guān)于ESP芯片上的Micropython固件(截至2024年1月25日)如何被燒毀的描述。
Micropython是一種解釋器語言。Arduino IDE與Arduino IDE的主要區(qū)別在于,你只需要在ESP32上閃爍Micropython固件一次,以便控制器理解Micropython指令。您可以使用Thonny,μpycraft或ESPTOOL.PY。對于安東尼,我在這里描述了這個過程。
一旦固件閃過,你就可以很容易地在對話框中與控制器對話,測試單個命令并立即看到答案,而無需事先編譯和傳輸整個程序。這正是Arduino IDE困擾我的地方。如果您可以檢查語法和硬件的簡單測試,以便在編寫程序之前通過命令行嘗試和改進函數(shù)和整個程序部分,則可以節(jié)省大量時間。出于這個目的,我總是喜歡創(chuàng)建小型測試程序。作為一種宏,它們總結(jié)了重復(fù)出現(xiàn)的命令。然后從這些程序片段開發(fā)整個應(yīng)用程序。
自動啟動
如果程序要通過打開控制器自動啟動,請將程序文本復(fù)制到新創(chuàng)建的空白磁貼中。將此文件保存在工作區(qū)的boot.py下,并將其上傳到ESP芯片。該程序?qū)⒃谙麓螐?fù)位或開機時自動啟動。
測試程序
tony - ide中當(dāng)前編輯器窗口中的程序通過F5按鈕手動啟動。這可以比鼠標(biāo)點擊開始按鈕或通過菜單運行更快地完成。只有程序中使用的模塊必須在ESP32的flash中。
在兩者之間,Arduino id ?
如果您以后將控制器與Arduino IDE一起使用,只需以通常的方式刷新程序。然而,ESP32/ESP8266隨后忘記了它曾經(jīng)說過Micropython。相反,任何包含Arduino IDE或AT-Firmware或Lua或…可以很容易地提供micropython固件。這個過程總是像這里描述的那樣。
這個項目
概述
播放列表的選擇是在這個項目中通過RFID進行的,播放列表的選擇是在這個項目中通過數(shù)據(jù)進行的。在這個項目中,通過讀取地圖上的ID來選擇播放列表。然而,這顯然超出了本文的范圍,可能是另一個博客系列的主題。根據(jù)ID(8位十六進制數(shù)字),ESP32可以指示DFPlayer Mini播放SD卡文件夾中的MP3文件。訂單名稱和編號與標(biāo)題編號一起顯示在顯示器上。用戶說明也顯示在顯示屏中。
RFID閱讀器
由于SPI總線,布線也比I2C總線更復(fù)雜,只有2條線。SPI總線設(shè)備沒有硬件設(shè)備地址,但是它們有一個芯片選擇連接(CS),如果要對設(shè)備進行尋址,它必須處于低電平。數(shù)據(jù)傳輸?shù)墓ぷ鞣绞揭灿幸稽c不同,它總是同時發(fā)送和接收。這里沒有必要說明更接近的過程,因為類Mfrc522為我們做了這些。我們只會通知建造商后續(xù)任務(wù)和傳輸速度。傳輸工作與3.2兆赫的艦隊。相比之下,I2C工作頻率高達(dá)400kHz。
我們自己的函數(shù)readuid()讀取卡片的清晰標(biāo)識,并將其作為十進制數(shù)和十六進制撥號返回。這些卡片是通過OLED顯示器請求的。因此,該函數(shù)不會阻塞整個進程,超時確保有序退出。在這種情況下,返回值為None,而不是卡ID。
為了讓播放列表卡發(fā)揮作用,我們需要一張主卡。為此,我們從堆棧中取出任何卡片或芯片,讀取ID,從而在程序開始時用十進制值證明變量,如下所示:
Masteride = 4217116188。
在第一次啟動時,ESP32注意到仍然沒有包含播放列表卡數(shù)據(jù)的文件,需要主卡。識別后,將請求播放列表卡。讀取ID后,將其寫入文件,并再次請求主卡。繼續(xù)閱讀直到最后一張播放列表卡。如果在請求主卡后10秒內(nèi)沒有提供播放列表卡,則檢測過程結(jié)束并開始主程序。為了完全從前面開始,我們可以通過thony - console刪除播放列表卡id。當(dāng)然,也可以在tony編輯器窗口中編輯該文件。
Dfplayer迷你
與前鋒的溝通總是以同樣的方式進行。發(fā)送和接收10字節(jié)的塊。這種積木的結(jié)構(gòu)是這樣的。類Dfplayer的方法broadcommand()負(fù)責(zé)正確的傳輸。
開始-字節(jié)0x7e
版本號0xff
有效負(fù)載長度0x06(從版本號到參數(shù)2包括1)
命令
反饋0x00(否)或0x01(是)
參數(shù)高
參數(shù)低
檢查高
檢查低
EndeByte 0 xef
命令代碼可以在數(shù)據(jù)表中找到。我用它來實現(xiàn)模塊dplayer .py方法中最重要的代碼。我們目前的項目只需要其中的幾個。但是看看文件pfplayer.py(2024年1月24日的Rev 1.3)
聲音文件的處理是用免費工具Audacity,也很容易將聲音文件格式重新編碼為MP3。更大的努力意味著改變文件名,使其符合DFPlayer Mini的要求。這些文件位于以兩位數(shù)字命名的文件夾中。這些是播放列表。
圖8:SD卡的文件夾視圖
文件名可以保留其舊名稱,但必須提供一個由三位十進制數(shù)組成的前綴。
圖9:帶有前綴的文件名
手動重命名可能仍然可以處理幾個文件,如果超過十個,就會變得非常煩人。這就是為什么我使用了另一個免費工具Advanced Renamer。安裝文件邀請您從芯片服務(wù)器下來。
圖10:下載高級重命名器
安裝時,只需跟隨助手即可。收集為SD卡上的文件夾選擇的文件的最佳方法是在工作目錄或SD卡上。標(biāo)記文件夾中的所有文件,并將包拉到重命名窗口。作為Batch方法,選擇Add,然后將其放入過濾器窗口1:添加屬性,如圖11所示。
圖11:高級重命名器中的過濾器設(shè)置
此窗口中的每個更改都會立即對預(yù)覽產(chǎn)生影響。要接管,請單擊右上方的“批量啟動”。就是這樣。
圖12:源名稱和結(jié)果
MP3播放器
在所有的準(zhǔn)備工作之后,是時候?qū)椖窟M行編碼了。我們開始吧。一如既往,節(jié)目從進口業(yè)務(wù)開始。如果您在編輯器窗口中打開mp3player.py將是最好的,然后您可以在那里閱讀概述,同時我們將介紹這里的工作方式。
# mp3player.py
#適用于RC522 @ 13,56 mhz
從dfplayer導(dǎo)入dfplayer
進口mfrc522
引腳,SoftI2C, SPI, ADC,復(fù)位
#從oled導(dǎo)入oled # vorssight: GND Vcc SCK SDA
從oled_SH1106導(dǎo)入OLED # vorssight: Vdd GND SCK SDA
從時間導(dǎo)入睡眠
從sys導(dǎo)入退出
從超時導(dǎo)入*
我們從DFPlayer .py中導(dǎo)入DFPlayer類,而從mfrc522.py中導(dǎo)入所有內(nèi)容。這兩個文件必須被放入ESP32的閃存中。兩個標(biāo)記都在電影管理器中,右鍵單擊,上傳到/。
模塊機提供接口操作的類。根據(jù)所使用的顯示模塊,必須激活或注釋以下兩行中的一行。
對于短暫的被動休息,我們從時間模塊獲得睡眠()。我們使用exit() out of sys函數(shù)確保一個干凈的程序退出。從模塊超時,我們得到所有(*)在我們的范圍,這是需要的非阻塞軟件定時器。當(dāng)從該模塊調(diào)用方法時,該船尾并不適用于該模塊。
沒有星號的,例如:
超時。timeoutms (1000)
與明星:
Timeoutms (1000)
接下來,在相應(yīng)的包中實例化對象。我們從ADC對象開始,我們需要從電位器讀取張力。我們將控制DFPlayer Mini的音量。
卷= ADC(銷(36)
vol.atten (vol.ATTN_11DB)
vol.width (vol.WIDTH_10BIT)
強力器的研磨觸點連接GPIO36。如果弱變?yōu)?1 dB,則達(dá)到高達(dá)2.4V的掃描。我們將分辨率設(shè)置為10位。
RX_Pin = 16
TX_Pin = 17
busyPin = 27
df = DFPlayer (busyPinNbr = busyPin,
txd = TX_Pin,
rxd = RX_Pin,
體積= 15)
Sleep(2) #等待玩家初始化
numOfTitles = df.getNumberOfFiles ()
print(" title gesamt:", numOfTitles)
DFPlayer類設(shè)置ESP32本身的UART1。構(gòu)造器只需要將busy-Pin、RX-Pin和tx-Pin上的gpio編號連接即可。缺省情況下,Pin已連接。通過詢問SD卡上的文件總數(shù)。
spi = spi(2,波特率= 3200000)
# cs = sda
RDR = mfrc522。MFRC522(spi, cs=5,波特率=3200000)
Spi2硬件接口占用GPIOS 18 (SCK), 23 (Mosi)和19 (Miso),還有5 (CS)。RFID板上的選片連接以SDA命名。我們將波特率定義為3200000Hz。
i2c = SoftI2C (sci =銷(22),sda =銷(21))
d = OLED (i2c)
對于顯示,我們實例化一個I2C對象,并在此過程中給出OLED對象的構(gòu)造函數(shù)。
主卡是向系統(tǒng)宣布播放列表標(biāo)簽的RFID日。我們在程序完成后立即確定數(shù)值,然后在此時輸入它。
MasterID=4217116188 # 0XFB5C161C
列表列表包含播放列表的名稱。
listen=[
"COUNTRY",
"BLACKMOORSNIGHT",
"YOUTUBE",
"SCHLAGER",
"HITS",
"VON CD"
"OLDIES"
]
下面是一些函數(shù)的聲明。Readuid()讀取標(biāo)簽的標(biāo)識號。我們交出OLED顯示對象,一個用于卡片類型的字符串和一段以毫秒為單位的時間,在此結(jié)束后,該功能將在任何情況下離開。變量song是全局聲明的,這樣在函數(shù)中分配的值在主程序中可用。我不會在Display和ReplaB中討論所有版本,它們部分用于告知用戶和開發(fā)過程中的故障排除,并通過自制文本進行解釋。
非阻塞軟件計時器的獲取是通過Timeoutms()方法設(shè)置的。在Timeoutms()中,函數(shù)是隱藏的compare(),一個所謂的Closure.Timeoutms()返回一個引用compare(),我們將標(biāo)識符分配給它。與sleep()不同的是,其他指令可以在計時器期間執(zhí)行。因此,While循環(huán)一直運行到函數(shù)reap(), alias compare(), True返回為止。這個過程的背景可以在裝飾器上的閉包文檔中找到。
ef readUID(display, kartentyp, timeout):
global song
display.clearFT(0, 1, 15, 2, False)
display.writeAt("PUT ON", 0, 1, False)
display.writeAt(kartentyp, 0, 2)
readTimeOut=TimeOutMs(timeout)
while not readTimeOut():
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
display.clearFT(0, 3, 15, 3)
display.writeAt("Card OK", 0, 3)
userID=0
for I in range(4):
userID=(userID<<8) | raw_uid[i]
userIDS="{:#X}".format(userID)
display.writeAt(userIDS+" ", 0, 4)
sleep(2)
df.reset()
song=0
return userID, userIDS
return None
使用RDR.MEQUEST(),讓我們放入一個輸入進程。如果請求成功,我們將在下一步中獲取ID。如果這一步也成功了,讓我們開始評估。從MFRC522中,我們得到一個字節(jié)- plet,我們分四個步驟將其轉(zhuǎn)換為32位數(shù)字。useride中前面的結(jié)果被推到左邊,8被推到左邊,插曲被裝飾。然后我們將整個結(jié)果轉(zhuǎn)換為十六進制字符串,通常是8位數(shù)字。
有兩秒鐘的時間讀取顯示,然后我們將DFPlayer Mini放回去,并將歌曲計數(shù)器設(shè)置為0,因為還應(yīng)該通過讀取ID啟動一個新的播放列表。如果讀取嘗試失敗或時間剛剛過期,則返回None,而不是數(shù)字和字符串形式的ID。
如果您已經(jīng)進入程序,此時,您已經(jīng)可以開始讀取主卡的ID。或者,您可以mp3player.py Download并在第73行輸入以下說明。然后保存并在編輯器窗口中啟動程序。
退出()
根據(jù)已釋放的Repl-Prompt,輸入如下說明?,F(xiàn)在把你的萬事達(dá)卡交給讀者。上述輸出數(shù)值為Masteride a。
Readuid (D,“Test”,6000)
0 xfb5c161c
(4217116188, ' 0 xfb5c161c ')
這個主卡使用下一個函數(shù)addid(),該函數(shù)負(fù)責(zé)注冊播放列表卡。如果ESP32的文件系統(tǒng)中還沒有名為slavecards.txt的文件,主程序?qū)⒃诘谝淮螁訒r調(diào)用它。但是也可以手工調(diào)用addid()來創(chuàng)建文件和/或注冊其他播放列表標(biāo)簽。
首先我們要主卡并讀取ID。如果操作成功,則M從十進制值和十六進制字符串中接收Tupel,否則為None。我們通過解壓到主ID上的數(shù)字、字符串和偏移量來粉碎這個圖。當(dāng)閱讀指令完成后,還有三秒鐘的時間放入新的播放列表卡。
def addUID(display):
display.clearAll()
m=readUID(display, "Master", 3000)
print("Master", m)
if m is not None:
mid, mids= m
if mid==MasterID:
print("Master OK")
u=readUID(display, "Slavecard", 3000)
if u is not None:
uid, uids=u
if uid is not None and uid != MasterID:
with open("slavecards.txt", "a") as f:
f.write("{}\n".format(uids))
display.writeAt("New slave written", 0, 4)
display.writeAt("{}".format(uids), 0, 5)
sleep(5)
return True
Else:
display.writeAt("ERROR!!!", 0, 3)
display.writeAt("Card not added!", 0, 4)
return False
Else:
display.writeAt("ERROR!!!", 0, 3)
display.writeAt("Not mastercard", 0, 4)
sleep(3)
return False
和之前一樣,MSo現(xiàn)在包含U,讀取過程成功時的ID值。如果uid不是None并且該卡不是master卡,則該卡被注冊。使用wither-A文件對象創(chuàng)建,并在標(biāo)識符F下打開附加文本行。我們還寫入讀入的十六進制字符串,并附帶行結(jié)束符號“\ n”= 0x0a。通過離開萎凋塊,文件將自動關(guān)閉。所以我們不需要考慮這個必要的措施。顯示消息的讀取時間為5秒后,該函數(shù)返回True。必須處理兩個可能的錯誤,RC522的讀取錯誤和不正確的主卡。
在程序開始時將讀取標(biāo)簽()調(diào)用并在ESP32文件系統(tǒng)根目錄下的一個文件slavecards.txt之后。當(dāng)天的空列表應(yīng)該記錄卡片的十六進制字符串。凋零指令不能打開文件,因為它還不可用,當(dāng)天仍然為空,并且IF構(gòu)造的Else部分返回None。如果文件存在,則將line By line讀入,刪除行結(jié)束符號并將字符串附加到列表中,直到循環(huán)檢測到文件的結(jié)束。在這種情況下,列表不是空的,而是返回的。
def readTags():
tags=[]
with open("slavecards.txt", "r") as f:
for line in f:
tags.append(line.strip("\n"))
if tags:
return tags
Else:
return None
SD卡上的每個文件夾可以包含不同數(shù)量的音樂標(biāo)題。我們必須知道在一次循環(huán)中完成的數(shù)字,這樣才能進行循環(huán)。Get()確定所有文件夾中的標(biāo)題數(shù)量,并將其放入列表文件帳戶中。我們從空列表開始,讓我們自己小聲說文件夾的數(shù)量。為了解決每個文件夾,我們在它的for循環(huán)中簡單地提到了第一個標(biāo)題,這樣你就不會被破裂和其他噪音所激怒,我們事先把音量調(diào)到0。
def getNumberOfTitels():
fileCount=[]
nof=df.getNumberOfFolders()
df.volume(0)
sleep(0.2)
for t in range(nof):
df.play(t, 0)
sleep(0.2)
df.stop()
sleep(0.2)
n=df.getNumberOfFilesInFolder()
d.writeAt("Track:{}".format(t), 0, 4, False)
d.writeAt("Songs:{}".format(n), 0, 5)
fileCount.append(n)
df.reset()
volume=int(vol.read()*100/1024)
df.volume(volume)
sleep(0.2)
return fileCount
在for循環(huán)中,我們將標(biāo)題的數(shù)量掛在后面的列表上。重置DFPlayer后,我們將音量恢復(fù)到電位器指定的值。返回標(biāo)題號列表。
作為最后一個函數(shù),我們聲明player()。在播放循環(huán)的運行期間,會不斷讀取播放列表卡。一張新卡從剛剛播放的播放列表中退出。在本例中,變量acard將空字符串返回給主程序。所以這在函數(shù)中是可能的,我們?nèi)致暶髯兞?。為了讓玩家正確開始,我們停止了它。然后進入for循環(huán)。玩家在這里表現(xiàn)得很固執(zhí),跳過了第一個標(biāo)題,所以我讓循環(huán)的運行索引S Start為-1。is playing()現(xiàn)在應(yīng)該立即返回我們檢查的內(nèi)容,然后文件夾T中的標(biāo)題S讓播放。
def player(d, t, nof):
global acard
df.stop()
for s in range(-1, nof):
if not df.isPlaying():
df.play(t, s)
d.clearFT(0, 5, 15, 5, False)
d.writeAt("Titel: {}".format(s), 0, 5)
while df.isPlaying():
volume=int(vol.read()*100/1024)
df.volume(volume)
u=readUID(d, "TAG TO STOP", 100)
if u is not None:
d.clearFT(0, 3, 15)
D.Cleart (0, 3, 15)
df.stop()
acard=""
return
d.clearFT(0, 3, 15)
df.stop()
在比賽進行期間,還有很多事情要做。必須查詢電位器,并將值傳遞給DFPlayer。然后我們向RC522發(fā)出讀取命令并發(fā)出可能被拆除的信息。在100毫秒= 0.1秒后出現(xiàn)無返回,進入下一輪While循環(huán)。但是如果注冊了一張新卡,我們停止DFPlayer并準(zhǔn)備使用card = “”播放一個新的播放列表。如果播放列表已經(jīng)完全播放,我們刪除顯示的下部,并給DFPlayer另一個停止命令。有時這讓各種命令都感到厭惡。這導(dǎo)致在開發(fā)程序時出現(xiàn)各種令人失望的時刻,這總是使得有必要打開新的解決方案。
有些變量必須為主程序初始化。
cards=[] # Liste der Karten-IDs leeren
acard="" # aktuelle Karten-ID
ncard="" # neue Karten-ID
song=0 # Stets mit Song 0 starten
第一個操作現(xiàn)在是讀取卡片id,如果文件slavecards.txt給出。當(dāng)程序第一次啟動時,這里沒有任何標(biāo)志。因此,我們使用try和except away來保護來自reap()的調(diào)用。我們在Except塊中創(chuàng)建文件。因此,我們通過Timeoutms()方法從接口中調(diào)用了一個非阻塞的軟件定時器allread()。當(dāng)計時器運行時,我們調(diào)用循環(huán)adduid() on。我們已經(jīng)討論過處理這個函數(shù)的方法。當(dāng)例程True返回時,一個卡被注冊,計時器被重新啟動。如果沒有更多的卡片,我們只需等待計時器并在第二次嘗試中將IDS放入列表中。
試一試:
cards=readTags()
except OSError as e:
allRead=TimeOutMs(10000)
while not allRead():
if addUID(d):
allRead=TimeOutMs(10000)
d.clearFT(0, 3, 15, 4, False)
d.writeAt(" ALL CARDS READ", 0, 3)
cards=readTags()
If the list is not empty, it goes into the main loop that is constantly going through, even while a title is played.
IF Cards:
d.writeAt("***MP3-PLAYER***", 0, 0, False)
d.writeAt("PUT ON MP3-TAG", 0, 1, False)
d.writeAt("Hole die Anzahl", 0, 2, False)
d.writeAt("Songs/Folder", 0, 3)
filesInFolder=getNumberOfTitels()
d.clearFT(0, 2, 15)
df.stop()
while 1:
uid=readUID(d, "PLAYLIST-TAG", 1000)
if uid is not None:
ncard=uid[1]
volume=int(vol.read()*100/1024)
df.volume(volume)
我們試著讀卡片。如果工作,我們顯示十六進制字符串的變量Ncard到,并詢問電位器下一步。
當(dāng)card的內(nèi)容與Ncard的內(nèi)容不匹配時,開始播放新播放列表。在這種情況下,將卡片已經(jīng)更新。
if acard != ncard:
acard=ncard
然后我們檢查列表卡中的ID是否包含在內(nèi)。如果是,我們確定條目的索引,并找到SD卡上的文件夾編號。我們將組織移交給播放列表player()。她獲得了對OLED對象的引用,文件夾編號和路上的標(biāo)題數(shù)量。
如果卡在卡中:
d.clearFT(0, 2, 15, 5, False)
t=cards.index(acard) # Ordnernummer
d.writeAt("PLAYLIST {}".format(t), 0, 3, False)
d.writeAt(listen[t], 0, 4)
player(d, t, filesInFolder[t])
卡片ID不在cards Found中,在進入主循環(huán)的下一輪之前,我們得到一個錯誤消息。
對于自主公司,不連接PC機,必須將名稱為main.py的程序上傳到ESP32的flash中。該過程如上所述?;蛘?,你也可以在“文件-菜單”中選擇“另存為”。然后選擇目標(biāo)Micropython設(shè)備。如果你現(xiàn)在感染了電池板上的ESP32,該程序在沒有PC的情況下啟動。
會議快結(jié)束了。玩家的裝備還有其他選擇。如果你想要聲音更大,在DFPlayer Mini的立體聲輸出上放一個放大器。只需幾個按鈕,你就可以在標(biāo)題中滾動,通過無線局域網(wǎng)連接,你可以用一個Android應(yīng)用程序完全控制它,這個應(yīng)用程序很容易使用麻省理工學(xué)院的應(yīng)用程序- inventor 2就可以創(chuàng)建。
本文編譯自hackster.io





