Anthias
mail
3 connectés     # # #

nextion

Petit haut-parleur + clavier
pour Arduino
avec un seul fil

bz


Les perles du Net
Quel buzzer choisir ?
Premier survol du schéma
Détails sur l’écriture
Détails sur la lecture
Autres approches en digital
La solution magique ATTiny
Les vraies notes de musique
La bibliothèque d’utilitaires « sons »
Synthétiseur tout fait
Amplification vers le haut-parleur
Conclusion
Annexe : Contenu du Pack_Sons

Maj : 23/08/19

Abstract :
It is simple to create sounds with an Arduino, but there is a variety of solutions from worse to the best. We need to experiment a simple, but efficient solution, and understand what we do.
On bonus, this system offer freely how to read a lot of push buttons, with this alone wire.

Résumé :
Il est simple de créer des sons avec un Arduino, mais il existe une variété de solutions de la pire à la meilleure. Nous devons expérimenter une solution simple mais efficace, en comprenant ce que nous faisons.
En bonus, ce système offre librement la possibilité de lire un grand nombre de boutons poussoirs, avec ce seul fil.

nextion  Les perles du Net

Dans ce texte, par facilité, je parlerai de « buzzer » mais le terme exact serait « petit haut-parleur », car au sens strict, un buzzer vibre à fréquence fixe quand il est alimenté en continu, alors que dans notre application nous fournirons un signal carré variable pour tenter de produire des sons variés bien que peu mélodieux.
Vous trouverez sur le Net pléthore de montages du buzzer (lire : petit haut-parleur), chacun ayant recopié sans le comprendre un montage trouvé n’importe où.
Les plus simplistes attaquent directement le buzzer sur un GPIO ce qui écroule complètement la sortie, d’autres rajoutent une résistance en protection, certains une diode de roue libre, d’autres un transistor…
Nous allons voir qu’un montage propre est un peu plus compliqué mais donne de meilleurs résultats.


De plus, avec un seul fil commun, il permet aussi de gérer 3 à 9 boutons poussoirs, ce qui économise les rares GPIOs disponibles sur une carte à ESP32.

 Haut de page

nextion Quel buzzer choisir ?

bz

La loterie !

pz

Disques acceptables

php

Dans tous les cas un vrai petit haut-parleur
sera bien meilleur que les petits gadgets !

Traditionnellement, nous utiliserons les modèles chinois à bas prix, rond de 14 mm de diamètre sur 8 mm de haut. Il sont constitués de disques piezzoélectriques avec une résistance parallèle interne de moins de 15 Ohms.

Mais la sélection est très difficile sur les sites chinois, les descriptions sont totalement farfelues !
La description « mini haut-parleur » « buzzer actif », « buzzer passif », peut s’appliquer au même composant qu’il est souvent impossible d’identifier. En tout cas si vous voyez une fréquence de résonnance indiquée, par exemple 2400*/- 200 Hertz, ou s’il est indiqué une tension continue, ce n’est pas le bon…
Dans un boitier identique les vrais buzzers et les pseudos haut-parleurs existent pour quelques Euros la dizaine.  Quand vous recevrez la petite enveloppe chinoise, vous aurez la surprise de la découverte.
Vous trouverez chez les chinois (4€ les 10) les TDK PS1240P02CT3 (voir le datasheet), qu’il faudra associer à la diode de roue libre ou resistance.
Evidement le son sera médiocre avec ce module qui accroche vers les aigus, le son serait bien plus agréable avec un vrai petit haut-parleur, mais sur une carte la place est comptée.

Il est aussi possible de monter les disques nus piezzo sous la carte, si la carte est posée sur entretoises.
Ne vous trompez pas en commandant, les descriptions chinoises sont farfelues et vous risquez de recevoir de vrais buzzers inutilisables.

Remarque :  Petits haut-parleurs originaux
Il est facile de récupérer les casques jetables lors des voyages en avion. Il existe deux familles suivant les compagnies :
 La version 30 Ohms, inutilisable ici, son très faible ;
 La version 300 Ohms, qui contient deux surprenants petits haut-parleurs, bien meilleurs que les faux buzzers noirs. Voir l’oscillogramme plus bas.


