Utilisation du module DY-HV20T avec rp pico en UART

Bonjour,

J'essaye désespérément de faire fonctionner ce petit player MP3 (dy-HV20T)...
Le module fonctionne en mode autonome, mais impossible de communiquer avec lui en UART. Besoin d'aide svp...

Voici le code de test :

from machine import UART, Pin
from time import *

uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart1.init(9600, bits=8, parity=None, stop=1)
busyPin = Pin(3, mode=Pin.IN)

while True:
    
    uart1.write(b'\xAA\x02\x00\xAC')
    uart1.read()

et le lien vers la doc du module qui répertorie les commendes UART : DY-HV20T datasheet

ce code est censé lire les mp3 présents sur la carte sd, mais aucun son ne sort...

quel arduino?

vous lui balancez des ordres à la mitrailleuse lourde là avec votre while True:

Sinon qu'attendez vous de

oui c'est parce que j'ai fait différents tests... ce n'est pas un arduino mais un raspberry pi pico.
Finalement j'ai réussi à faire jouer le player avec ce code (le problème venait en fait d'un faux contact d'un fil dupont au niveau du GND) :

from machine import UART, Pin
from time import *

uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart1.init(bits=8, parity=None, stop=1)
# Play
uart1.write(b'\xaa\x02\x00\xac')
# query play status
uart1.write(b'\xAA\x01\x00\xAB')
# query current song
uart1.write(b'\xAA\x0D\x00\xB7')
uart1.readline()
sleep_ms(10000)
# Stop
uart1.write(b'\xAA\x04\x00\xAE')
# query play status
uart1.write(b'\xAA\x01\x00\xAB')
uart1.readline()

J'ai bien le 1er morceau qui démarre pendant 10 secondes, puis se stoppe, mais je n'ai aucune réponse des code Query play status, et query current song...

Bon ça avance un peu, avec ce code, j'obtiens un retour, mais je ne sais pas comment l'interpréter ?

from machine import UART, Pin
from time import *

uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart1.init(bits=8, parity=None, stop=1)
# Play
uart1.write(b'\xaa\x02\x00\xac')
# query play status
uart1.write(b'\xAA\x01\x00\xAB')
# query current song
uart1.write(b'\xAA\x0D\x00\xB7')
print(uart1.read())
sleep_ms(10000)
# query current song
uart1.write(b'\xAA\x0D\x00\xB7')
#uart1.write(b'\xAA\x01\x00\xAB')
print(uart1.read())
# Stop
uart1.write(b'\xAA\x04\x00\xAE')
# query play status
uart1.write(b'\xAA\x01\x00\xAB')
print(uart1.read())

et j'ai ça comme réponse :

None
b'\xaa\x01\x01\x01\xad\xaa\r\x02\x00\x01\xba'
None

Vous ne pouvez pas balancer une commande et quelques nano secondes plus tard essayer d'interroger le module. Quand vous faite

vous envoyez 4 octets à 9600 bauds, ça va prendre environ 4ms avant que le module n'ait reçu la commande, il lui faut ensuite un peu de temps pour la décoder et faire ce qu'il faut (genre lancer une musique)

essayez un truc du genre

from machine import UART, Pin
from time import sleep_ms

uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart1.init(bits=8, parity=None, stop=1)

# Envoi de la commande "play"
uart1.write(b'\xAA\x02\x00\xAC')

# Attendre pour s'assurer de la réception
sleep_ms(20)

# Interroger l'état de lecture
uart1.write(b'\xAA\x01\x00\xAB')

# Lire et imprimer la réponse en hexadécimal
response = uart1.read()
if response:
    print("Réponse:", ' '.join(f'{byte:02X}' for byte in response))

# Envoi de la commande "stop"
uart1.write(b'\xAA\x04\x00\xAE')

pour voir ce que ça dit

oui effectivement, c'est une question de temps de réponse, mais votre code ne fonctionne pas, car la musique est stoppé trop vite, mais en commentant la commande stop et rajoutant un délai de 20ms entre l'interrogation de l'état de lecture et la lecture de la réponse, j'obtiens : Réponse: AA 01 01 01 AD
Maintenant, j'ai encore du mal à interpréter cette réponse...
D'après la doc, AA c'est le code de démarrage d'une commande, 01 indique que le lecteur joue, le 2eme 01 qu'il lit un fichier depuis la carte sd, le 3eme 01, je ne sais pas trop la signification... et le AD la fin de la commande...
Mon interpretation est correct ?

oui il faut toujours attendre un peu, j'ai tapé ça trop vite

effectivement il faudrait rajouter soit l'attente active sur la pin BUSY soit un délai

--

la doc dit

donc AA pour le marqueur de début de réponse

le deux 01 01 ne sont pas spécifiquement documentés, il se peut que ce soit lié à

On est sûr cependant que le troisième 01 c'est l'état de lecture, donc il est en train de jouer (ce serait 00 en mode stop et 02 en pause)

Ensuite vous avez le checksum (SM) de la commande obtenu en additionnant modulo 8 tous les éléments AA + 01 + 01 + 01 ➜ ce qui donne bien AD

ok merci, et pour ces codes, que veut dire S.N.H et S.N.L ?

