Où l’on parle Fuzz Factory, archi électronique, DAC et VCA

Épisode précédent

Architecture

Avançons un peu dans la conception de la Fuzz Flaxtory. Je pense mettre en œuvre l’architecture suivante:

"Architecture

Et si on ajoute le “golden sample”:

"Architecture

En bleu les circuits analogiques, en violet les périphériques d’entrée du MCU, en orange les périphériques de sortie du MCU. Tant qu’on est là, un peu de vocabulaire:

  • IC : Input Capture, mesure de fréquence.
  • Comp : comparateur, transforme un signal sinusoïdal en signal carré, conditionnement nécessaire pour les input capture.
  • Peak : Peak Detector, détecteur d’enveloppe, pour mesurer l’amplitude d’un signal analogique.
  • DAC : Digital to Analog Converter, génère un signal analogique à partir de commandes numériques.
  • ADC : Analog to Digital Converter, transforme un signal analogique en donnée numérique.
  • PWM : Pulse Width Modulation, signal modulé en largeur d’impulsion.
  • Digipot : Digital Potentiometer, potentiomètre numérique.
  • VCA : Voltage Controlled Amplifier, permet de moduler l’amplitude d’un signal analogique.
  • GPIO : General Purpose Input Output, signal tout-ou-rien binaire standard.
  • MCU : Mirco Controller Unit.

Quelques explications. Pour rappel, mon objectif est de faire une PLL qui suive le signal audio d’entrée et génère un signal de sortie dont la fréquence dépendra de la fréquence du signal d’entrée. Comme je l’avais expliqué dans l’épisode précédent (c’est très hautain dit comme ça …) le circuit de la Fuzz Factory oscille de façon autonome dans certaines plages de valeur du GAIN et du STAB. Pour faire varier la fréquence il faut faire varier ces deux paramètres. Ce qui n’est pas trivial, mais j’y reviendrai plus tard. Pour le contrôle de ces deux paramètres j’ai un DAC pour STAB et un digipot pour GAIN.

La Fuzz Factory peut osciller sans signal d’entrée, donc je pourrais la découpler complètement du signal d’entrée. Quand on met un signal d’entrée avec suffisamment d’amplitude, c’est ce signal d’entrée qui prend la main sur la fréquence du signal de sortie. Comme j’ai bien envie de jouer avec la limite entre ces deux modes (que j’appelle “oscillation libre” et “oscillation contrainte”), j’ai mis un VCA en entrée, pour pouvoir contrôler l’amplitude du signal que j’injecte dans la Fuzz Factory, et idéalement la maintenir à la limite des deux modes, ou au contraire augmenter l’amplitude pour que le signal d’entrée garde la main sur la fréquence de sortie, même quand on ne joue pas fort. Pour pouvoir contrôler précisément l’amplitude du signal, il faut pouvoir asservir, et donc mesurer la grandeur qui nous intéresse (l’amplitude du signal) en entrée et en sortie du VCA, pour pouvoir compenser. D’où la présence d’un détecteur d’enveloppe / crête en entrée et en sortie. La mesure en sortie est potentiellement overkill, vu qu’on peut très bien contrôler le VCA en boucle ouverte si il est suffisamment stable. Dans le doute, je préfère ne pas prendre de risque et provisionner la possibilité de faire un asservissement précis. Il est à noter que, pour le moment, je n’ai aucune idée de la façon dont je devrais m’y prendre pour savoir quelle est l’amplitude requise en entrée pour basculer entre l’oscillation libre et l’oscillation contrainte.

Le trapèze est un multiplexeur, il permet de choisir quel signal je fais entrer dans la Fuzz : soit le signal d’entrée en direct, soit le signal en sortie du VCA, soit la masse. En pratique je pense que je ne vais pas mettre la masse, ou alors plutôt avec un circuit de mute en série. Pour couper le signal d’entrée de la fuzz - et donc la laisser osciller librement - je vais plutôt utiliser le VCA et mettre l’amplitude à 0, ce qui revient à la même chose. Je pourrais aussi me dire que pour le signal direct je pourrais simplement mettre le VCA à une valeur fixe, mais je préfère me garder la possibilité d’avoir les micros de la guitare attaquer directement la fuzz, pour un fonctionnement “standard” de Fuzz Factory. Et donc, pour être le plus transparent possible, il me faudra un relai. Dans tous les cas, cet étage sera contrôlé par des sorties GPIO du MCU, vu que les commandes seront “lentes”.

