I2C + ds1307 + LCD = ... le bazard

bonjour à tous

pour mon projet de régulation de chauffage j’utilise un LCD en I2C, ainsi qu’une horloge DS1307

à priori ça semblait fonctionner pas trop mal, sauf que de temps en temps, j’ai le 1307 qui fait totalement n’importe quoi. Ca a commencé quand j’ai rallongé mon bus I2C pour déporter l’écran. Avec une longueur d’environ 2m, rien de bien énorme non plus.
L’écran lui fonctionne normalement, j’ai même rajouté un second écran “local” (en plus de celui déporté), les deux fonctionnent (sur la même adresse) et affichent bien la même chose.
Mais le DS1307, non, lui il part en sucette et transmet des valeurs totalement fantaisistes (par exemple heure à 85, etc etc). Et une fois qu’il est parti en vrille, la seule solution est de lui enlever la pile pour le remettre à zéro, sinon rien à faire il n’est plus possible de régler aucune valeur.

J’ai essayé de diminuer la vitesse du bus avec Wire.setClock(10000); mais ça ne change rien.

Du coup j’ai supprimé ma rallonge et gardé uniquement l’écran “local” de manière à revenir à la configuration initiale, et… c’est mieux mais ça foire toujours !

Donc je ne sais pas trop, est-ce le DS1307 qui est défectueux ? Un problème sur mon bus I2C, par exemple les résistances de tirage de valeur inadaptées ? Actuellement il y a à priori des réistances partout : sur le shield avec le DS1307, et sur les deux écrans. J’ai lu je ne sais plus où qu’avec une liaison un peu longue ce n’est pas plus mal d’'avoir des résistances aux deux bouts, c’est ce que j’ai. Mais du coup je me dis que si il y en a plusieurs, il faudrait en augmenter la valeur… actuellement il y a sur les écrans des 4,7k (du moins c’est ce que je mesure à l’ohmetre entre scl/sda et Vcc, parceque pour ce qui est de lire la valeur sur les CMS, mes yeux n’ont plus envie…) et pareil sur le shield avec le DS1307

Donc concrètement… je fais quoi ? je vire les résistances du DS1307 et je ne garde que celles des deux écrans?

L’I2C a été prévue pour des liaisons entre circuits intégrés sur une même carte.
Donc 2 m c’est extrêmement long :frowning:

Le coté génial de l’I2C est l’emploi de collecteur ouvert qui permet de réaliser des fonctions OU câblé sans aucun élément externe, donc un gain de place sur les cartes.

Son défaut (question portée) c’est les collecteurs ouverts, pas de chance.
Un collecteur ouvert muni de sa résistance de collecteur n’est rien d’autre qu’un transistor qui fonctionne en émetteur commun.
J’ai bien “résistance de collecteur” et non pas pull-up, terme que je hais car il fait perdre la réalité de l’électronique.

On a donc un système : émetteur, canal de transmission, récepteur.
Émetteur :
L’impédance de sortie d’une émetteur commun est justement égal à la résistance de collecteur (raison de plus pour haïr le terme pull-up en dehors du domaine purement numérique de fixation de niveau logique)

Récepteur :
L’impédance d’entrée d’un récepteur I2C est égal à une très forte impédance (dont on peut négliger le rôle) et une capacité parasite.

Origine du défaut :
La capacité parasite devra se charger à travers la résistance de collecteur. Donc si la constante de temps T= R*C est trop grande (R ou C trop grand) les fronts des signaux I2C seront écroulés et les signaux seront incompréhensibles.

Liaison :
Il faut ajouter l’inductance de fils et encore de la capacité parasite entre fils.
Donc plus le fil est long plus il y a de défaut.

Conseils :
Difficile d’en donner parce que je n’ai pas vraiment eu d’expérience avec l’I2C en grande longueur mais au vu de ce que je connais par ailleurs je dirai (en mon âme et conscience)

  1. Câbler plutôt les modules en étoile afin de séparer les connexions longues et courtes.

  2. Adapter au cas par cas les valeurs des résistances de collecteur.
    C’est à dire conserver un bon temps de charge → si la capa augmente on diminue la résistance.

Garder 10k pour les distances courtes (<20/30 cm) et diminuer pour les liaisons longues.
Tout en gardant en mémoire que du point de vue courant toutes les résistances se retrouve en parallèle et donc attention à ne pas faire passer trop de courant dans les transistors.

