J’ai préparé mes réponses et commentaires que je copie tels quels. Je ne sais pas si c’est la façon de procéder sur le forum. Merci de m’éclairer.
Maintenant, je vais modifier le code et le montage en conséquence et revenir avec le résultat.
1 - Pilotage du point décimal
Supprimer les lignes de code concernées
Modifier le circuit en reliant directement la résistance au 5 volts
const int alim_signe = 10; // le signe (—— ) si nécessaire
Je ne le vois pas sur ton schéma de montage, et je pense effectivement que tu n’en n’a pas besoin, tu peux le piloter directement de ton aduino, les pilotages des alimentations afficheurs sont là parce qu’ils se partagent le même décodeur, or celui du signe n’en a pas besoin.
Par conséquent, ça ne sert pas non plus de le piloter
// initialisation de la broche du point décimal DP int PTdecimal = 13 ;
à priori tu n’as pas l’air de vouloir changer de précision dans l’affichage, alors pourquoi le rendre pilotable ? Tu pourrais l’afficher en permanence en le liant au +5V
J’avais remplacé la broche 10 par la 6, mais effectivement nul besoin de piloter le point décimal qui doit être présent de manière permanente.
2 – Signe ( — ) en cas de température négative
Supprimer le delay (5)
Ajouter cette commande pour éteindre le signe
digitalWrite(signe, LOW);
Déplacer ce bout de code au tout début de la fonction " afficher_nombre"
// Lecture d’une condition particulière pour déterminet si la température est négative
if (temp < 0 ) {
// Si c’est le cas, on allume le transistor du digit du signe négatif
digitalWrite(alim_signe, HIGH);
// on allume le segment "g" horizontal central
digitalWrite(signe, HIGH);
delay(5); }
else {
// on éteint le transistor allumé
digitalWrite(alim_signe, LOW); }
dans ton else, tu n’éteint pas le signe, ce qui explique pourquoi une fois allumé il ne s’éteint plus jamais.
Aussi, je trouve que ce bout de code devrait appartenir à afficher_nombre plutôt que de traiter la valeur absolue.
De plus, l’appel à delay(5) me parait simplement te faire perdre du temps. Les autres occurences sont justifiées car les afficheurs vont être éteint ensuite et on veut s’assurer que la LED aie eu le temps de produire la lumière et que l’observateur aie le temps de voir le chiffre s’afficher. Mais sur celle-ci, l’afficheur ne va pas être coupé, donc pas besoin de ce temps de pause.
Q 1 ? : Pourquoi le signe reste-t-il allumé si le digit n’est plus alimenté ?
3 – Affichage des valeurs négatives
Enlever cette ligne de code
3.1 –
// initialisation d’une variable temporaire de type "float" pour isoler la décimale plus tard float temporaire ;
float temporaire ;
Si ce n’est qu’une variable temporaire à un calcul, tu peux le déclarer au plus proche du calcul et éviter d’en faire une variable globale (qui est plutôt une mauvaise pratique). De manière générale, toujours déclarer les variables au plus proche de leurs utilisations.
De plus, je pense que tu n’en as pas besoin et que c’est une solution à un problème que tu as mal compris, mais j’y reviens dans un point plus bas.
3.2 –
// Conversion la température en entier int temp = (int)temperature;
lorsque tu cast un flottant en entier, tu le tronques. C’est pour ça qu’auparavent tu perdais purement et simplement tes décimales. De plus, je ne comprends pas pourquoi tu as besoin de le convertir plutôt que de changer afficher_nombre pour qu’il prenne un float en entrée.
Q 2 ? : Que veut dire le terme "cast" ?
J’ai trouvé cette solution pour aller ensuite chercher la décimale, parce que je ne maîtrise pas les types "char" et "float".
Q 3 ? Il faudrait donc modifier "afficher_nombre" de manière à avoir
void afficher_nombre(float nombre) ou void afficher_nombre(int nombre) ?
4 – Obtention des chiffres à afficher
4.1 -
if (nombre > 9) // si le nombre reçu dépasse 9 {
dizaine = nombre / 10; // on récupère les dizaines
unite = nombre - (dizaine * 10); // on récupère les unités
// on récupère la première décimale à partir de la variable float créée en amont,
// après avoir transformé sa valeur en un entier pour pouvoir appliquer le modulo
decimale = (int) (temporaire * 10) % 10 ; }
Comme déjà relevé, ta condition du if. Tu ne traites la décomposition que si le nombre est supérieur à 9, or ce n’est pas ce que tu veux et tu semble l’avoir compris. Le rôle que tu peux donner à une telle condition pour moi est double : soit il va permettre de gérer des nombres non-affichable (valeur supérieure à 99.9), soit il va permettre de gérer le format d’affichage (éviter d’afficher '07.0' mais plutôt '7' ou '7.0' etc…) donc quel format d’affichage est-ce que tu veux ?
La présence des zéros ne me dérangent pas pour l’instant et je pense qu’il faudrait ajouter pas mal de code pour éteindre les digits concernés le cas échéant ???
4.2 –
La méthode que tu as appliqué sur la décimale, tu peux l’appliquer pour extraire n’importe quel chiffre. Tu fais en sorte de mettre le chiffre qui t’interesse dans les unités en multipliant par la puissance de 10 appropriée, puis tu tronques en castant en int, et enfin tu extrait l’unité par un modulo 10. Donc tu peux avoir le code.
dizaine = static_cast<int>(nombre/10)%10;
// on cherche le chiffre 101 donc on multiplie par 10-1
unite = static_cast<int>(nombre)%10;
// on cherche le chiffre 100 donc on multiplie par 100
decimale = static_cast<int>(nombre*10)%10;
// on cherche le chiffre 10-1 donc on multiplie par 101
Aussi, en les tronquant ainsi, tu va avoir la décimale immédiatement inférieure. Est-ce que ça te convient ou est-ce que tu cherches un arrondi ? Une température de 17.48 doit afficher 17.5 ou 17.4 ? Et quid de 17.45 ? (Attention sur l’arrondi à 17.96 qui va donner 18.0 et donc modifier aussi l’unité)
Là encore, à ce stade, je ne cherche pas l’ultime précision : 17.4 me convient. Initialement, je pensais même me satisfaire d’un affichage sans décimale comme celui réalisé précédemment qui me sert uniquement pour mesurer la température du compost.
5 – Affichages de debug
OK, c’est bien noté et je reçois sur le moniteur série les informations attendues, c’est-à-dire les températures mesurées y compris lorsqu’elles sont négatives à la différence de ce qui se passe sur les afficheurs
// Affichage dans le moniteur série pour contrôle
Serial.print ("température : ") ;
Serial.print (temperature) ;
Serial.println( ) ;
Serial.print ("variable temporaire : ") ;
Serial.print (temporaire) ;
Serial.println( ) ;
Ce sont des affichages de debug, ce sont des informations utiles pour trouver un problème, ce sont donc des informations que tu peux nous donner quand tu demandes de l’aide.
6 – Améliorations et évolutions futures
La valeur de 5 secondes a été choisie pour les tests. Dans la réalité une mesure toutes les dix minutes ou plus serait suffisante car ce projet doit intégrer une station météo.
Ta remarque est importante car j’envisage de mettre ces mesures en mémoire pour ultérieurement pouvoir consulter des statistiques ou lancer des alertes… Je ne suis pas au bout de mes peines…
// valeur fixant le temps de rafraichissement de la lecture de la sonde while ((millis() - temps) < 5000)
Je suppose que cette boucle est là pour ne pas changer en permanence de valeur au point que ce soit illisible. C’est une bonne idée mais pour moi ce n’est pas le rôle de la fonction d’affichage. Sur ton application ça ne va peut-être pas poser problème, mais ça me semble être une erreur de conception qui pourrait te bloquer dans des évolutions, car il rend ton affichage bloquant (et pour 5 secondes !).
Pour moi, ce que tu cherches à faire c’est de prélever ta mesure toute les 5 secondes, soit de l’échantillonage. C’est donc une condition qu’on devrait trouver plutôt au prélevement de la mesure sur la sonde (actuellement dans la fonction loop). Ainsi tu pourrais faire l’appel au prélèvement que si 5 secondes se sont écoulées et continuer d’afficher à chaque tour de boucle. De plus, avec une telle structure, tu pourras appliquer des calculs pour adoucir ta mesure si la lib ne le fait pas déjà, comme une moyenne ou une médiane glissante sur X mesures.
// Fonction traduisant le chiffre décimal en une représentation binaire pour contrôler le décodeur BCD
// et afficher ce chiffre sur l’afficheur 7 segments sélectionné.
void afficher(char chiffre)
ETC…
{ C’est juste, et je sais que c’est le code du tuto, mais je vais proposer une autre version que je trouve plus lisible, plus concise et plus optimisée. Je pense que le tuto l’a évité pour s’épargner le concept de masque, et l’explication des éléments de langages que sont les opérateurs binaires, l’opérateur ternaire et les notations litérales alternatives (parce que c’est plus le rôle d’un tuto de langage que de tuto embarqué). Je pose ça là et on pourra en parler, mais essaie déjà de comprendre le reste du code avant.
void afficher(char chiffre) {
digitalWrite(bit_A, (chiffre&0b0001)?HIGH:LOW);
digitalWrite(bit_B, (chiffre&0b0010)?HIGH:LOW);
digitalWrite(bit_C, (chiffre&0b0100)?HIGH:LOW);
digitalWrite(bit_D, (chiffre&0b1000)?HIGH:LOW); }
Je ne demande qu'à apprendre, mais n'allons pas trop vite en besogne