Pour avoir la fréquence que l’on veut, il faut asservir GAIN et STAB, et donc mesurer les fréquences d’entrée et de sortie de la fuzz, d’où la présence d’un input capture en amont et en aval. Pour cet asservissement je ne tiens pas compte de l’amplitude, uniquement la fréquence. L’on peut donc noter que, bien que j’ai mis la mesure ici sur le signal d’entrée, il serait tout à fait possible de le faire sur la sortie du VCA, pour être sûrs d’avoir toujours un signal “lisible”. Bon, mettre un circuit de conditionnement overkill devrait tout autant faire l’affaire.

Lorsque la fuzz oscille librement, l’amplitude de son signal de sortie sera fixe, ou dépendante de la position des réglages de GAIN et STAB, en tous cas ne dépendra pas du signal d’entrée. Il faut pouvoir reproduire l’amplitude en sortie, j’aurai donc un VCA en sortie. Il sera asservi sur l’amplitude du signal d’entrée, donc il y a une mesure de l’amplitude du signal d’entrée, et du signal de sortie, pour pouvoir compenser. Là encore, on pourrait se dire que la mesure de l’amplitude en sortie est surnuméraire, mais encore une fois, je préfère ne pas prendre de risques.

Comme je l’avais évoqué dans l’épisode précédent, lorsqu’un signal est présent en entrée de la fuzz, il peut prendre la main sur la fréquence du signal de sortie. De ce fait, il n’est plus possible d’utiliser la mesure de la fréquence de sortie de la fuzz pour déterminer si les positions de STAB et GAIN sont adaptées pour générer la fréquence que l’on veut, vu que de toutes façons la fréquence de sortie ne dépend plus de ces réglages, mais uniquement du signal d’entrée. L’on pourrait se dire que ce n’est pas un problème, car si de toutes façons il n’est plus possible de contrôler l’oscillation de la fuzz, régler STAB et GAIN n’a plus de sens. Certes, mais j’imagine quand même deux cas:

  • A la jonction entre les modes libres et contraints, je ne voudrais pas que la fréquence diverge trop, pour garder la continuité fréquentielle entre les deux modes,
  • Même quand le signal d’entrée a la main sur la fréquence de sortie, STAB et GAIN modifie la texture du son, et j’ai bien envie de voir ce que produit sur la texture du son le fait de faire suivre le réglage d’oscillation intrinsèque même quand c’est le signal d’entrée qui définit la fréquence de sortie. Peut-être que ça sera nul et sans intérêt, mais j’ai vraiment envie de savoir ce que ça donne, et tant qu’on a pas testé … Qui sait ? Peut-être c’est cool ?

Je ne reviens pas sur le contrôle du STAB, c’était le sujet de l’épisode précédent.

VCA

Ça fait un bout de temps que je cherche des méthodes simples et fiables pour contrôler l’amplitude d’un signal. Il y a quelques années j’avais fait un tremolo à commande numérique, à base de digipot. Le prototype à base de Nucleo + shield de prototypage marchottait bien, puis j’ai fait un circuit dédié et un PCB, et je l’ai fabriqué, et ça n’a jamais remarché. Ça m’a violemment déprimé, surtout que j’y avais passé énormément de temps. C’était un de mes premiers circuits et un de mes premier routages, donc je suis tombé dans plein de pièges de débutant, dans lesquels je tombe moins maintenant, donc je pourrais me dire que je pourrais revenir dessus, mais je n’ai pas envie. Trop de passif d’une part, et en plus c’est cher, la résolution est très limitée (8 bits max sur les digipots les plus évolués et les plus chers) et il faut gérer le zero-crossing, ce qui n’est pas une sinécure, même si j’avais trouvé un trick plutôt efficace à base de bascule RS sur le chip select de la SPI. Bref.

