L'objectif n'était pas de réaliser un instrument de mesure professionnel, mais plutôt de concevoir un appareil simple permettant de relever une couleur et d'en obtenir une représentation numérique. Cette information peut ensuite être réutilisée dans différents contextes, par exemple pour retrouver sur un site internet une couleur observée sur une création.
Pour parvenir à un appareil réellement portable et agréable à utiliser, plusieurs contraintes se sont naturellement imposées :
La réalisation de cet appareil a ainsi constitué un projet particulièrement intéressant, mêlant capteur de couleur, traitement des mesures, électronique embarquée et conception d'une interface utilisateur.
Plutôt qu'une pile bouton type CR2032, j'ai choisi un accumulateur Li-ion 2032 rechargeable, pour les raisons suivantes :
Un connecteur USB-C permet la recharge.
Afin de minimiser la consommation, j'ai intégré un écran e-paper :
Le capteur retenu est le TCS3400 (anciennement Osram / ams). Il fournit :
Ce capteur permet des mesures colorimétriques de base, mais ne correspond pas directement à la réponse spectrale de l'œil humain.
Pour assurer une mesure stable :
Objectif : se rapprocher des conditions d'un illuminant standard D65.
Le système :
Points critiques à considérer :
La première étape consiste à normaliser les valeurs. Plusieurs approches sont possibles :
Étape 1 : correction offset + gain via références noir/blanc. Mesures de référence :
Formule type (identique pour G et B) :
Rcorr = Rmes − Rnoir RBlanc − RNoir
Vérification impérative :
Pour les capteurs RGB filtrés (comme le TCS3400), une pratique robuste consiste à combiner la correction noir avec une normalisation par la composante Clear :
RCORR = Rmes − Rnoir Cmes − Cnoir
GCORR = Gmes − Rgreen Cmes − Cgreen
BCORR = Bmes − Rblue Cmes − Cblue
On cherche une matrice 3×3 de passage :
X Y Z = M · Rcorr Gcorr Bcorr
La matrice M est déterminée par régression en moindres carrés à partir d'un jeu de patchs de référence, par exemple le ColorChecker Classic.
Soit :
R = [r1 ... rN] avec ri = [Rcorr, Gcorr, Bcorr]T
On minimise :
‖X − MR‖F
Solution analytique (moindres carrés) :
M = X · R+
où R+ est la pseudo-inverse de Moore-Penrose de R. De façon équivalente, lorsque R·RT est inversible :
M = XRT(RRT)−1
En pratique, ce calcul se fait simplement avec numpy :
M = X @ np.linalg.pinv(R)
Utilisation du modèle CIE 1931 (observateur 2°, illuminant D65). L'espace CIELAB (L*, a*, b*) est conçu pour correspondre à la perception visuelle :
Formules (simplifiées) :
L* = 116 · f(Y / Yn) − 16
a* = 500 · [f(X / Xn) − f(Y / Yn)]
b* = 200 · [f(Y / Yn) − f(Z / Zn)]
où Xn, Yn, Zn sont les coordonnées du blanc de référence (illuminant D65).
Une fois la couleur exprimée en CIELAB, il suffit de comparer la valeur mesurée avec une base de données des couleurs RAL (dont les valeurs CIELAB sont disponibles publiquement). La proximité entre deux couleurs est évaluée par une distance ΔE.
Deux méthodes :
ΔE76 = (L*1 − L*2)2 + (a*1 − a*2)2 + (b*1 − b*2)2
La couleur RAL retenue est celle qui minimise ΔE avec la mesure.
Une fois la couleur mesurée :
⚠️ Limitation : une LED RGB standard ne peut pas reproduire toutes les couleurs (gamut limité). Certaines teintes sortiront donc approximatives.
| Référence | R | G | B |
|---|---|---|---|
| Blanc | 987 | 1011 | 924 |
| Noir | 20 | 21 | 18 |
| # | Red | Green | Blue | Rcorr | Gcorr | Bcorr |
|---|---|---|---|---|---|---|
| 1 | 142 | 103 | 82 | 0.1262 | 0.0828 | 0.0706 |
| 2 | 417 | 291 | 236 | 0.4105 | 0.2727 | 0.2406 |
| 3 | 164 | 221 | 264 | 0.1489 | 0.2020 | 0.2715 |
| 4 | 117 | 135 | 85 | 0.1003 | 0.1152 | 0.0740 |
| 5 | 286 | 307 | 335 | 0.2751 | 0.2889 | 0.3499 |
| 6 | 288 | 487 | 399 | 0.2771 | 0.4707 | 0.4205 |
| 7 | 561 | 221 | 131 | 0.5595 | 0.2020 | 0.1247 |
| 8 | 101 | 144 | 238 | 0.0838 | 0.1242 | 0.2428 |
| 9 | 468 | 160 | 174 | 0.4633 | 0.1404 | 0.1722 |
| 10 | 105 | 92 | 119 | 0.0879 | 0.0717 | 0.1115 |
| 11 | 324 | 399 | 187 | 0.3144 | 0.3818 | 0.1865 |
| 12 | 595 | 331 | 153 | 0.5946 | 0.3131 | 0.1490 |
| 13 | 44 | 80 | 181 | 0.0248 | 0.0596 | 0.1799 |
| 14 | 128 | 213 | 114 | 0.1117 | 0.1939 | 0.1060 |
| 15 | 369 | 86 | 87 | 0.3609 | 0.0657 | 0.0762 |
| 16 | 628 | 492 | 190 | 0.6287 | 0.4758 | 0.1898 |
| 17 | 303 | 138 | 209 | 0.2927 | 0.1182 | 0.2108 |
| 18 | 102 | 228 | 293 | 0.0848 | 0.2091 | 0.3035 |
| 19 | 753 | 773 | 701 | 0.7580 | 0.7596 | 0.7539 |
| 20 | 495 | 511 | 472 | 0.4912 | 0.4949 | 0.5011 |
| 21 | 320 | 340 | 317 | 0.3102 | 0.3222 | 0.3300 |
| 22 | 201 | 212 | 198 | 0.1872 | 0.1929 | 0.1987 |
| 23 | 110 | 113 | 104 | 0.0931 | 0.0929 | 0.0949 |
| 24 | 59 | 60 | 52 | 0.0403 | 0.0394 | 0.0375 |
| # | Nom du patch | R | G | B | Rnor | Gnor | Bnor |
|---|---|---|---|---|---|---|---|
| 1 | Dark Skin | 115 | 82 | 68 | 0.4510 | 0.3216 | 0.2667 |
| 2 | Light Skin | 194 | 150 | 130 | 0.7608 | 0.5882 | 0.5098 |
| 3 | Blue Sky | 98 | 122 | 157 | 0.3843 | 0.4784 | 0.6157 |
| 4 | Foliage | 87 | 108 | 67 | 0.3412 | 0.4235 | 0.2627 |
| 5 | Blue Flower | 133 | 128 | 177 | 0.5216 | 0.5020 | 0.6941 |
| 6 | Bluish Green | 103 | 189 | 170 | 0.4039 | 0.7412 | 0.6667 |
| 7 | Orange | 214 | 126 | 44 | 0.8392 | 0.4941 | 0.1725 |
| 8 | Purplish Blue | 80 | 91 | 166 | 0.3137 | 0.3569 | 0.6510 |
| 9 | Moderate Red | 193 | 90 | 99 | 0.7569 | 0.3529 | 0.3882 |
| 10 | Purple | 94 | 60 | 108 | 0.3686 | 0.2353 | 0.4235 |
| 11 | Yellow Green | 157 | 188 | 64 | 0.6157 | 0.7373 | 0.2510 |
| 12 | Orange Yellow | 224 | 163 | 46 | 0.8784 | 0.6392 | 0.1804 |
| 13 | Blue | 56 | 61 | 150 | 0.2196 | 0.2392 | 0.5882 |
| 14 | Green | 70 | 148 | 73 | 0.2745 | 0.5804 | 0.2863 |
| 15 | Red | 175 | 54 | 60 | 0.6863 | 0.2118 | 0.2353 |
| 16 | Yellow | 231 | 199 | 31 | 0.9059 | 0.7804 | 0.1216 |
| 17 | Magenta | 187 | 86 | 149 | 0.7333 | 0.3373 | 0.5843 |
| 18 | Cyan | 8 | 133 | 161 | 0.0314 | 0.5216 | 0.6314 |
| 19 | White | 243 | 243 | 242 | 0.9529 | 0.9529 | 0.9490 |
| 20 | Neutral 8 | 200 | 200 | 200 | 0.7843 | 0.7843 | 0.7843 |
| 21 | Neutral 6.5 | 160 | 160 | 160 | 0.6275 | 0.6275 | 0.6275 |
| 22 | Neutral 5 | 122 | 122 | 122 | 0.4784 | 0.4784 | 0.4784 |
| 23 | Neutral 3.5 | 85 | 85 | 85 | 0.3333 | 0.3333 | 0.3333 |
| 24 | Black | 52 | 52 | 52 | 0.2039 | 0.2039 | 0.2039 |
Pour construire la matrice M, j'ai utilisé un script Python (nécessite la
librairie numpy) :
np.linalg.pinv). Exemple de résultat obtenu pour M :
M = 1.72431563 0.27218649 0.18021445 −0.5794922 1.26611686 −1.1258736 0.53206025 0.21724840 2.68620501
Rappel : soit une matrice 3×3 M et un vecteur colonne v :
M = a b c d e f g h i v = x y z
Le produit M·v donne un nouveau vecteur v' :
v' = M · v = a·x + b·y + c·z d·x + e·y + f·z g·x + h·y + i·z
// Multiplie une matrice 3x3 par un vecteur colonne 3x1
void mat3x3_vec3_mult(const float mat[3][3], const float vec[3], float result[3])
{
for (uint8_t i = 0; i < 3; ++i)
{
result[i] = 0.0f;
for (uint8_t j = 0; j < 3; ++j)
{
result[i] += mat[i][j] * vec[j];
}
}
}
L’alimentation du module est assurée par un accumulateur rechargeable LIR2032, une pile bouton lithium-ion de 3,6 V et d’une capacité typique de l’ordre de 40 mAh. Sa faible taille permet de conserver un format compact tout en offrant une alimentation autonome pour le module.
La recharge de l’accumulateur est assurée par le MCP73831-2-OT, un circuit intégré spécialement conçu pour la gestion de la charge des accumulateurs lithium-ion et lithium-polymère à cellule unique. Il fonctionne selon un profil de charge courant constant / tension constante (CC/CV) et intègre la régulation de la tension de charge ainsi que la limitation du courant.
Dans cette application, le MCP73831-2 est configuré pour une tension de charge adaptée à l’accumulateur LIR2032. Le courant de charge est défini par une résistance externe, ce qui permet d'adapter la recharge aux caractéristiques de l’accumulateur. Le circuit fournit également une sortie d’état permettant d’indiquer le déroulement de la charge et sa fin.
Cette solution présente l’avantage de regrouper la gestion complète de la recharge dans un composant très compact, tout en nécessitant peu de composants externes.
Deux transistors MOSFET Q3 et Q4, commandés par le microcontrôleur, permettent de couper complètement l’alimentation du circuit lorsque celui-ci passe en veille profonde. Cette fonction permet couper la consommation de l’accumulateur pendant les périodes d’inactivité.
Un petit bouton-poussoir permet de réveiller le système lorsqu’il est en veille et, lorsque celui-ci est actif, de déclencher une nouvelle mesure.
La tension fournie par l’accumulateur est ensuite régulée à 3,3 V par un régulateur linéaire LDK130, afin d’assurer une alimentation stable aux différents composants du module.
Le microcontrôleur STM32L432KCUx, choisi pour sa très faible consommation, assure la gestion de l'ensemble du système. Il pilote notamment l'afficheur e-paper E2154 ainsi que le capteur de couleur TCS34003FNM. Il permet également de reproduire la couleur mesurée à l'aide d'une LED RGB APTF1616LSEKJ3ZGKQBC.
L'afficheur e-paper E2154 a été retenu principalement pour sa très faible consommation et sa bonne lisibilité. Contrairement à un écran traditionnel, l'image reste visible sans que l'afficheur ait besoin d'être alimenté en permanence. Une fois l'information affichée, la consommation devient pratiquement nulle.
L'écran permet ainsi d'afficher les différentes informations de mesure, notamment les valeurs des composantes de couleur.
L'éclairage de la zone de mesure est assuré par six LED CSL1101WBBW1, dont les caractéristiques spectrales sont particulièrement proches de celles de l'illuminant standard D65.
Cette vue présente l’implantation des composants sur le circuit imprimé.
Une partie des composants est également placée sur la face inférieure du PCB.
Le display, quant à lui, vient simplement se poser sur une mousse de 3 mm d’épaisseur,
qui assure son maintien et son appui.
| ID | Designator | Empreinte | Qté | Désignation |
|---|---|---|---|---|
| 1 | BT1 | SMTU2032C | 1 | LIR2032 |
| 2 | C1, C2 | C_0805 | 2 | 1 µF |
| 3 | C3 | C_0805 | 1 | 100 nF |
| 4 | C4, C6 | C_1206 | 2 | 4.7 µF / 50 V |
| 5 | C5 | CP_EIA-7343-15 | 1 | 470 µF |
| 6 | C7, C20 | C_0805 | 2 | 10 nF |
| 7 | C8, C16, C18 | C_1206 | 3 | 10 µF |
| 8 | C9, C10, C11, C12, C13, C14, C15 | C_0805 | 7 | 1 µF / 25 V |
| 9 | C17, C21 | C_0805 | 2 | 100 nF |
| 10 | C19 | C_1206 | 1 | 1 µF / 6.3 V |
| 11 | D1, D2, D3 | SOD-123 | 3 | MBR0530 |
| 12 | D4, D5, D6, D7, D9 | LED_CSL1104 | 5 | LED |
| 13 | D8 | LED_CSL1104 | 1 | CSL1101WBBW1 |
| 14 | D10 | LED_PGCTR_LUM | 1 | SML-LXIL0603UPGCTR |
| 15 | D11 | D_SMA | 1 | SS22 |
| 16 | H2 | FFC24-0.5 | 1 | e-Paper E2154 |
| 17 | IC1 | TCS34003FNM | 1 | TCS34003FNM |
| 18 | J1 | Socket 2x05 1.27 mm | 1 | Connecteur de programmation |
| 19 | J2 | USB-C | 1 | USB-C Power Only |
| 20 | L1 | INDPM6868X420N | 1 | 68 µH |
| 21 | LED1 | APTF1616LSEKJ3ZGKQBC | 1 | APTF1616LSEKJ3ZGKQBC |
| 22 | Q1 | SOT-323 | 1 | Si1308EDL |
| 23 | Q2, Q4 | SOT-23 | 2 | IRLML6244 |
| 24 | Q3 | SOT-23 | 1 | IRLML6402 |
| 25 | R1, R2, R3, R4, R6, R11 | R_0805 | 6 | 820 Ω |
| 26 | R5 | R_0805 | 1 | 0.47 Ω |
| 27 | R7 | R_0805 | 1 | 10 Ω |
| 28 | R8, R10, R24 | R_0805 | 3 | 4.7 kΩ |
| 29 | R9 | R_0805 | 1 | 75 kΩ |
| 30 | R12, R15, R16, R17 | R_0805 | 4 | 51 kΩ |
| 31 | R13 | R_0805 | 1 | 10 kΩ |
| 32 | R14 | R_0805 | 1 | 2.2 kΩ |
| 33 | R18 | R_0805 | 1 | 600 Ω |
| 34 | R19, R20 | R_0805 | 2 | 150 Ω |
| 35 | R21 | R_0805 | 1 | 62 kΩ |
| 36 | R22 | R_0805 | 1 | 200 kΩ |
| 37 | R23 | R_0805 | 1 | 100 kΩ |
| 38 | SW1 | B3FS-100xP | 1 | SW_MEC_5G |
| 39 | TP1, TP8 | Picot low | 2 | VDD |
| 40 | TP2, TP9 | Picot low | 2 | GND |
| 41 | TP3 | Picot low | 1 | I2C1_SCL |
| 42 | TP4 | Picot low | 1 | MOSI |
| 43 | TP5 | Picot low | 1 | CS |
| 44 | TP6 | Picot low | 1 | SCK |
| 45 | TP7 | Picot low | 1 | I2C1_SDA |
| 46 | TP10 | Picot low | 1 | BUSY |
| 47 | U1 | SOT-23-5 | 1 | LDK130 |
| 48 | U2 | QFN-32 5×5 mm | 1 | STM32L432KCUx |
| 49 | U3 | SOT-23-5 | 1 | MCP73831-2-OT |
Le boîtier a été entièrement modélisé sous FreeCAD à partir des dimensions du circuit imprimé. J'ai conçu les différentes parties du boîtier afin qu'elles s'adaptent précisément à la carte et aux composants. Le modèle a ensuite été exporté et imprimé en 3D pour réaliser le boîtier final.
Les fichiers nécessaires à la reproduction de ce projet sont réservés aux membres du site.
Schéma, circuit imprimé et fichier projet KiCad.
🔒 Connexion nécessaireCode source C du microcontrôleur et fichiers associés.
🔒 Connexion nécessaireModèles STEP pour la CAO et fichiers 3MF prêts à imprimer.
🔒 Connexion nécessaire