├── LICENSE ├── README.md ├── package.json ├── pyproject.toml ├── sample_files ├── 01 │ ├── 001.mp3 │ ├── 002.mp3 │ └── 003.mp3 ├── 02 │ ├── 001.mp3 │ ├── 002.mp3 │ └── 003.mp3 └── 03 │ ├── 001.mp3 │ ├── 002.mp3 │ └── 003.mp3 ├── src └── dfplayer │ ├── __init__.py │ └── __main__.py └── tests └── empty_file /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 redoxcode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![pypi version shield](https://img.shields.io/pypi/v/micropython-dfplayer)](https://pypi.org/project/micropython-dfplayer/) [![pypi downloads per month shield](https://img.shields.io/pypi/dm/micropython-dfplayer?color=brightgreen)](https://pypi.org/project/micropython-dfplayer/) 2 | ## Description 3 | A micropython library to control the [DFPlayer mini](https://www.dfrobot.com/product-1121.html) mp3 player module. 4 | 5 | This library focuses on the most essential functions. Some advanced functions of the DFPlayer, like the equalizer modes are not implemented yet. 6 | 7 | Further this library is made to use the folders function of the dfmini. You can use up to 99 folders and 255 files per folder. 8 | The files on your micro sd card need to be structured like this: 9 | 10 | . 11 | ├── 01 12 | │   ├── 001.mp3 13 | │   ├── 002.mp3 14 | │   └── ... 15 | ├── 02 16 | │   ├── 001.mp3 17 | │   ├── 002.mp3 18 | │   └── ... 19 | ├── 03 20 | │   ├── 001.mp3 21 | │   ├── 002.mp3 22 | │   └── ... 23 | └── ... 24 | 25 | There should be no gaps in the numbering scheme. 26 | It might be best to prepare the whole file structure on your harddrive first and then copy them in one go on a freshly formated micro sd card, as the DFPlayer might get confused from artifacts left on the sd cards filesystem. 27 | You can use the files in [/sample_files](https://github.com/redoxcode/micropython-dfplayer/tree/main/sample_files) to test your module. 28 | 29 | Sometimes the module isn't able to keep up if you try to send commands to fast, so some delay between the commands is needed. 30 | 31 | ## Connection 32 | - Connect GND of the DFPlayer to the GND of your microcontroller (and your power source) 33 | - Connect VCC of the DFPlayer to 3.3V / 5V 34 | - Connect the RX pin of the DFPlayer to the TX pin of your microcontroller. This is used to send data to the DFPlayer mini. 35 | - Connect the TX pin of the DFPlayer to the RX pin of your microcontroller. This is optional and only needed if you want to return data from the DFPlayer (as in ```get_files_in_folder()```, ```get_volume()``` or ```ìs_playing()```) 36 | 37 | ![DFPlayer mini pinout](https://dfimg.dfrobot.com/nobody/wiki/77048a25b85b6e29438244020e7237e1.png) 38 | 39 | ## Examples 40 | 41 | ### Play a file from a folder 42 | ```Python 43 | import time 44 | from dfplayer import DFPlayer 45 | df=DFPlayer(uart_id=1,tx_pin_id=4,rx_pin_id=5) 46 | #wait some time till the DFPlayer is ready 47 | time.sleep(0.2) 48 | #change the volume (0-30). The DFPlayer doesn't remember these settings 49 | df.volume(25) 50 | time.sleep(0.2) 51 | #play file ./01/001.mp3 52 | df.play(1,1) 53 | ``` 54 | ### Find the number of files in a folder 55 | If a folder doesn't exist, get_files_in_folder will return 0 56 | ```Python 57 | import time 58 | from dfplayer import DFPlayer 59 | df=DFPlayer(uart_id=1,tx_pin_id=4,rx_pin_id=5) 60 | #wait some time till the DFPlayer is ready 61 | time.sleep(0.2) 62 | print(df.get_files_in_folder(1)) 63 | time.sleep(0.2) 64 | print(df.get_files_in_folder(4)) 65 | ``` 66 | 67 | ## API 68 | ### class DFPlayer(uart_id,tx_pin_id=None,rx_pin_id=None) 69 | - uart_id: Uart channel you want to use (0 or 1 for pi pico) 70 | - tx_pin_id: Pin id for uart tx if your board supports changing the pins of the uart channel. 71 | - tx_pin_id: Pin id for uart rx if your board supports changing the pins of the uart channel. 72 | 73 | ```play(folder,file)``` 74 | - play a file from a folder (stops all previous playback) 75 | - folder: Folder number of the file you want to play 76 | - file: File number of the file you want to play 77 | 78 | ```stop()``` 79 | - stop all playback 80 | 81 | ```volume(vol)``` 82 | - set the volume of the module. 83 | - vol: Volume of the module. The range is 0 to 30. The DFPlayer doesn't remember these settings 84 | 85 | ```volume_up()``` 86 | - increase the volume by 1 up to the maximum of 30. 87 | 88 | ```volume_down()``` 89 | - decrease the volume by 1 down to the minimum of 1. 90 | 91 | ```get_volume()``` 92 | - returns the current volume setting of the module or -1 on communication error 93 | 94 | ```ìs_playing()``` 95 | - returns if currently some playback is running or -1 on communication error 96 | 97 | ```get_files_in_folder(folder)``` 98 | - returns the number of files in a folder or 0 if the folder doesn't exist or -1 on communication error 99 | - folder: folder to get the number of files in 100 | 101 | ```reset()``` 102 | - reset the module 103 | 104 | ```send_cmd(cmd,param1=0,param2=0)``` 105 | - sends a command byte with 2 bytes for parameters to the module. This can be used to send commands not yet implemented in this library. Use the modules [documentation](https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299) as reference. 106 | - cmd: cammand byte (0-255) 107 | - param1: parameter 1 or MSB of a 2 byte parameter 108 | - param2: parameter 2 or LSB of a 2 byte parameter 109 | 110 | ```send_query(cmd,param1=0,param2=0)``` 111 | - like send_cmd, but returns the bytes the module sends as answer to the query 112 | - cmd: cammand byte (0-255) 113 | - param1: parameter 1 or MSB of a 2 byte parameter 114 | - param2: parameter 2 or LSB of a 2 byte parameter 115 | 116 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "urls": [ 3 | ["dfplayer/__init__.py", "github:redoxcode/micropython-dfplayer/src/dfplayer/__init__.py"], 4 | ["dfplayer/__main__.py", "github:redoxcode/micropython-dfplayer/src/dfplayer/__main__.py"] 5 | ], 6 | "deps": [ 7 | ], 8 | "version": "1.0.5" 9 | } 10 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # pyproject.toml 2 | 3 | [build-system] 4 | requires = ["setuptools>=61.0.0", "wheel"] 5 | build-backend = "setuptools.build_meta" 6 | 7 | [project] 8 | name = "micropython-dfplayer" 9 | version = "1.0.5" 10 | description = "Library to use the DFPlayer mini mp3 player module with micropython" 11 | readme = "README.md" 12 | authors = [{ name = "redoxcode", email = "redoxcode@github.com" }] 13 | license = { file = "LICENSE" } 14 | classifiers = [ 15 | "License :: OSI Approved :: MIT License", 16 | "Programming Language :: Python :: Implementation :: MicroPython" 17 | ] 18 | keywords = ["dfmini","dfplayer", "mp3"] 19 | dependencies = [] 20 | 21 | [project.optional-dependencies] 22 | dev = [] 23 | 24 | [project.urls] 25 | Homepage = "https://github.com/redoxcode/micropython-dfplayer" 26 | 27 | 28 | -------------------------------------------------------------------------------- /sample_files/01/001.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/01/001.mp3 -------------------------------------------------------------------------------- /sample_files/01/002.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/01/002.mp3 -------------------------------------------------------------------------------- /sample_files/01/003.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/01/003.mp3 -------------------------------------------------------------------------------- /sample_files/02/001.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/02/001.mp3 -------------------------------------------------------------------------------- /sample_files/02/002.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/02/002.mp3 -------------------------------------------------------------------------------- /sample_files/02/003.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/02/003.mp3 -------------------------------------------------------------------------------- /sample_files/03/001.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/03/001.mp3 -------------------------------------------------------------------------------- /sample_files/03/002.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/03/002.mp3 -------------------------------------------------------------------------------- /sample_files/03/003.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/sample_files/03/003.mp3 -------------------------------------------------------------------------------- /src/dfplayer/__init__.py: -------------------------------------------------------------------------------- 1 | import machine 2 | import time 3 | 4 | class DFPlayer: 5 | def __init__(self,uart_id,tx_pin_id=None,rx_pin_id=None): 6 | self.uart_id=uart_id 7 | #init with given baudrate 8 | self.uart = machine.UART(uart_id, 9600) 9 | 10 | #not all boards can set the pins for the uart channel 11 | if tx_pin_id or rx_pin_id: 12 | self.uart.init(9600, bits=8, parity=None, stop=1, tx=tx_pin_id, rx=rx_pin_id) 13 | else: 14 | self.uart.init(9600, bits=8, parity=None, stop=1) 15 | 16 | def flush(self): 17 | self.uart.flush() 18 | if self.uart.any(): 19 | self.uart.read() 20 | 21 | def send_query(self,cmd,param1=0,param2=0): 22 | retry=True 23 | while (retry): 24 | self.flush() 25 | self.send_cmd(cmd,param1,param2) 26 | time.sleep(0.05) 27 | in_bytes = self.uart.read() 28 | if not in_bytes: #timeout 29 | return -1 30 | if len(in_bytes)==10 and in_bytes[1]==255 and in_bytes[9]==239: 31 | retry=False 32 | return in_bytes 33 | 34 | def send_cmd(self,cmd,param1=0,param2=0): 35 | out_bytes = bytearray(10) 36 | out_bytes[0]=126 37 | out_bytes[1]=255 38 | out_bytes[2]=6 39 | out_bytes[3]=cmd 40 | out_bytes[4]=0 41 | out_bytes[5]=param1 42 | out_bytes[6]=param2 43 | out_bytes[9]=239 44 | checksum = 0 45 | for i in range(1,7): 46 | checksum=checksum+out_bytes[i] 47 | out_bytes[7]=(checksum>>7)-1 48 | out_bytes[7]=~out_bytes[7] 49 | out_bytes[8]=checksum-1 50 | out_bytes[8]=~out_bytes[8] 51 | self.uart.write(out_bytes) 52 | 53 | def stop(self): 54 | self.send_cmd(22,0,0) 55 | 56 | def play(self,folder,file): 57 | self.stop() 58 | time.sleep(0.05) 59 | self.send_cmd(15,folder,file) 60 | 61 | def volume(self,vol): 62 | self.send_cmd(6,0,vol) 63 | 64 | def volume_up(self): 65 | self.send_cmd(4,0,0) 66 | 67 | def volume_down(self): 68 | self.send_cmd(5,0,0) 69 | 70 | def reset(self): 71 | self.send_cmd(12,0,1) 72 | 73 | def is_playing(self): 74 | in_bytes = self.send_query(66) 75 | if in_bytes==-1 or in_bytes[5]!=2: 76 | return -1 77 | return in_bytes[6] 78 | 79 | def get_volume(self): 80 | in_bytes = self.send_query(67) 81 | if in_bytes==-1 or in_bytes[3]!=67: 82 | return -1 83 | return in_bytes[6] 84 | 85 | def get_files_in_folder(self,folder): 86 | in_bytes = self.send_query(78,0,folder) 87 | if in_bytes==-1: 88 | return -1 89 | if in_bytes[3]!=78: 90 | return 0 91 | return in_bytes[6] 92 | 93 | -------------------------------------------------------------------------------- /src/dfplayer/__main__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/src/dfplayer/__main__.py -------------------------------------------------------------------------------- /tests/empty_file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redoxcode/micropython-dfplayer/19dd9b246b3496fba16fa8129d014fd9743c0c50/tests/empty_file --------------------------------------------------------------------------------