Dans un autre projet que j’avais à peu près au même moment avec Trublion, nous avions mis en œuvre un circuit de gestion de volume dédié audio de chez Cirrus Logic (un CS3308 de mémoire). Ce composant était très performant, mais surdimensionné (8 canaux), pas forcément adapté (gain gradué en dB) et surtout horriblement cher, genre 18€ pièce ! Je n’ai pas du tout envie de partir là-dessus.

J’ai donc cherché quelles étaient les autres méthodes existantes pour faire de la modulation d’amplitude en BF.

Les deux circuits les plus simples qui existent utilisent un pont diviseur résistif variable, composé soit avec un FET, soit avec un couple LED-LDR, à savoir LED + photorésistance. Les fameux compresseurs “optiques” ou “solid-state”… Personnellement, je n’ai pas envie de me battre à rendre un circuit à base de FET linéaire, et les LED+LDR c’est assez relou mécaniquement - et pas très linéaire non plus, et généralement on est limité sur une plage d’amplitude et on ne peut pas atteindre une amplitude nulle, il y a toujours un signal résiduel. Il y a bien les composants tout-fait de chez THAT, mais leur disponibilité limitée et leur prix exorbitant me refroidissent. J’ai essayé de bricoler avec un optocoupleur acheté sur Farnell, que j’ai essayé d’utiliser en résistance variable en balançant dedans un PWM, ça a totalement foiré.

Si on reste sur du full solid state, une topologie très utilisée dans les synthés analogiques c’est l’OTA. Les LM13700 sont faciles à approvisionner et ne coûtent pas cher, le problème c’est que je ne comprends pas du tout comment ils fonctionnent, et je n’ai jamais réussi à faire un circuit sur table qui marche avec.

On trouve des schémas de VCA à base de transistors en LTP + ampliop. Et ça marche pas mal du tout, aussi bien en simulation qu’en vrai : j’ai fait le test à la rache avec des transistors traversants même pas appairés, et ça fait complétement le taf, c’est très linéaire, ça marche avec une tension de référence (alimentation non-symétrique), et ça permet d’avoir une amplitude qui varie jusqu’à zéro, là où les circuits à base de FET et LDR ont toujours une plage limitée.

VCA - Schéma

VCA - Simulation

Globalement c’est un étage d’entrée d’ampli OTA, donc un long tail pair, avec le signal de contrôle qui vient moduler le bias des transistors.Alors oui, ça demande pas mal de composants, mais ça reste raisonnable et ça fait le taf. Pour ne pas prendre de risques je laisse le réglage de bias et je vais utiliser des transistors appairés. A noter qu’il semblerait que le gain statique soit inférieur à 1, donc il faudrait ajouter un étage de gain derrière.

J’ai fait une simu avec un détecteur de crête basique:

VCA - Simulation

Pour faire la blague, j’ai modifié le signal modulé : plutôt que prendre un sinus à fréquence fixe, j’ai juste mis un comparateur sur le signal d’entrée (en bas à droite), qui transforme donc le signal de guitare d’entrée en un magnifique signal carré full range:

VCA - Simulation

Le signal d’entrée est en vert, le signal de sortie en bleu. C’est un peu brutal :P Et donc, je transforme le signal d’entrée en carré (monster fuzzzz !) puis je module son amplitude avec l’amplitude du signal d’entrée. Je re-synthétise, d’une certaine façon. J’y ai entré mon fameux sample de guitare de test que j’utilise tout le temps. On obtient ça:

VCA - Simulation

Le sample :

Et en sortie de cet “effet”:

Le signal est là, la dynamique à peu près. Je pense que la brutalité de la mesure de l’enveloppe détruit pas mal de la dynamique. Est-ce que je pourrais l’améliorer pour en faire une pédale distincte et utilisable ? Mmmmm … :P

Peak detector