le H veut dire HIGH et le L veut dire LOW dans leur doc

image

On fait cela quand quand une donnée tient sur plusieurs octets. Ici SN ça doit être "Song Number" et doit être codée sur 2 octets

Ce que vous dit la spec, c'est que l'octet de poids fort est donné avant l'octet de poids faible dans la réponse.

ok, mais il y a un truc que je ne comprends pas, j'ai envoyé la commande Query number of song, et j'ai obtenu : AA 0C 02 00 0e C6. D'après ce que je comprends 00 0e devrait correspondre au nombre de song présents sur la carte sd, or si je convertis 00 0e en décimal ça me donne 14, mais il n'y a que 7 mp3 présents sur la carte sd

Votre interprétation est correcte et la trame a un checksum correct (AA + 0C + 02 + 00 + 0E = C6)

il y a parfois des fichiers cachés sur les cartes SD, mis par l'OS quand vous avez inséré la carte SD sur votre PC ou Mac (fichiers d'index, poubelle avec les anciens fichiers, etc)

Mettez la carte SD sur votre PC et demandez à voir tous les fichiers (si vous êtes sur UNIX faites un ls -als dans un terminal par exemple

oui effectivement, il y a pas mal de fichiers cachés :

16 drwx------@ 1 jojo  staff         0  2 nov 16:30 .
    0 drwxr-xr-x  6 root  wheel       192  2 nov 16:30 ..
   16 drwx------@ 1 jojo  staff      8192  2 nov 16:30 .Spotlight-V100
   16 drwx------  1 jojo  staff      8192 28 mai 21:34 .Trashes
   16 -rwx------  1 jojo  staff      4096  2 nov 16:30 ._.Spotlight-V100
   16 -rwx------  1 jojo  staff      4096  2 nov 14:26 ._01.mp3
   16 -rwx------  1 jojo  staff      4096  2 nov 14:26 ._02.mp3
   16 -rwx------  1 jojo  staff      4096  2 nov 14:26 ._03.mp3
   16 -rwx------  1 jojo  staff      4096  2 nov 14:26 ._04.mp3
   16 -rwx------  1 jojo  staff      4096  2 nov 15:01 ._05.mp3
   16 -rwx------  1 jojo  staff      4096  2 nov 15:01 ._06.wav
   16 -rwx------  1 jojo  staff      4096  2 nov 14:26 ._07.mp3
   16 drwx------  1 jojo  staff      8192  2 nov 16:30 .fseventsd
12816 -rwx------@ 1 jojo  staff   6560162  2 nov 14:26 01.mp3
20608 -rwx------@ 1 jojo  staff  10545652  2 nov 14:26 02.mp3
20512 -rwx------@ 1 jojo  staff  10500178  2 nov 14:26 03.mp3
18608 -rwx------@ 1 jojo  staff   9520064  2 nov 14:26 04.mp3
  128 -rwx------@ 1 jojo  staff     57933  2 nov 15:01 05.mp3
  608 -rwx------@ 1 jojo  staff    310128  2 nov 15:01 06.wav
30208 -rwx------@ 1 jojo  staff  15460309  2 nov 14:26 07.mp3

je les avais pourtant effacé...

souvent sur les cartes SD la destruction n'est pas immédiate. Sur le Mac vous avez en plus la poubelle, l'index spotlight etc

Si vous êtes à l'aise dans le terminal vous pouvez faire (après un cd au bon endroit sur la carte) un rm ._*.mp3 er rm ._*.wav par exemple et tout de suite après éjecter fermer le terminal et la carte

J'ai bien avancé sur la compréhension du module, j'arrive à lancer pas mal de commande, par contre, je ne comprends pas comment fonctionne la commande specified path :


Par exemple comment faire si je veux que le module joue ce mp3 : "I/05/01.mp3" ?

Je serai tenté de mettre tous les octets du chemin en ASCII dans le path, calculer length en conséquence en tentant compte des autres octets et d’utiliser 0x01 pour le drive (carte SD) et de calculer le checksum associé

c'est ce que j'ai essayé de faire, mais ça ne fonctionne pas.
J'ai fait ce petit code pour transformer le path en ASCII et formatter la commande, mais lorsque j'envoie la commande rien ne se passe...


path = "I/05/01.mp3"
long = len(path)

# Conversion en valeurs ASCII
ascii_values = [ord(char) for char in path]

print(ascii_values)

data_list = [0xAA, 0x08, long, 0x01]
cmd = data_list + ascii_values
print(cmd)

checksum_result = sum(cmd) & 0xFF
cmd.append(checksum_result)
print(cmd)

ça me donne ça comme résultat :

[170, 8, 11, 1, 73, 47, 48, 53, 47, 48, 49, 46, 109, 112, 51, 105]

Je ne donnerai que le nom du répertoire I/05

Ensuite ce sont les fonctions de choix des fichiers pour jouer un élément de ce répertoire

Et pour la longueur de la commande faut rajouter aussi le compte des autres octets en paramètres donc juste +1 pour le drive

non ça ne fonctionne toujours pas

Vous recevez quelque chose en retour ?

Sinon il classe peut être les répertoires en fonction de leur offre de création quel que soit le nom et dans ce cas c’est juste un seul octet