Sous 5V une résistance équivalente de 1 k ne provoque pas plus de 5 mA ce n’est pas non plus la mer à boire.
Mais 100 ohms c’est plutôt à éviter :grin:.

Sinon si cela ne fonctionne toujours pas il existe des circuits intégrés dédiés pour augmenter la portée des liaisons I2C.

ben ce qui me turlupine, c'est que le DS1307 lui il est sur un shield, donc directement empilé sur la carte mega2560.

les deux écrans sont au bout de fils, l'une d'une vingtaine de cm (juste de quoi ouvrir le couvercle de la boite sans le débrancher) et l'autre au bout du fil de 2m (un câble réseau).
Je crois par contre que j'ai cablé scl et sda sur la même paire torsadée, ce qui n'est sans doute pas optimal du point de vue de la capa parasite... cela dit, même en débranchant ce long fil de l'arduino, ça merde toujours...

Et pourtant les deux écrans fonctionnent à la perfection, même en changeant de page rapidement pour stresser un peu le bus, pas de soucis.

Par contre le DS1307 part en sucette sévèrement.

Et comme je disais, même en débranchant le long fil, ça foire encore. Moins, mais quand même.

La avec les 3 appareils connectés, j'ai donc trois résistances de 4,7k, ce qui me donne au final 1,57k si j'ai pas tout oublié, à priori ça reste dans les limites acceptables, non ?

Penses-tu qu'il soit utile que je vire celles sur le DS1307 pour ne garder que celles des écrans, donc au bout des fils ? Pourtant à priori ça devrait plutot aller mieux avec une résistance globale plus faible, si j'ai bien suivi ?

Je m’occuperai en priorité du fil de 2m en débranchant les deux autres modules I2C.
Ce sera leur tour après → une chose à la fois.
Je propose en priorité le module au bout de 2 m car si cela ne fonctionne pas ce n’est pas la peine de perdre du temps avec les autres, il faudra trouver une autre solution.

Première vérif indispensable : le module qui doit fonctionner au bout de 2 m fonctionne -t-il au bout de 20 cm ?
J’espère que oui.
Essaye ensuite d’augmenter la distance progressivement
Si cela ne fonctionne pas diminue la valeur des résistances jusqu’à 1 k.
Note importante :
C’est de la mise au point, c’est toi qui voit le résultat des tests, tu as le droit de prendre des initiatives en fonction de ce que tu constate.
Et n’hésite pas à recommencer un test si jamais tu as un doute.

J’ai des questions sur les alim parce que la sensibilité des accès I2C est bien moins souple que celles des mêmes entrées en mode numérique classique.
Quelles sont les valeurs d’alim ?
Comment sont alimenté les 3 modules I2C ?
A partir de quoi : alim extérieure, 5V de la carte ? autres possibilités ?

Un schéma serait le bienvenu ( c’est bien plus facile de lire un schéma que 25 lignes de texte)

il y a un transfo 6V (qui délivre en fait 11v) qui alimente la carte arduino. C'est donc le régulateur intégré qui fournit l'alim 5v. Mais quand j'alimente le montage via le câble USB ça ne change rien, que ce soit depuis le PC ou depuis une alim USB type chargeur de portable

Le module au bout du cable de 2m fonctionne parfaitement ! c'est bien le problème, justement, sinon j'aurais compris.

Je résume, j'ai :

un DS1307 directement sur un shield empilé sur la carte mega. c'est lui qui foire
un écran LCD au bout d'un fil de 20cm -> ok
un autre écran LCD (identique) au bout d'un fil de 2m -> ok aussi

le problème du DS1307 à commencé quand j'ai rajouté le fil de 2m. Mais maintenant quand je le supprime ça continue à déconner.

Je vais essayer avec un autre module RTC.

je viens de mesurer le 5V est à 4,91 sur l’alim externe, ou 4,95 sur l’USB. rien d’alarmant de ce coté il me semble. je n’ai ps l’oscillo sous la main pour vérifier la stabilité, par contre.

voila le montage (sans l’écran le plus proche)

et ce qui se passe pour le DS1307…

