J'étais chez ma soeur lorsqu'elle m'a montré sa sonnette qui faisait un gros "hum", j'ai compris immédiatement qu'il s'agissait d'un condensateur de filtration défectueux. Il s'agit d'une sonnette sans fil qui se branche dans la prise murale à 120VAC. Il existe aussi des versions qui fonctionnent sur pile. Le bouton de la sonnette utilise une pile au lithium CR2032. Le fonctionnement de ces sonnettes est le même que celui des portes de garages. Le bouton de la sonnette contient un émetteur à 433.9Mhz qui émet un code tandis que le module sonnette contient le récepteur décodeur. Comme il s'agit d'une sonnette l'appareil contient aussi un générateur de son. Dans le cas spécifique de cet appareil, il y a 4 transistors utilisés comme amplificateurs radio-frquence ainsi qu'un circuit intégré TX102R qui est le récepteur décodeur fonctionnant à 433.9Mhz IC1. Un deuxième circuit intégré marqué SXD0033R, IC2 et le générateur de mélodies. Ce circuit utilise la synthèse FM comme on retrouvait dans les ordinateurs des années 80 tel que les Commodore VIC20 et 64. Mais comme il est déjà pré-programmé avec un certain nombre de mélodies il suffit d'un petit boitier SOIC-8, puisqu'il n'a pas besoin d'une interface de programmation. Le troisième circuit intégré IC3 est simplement un ampli audio LM386. Cette sonnette est fabriquée en Chine par la compagnie Quhwa.
réparation
photos du circuit imprimé
Comme je l'avais spoçonné dès le départ il s'agissait bien du condensateur de filtration de l'alimentation qui était défectueux (C6). La réparation fut donc des plus simple et rapide. J'ai dessiner le circuit d'alimentation pour illustration.
Le condensateur C1 en série avec la résistance R2 limite le courant maximum qui peut circuler dans le circuit à environ 100mA puisque l'impédance de Zc1=1/(2*PI*60*2.2e-6)=1206 ohms. La zener diode 1N4739A a une tension de régulation de 9.1 volts, donc c'est à cette tension que le circuit électronique fonctionne. C6 est le condensateur que j'ai du remplacé.
Si vous voulez voir cette sonnette en action suivez ce lien.
J'utilise Ubuntu 24.04LTS sur mon ordinateur de développement. La version de SDCC qui est installé par la commande sudo apt install sdcc est la version 2.4.0 alors que la dernière version disponible est 2.5.0. Donc pour mettre à jour SDCC sur mon ordinateur je devais reconstruire les binaires à partir des sources. La procédure est simple lorsque les dépendances sont satisfaites. Donc on doit d'abord s'assurer qu'elles le sont.
prérequis
Le projet SDCC utilise le compilateur GCC ainsi que les outils binutils. Lorsque j'avais installé la version 4.4.0, lorsque j'ai lancé la commande ./configure j'ai eu une erreur me disant que libboost-graph-dev devait-être installé. Je l'ai donc installé avec la commande sudo apt install libboost-graph-dev. Avant de relancé ./configure assuront nous donc d'avoir les outils et les librairies nécessaires installées sur le système.
$ apt list --installed gcc binutils libboost-graph-dev
En train de lister... Fait
binutils/noble-updates,noble-security,now 2.42-4ubuntu2.8 amd64 [installé]
gcc/noble,now 4:13.2.0-7ubuntu1 amd64 [installé]
libboost-graph-dev/noble,now 1.83.0.1ubuntu2 amd64 [installé]
procédure
Une fois l'archive des sources du projet a été téléchargée. Il suffit de décompresser l'archive dans le dossier de son choix. Le dossier principal s'appelle sdcc-src-2.5.0 et contient le dossier sdcc-4.5.0. Dans un terminal on se déplace vers ce dernier dossier et on lance les 3 commandes suivantes:
./configure Cette commande sert à vérifier que le système possède les outils et les librairies nécessaire à la construction des binaire. S'il manque un outil ou une librairie un message d'erreur s'affiche. Cette opération prend moins d'une minute.
make Cette commande compile tous les binaires du projet. Sur mon ordinateur ça prend environ 30 minutes. S'il y a une erreur alors il faut la régler et relancer make. Dans mon cas il n'y a pas eu d'erreur.
sudo make install Cette dernière commande copie les binaires dans /usr/local/bin et effectue d'autres tâches connexes. Ce n'est pas long, moins d'une minute.
Le Charlieplexing est une technique qui permet de contrôler un grand nombre de DELs avec petit nombre d'entrée/sortie binaires d'un MCU. Pour utiliser cette technique il faut que chaque E/S utilisée soit configurable selon 3 états.
En mode entrée haute impédance. C'est à dire sans résistance pull up.
En mode sortie haute. C'est à dire à Vdd.
En mode sortie basse. C'est à dire à Vss
Cette technique est rendue possible par le fait que les Diode Électro-Luminescentes comme leur nom l'indique ne conduisent que dans un seul sens. En connectant 2 DELs tête bèche entre 2 E/S d'un MCU on peut allumer l'une ou l'autre ou les éteintre. Si Une des broche est configurée en mode sortie haute et l'autre en mode sortie basse la DEL dont l'anode est sur la sortie haute va allumée. Il suffit d'inverser la polarité des 2 broches pour allumer l'autre DEL. Pour les éteindre il suffit de configurer les 2 E/S en mode entrée haute impédance.
Dans ce circuit si PB3 et PB6 sont en mode entrée haute impédance les 2 DELs sont éteintes.
Si PB6 est en mode sortie haute et PB3 en mode sortie basse alors D26 est allumée.
Si PB6 est en mode sortie basse et PB3 en mode sortie haute alors D25 est allumée.
Pour que cette technique fasse du sens dans son utilisation il faut avoir plus de DELs à contrôler que le MCU dispose d'E/S. Le nombre de DELs multiplexables par cette technique est de N*(N-1) où N est le nombre d'E/S disponibles. Dans le circuit de démonstration qui suis on dispose de 4 E/S donc on peut contrôler 12 DELs.
Notez que les broches 7 et 8 du MCU ne sont pas utilisées pour le multiplexeur. La raison en est qu'elles ne sont pas configurable en mode sortie push-pull. Ce sont des broche open drain conçues pour les bus I2C.
À un instant donné une seule DEL peut-être allumée mais en faisant fonctionner le multiplexeur rapidement avec la persistance de la vision on peut créer l'illusion qu'elles sont toutes allumées en même temps.
Circuit de démonstration
interconnection des DELs
Dans la table suivante C est pour cathode et A pour anode.
PA0
PA2
PB5
PB6
D1C
D1A
D2A
D2C
D3A
D3C
D4A
D4C
D5A
D5C
D6A
D6C
D7C
D7A
D8C
D8A
D9C
D9A
D10C
D10A
D11C
D11A
D12A
D12C
vidéo de démonstration
Circuit version 2
J'ai fait un montage permanent avec des DELs bleus montées en cercle. Le Firmware contient un engin d'animation avec un jeu de commandes simple pour créer différentes animations.
Ce circuit utilise 3 switches boutons à contact temporaire. 2 servent pour sélectioner l'animation. Le 3ième est pour faciliter la programmation du MCU.
Description du firmware
Les fichiers du projet sont disponible ici. C'est écris en assembleur pour SDCC
La minuterie TIMER 4 est configurée pour générer une interruption à intervalle d'une milliseconde. Le fonctionnement du multiplexeur est géré par la routine d'interruption suivante. Ce code est dans le fichier hardware_init.asm
;------------------------------
; TIMER 4 is used to maintain
; timers and ticks
; interrupt interval is 1 msec
;--------------------------------
Timer4UpdateHandler:
clr TIM4_SR ; reset interrupt flag
; multiplexer control
call leds_off
ld a,mx_step
inc a
cp a,#12
jrmi 1$
clr a
4$:
; check if pause is active
btjf flags,#F_PAUSE,1$
dec pause_timer
jrne 1$
; end of pause
bres flags, #F_PAUSE
1$:
; turn on LED if bit set
; shift the corresponding bit in carry
ld mx_step, a
ldw x, led_set
tnz a
jreq 3$
2$: srlw x
dec a
jrne 2$
3$: srLw x ; now bit is in carry flag
jrnc 9$ ; bit is reset
; bit set turn on LED
ld a,mx_step
call led_on
9$: callr read_buttons
iret
La variable mx_step contient un entier dans l'intervalle {0..11} qui indique quelle DEL doit-être contrôlée à cette étape. cette valeur est incrémentée à chaque interruption de sorte que la boucle de 12 DELs est parcourue en 12 interruptions soit 12msec. Ce qui donne une fréquence du multiplexeur de 83 cycles/seconde. C'est suffisant pour éviter l'effet de scintillement.
Les bits 0..11 de la variable led_set contiennent le patron de configuration allumée/éteint des 12 DELs. Si le bit est à 0 la DEL reste éteinte et elle est allumée si le bit est à 1
L'interruption gère aussi la lecture des boutons tactiles ainsi que le délais de la routine pause qui contrôle la vitesse de l'animation.
Notez que le fonctionnement du multiplexeur est indépendant de l'animation. On pourrait mettre un patron dans la variable led_set et à partir de là faire tourner le programme dans une bouche infinie. Le résultat serait une configuration de DELs fixe. Puisque le logiciel d'animation est un programme client du multiplexeur il est dans un fichier différent, animation-demo.asm
Une animation est une liste de mots de 16 bits. Chaque mot est structuré de la façon suivante:
bits
description
0..11
ensemble de bits représentant chaque DEL, bit 0 pour la DEL 1 à bit 11 pour la DEL 12
12..15
commande
Liste des commandes
commande
valeur
description
CPY
0
copie les bits 0..11 dans la variable led_set.
INC
1
copie les bits 0..11 dans la variable led_set et incrémente la variable anim_step.
DEC
2
copie les bits 0..11 dans la variable led_set et décrémente la variable anim_step.
RST
3
Boucle l'animation à partir du début de la liste.
SPD
4
Initialise la variable anim_delay avec les bits 0..7 et incrément la variable anim_step. Ce délais détermine le temps en multiple de 12 msec entre chaque étape de l'animation.
RND
7
Initialise la variable led_set avec une valeur aléatoire.
Le bit 15 de chaque commande est appellée INV et a pour effet lorsqu'il est à 1 d'inverser les bits 0..11 avant de les copier dans anim_step.
La variable anim_step est lue et sert à indexer la table de l'animation dont l'adresse est conservée dans la variable anim_table. Les bits 12..15 sont extrait et un sélecteur de commande est utilisé pour sélectionner le code à exécuter pour cette commande. Pour les commandes 0..3 ainsi que 7 la routine pause est appellée pour générer un délais avant l'exécution de la prochaine commande. Ce délais est consrvé dans la variable anim_delay et contrôle la vitesse d'exécution de l'animation.
La liste des animations disponible est conservée dans la table anim_list et l'animation désirée est sélectionnée en utilisant les boutons btn1 et btn2. Au démarrage c'est la première animation de la liste qui est active. btn1 descend dans la liste et btn2 remonte. L'indice de l'animation active est conservé dans la variable anim_select.