Pilotage système de refroidissement

Je me suis lancé il y a peu dans la programmation (en partant de 0).

Mon objectif est de piloter des ventilos en vitesse via un signal PWM en fonction de la température de l'eau. J'ai aussi des alarmes en fonction du débit de l'eau ou de la température de celle-ci.

La vitesse suit des courbes prédéfini (courbe 1 de XX°C à YY°C, courbe 2 de YY°C à ZZ°C, etc. ...).

Et au final j'affiche des infos sur un écran OLED SSD1306.

J'ai fait des tests sur différent module pour voir si chaque élément fonctionnait, ce qui a été assez concluant. J'ai donc regroupé tous les "modules" et c'est là que tout ce complique.

Actuellement je n'arrive pas à afficher la vitesse des ventilos. Cette vitesse est une valeur calculée indicative car il y a 7 ventilateurs pilotés et que je ne récupère pas la vitesse réelle de chacun.

La vitesse est donc calculé de la façon suivante (j'ai remis toutes les lignes de code avec la déclaration des variables) :

float TEMP_EAU; // température d'eau en °C
const float AE = (0.72-.27)/50; // valeur a pour linéarisation de la temparature d'eau
const float BE = 0.27; // valeur b pour linéarisation de la temparature d'eau
static uint16_t SIGNAL_PWM = 1023; // défini la variable pour la gestion du signal du PWM des ventilos
static uint32_t RPM_VENTILO = 0; // Variable pour afficher la vitesse des ventilos
const uint16_t VMAX_VENTILO = 2000; // Initialise la valeur de vitesse maxi des ventilos pour le calcul de la vitesse réelle
uint16_t Vtne = analogRead(CAPTEUR_TEMP_EAU); // lecture de la valeur en V de la sonde de température d'eau
TEMP_EAU = Vtne/(AE*1024.0) - BE / AE; // température de l'eau (en °C)
SIGNAL_PWM = map(TEMP_EAU, PALIER_VITESSE_1, PALIER_VITESSE_2, Point1, Point2); // mise à l'échelle remap du PWM en fonction de la température d'eau
RPM_VENTILO = (SIGNAL_PWM * VMAX_VENTILO) / Point4;

En gros les valeurs pour :
SIGNAL_PWM = 90
VMAX_VENTILO = 2000
Point4 = 255

Donc RPM_VENTILO devrait m'afficher 706 mais c'est pas du tout le cas. Pour chercher d'où venait le problème, j'ai mis un test intermédiaire avec une variable tempo. Visiblement il n'arrive pas à faire 90 * 2000

Pourtant j'ai défini TEMPO comme suit :

static double TEMPO = 0; // VARIABLE DE TEST

mais en compilant j'ai un message : warning: integer overflow in expression [-Woverflow] lorsque j'impose 90 * 2000 à TEMPO ce qui expliquerait que la vitesse des ventilos ne s'affiche pas correctement mais du coup je ne sais pas trop ce qui bloque.

Là je suis un peu perdu.

Le problème est que l'opération (SIGNAL_PWM * VMAX_VENTILO) se fera avec des uint16_t (avec éventuellement débordement) et qu'ensuite le résultat sera placé dans le uint32_t RPM_VENTILO.

Il faut forcer le compilateur à faire le calcul avec des longs :
RPM_VENTILO = ((uint32_t)SIGNAL_PWM * VMAX_VENTILO) / Point4;

90*2000 = 180 000
Cette valeur ne "rentre pas" dans un uint16 (qui ne peut contenir que des valeurs entre 0 et 65535)
C'est pour ça que le compilo te dit "integer overflow in expression".

Utilise les variables plus grandes, sur 32 bits
Si tu nous montrais la ligne de code de qui déclenche le warning ?
Si tu écris quelque chose comme xxxxx = 90*2000, le compilo considère que 90 et 2000 sont de type int (le type par défaut) qui a 16 bits sur Arduino. Jusque là ça va, mais quand tu fais la multiplication des ces 2 ints, ça ne va plus (ça déborde).
Le compilateur ne met qu'un warning, mais en fait pour ton programme c'est bel et bien une erreur qui t'empêche d'arriver au bon résultat.

Il faut déclarer qu'au moins un des 2 entiers est un "long" de 32 bits :
xxxx = 90 * 2000L;

L'autre moyen est de déclarer SIGNAL_PWM en long, car map() retourne un long.

Merci pour vos retours.

Effectivement en déclarant SIGNAL_PWM en unsigned long ça fonctionne.

Est-ce qu'un uint32_t est équivalant ?

Du coup tout semble fonctionner pour le moment.

Ma machine à état fonctionne, mon alarme en cas de débit trop faible aussi même si je n'arrive pas à alimenter le buzzer mais avec une led à la place ça fonctionne. On dirait que ça manque de puissance (je vais regarder).

Je vais maintenant faire un test en "grandeur nature" en alimentant tout via une alim ATX (sans passer par le port USB) et brancher un Ventilateur voir si le PWM fonctionne bien comme prévu.

Je regarderai également l'alerte de température trop haut et les sécurités que j'ai mis.

Bonjour,

C'est équivalent sur les cartes avec processeurs AVR.
Ca peut être différent sur d'autres processeurs (en particulier les processeurs 64bits).

D'une manière générale la taille en octet d'une variable dépend du résultat de la compilation donc du compilateur.

Pour éviter les problèmes entre les "résultats" de plusieurs compilateurs ont été défini les
intXY_t et les uintXY_t.

Quand le compilateur trouve "int" il fait les optimisations qu'il veut.
Quand le compilateur trouve int16_t il sait qu'obligatoirement il devra faire une variable sur 16 bits et s'il trouve int32_t sur 32 bits.

Vu de ton coté si tu utilises un int il faudra que tu te renseignes sur le compilateur : avec avr-gcc un int sera sur 16 bits, avec le compilateur pour un esp32 je crois qu'il sera sur 32 bits.

Si tu utilises un intXY_t c'est toi qui fixeras le nombre de bit XY pouvant être égal à 8, 16, 32, 64 si le compilateur le permet.

Je ne sais pas répondre. J'ai une carte Aduino Uno R3 de chez ELEGOO et j'utilise VSCode. J'ai essayé autant que possible de mettre les variables au strict nécessaire.

Pour mon montage final je passerai sur Nano avec une plaque d'interface pour regrouper GND et VCC. A voir si je trouve tout fait ou si je fait moi même.

[EDIT On]
J'ai trouvé pour le buzzer j'avais mis un buzzer passif ald d'actif. Du coup ça fonctionne.

Va maintenant falloir que je dessine la boite et que je réalise le câblage pour intégrer tout ça.
[EDIT Off]

Bonjour,

Nouvelle question vis à vis de mon projet. Je suis en train de dessiner une carte d'interface sous KiCad pour faire le lien entre l'Arduino Nano et les capteurs et je me pose une question.

J'ai prévu d'alimenter l'Arduino directement via un connecteur Molex en 12V (VIN + GND) mais j'aimerai pouvoir facilement mettre à jour le programme sans faire trop de débranchement/rebranchement.

Du coup je me demande s'il est possible de laisser l'alim Molex et de brancher via un adaptateur au niveau des broches RX/TX vers une prise USB ?

Si oui y a t'il des choses à respecter comme des résistances ou autres ?

Merci

Si tu fais un circuit imprimé autant passer à la nano ou même à la pro-mini.
La Uno te serviras toujours pour du maquetage.
Les nano, pro-mini achetées sur Aliexpress fonctionnent parfaitement, on trouve même maintenant des nanos équipées de connecteurs USB de type C.

Si tu hésites à souder une carte microcontroleur sur une carte mère tu peux toujours passer par des barettes à tulipe mâle-femelle pour la carte mère, mâle-mâle pour la carte fille (nano, pro-mini).
--> Attention barettes à connecteurs ronds et fins, pas les gros carrés qui sont adaptés aux breadboard.
Le mot clé de recherche est "headers".

Quand à l'alimentation, le 12V direct sur Vin fonctionne mais n'est pas ce qui se fait de mieux : tu vas au devant de problème d'échaufffement du régulateur interne aux cartes.
Ce régulateur n'est pas dimentionné pour fournir de la puissance et un régulateur a un mauvais rendement contrairement aux convertisseurs.

AMHA un convertisseur 12 V vers 5 V sur la carte mère et la carte micro alimentée directement sur sa pin 5 V sera plus simple à gérer.
C'est parfaitement possible à condition de ne rien mettre sur l'entrée de Vin.

mes 5cts.

Je suis bien partie sur un Nano comme indiqué dans mon message.

Pour les headers normalement j'ai ce qu'il faut pour garder la carte nano démontable et la remplacer en cas de problème.

Pour l'alim j'avais compris qu'il fallait être entre 6 et 20V pour garantir une tension de fonctionnement / sortie de 5V.

De plus, pour moi la broche 5V est une sortie et non une entrée qui est VIN, non ?

Oui, 20V si le courant nécessaire est faible (aucun périphérique ou presque).

Si la carte est alimentée par VIN, la broche est une sortie.
Si la carte est alimentée par la broche 5V, la broche est une entrée.

Ok, donc si je branche ma carte en 5V + GND via l'alim de mon PC et ce que sur cette même ligne je branche l'alim de mon écran OLED, et autres capteurs qui ont besoin du +5v et GND est-ce ok ? sachant que les signaux irons sur l'Arduino.

C'est OK, bien sûr. L'alim 5V d'un PC est très puissante.
En cours de développement, pour un OLED + quelques capteurs, l'USB doit suffire.

Oui l'USB fonctionne très bien mais je fais des montages à blanc pour tester avant l'utilisation grandeur nature.

J'ai fait un test en alim +5V et j'ai noté des écarts dans les mesures sur mes ponts diviseurs pour les températures.

J'ai +4 à 5 °C en valeurs affichées, ce qui semble dire que j'ai pas 5V quelques part ... et c'est à mon alim PC de test (5.2V ald 5V).

Il faut que je mesure sur mon PC pour est sûr d'avoir 5V sinon je serai obligé de passer par la carte Arduino.

Pourquoi ne pas utiliser la référence interne 1.1V ?
analogReference(INTERNAL);
Une fois calibrée (tension de référence mesurée sur la broche AREF), la mesure sera stable quelque soit l'alimentation.
Il faut recalculer les ponts diviseurs.

Il va falloir que je creuse l'idée car là je ne connais pas du tout.

Il suffit d'ajouter la ligne analogReference(INTERNAL), la tension 1.1V peut ensuite être mesurée sur la broche AREF, et la valeur exacte peut être utilisée dans le code pour le calcul.

La NANO et la UNO possèdent cette broche AREF, pas la PRO MINI. Donc c'est OK.

Si c'est le même CI, mais il faut aller mesurer avec une pointe fine directement sur le boîtier du CI : un peu de dextérité obligatoire.

Note : cette valeur, tu peux l'introduire en "dur" dans le code ou utiliser l'EEPROM du microcontrôleur.
Si tu as plusieurs exemplaires à faire il suffit de mesurer chaque puce et d'enregistrer la valeur dans l'EEprom correspondante : le code restera le même puisqu'il puisera ses informations dans l'eeprom du micro qui l'héberge.

Donc si j'ai bien compris. J'ajoute une ligne analogReference(INTERNAL) pour prendre en compte une mesure de la Ref interne qui est à 1.1V et mon pont diviseur je le branche d'un coté sur la broche 4 (comme avant) et de l'autre sur AREF ald du 5V sachant que le GND reste le GND.

Pour le reste pas de risque de conflit avec les capteurs effet hall, DHT11, écran OLED qui resterons sur le +5V ?

Ci-dessous mon schéma d'origine (sans AREF). Désolé pour la qualité du schéma mais c'est mon premier je ferai plus propre plus tard.