à noter aussi que quand le DS1307 part en sucette, de temps en temps ça me bloque aussi l’arduino qui ne réagit plus au codeur, impossible de sortir du menu autrement que par un reset de la carte. Mais pas à tous les coups.
Par exemple là c’est bloqué, et le curseur est passé de lui même du champ heure au champ mois juste avant que ça freeze. Pourtant pour changer de champ je dois normalement appuyer sur le bouton du codeur.

Peut-être est-ce ma méthode de réglage de l’heure qui induit aussi trop de com sur le bus ? ce que je fais c’est à chaque incrément détecté sur le codeur :
-je lis la valeur dans le DS1307
-je l’incrémente de 1
-je l’écris dans le DS1307
-je la relis pour l’afficher

ce qui me permet d’avoir la même fonction qui se charge de ça pour tous les champs de l’heure à l’année, car les bornes de la valeur sont fixées par le DS1307 : si on lui envoie une valeur > ou < au maxi possible pour le champ, il prends la valeur mini/maxi possible.
Ainsi si j’essaye par exemple d’envoyer 24 ou -1 dans le champ heure, il restera de lui même à 23 ou 0, comme je le relis avant de l’afficher, ça me limite tout seul sans faire un test avant d’envoyer la valeur.

Quand ça part en vrille ce n’est pas forcément en cas de dépassement de valeur maxi, ça le fait n’importe quand à la faveur d’une écriture, et tous les champs délirent en même temps. Pourtant quand j’écris une valeur, je n’écris que le champ concerné, les autres sont simplement relus

Le module au bout du cable de 2m fonctionne parfaitement ! c'est bien le problème, justement, sinon j'aurais compris.

J'avais compris qu'il ne fonctionnait pas.

le problème du DS1307 à commencé quand j'ai rajouté le fil de 2m. Mais maintenant quand je le supprime ça continue à déconner.

Cela peut sentir la fausse manip !

un DS1307 directement sur un shield empilé sur la carte mega. c'est lui qui foire
.........................
Je vais essayer avec un autre module RTC.

C'est un bon choix de manip.
Ce n'est pas nécessaire que ce soit un module RTC, n'importe qu'el module I2C conviendra et permettra de vérifier si la carte est toujours fonctionelle.

Les écrans ils fonctionnent ?
As tu lancé un coup de scanner I2C pour voir si les modules sont reconnus ?
Le Ds1307 est souvent accompagné d'une Eeprom ( pratique pour enregistrer la date de remise à l'heure pour surveiller les dérives) s'il y en a une est-elle reconnue ?

Au passage si tu en as la possibilité change le DS1307 par un DS3231 qui est beaucoup plus précis.
Il a juste les quelques octets de ram sauvegardée en moins.

j’ai un 3231 mais il faut que je change de lib, pour le 1307 j’utilisais la mienne. du coup je dois modifer mon programme un peu partout, mais ça sera sans doute mieux au final

pas d’eeprom sur mon shield, juste le 1307 et un support SD qui ne fonctionne pas sur la mega en softSPI, (alors que sur la uno il marche impec, j’avais ouvert un sujet là dessus…) du coup j’ai rajouté un second module SD sur les pins SPI de la mega.

les écrans fonctionnent parfaitement, tous les deux. Donc à priori la méga est toujours fonctionelle.
J’en met deux car le boitier principal sera dans la chaufferie, et il y aura juste le petit boitier qui sera dans la maison, derrière le mur. Et le mur fait 1m20 d’épaisseur, d’où la longueur du câble…
Et pour ajuster les réglages si il faut contourner toute la baraque pour rentrer à chaque valeur à changer, ça va être fastidieux !

je ferai un essai avec le scan i2C. je l’avais fait au début avant de rallonger le fil, mais à priori ça doit fonctionner puisque tant qu’il s’agit de lire l’heure ça fonctionne.

Par contre je viens de relire la datasheet du DS1307 et ma méthode de me servir de lui pour borner mes valeurs n’est à priori pas valable. Il est précisé que si la valeur envoyée est hors limites le comportement est indéfini. Mais à priori le soucis ne vient pas de là, vu que quand ça délire ça peut le faire à tout moment sur une écriture, que la valeur soit ok ou non.

68tjs:
Cela peut sentir la fausse manip !

bah à priori non, vu que l'écran au bout du fil lui a fonctionné direct

Donc en résumé :
Le système est dans la chaufferie.

  • Un écran dans la chaufferie --> Ok
  • Un écran de l'autre coté du mur de 1 m20 d'épaisseur (tu habites dans un ancien bunker ? :grin: )
  • Une horloge Ds1307 --> Ko ou c'est le shield entier qui est KO ?

