Pour faire suite à notre introduction au bus I2C, nous allons creuser un peu plus en détail un cas particulier qui pose souvent des problèmes: l'utilisation de longs fils pour des communications avec I2C. C'est notamment un cas de figure que vous pourriez être amenés à rencontrer avec les capteurs Yoctopuce dotés d'une partie sécable, si vous décidez de déporter le capteur de plusieurs mètres.
A l'origine, le bus I2C a été conçu pour une communication entre des puces d'un même circuit, donc sur des distances de quelques dizaines de centimètres. Mais l'apparente robustesse de ce protocole permet d'imaginer de l'utiliser au-delà, typiquement pour positionner un capteur à quelques mètres. Alors, comment connaître la limite ?
Problèmes potentiels
Lorsqu'on utilise un long bus pour transmettre des signaux, différents problèmes peuvent affecter l'intégrité du signal:
- La capacitance du câble, qui ralentit les flancs du signal
- L'inductance du câble, qui provoque des undershoots
- La réflexion du signal au bout du câble (écho)
- Les interférences électromagnétiques externes (EMI) sur le câble
- Les effets de bord des circuits actifs en réaction aux autres problèmes
En pratique, sur un bus I2C, ces différents problèmes n'ont pas tous la même importance...
La capacitance: problèmatique incontournable
La capacitance est un effet d'inertie entre deux fils côte à côte, qui agissent comme un condensateur. Dans le protocole I2C, les flancs descendants sont tirés activement vers la terre, et sont donc toujours assez nets. Par contre, les flancs ascendants sont générés par les résistances pull-up, qui se combinent avec la capacitance pour former un circuit "RC":
Circuit RC équivalent à une ligne I2C de 10m
Le produit de la résistance et de la capacitance des fils donne la constante de temps du circuit τ, qui détermine le temps nécessaire pour atteindre 63% de la tension. Comme la capacitance est proportionnelle à la longueur du fil, on voit venir le problème avec les longs fils: plus le câble est long, plus la constante de temps sera grande. Par exemple, sachant qu'un câble de 20m aura typiquement une capacitance de 1nF, si on utilise une résistance pull-up de 4.7kΩ, il faudra 4.7μs au signal pour atteindre 63% de la tension désirée.
C'est la raison pour laquelle les capteurs Yoctopuce sécables basés sur I2C travaillent à une fréquence d'environ 60 kHz seulement:
Capture du signal SCL d'un Yocto-Temperature déporté avec un câble de 10m (pull-up 4.7k)
Evidemment, si vous devez travailler avec un appareil existant sans pouvoir modifier la fréquence de transmission, il ne vous reste que la possibilité de renforcer les pull-ups pour baisser la constante de temps. Cela peut se faire facilement en rajoutant une résistance en parallèle aux pull-up existants dans l'appareil, entre le Vdd et chacune des lignes de données. Vous pouvez essayer 2 kΩ ou 1 kΩ, mais ne descendez pas plus bas que 690 Ω.
Pour une communication I2C fiable, la fréquence ne devrait pas dépasser 1/6τ, pour que le signal puisse atteindre 95% de la tension à chaque demi-période. Avec des pull-ups de 1 kΩ, on obtient la table de correspondance suivante entre la longueur du bus et la fréquence maximale de transmission:
Longueur du bus | Fréquence max |
---|---|
8 m | 416 kHz |
10 m | 333 kHz |
20 m | 166 kHz |
30 m | 111 kHz |
50 m | 67 kHz |
75 m | 44 kHz |
100 m | 33 kHz |
L'inductance: potentiellement problématique
L'inductance est un autre effet d'inertie, qui s'oppose aux variations rapides du courant qui circule dans un fil. Ce genre de variations se produit par exemple lorsque l'un des circuits tire une ligne du bus I2C vers la terre. L'inductance et la capacitance des fils se combinent pour former un circuit oscillant "LC", qui parasite le signal transmis par un motif très typique:
Oscillations sur le signal SCL d'un Yocto-Temperature déporté avec un câble de 10m
Pour l'illustration ci-dessus, nous avons largement grossi l'échelle de temps (un carré = 200ns). En réalité, la fréquence de ces oscillations est bien supérieure aux vitesse de communication I2C, et tant que leur amplitude reste relativement basse, elles ne sont en général pas problématiques.
Par contre, ce qui peut poser problème est le fait que la tension du signal passe en dessous de 0V (en dessous de la terre): à cause de l'inductance, la tension continue à descendre plus loin que l'émetteur ne l'a demandé: c'est un undershoot. Plus le câble sera long, plus l'inductance sera forte et plus l'undershoot sera grand. Au delà de -0.7V, la tension va se décharger dans les diodes de protection des circuits récepteurs qui, selon l'amplitude, pourraient finir par lâcher et mener à la destruction du circuit.
Pour plus de sécurité, on peut donc ajouter des diodes de protection externes entre les lignes SCL/SDA et la terre pour éviter ce cas de figure.
Les réflexions: pas très significatives
Lorsqu'un signal électrique est envoyé sur une paire de fils, il va avoir tendance à revenir en écho lorsqu'il rencontre l'extrémité, si celle-ci n'est pas terminée avec une impédance équivalente à celle du câble. Or, le standard I2C dépendant fortement de résistances pull-up spécifiées, il n'est en général matériellement pas possible de terminer un bus I2C pour éviter les échos.
Pourtant, l'écho n'est en général pas un problème sur un bus I2C. En effet, sur un câble de 10m, la réflexion du signal revient après 100ns déjà, et est faible. D'ailleurs, nous n'avons même pas réussi à vous en faire une capture d'oscilloscope, car il est assez systématiquement masqué par les oscillations LC dues à l'inductance...
Les perturbations électromagnétiques: pas très significatives
Les perturbations électromagnétiques sont des fluctuations de tensions qui peuvent apparaître spontanément sur un fil électrique, induites par les champs électromagnétiques environnants. Dans un environnement très bruité, à proximité d'équipements industriels, on pourrait observer des tensions induites sur un câble de 10m atteignant 100mV.
Mais même dans ce cas assez extrême, vu les seuils de tension définis par I2C, de telles fluctuations pourraient difficilement affecter directement l'interprétation d'un bit sur la ligne.
Néanmoins, pour éviter tout risque, et surtout pour éviter de créer EMI avec le bus I2C lui-même, pour les transmissions sur plus d'un mètre, on peut utiliser du câble réseau blindé, fait de paires torsadées: utilisez une paire pour les fils GND et SCL, et une autre paire pour les fils VDD et SDA. Vous pouvez faire cela très facilement à l'aide d'une paire d'adaptateurs RJ45
Déporter un capteur Yoctopuce facilement à l'aide d'un câble RJ45
Les répéteurs I2C: le piège
On trouve parfois sur un bus I2C des circuits répéteurs. Ils peuvent servir à changer la tension de travail sur une section du bus, à isoler électriquement une section du bus, et même à amplifier le signal pour le transmettre sur une plus grande distance. Ces circuits sont a priori très utiles, mais ils cachent un piège moins connu et plus perfide que les problèmes vus précédemment...
Un répéteur fait office de passerelle entre deux segments de bus I2C. Les lignes I2C étant bidirectionnelles, un répéteur doit donc surveiller les lignes I2C sur les deux segments, et lorsqu'il détecte qu'une ligne baisse sur un côté A, il doit la baisser sur l'autre côté B. Lorsque la ligne côté A remonte, il relâche la ligne côté B.
Principe de fonctionnement d'un répéteur I2C, dans cet exemple de A vers B
Si entre temps un autre chip du côté B maintient la ligne en bas, comme cela peut se produire naturellement lors d'une communication I2C, alors le répéteur doit rebaisser la ligne côté A immédiatement, avant que le circuit côté A ait eu le temps de réaliser qu'elle avait commencé à monter. Pour cette raison, les répéteurs doivent réagir aux changements du bus avec des tolérances de temps très serrées, même lorsque la fréquence de transmission est relativement basse.
Cas particulier demandant une réaction rapide en retour de B vers A
Mais que se passe-t-il si la ligne a une forte capacitance, et remonte plus lentement que d'habitude ? Lorsque le répéteur relâche la ligne, si elle ne monte pas assez vite, le répéteur va considérer qu'un autre nœud est en train de la tirer vers le bas. Il va donc tirer la ligne de l'autre côté vers le bas, causant une erreur de transmission.
Confusion causée par une ligne à forte capacitance
Voici un exemple que l'on peut observer si l'on déporte le capteur sécable du Yocto-Meteo-V2 de 10m ou plus:
effet de bord du changeur de niveau I2C présent dans le capteur du Yocto-Meteo-V2
La remontée un peu trop lente de la ligne SCL cause une hésitation du répéteur/changeur de niveau, qui crée une large oscillation "LC" traversant les seuils de tension définis par I2C. Le répéteur ne transmet pas cette hésitation de l'autre côté du bus qu'il contrôle, mais elle affecte par contre les autres capteurs présents sur le bus en créant des fausses impulsions d'horloge.
Au final, le répéteur sur lequel on pourrait espérer s'appuyer pour gérer un long bus peut donc s'avérer contre-productif sur d'autres nœuds, à cause de ses effets de bord. C'est en particulier le cas dans les configurations de bus en étoile, où la disposition de plusieurs répéteurs en parallèle représente un risque majeur d'interférences mutuelles s'ils n'ont pas été choisis et testés en connaissance de cause.
Solutions pratiques
Concrètement, pour venir à bout de ces problèmes, il faut procéder méthodiquement:
- Procurez-vous une paire d'adaptateurs RJ45 (RJ45-Adapter ou équivalent) pour les monter aux deux côtés de votre bus I2C, et des câbles réseau de différentes longueurs (1m, 2m, 5m, 10m, 20m). Ainsi vous pourrez facilement répéter des expériences avec différentes longueurs de bus.
- Procurez-vous des résistances à fil de 3kΩ, 2kΩ, 1kΩ et 690Ω (une paire de chaque).
- Commencez par reproduire un état simple qui fonctionne, sans rajouter de pull-up, avec un câble de 1m, et vérifiez le bon fonctionnement de l'appareil.
- Augmentez progressivement la longueur du bus, et vérifiez si le fonctionnement de l'appareil est affecté. Si vous utilisez un capteur Yoctopuce, ouvrez la fenêtre de logs du module: elle y indique toutes les erreurs de communication I2C et vous permettra donc de détecter les premières erreurs conduisant à des retransmissions, avant même qu'elles soient clairement apparentes à l'utilisation du module.
- Quand la première erreur de transmission apparaît, essayez d'ajouter une paire de résistances pull-up de 3kΩ. Vous pouvez les insérer directemant dans le bornier de l'adaptateur RJ45 (du côté alimenté du bus, en parallèle avec les pull-up existants). Si cela ne suffit pas, remplacez-les par 2kΩ ou 1kΩ
- Continuez ainsi à allonger le bus et à baisser la valeur des pull-up pour trouver la limite utilisable de votre appareil.
Si vous avez la possibilité de ralentir la vitesse de communication, c'est de toute manière souhaitable. Mais évidemment, ce n'est pas toujours possible si ce n'est pas vous qui avez conçu l'appareil. Si vous utilisez un Yocto-I2C pour communiquer sur le bus I2C, vous pouvez facilement changer la vitesse de communication dans la configuration du module. Sachez qu'en dessous de 62 kHz, le Yocto-I2C bascule dans un mode bit-banging, où il ne surveille plus chaque transition sur le bus mais lit l'état des lignes après chaque demi-période. Il sera donc plus robuste aux éventuelles hésitations des répéteurs I2C si vous choisissez de travailler à faible vitesse, comme 10 kHz ou même 1 kHz.
Au final, si vous ne trouvez pas de solution pour allonger votre bus avec cette méthode, il vous reste la possibilité de brancher un oscilloscope: en voyant le signal, on comprend toujours mieux ce qui se passe. Et si le problème parait insoluble, reposez-vous sérieusement la question de savoir si I2C est vraiment le bon protocole pour votre application. Les standards RS485 et SDI-12 sont clairement mieux conçus pour transmettre des informations sur des grandes distances.