Haut de page

nextion  Premier survol du schéma

Une première solution utilisait un mosFet N, avec filtre de grille et RC d’isolation, mais cette solution amenait trop de distorsions et a été abandonnée.

Un seul fil GPIO est utilisé, en écriture il produit des sons, et en lecture, il lit les touches.
La pin marquée BUZ est à relier à une sortie GPIO. pinMode(buzzer, output); Voir sur les documents Expressif les nombreuses limitations des GPIOs !

La nouvelle version est plus simple, en utilisant un mosFet P simple (SI2305 ou BS 250 ou autre), sans filtre, afin d’être en consommation nulle au repos.
Le condensateur en parallèle sur le buzzer (0.1µF au moins) casse les pics de suroscillations, plus la valeur sera grande, plus les pics seront rabotés au prix d’une baisse de niveau. On ne peut pas aussi simplement extraire la fondamentale d’un signal carré de fréquence variable, il y aura toujours les raies impaires dans le spectre, mais à la différence d’un filtre d’entrée qui dissymétrise le signal, il n’y aura qu’une seule fondamentale.


Utilisation de la prise <EXT>

Une résistance, ou un potentiomètre de 47 Ohms (l’autre extrémité à la masse en <1>) ou un strap  en <2><3> activent le haut-parleur interne.
Sinon un haut-parleur externe sera branché en <1><3>.

 

Rôle d'une diode de roue libre (à la place de CBD1)

La résistance en parallèle ainsi que la diode de roue libre sont inutiles avec un vrai haut-parleur.
Avec des disques piézo-électriques seuls, c'est absolument indispensable, car l’ensemble se comporte comme un simple condensateur qui se chargerait à Vcc sur les impulsions positives sans pouvoir de décharger, et l’on n’entendrait qu’un unique petit « clic ».

La prise strap en série permet de tester divers haut-parleurs et buzzers en avec les composants nécessaires à la demande.

 


nextion Détails sur l’écriture (production de sons)

Pour produire les sons, les signaux carrés seront émis pour attaquer la Gate du mosFet , dont l’impédance d’entrée est très élevée (à la différence d’un transistor qui demande un courant de base).

Pour avoir  un son plus fort vous pouvez tirer un vrai haut-parleur au 5 V et pour le mélomanes les plus fous, au 12 V s’il existe, afin de sonoriser la quartier.

Rôle du condensateur CDB1

Le condensateur en parallèle (0.1µF au moins) casse les pics de suroscillations, plus la valeur sera grande, plus les pics seront rabotés au prix d’une baisse de niveau. On ne peut pas aussi simplement extraire la fondamentale d’un signal carré de fréquence variable, il y aura toujours les raies impaires dans le spectre, mais à la différence d’un filtre d’entrée qui dissymétrise le signal, il n’y aura qu’une seule fondamentale.

Résultats avec un vrai haut-parleur :


sans condensateur

Haut de page

nextion  Autres approches, toujours en signal digital

Approche PWM ou modulation Delta
L’ESP32 possède 16 PWM, mais il y en a peu d’utilisables à cause de limitations.
Les fréquences utilisables sont : 1,5,8 et 10 kHz. La résolution est entre 1 et 16 bits.
En pratique cela n’est pas assez rapide pour produire une gamme de sons
Cela est parfait pour piloter la vitesse de moteurs, les variations lentes d’éclairage d’une led, mais pas pour faire de la musique.

Haut de page

nextion  La solution magique ATTiny 85

Un gros problème apparait quand on doit gérer simultanément des routines qui prennent du temps machine, par exemple :
Quand l’ESP32 ne fait rien, en sommeil entre deux actions, je commande des leds WS2182 (voir sa page ici) qui « pompent » doucement, avec une faible lueur jaune pour montrer que le système est vivant.
Pendant ce temps le clavier est actif (déclenché par une interruption), et un son long peut être en train de jouer… C’est du multitâches. .
Il existe évidement la solution Expressif pour activer le deuxième cœur, mais cela ne se fait pas simplement, il faut utiliser ESP-IDF, basé sur FreeRTOS, et la programmation implique de nombreux outils qui dépassent les compétences du bricoleur habitué au seul Arduino.