On ne dirait pas comme ça, mais ce circuit est important. Je vais utiliser un circuit redresseur simple alternance, du même genre que sur le Rhodes MK3-EK10. Un LM1458 pour l’AOP, cela va de soit, et des diodes standard, ça devrait le faire. Je vais aussi envoyer le signal d’entrée directement sur une entrée analogique, pour voir si je peux en faire quelque chose. L’on serait sur un produit grande série, je ferai la détection de crête en SW, mais là j’ai besoin de me simplifier la vie. Mais j’ai aussi bien envie de tester voir si ça marche, la détection de crête en SW.

Par ailleurs, et comme je l’ai déjà subi sur d’autres projets avec Trublion, il est nécessaire de faire un frontend assez pointu en entrée du MCU si on veut garder de la range du signal. En effet, l’amplitude du signal redressé ne va pas être énorme, et il va surtout être centré sur la tension de référence, qui est bien au-dessus de la range des entrées analogiques du MCU. Il faut donc amplifier ce signal et lui ajouter un offset pour le faire rentrer dans la range 0-3.3V. Pour cela, la méthode la plus clean c’est de faire un étage différenciateur avec un ampliop. Problème : on subit alors les tensions de déchet, vu qu’on est proche du rail négatif, et perdre 1V sur 3.3V, ce n’est pas du tout négligeable. Pour ne pas avoir d’ennuis je vais partir sur de l’AOP rail-to-rail, tant pis pour le surcoût. L’avantage ici c’est qu’on est sur un signal assez lent et qu’on ne cherche pas la haute fidélité, donc n’importe quel AOP peut faire l’affaire. Derrière il y aura juste un RC pour attaquer l’entrée analogique du MCU, donc grosse résistance, donc pas de problème de stabilité. Je pense partir sur un MC33202, qui est pas très cher, mais limité à 13V sur son alim. J’hésite à prévoir une protection, des fois qu’on veuille mettre plus que 12V sur l’alim, mais je n’y croi spas trop. ON ne cherche pas le headroom sur ce genre de circuit, donc ça n’arrivera pas.

Au final, j’ai jeté mon dévolu sur cette topologie:

Détecteur de crêtes - Simulation

L’avantage ici c’est que l’étage de détection amplifie en même temps qu’il redresse, ce qui permet d’avoir une amplitude raisonnable en sortie sans avoir trop d’étages de gain.

Détecteur de crêtes - Simulation

Signal d’entrée en vert, signal de sortie du redresseur en bleu, signal de sortie en rouge. Pour une excursion de 200mV en entrée on a plus d‘1V en sortie. On constate l’effet lissant du filtre RC supplémentaire en comparant le ripple sur les courbes bleue et rouge.

L’inconvénient … Ben c’est qu’il faut 3 AOPs. Ce qui est doublement relou parce que les AOP étant en boîtier doubles, J’en ai un utilisé à moitié seulement. Un solution facile c’est de les faire aller par 2, comme ça ça fait 6 en tout, ce qui est regroupable en multiples de 2. Grmpf … Une autre solution est de créer une tension de référence par circuit, avec son buffer dédié, ce qui permet de les rendre plus indépendants, et de limiter la surcharge de l’étage de sortie. Je vais appliquer cette deuxième solution.

Au final, l’AOP d’entrée à gauche doit être compensé, donc on met un LM1458, et les deux suivants sont des MC33202. La capa C1 de 100n est optionnelle et est censée améliorer la réactivité. Les simus montrent des résultats contrastés, donc je ferai des essais pour voir comment ça se comporte. Derrière la capa du détecteur j’ajoute un filtre RC (R4-R5-C3) qui va atténuer l’amplitude et lisser le signal. Au pire, si ça devient trop lent, je ne monte pas la capa. U2 est juste un buffer, nécessaire pour que l’étage d’offset qui suit fonctionne. Il va soustraire la tension qu’il est présentée sur son entrée négative. Soit on met une valeur fixe avec une zener (3.9V ou 4.3V devrait être pas mal), soit on le définit avec un pont diviseur sur l’alim + buffer. La deuxième solution me semble inutilement plus complexe, donc je vais rester sur la solution zener.

Saisi sous Kicad ça donne ça:

Détecteur de crêtes - Simulation

Oui, ça fait du monde quand-même. Et ça à chaque mesure d’enveloppe que je vais faire. Bigre … Le routage va être sympathique.