Le coupable semble bien être le DS1307.
Les registres des DS1307 et Ds3231 sont les mêmes pour les fonctions calendaires, il n'y a que des fonctions supplémentaires ou en moins donc je pense que tu devrais pouvoir tester un DS3231 sur des fonctions communes comme l'heure ou la date avec ta bibliothèque actuelle.

bon alors les nouvelles : j'ai viré le 1307, remplacé par le 3231. En effet ça fonctionne avec ma librairie sans problème. Par contre... même comportement. De temps en temps ça délire.

du coup comme la le module DS3231 est débrochable, j'ai essayé de le virer (ce que je ne pouvais pas faire avec le DS1307) et surprise, les valeurs délirantes qui s'affichent sont celles qui sont lues par la lib quand le module est absent.

La différence avec le 1307 c'est que là de temps en temps les champs de l'heure restent éditables et seulement ceux de la date partent en vrille... Mais une fois en vrac il faut quand même comme avec l'autre enlever la pile pour retrouver un fonctionnement normal.

Deux modules, même librairie, même comportement... je vais essayer avec une autre lib, je crois...

Reste que le système complet se freeze de temps en temps. Je croyais que c'était que le RTC qui me causait ça, mais j'ai eu le cas dans un autre menu :frowning:

bon alors les re-nouvelles : j'ai changé de câble. là c'est un câble cat5, pourtant bien plus long (il doit faire une dizaine de mètres) et... ça fonctionne !

entre temps j'avais ajouté une fonction pour changer d'état un relais toutes les 2s de manière à vérifier lors des freeze si c'est toute la carte ou juste l'i2c qui bloquait. c'est bien toute la carte.

il me semble que les plantages arrivent quand je manipule le codeur. peut-être une interférence entre les lignes du codeur et celles de l'i2c dans le cable ?

Difficile à dire mais plus tu te rapproches des limites de fonctionnement plus les petits défauts prennent de l'importance.

mais je comprends pas pourquoi ça plante le micro. le module I2C seul peut faire bloquer tout le MCU ? manifestement oui...

Du coup faute de mieux j'ai activé le watchdog avec un timeout de 4s histoire d'avoir de la marge (les lectures de DS18B20 c'est long ! ).
Au moins si ça foire je perds probablement l'heure, mais le reste de la régul devrait repartir. Ca évitera au moins au circuit solaire de caraméliser en cas de plantage en plein soleil :stuck_out_tongue:

bricofoy:
Du coup faute de mieux j'ai activé le watchdog avec un timeout de 4s histoire d'avoir de la marge (les lectures de DS18B20 c'est long ! ).

Bonjour Bricofoy
ce qui est long avec les ds18b20 ce n'est pas la lecture , mais la conversion en interne du ds18b20

il ne faut pas faire comme la majorité des programmes :

  • envoi de la commande de conversion
  • delai d'attente bloquant (750 ms par capteur, 1seconde par securité)
  • envoi de la commande de lecture
  • lecture

mais

  • envoi de la commande conversion
  • verif si le delai de conversion est écoulé
    -- si oui
    -- commande lecture
    -- lecture

c’est ce que je fais :wink:

j’ai même une machine à états juste pour ça dans mon soft :

////////////////////////gettemp state machine///////////////////////////////////
//
void gettemp_start()
{
	sensors.begin(); // Start up the dallas library
	sensors.setWaitForConversion(false); //don't wait !
	loadSensorsAddresses(); //fill the addresses array with the values in EEPROM
	setSensorsResolution();
	gettemp.next(gettemp_request);
}	

void gettemp_request()
{
	sensors.requestTemperatures();
	gettemp.next(gettemp_wait);
}

void gettemp_wait()
{	//we need to wait that time for conversion to finish
	if (gettemp.elapsed(750/(1<<(12-TEMPERATURE_RESOLUTION))))
		gettemp.next(gettemp_read);
}

void gettemp_read()
{
	byte i=gettemp.runCount();
	if (i<SENSOR_NBR)
	{
		if(!TForce[i])
			T[i] = sensors.getTempC(sensorAddress[i]);
	}
	else gettemp.next(gettemp_request);
}

malgré tout, lire les 10 sondes de temps en temps ça rame