Pour résoudre ce problème, je rajoute sur ma nouvelle carte de développement (publication à venir) un ATTiny 85 qui va gérer seul avec ses petites 8 pattes, clavier, son, détection de présence (radar et ultrasons) et leds.
Il communique via un seul GPIO avec l’ESP32 et ils échangent des commandes de quelques bytes pour lancer des actions, chacun vivant à part.
Il ne prend que très peu de place sur la carte mais fait beaucoup de choses. Toute la carte est en CMS, sauf l’ATTiny 85 qu’il faut prendre en boîtier DIL 8 pattes car il est plus simple de le sortir de son support pour le reprogrammer.
Pour reprendre les exemples précédents, mes bibliothèques, sons, clavier et WS2182 et leurs routines .ino, sont seulement implantées dans l’ATTiny 85, laissant à l’ESP32 les tâches nobles.
Cet ajout d’un deuxième microcontrôleur peut sembler surabondant, mais à 2€ le composant, il va vite apparaitre comme un sous-traitant incontournable.
L'ATTiny 85 est vraiment un composant fascinant.
Il dispose de :  8k Bytes de flash pour le programme, 512 bytes EEprom, 512 bytes Sram, ADC 10 bits.
Cela permet de faire tourner beaucoup de routines performantes.
Si vous ne l’avez pas testé, lisez un descriptif des multiples combinaisons du vieux NE555, et pour vous faire la main, réalisez toutes les temporisations et monostables en ATTiny, c’est encore beaucoup mieux… Vous développez sur une carte Arduino quelconque, et quand le firmware est au point, il suffit de le transférer vers l’ATTiny.
Je les utilise aussi pour des décodages de clavier de portier, la conversion de signaux NMEA183 en RS232, des déclencheurs photo, etc..

Haut de page

nextion L’approche convertisseur Digital vers Analogique

Dans les exemples précédents, nous attaquions via un mosFet, le haut-parleur en signaux carrés générant plein d’harmoniques désagréables.
Maintenant les commandes seront des sinusoïdes pures ce qui améliore considérablement les résultats après amplification.

L’ESP32 possède deux broches spéciales utilisables en convertisseur Digital vers Analogique, ce n’est que du 8 bits, mais suffisant pour des applications basses fréquences. DAC1 utilise GPIO25, et DAC2 utilise GPIO26.

Considérons ce début de programme :

Il ne fait que créer un tableau de de 256 bytes représentant une période de sinus, entre 0 et 255.

#define stepResol 8
int8_t sn[256];// = 2 exp stepResol
// ---------------------------------
void setup() {...
int resol = pow(2,stepResol);//  8-> 256
for (int i = 0; i < resol; i++)      {
    sn[i] = (int) (127*(1+sin (PI*i*2/resol)+.5))) ; }}

 

Nous pouvons envoyer ce tableau dans un des DAC ce beau signal sinusoïdal de 731 Hz.
Attention ici le mosFet ne convient plus, nous parlerons plus tard de l’amplification à transistors.

Les puristes remarquent un petit glitch en fin de période (sur les curseurs), il est inévitable car dans la boucle for, si la condition est FALSE, l’exécution prend quelques cycles de plus que pour les 256 conditions TRUE (256 fois).
C’est imperceptible à l’oreille d’un musicien car le haut-parleur lisse ce minuscule défaut.

void loop() {
for (byte j = 0; j < pow(2,resol); j++){
dacWrite(dacOutput, sn[j]); }}

Si maintenant nous changeons la taille de la table (2 exp 8 = 256) en passant à une résolution de 5,
la table n’a plus que (2 exp 5 = 16) termes et la fréquence est (2 exp (8-5) =  8) fois plus grande.
Suivant la résolution nous obtenons :

 