Input Capture

Pour les mesures de fréquence, il faut que je transforme le signal en carré. Le plus simple c’est de mettre un comparateur à sortie collecteur ouvert pull-up à 3.3V.

Comparateur - Simulation

Comparateur - Simulation

En vert le signal d’entrée, en bleu le signal de sortie. Simple, efficace.

L’idée est d’exploiter les entrées PWM du MCU, pour qu’il fasse les mesures en automatique en HW, et juste venir poller de temps en temps les valeurs dans les registres. L’avantage c’est qu’on évite de faire des interruptions, par contre le défaut c’est que comme on mesure une fréquence qui est assez basse et peut fortement varier (en gros pour de la guitare / basse 10Hz - 10kHz) le rafraîchissement sera très aléatoire. Je doute que ça soit vraiment un problème. Déjà l’oreille humaine ne perçoit pas les variations très rapides. On a l’habitude de dire qu’en-dessous de 10ms de latence on ne perçoit plus de décalage, donc si on poll à 5ms par exemple, ça devrait convenir. De plus, rien n’empêche d’avoir une fréquence de rafraîchissement beaucoup plus élevée pour la(les) PLL(s). Si on poll moins vite l’entrée, on aura juste une consigne qui varie plus lentement, ce qui est sans doute préférable, d’ailleurs, pour des questions de stabilité. Bref, à mon avis: - Boucle de régulation de PLL à 100us - Polling de la fréquence d’entrée à 5ms (1ms ?)

Fonctions annexes

Je pense ajouter plusieurs autres fonctions: - Entrée pédale d’expression. Vu qu’en pratique c’est juste une entrée analogique, je peux même en mettre deux, c’est juste une question de place sur le PCB pour les jacks. - MIDI IN / OUT : je vais mettre les interfaces HW + connecteurs correspondantes, pour pouvoir plus tard m’en servir comme expander, ou générer du MIDI à partir du signal d’entrée, et donc faire un guitar-to-MIDI :P

Interface

Pour l’interface homme-machine (boutons et affichage), je pense faire la même chose que ce que j’avais fait sur le tremolo (et qui était d’ailleurs la seule partie de la carte qui marchait …), à savoir: - Affichage 7 segments - Encodeurs avec LEDs bi-couleur et / ou RGB

Ça aura l’avantage d’être moderne et compact.

Architecture globale

Au final, tout mis bout à bout on obtient l’architecture suivante:

Architecture

Pour la partie MCU, je suis partit à utiliser une Nucleo, mais je me tâte fortement pour intégrer le MCU directement. Mais je pense que ça fait trop de problèmes d’un coup, donc il vaut mieux que je reste sur la Nucleo dans un premier temps, et que je garde l’intégration plus poussée pour plus tard. Ça sera un beau défi, surtout parce que le développement SW ne va pas se passer de la même façon sur une Nucleo ou sur le MCU en direct. Par contre ça va me permettre d’intégrer vraiment à fond et de mon galérer sur l’intégration mécanique.

Par défaut je vais partir sur le STM32F152, toujours le même, qui inclut de l’EEPROM intégrée. Il faudrait tout de même que je provisionne une EEPROM externe, à tout hasard, si je décide de changer de MCU (genre s’il n’est pas assez puissant). Ou il faudrait que je voie comment faire des écritures en Flash. A priori on a de la data Flash utilisable pour ça, même si ce n’est pas très explicite dans les reference manual. La Flash étant en général découpée en plusieurs blocs, il suffira d’en allouer un aux datas NVM. Yakafokon, comme toujours.

Si je mets une Flash externe ça me ferait quatre SPI, ce qui n’est pas rien. Il va falloir multiplexer. Je pense mettre les deux digipots de gain ensemble, et le 7 segment + EEPROM ensemble.

Pour le routage, je vais peut-être ne pas me faire autant chier que je ne l’avais fait sur le tremolo, et ne pas optimiser les connections entre les shift register et les 7 segments, car sur ce projet je vais faire fabriquer le PCB à l’extérieur, donc je ne vais pas me limiter sur le nombre de vias.

A suivre …

- Flax