Avec 256 points, la résolution est bien trop grande pour ce que nous voulons faire.
Comme lors de la compression d’image avec perte (bmp -> jpg) la dégradation ne se fait pas sentir si l’on n’est pas trop exigeant.
Pour notre petit haut-parleur, la table de 16 octets sera suffisante. Un petit condensateur lissera les marches d’escalier.

Résolution Taille table Fréquence
3 8 23.4 kHz
4 16 11.7 kHz
5 32 5.85 kHz
6 64 2.92 kHz
7 128 1.46 kHz
8 256 731 Hz
9 512 386.5 Hz

Nous savons faire une fréquence unique avec une table unique, mais on peut faire bien mieux !


 Multiplication de fréquence
Si dans la condition « for » nous remplaçons j++ par j+=shift, suivant la valeur de byte shift nous sautons des points dans la table.
Avec shift = 2 nous prenons un point sur 2 donc doublons la fréquence
Avec shift = 3 nous prenons un point sur 3 donc triplons la fréquence...

256 points -> 731 Hz

16 points -> 11.7 kHz
 Décrémentation de fréquence
Si dans la boucle « for » nous ajoutons un delayMicrodeconds (tempo), nos rallongeons la boucle donc baissons la fréquence.
Pour la table de 256, avec une tempo de 160 µS, la fréquence est de 23.4 Hz, la période est de 42.74 mS, il y a 256 boucles,
donc le traitement de la condition for + dacWrite +160 µS prend à peu près 42.74/255 = 167 µS, donc <condition for> + dacWrite = 7 µS
En rajoutant notre délai, la nouvelle fréquence sera environ de 1/(256* (7+tempo)), car il y a l’arrondi, le délai ne prenant que des entiers.

Par exemple pour s’approcher du La 3 à 440 Hz, l’appel avec shift=1 et tempo= 3µS, nous donnera 421 Hz plus proche du Sol# ou La bémol à 415 Hz.
C’est comme jouer une partition sur un piano désaccordé...

Fréquence en Hz délai en µS
542 1
240 10
148 20
84.6 40
44.3 80
23.4 160

 En passant à cette petite boucle « for » les entiers shift et tempo, nous pouvons obtenir toute la gamme audible. Les fréquences se calculent par de simples tables Excel.
Cela a toutefois un défaut, les fréquences obtenues sont serrées, mais ne tombent pas juste sur les notes de la gamme.
Pour des bruitages, aucun problème, mais pour jouer un son parfait sur un bon haut-parleur, les écarts aux vraies notes seront sensibles pour un musicien.

 

 Amélioration de la résolution

Dans ce chapitre nous prendrons un shift de 2, donc 128 points par période. Le delayMicrosecond est trop long pour faire un réglage fin.
Nous remarquons que delayMicrosecond(255), qui nous donnait une fréquence de 14.95 Hz prend exactement le même temps que :
for (int i = 0; i < 20540; i++)         {
        asm volatile("nop");  }// attendre 1 cycle d'horloge
Donc <la boucle for> + <l’instruction nop> prennent exactement 255µS/20540, soit environ 12.41 nanoSecondes, soit 3 coups d'horloge (2 pour la boucle, 1 pour le nop) à 240 MHz.
Cela donne un delai 80 fois plus fin que delayMicrosecond()
Nous pouvons maintenant ajuster plus finement les notes de la gamme, par exemple :
Octave 1 : La  110 Hz  avec 2616 boucles  (exactement)
Octave 2 : La  220 Hz
 avec 1207 boucles  (exactement)
Octave 3 : La  440 Hz  avec   501 boucles (exactement)
en descendant les octaves le nombre de boucles augmente ainsi que la résolution, mais en montant les octaves la précision diminue de plus en plus :


Equation Fréquence/ tempo

Octave 4 : La 880  Hz, avec 149 ->  886 Hz et avec 150  -> 874.4 Hz
Octave 5 : La 1760  Hz, impossible, trop rapide, avec 1 boucle -> 1464 Hz seulement
La synthèse ne sera juste que dans les graves ce qui pose problème…Avec un shift de 2, donc 128 points on obtient un nouveau jeu de fréquences mais le problème se pose toujours.

Si l'on prend un shift de 1, on descend encore d'une octave sur les valeurs précedentes.



 Oublier le DAC 8 bits de l’ESP32 ?

Faut-il oublier le DAC 8 bits de l’ESP32 pour rajouter un meilleur, comme le DAC 12 bits MCP4725 utilisant une commande I2C pour un coût très modique ?
L’avantage de l’approche I2C est que cela ne consomme aucun GPIO supplémentaire, car de toute manière, SDA et SCL de l’I2C sont déjà utilisés par d’autres périphériques.
Pour cette application <son>, cela est inutile, car la limitation n’est pas du tout dans la finesse de la courbe, mais dans la vitesse pour passer les octets de commande.
Plus la résolution est grande, plus la fréquence du signal sera faible.

Haut de page

nextion  Les vraies notes de musique

Vous trouvez partout des tables de fréquence des notes arrondies, mais quand on veut créer des sons exactement avec un synthétiseur, cela n’est pas suffisamment précis.

Ma table Excel ci jointe vous donne les notes exactes. Elle est très simple !
Elle se base sur la fréquence de référence du La3 à 440 Hertz.
On passe d’une octave à l’autre en multipliant/divisant par 2.
On passe d’une note à l’autre en multipliant/divisant par 2 puissance 1/12
Remarquez les touches noires du piano, qui sont les dièse/bémol intercalés entre certaines notes.

Cliquez pour obtenir la feuille Excel

Haut de page

nextion  La bibliothèque d’utilitaires « sons »

La classe < C_utils_Sons> utilise seulement la sortie numérique et le mosFet comme décrit en début de page.
Elle n’utilise pas la synthèse sinusoïdale du chapitre précèdent.

La classe < C_utils_Sons> contient les outils nécessaires pour produire divers bruitages, sans utiliser le fonction « tone » qui ne fonctionne pas sur ESP332.
Elle est remplacée par la méthode « ton ». Cette méthode accepte plusieurs formats :
 void ton (float note, uint8_t octave, int duration, int pause)
 void ton (float note, uint8_t octave, int duration)
 void ton (float frequency, int duration)

Dans cette classe, les notes (et dièses) sont écrites en clair et leur interprétation est très précise.
En utilisant le terminal série de la démo, on peut lancer la collection de tous les sons ou lancer chaque son séparément en tapant son numéro au clavier.

La démo incluse montre les nombreux exemples à tester pour agrémenter les programmes :
 Des petits sons gadgets pour agrémenter les actions courantes.
 Les classiques sirènes (samu, pompiers, ambulance, police) qui sont fidèles, car le ministère de l’intérieur publie les normes très rigoureuses.
 Quelques thèmes musicaux médiocres, identifiables en 8 mesures.

J’avais espéré créer de sons d’explosion, de chocs métalliques, des chants d’oiseau, etc.., mais cela est impossible sans utiliser de lourdes listes de centaines d’octets, il faut passer au MP3. Je tenais à ce que ma bibliothèque soit le plus compacte possible. J’ai renoncé à tout ce que je ne peux pas jouer au piano, avec un seul doigt de la main droite.
Cela limite considérablement les possibilités, ce qui explique les rendus pauvres, car une partition comporte les deux mains et plusieurs doigts par main pour chaque temps.

Haut de page

nextion  Synthétiseur tout fait

De nombreux circuits synthétiseurs audio existent, en solution « clefs en main », fournissant une sortie audio parfaite, bien meilleure que ce qui fait l’objet de cette page consacrée à l’approche par le firmware seul.
C'est une excellente approche pour des oreilles sensibles. Une recherche sur Internet <synthétiseur audio arduino> vous donnera de nombreuses pistes. Il y a beaucoup moins de choix en synthétiseurs BF qu’en HF.

Pensez aussi au très riche format Midi très bien documenté.

Autre alternative performante, la carte annexe jouant des MP3 contenus dans sa mémoire SD. Vous pouvez échantillonner toute musique, voix parlées ou chantées, des bruits…
Il existe de multiples applications spécialisées, pour traiter les sons.

Mais cela nous éloigne évidemment du cahier des charges original pour cette page, qui était de faire du son en utilisant simplement une sortie GPIO et quelques lignes de code…

Haut de page

nextion Amplification du signal vers le haut-parleur

Si l’on veut plus de puissance (?) , il faut rajouter un petit circuit intégré amplificateur. Voir par exemple le LM4890MX.
Il existe des modules chinois qui comportent l’ampli et le haut-parleur sur la même plaquette comme le SC8002B, mais vous pouvez utiliser un quelconque ampli de récupération qui traîne dans une de vos boîtes.
Avantages et inconvénients de l’amplificateur SC8002B (ou LM4871)
 + Coût dérisoire
 + Fonctionne à 3.3 V (c’est rare)
 + Surpuissant pour notre application, mais le niveau est simple à contrôler avec une résistance
 + Meilleur son possible sur un petit haut-parleur
 - Consommation permanente de quelques milliampères incompatible avec des montages « low power », mais une coupure automatique de l’alimentation en rajoutant un MosFet est simple
 - S’il n’est pas en stock, délai pour commande en Chine

Haut de page

nextion  Conclusion

N’hésitez pas à m’envoyer vos remarques sur le fond (parties à compléter ou modifier), et sur la forme (fautes de frappe…).

L’expérimentation sur Arduino est très enrichissante, mais se contenter de pomper des pages douteuses sans comprendre ce que l’on fait n’est pas une bonne idée.
Il faut essayer d’aller plus profondément si l’on veut en tirer une satisfaction intellectuelle…


Ne vous attendez pas à faire du son haute-fidélité aussi simplement avec un Arduino, pensez à l’alternative des circuits spécialisés évoqués.
Pour de simples petits sons ponctuant un programme, le montage décrit dans cette page suffit.

De plus, les fréquences sont calculées exactement, mais l’horloge de l’ESP32 n’est pas très stable.
Pour s’en convaincre, il suffit de réaliser une pendule élémentaire qui se base sur millis(), sans autre code parasite et la laisser tourner pour regarder la dérive importante, variable d’un chip à l’autre.
Donc quand vous lisez « le La 3 est callé exactement à 440 Hz », il faut comprendre « pour autant que millis() batte exactement la milliSeconde », ce qui n’est jamais exact.
Vous trouverez joint un petit programme qui envoie le temps toutes les minutes, calez vous sur un top à l’heure entière et laissez tourner pour voir les dérives, entre autres liés à la température (testez dans le frigo sur batterie).

Haut de page

nextion  Annexe : Contenu du Pack_Sons

Classe de base
 Classe <C_utils_Sons> pour l’utilisation de la sortie digitale sur un GPIO et haut-parleur sur mosFet. Collection des petits gadgets pour générer divers sons.

Fichiers ino
 Demo_Sons : Test des méthodes de la classe et collection de sons
 Dac : Synthétiseur sinusoïdal basse fréquence utilisant une sortie DAC 25 ou 26
 Top_Hour : Petit gadget pour vérifier la stabilité de l’horloge 240 MHz de l’ESP32

Fichiers Excel
 Vraie_gamme : Calculs exacts des fréquences des notes de la gamme
 Frequence_delai_nop : Détail de la courbe des fréquences octave 3 avec le synthétiseur
 Clavier_diodes : Tensions du clavier à touches. Faites varier les valeurs en entrant en colonne E2 la tension des diodes que vous testez (0.6 V pour silicium 1N4148, moins de 0.4 pour de bonnes zeners)

L’ensemble des outils, la classe et
les fichiers.ino de démonstration,
est disponible ici dans le <Pack_Sons> :

zip

mise à jour: 2023 02 19

Haut de page

© Christian Couderc 1999-2023     Toute reproduction interdite sans mon autorisation


* Page vue   3886   fois       IP : 3.236.223.106

 Haut de page         Dernière retouche le 19 Août 2023 à 13 h         Retour page précédente

   Collector