Comment faire un fchier de configuration pour 40 catpeurs

Bonjour à tous,

Voici le scénario.
J'aurai 10 stations (voir plus). Chacune a4 capteurs de température que je dois calibrer.
J'ai un fichier ino pour ces 10 stations et j'aimerais que les valeurs d'ajustement soit dans mon fichier ino ou un fichier inclu. (calibration.h, par exemple)

Pour calibrer un capteur, je dois prendre la mesure dans la glace et sauver cette valeur dans 'rawLow'
Prendre la mesure dans de l'eau bouillante e sauver cette valeur dans 'rawHigh'
Sachant que la glace a une température de 0,1°C et que l'eau bouillante (selon la pression et l'altitude) à une valeur de 97°C, je mesure aussi ces températures avec un termomètre.
Je dois donc encore sauver ces valeurs dans 'referenceLow' et 'referenceHigh'.

Puis avec cette formule

float CorrectedValue = (((temperature - RawLow) * ReferenceRange) / RawRange) + ReferenceLow;

J'ai une valeur corrigée.
Pour une station j'ai fait ceci, mais à chaque dois que j'upload ce code pour une autre station, je dois modifier les valeurs que j'aurai sauver dans un autre fichier. C'est assez compliquer et source d'erreur...
(je n'ai calibré que la sonde 1 et 4 pour une station)

struct calibration{
  float rawLow;
  float rawHigh;
  float referenceLow;
  float referenceHigh;
  float rawRange;
  float referenceRange;
};
calibration DS18B20Calib1 = { // Calibration for sensor 1
  0.6,  // rawLow
  96,   // rawHigh
  0.1,  // referenceLow
  97.6, // referenceHigh
  DS18B20Calib1.rawHigh - DS18B20Calib1.rawLow,
  DS18B20Calib1.referenceHigh - DS18B20Calib1.referenceLow
};

calibration DS18B20Calib2 = { // Calibration for sensor 1
  0.1,  // rawLow
  99,   // rawHigh
  0.1,  // referenceLow
  99.7, // referenceHigh
  DS18B20Calib2.rawHigh - DS18B20Calib2.rawLow,
  DS18B20Calib2.referenceHigh - DS18B20Calib2.referenceLow
};

calibration DS18B20Calib3 = { // Calibration for sensor 1
  -2.3,  // rawLow
  99,   // rawHigh
  0.1,  // referenceLow
  99.7, // referenceHigh
  DS18B20Calib3.rawHigh - DS18B20Calib3.rawLow,
  DS18B20Calib3.referenceHigh - DS18B20Calib3.referenceLow
};

calibration DS18B20Calib4 = { // Calibration for sensor 1
  0.3,  // rawLow
  96,   // rawHigh
  0.1,  // referenceLow
  97.6, // referenceHigh
  DS18B20Calib4.rawHigh - DS18B20Calib4.rawLow,
  DS18B20Calib4.referenceHigh - DS18B20Calib4.referenceLow
};

Je pensais la simplifier en gardant que ceci

struct calibration{
  float rawLow;
  float rawHigh;
};
calibration DS18B20Calib1 = { // Calibration for sensor 1
  0.6,  // rawLow
  96  // rawHigh
};

Car referenceLow et referenceHigh sont toujoures les mêmes (sauf si je dscends au bord de mer :slight_smile: )
Maintenant si je dois faire 40x fois. ca risque d'être compliquer, surtout si je dois être sûre que les valeurs correspondent à la bonne station (1 à 10)
Je me demande comment vous feriez ce fichier de configuration avec des struc de manière à ce que cela ressemble à un array. L'idée sera que pour la station 1, l'index sera 1, pour la station 2, l'index sera 2 et ainsi de suite, un peut comme si je faisait un array
J'ai vu un truc du genre avec des struc

mesCapteur[i].quelque_chose

Comment je pourrais faire pour que le résultat soit le suivant

ds18b20[i].rawLow
ds18b20[i].rawHigh
ds18b20[i].referenceLow
ds18b20[i].referenceHigh

i étant l'ID de la station
Voyez-vous ou je veux en venir? Mais je ne vois comment faire une tableau avec des struct?
Milles mercis pour vos lumières :slight_smile:

// definition du nouveau type t_demo
struct t_demo {
  float tMin;
  float tMax;
};

// création d’un tableau de t_demo

t_demo mesReferences[] = {
  {1.1, 98.4},
  {0.3, 99.5},
  {0.7, 99.7}
};

Ensuite vous accédez à mesReferences[x].tMin ou mesReferences[x].tMax

Faudra ensuite trouver un moyen de numéroter vos stations…

Merci J-M-L !!!

Donc ca donnerai ceci

struct calibration {
  float rawLow;
  float rowHigh;
};

calibration ds18b20[] = {
  {1.1, 98.4}, // station 1
  {0.3, 99.5},  //station 2
  {0.7, 99.7}  // station 3
};

// station 1
ds18b20[0].rawLow
ds18b20[0].rawHigh
// Station 2
ds18b20[1].rawLow
ds18b20[1].rawHigh
// station 3
ds18b20[2].rawLow
ds18b20[2].rawHigh

Si c'est bien cela, cela fonctionne que pour une capteur. Le problème est que j'ai 4 capteurs par station
Ou alors on pourrais voir ainsi

struct calibration {
  float rawLow;
  float rowHigh;
};

calibration ds18b20[] = {
  {1.1, 98.4}, // capteur 1
  {0.3, 99.5},  //cateur 2
  {0.7, 99.7}  // capteur 3
// On ajoute encore 37 capteurs
};

// capteur 1
ds18b20[0].rawLow
ds18b20[0].rawHigh
// capteur 2
ds18b20[1].rawLow
ds18b20[1].rawHigh
// capteur 3
ds18b20[2].rawLow
ds18b20[2].rawHigh

Mais il faudrait encore pouvoir sélectionner les bons capteurs correspondant à la station à laquelle ils sont attachés

Bon, au pire des cas, on pourrait dire que les 4 premiers sont pour la première, les 4 suivants pour la seconde, mais cette manière me semble aussi être une source d'erreur

// capteur 1 station 1
ds18b20[0].rawLow
ds18b20[0].rawHigh
// capteur 4 station 1
ds18b20[4].rawLow
ds18b20[4].rawHigh
// capteur 1 station 3
ds18b20[12].rawLow
ds18b20[12].rawHigh
// capteur 4 station 3
ds18b20[15].rawLow
ds18b20[15].rawHigh

on pourrait pas faire un truc du genre avec un struct

// capteur 1 station 1
ds18b20[0][0].rawLow
ds18b20[0][0].rawHigh
// capteur 4 station 1
ds18b20[0][3].rawLow
ds18b20[0][3].rawHigh
// capteur 1 station 3
ds18b20[2][0].rawLow
ds18b20[2][0].rawHigh
// capteur 4 station 3
ds18b20[2][3].rawLow
ds18b20[2][3].rawHigh

Ou alors je pourrais éventuellement faire ceci, non?

struct calibration {
  float refLow;
  float refHigh;
  float raw1Low;
  float row1High;
  float raw2Low;
  float row2High;
  float raw3Low;
  float row3High;
  float raw4Low;
  float row4High;
};

calibration ds18b20[] = {
  {0.1, 97, 0, 0, 0, 0, 0, 0, 0, 0}, // reference
  {0, 0, 1.1, 98.4, 1.1, 98.2, -0.1, 97, -1, 97.8}, // station 1
  {0, 0, 1.1, 98.4, 1.1, 98.2, -0.1, 97, -1, 97.8}, // station 2
  {0, 0, 1.1, 98.4, 1.1, 98.2, -0.1, 97, -1, 97.8}, // station 3
};

ou soit je répète les références pour chaque station et je supprime la ligne // reference

Cette solution me plait bien

struct calibration {
  float refLow;
  float refHigh;
  float raw1Low;
  float row1High;
  float raw2Low;
  float row2High;
  float raw3Low;
  float row3High;
  float raw4Low;
  float row4High;
};

calibration ds18b20[] = {
  {0.1, 97.6, 0, 0, 0, 0, 0, 0, 0, 0},              // reference
  {0.1, 97.6, -0.9, 95.8, 0, 0, 0, 0, -1.9, 95.8},  // station 1
  {0.1, 97.6, -0.5, 95.8, 0, 0, 0, 0, -2.2, 95.8},  // station 2
  {0.1, 97.6, -0.3, 96, 0, 0, 0, 0, -03, 96},       // station 3
  {0.1, 97.6, 0.6, 96, 0, 0, 0, 0, 0.3, 96},        // station 4
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}               // station 5 (pas encore calibrée)
};

L'avnetage est que si je calibre des capteurs alors qu'il y a une autre pression ou une atre altitude, je peux modifier les reference pour une station.
L'inconvénient est que si je ne calibre pas les capteurs 2 et 3 en même temps que les capteurs 1 et 4 (c'est mon cas), il faudra que l'eau bouille à la meme température. Mais bon, je ne pense pas qu'il y aura une grande différence du moment ou elle bouille....

Je pourrais en effet supprimer la ligne // reference

La solution ne me semble pas très industrielle car elle implique de recompiler le code pour chaque station ou de surcharger le code avec des paramètres inutiles à la station.
Je pense qu’il serait plus pratique de prévoir le stockage des paramètres des capteurs dans l’EEPROM de l’ATmega et soit:

  • intégrer la procédure de calibration dans le logiciel de la station
  • soit intégrer une fonction de téléchargement des paramètres à partir d’un PC.

La première solution n’est pas très satisfaisante à mon sens car il faut avoir la station à disposition pour effecteur la calibration.
La seconde solution me parait plus pratique car elle autorise la calibration des capteurs sur une plateforme indépendante et offre la possibilité de remplacer un capteur en panne directement sur site avec la seule contrainte d’avoir un outil qui permette d’envoyer les paramètres de calibration à la station.

D’accord avec fdufnews sur les contraintes que cela impose - mais à vous de voir

Pour les 4 capteurs faites une structure de structure par exemple

struct t_capteur {
  const byte broche;
  float tMin;
  float tMax;
};
const byte nbCapteurs = 4;
struct t_station {
  const char* nom;
  t_capteur capteurs[nbCapteurs];
};

// puis définir les stations
t_station stations[] = {
  {"station rouge", {{3, 0.5, 99.2}, {4, 0.6, 99.7}, {5, 0.2, 98.7}, {6, 0.5, 99.2}}},
  {"station bleue", {{7, 0.2, 98.2}, {8, 0.2, 98.7}, {9, 0.6, 99.1}, {10, 0.9, 99.1}}},
  {"station verte", {{11, 0.3, 99.6}, {12, 0.7, 99.1}, {13, 0.7, 98.8}, {14, 0.3, 99.9}}},
};
const byte nbStations = sizeof stations / sizeof stations[0];

J’ai mis une broche ou un nom pour montrer que vous pouvez avoir plein de trucs dans les structures

Vous accédez à l’ élément tMin du capteur c de la station numéro n par

stations[n].capteurs[c].tMin

Houa, merci beaucoup pour toutes ces propositions. Super!! Je vais essayer la dernière proposition de J-M-L.

En effet, cette solutiojn n'est trop industrielle, comme le dit fdufnew. D'autant plus que si je dois remplacer une station, je devrai uploader le code dans le froid hivernal, sur le terrain. L'idée de l'EEPROM est très bien. Ce que je pensais aussi faire est de mettre ces données de calibration sur une carte SD, car mes stations ont un slot SD. L'aventage est que si je dois changer de station, je mets la carte SD dans la nouvelle station. Je dois encore réfaichir car la calibration ne dépend pas de la station mais des 4 capteurs qui y sont attachés. (il y a d'autres données de configuration) Mais en effet, les observations sont très pertinentes. Merci, je vais optimiser tout cela se soir.

Les cartes SD dans le froid et l’humidité c’est pas forcément un bon deal…

Quitte à aller sur place pour faire une réparation, prenez un petit bout de code qui calibre les capteurs et écrit au bon endroit en EEPROM puis ensuite rechargez votre programme comme ça il n’a pas besoin d’être recompilé (et mieux mettez le code de calibration dans votre programme)

voici un bout de code qui affiche tout ce que l’on a:

struct t_capteur {
  const byte broche;
  float tMin;
  float tMax;
};
const byte nbCapteurs = 4;
struct t_station {
  const char* nom;
  t_capteur capteurs[nbCapteurs];
};

// puis définir les stations
t_station stations[] = {
  {"station rouge", {{3, 0.5, 99.2}, {4, 0.6, 99.7}, {5, 0.2, 98.7}, {6, 0.5, 99.2}}},
  {"station bleue", {{7, 0.2, 98.2}, {8, 0.2, 98.7}, {9, 0.6, 99.1}, {10, 0.9, 99.1}}},
  {"station verte", {{11, 0.3, 99.6}, {12, 0.7, 99.1}, {13, 0.7, 98.8}, {14, 0.3, 99.9}}},
};
const byte nbStations = sizeof stations / sizeof stations[0];

void setup() {
  Serial.begin(115200);
  for (byte s = 0; s < nbStations; s++) {
    Serial.println(stations[s].nom);
    for (byte c = 0; c < nbCapteurs; c++) {
      Serial.write('\t'); Serial.print(F("Broche: ")); Serial.print(stations[s].capteurs[c].broche);
      Serial.write('\t'); Serial.print(F("tMin: ")); Serial.print(stations[s].capteurs[c].tMin);
      Serial.write('\t'); Serial.print(F("tMax: ")); Serial.println(stations[s].capteurs[c].tMax);
    }
  }
}

void loop() {}

le moniteur série (@ 115200 bauds) affichera

[color=purple]
station rouge
	Broche: 3	tMin: 0.50	tMax: 99.20
	Broche: 4	tMin: 0.60	tMax: 99.70
	Broche: 5	tMin: 0.20	tMax: 98.70
	Broche: 6	tMin: 0.50	tMax: 99.20
station bleue
	Broche: 7	tMin: 0.20	tMax: 98.20
	Broche: 8	tMin: 0.20	tMax: 98.70
	Broche: 9	tMin: 0.60	tMax: 99.10
	Broche: 10	tMin: 0.90	tMax: 99.10
station verte
	Broche: 11	tMin: 0.30	tMax: 99.60
	Broche: 12	tMin: 0.70	tMax: 99.10
	Broche: 13	tMin: 0.70	tMax: 98.80
	Broche: 14	tMin: 0.30	tMax: 99.90
[/color]

Comme tu utilises des DS18B20, tu peux aussi te servir de leur adresse et rajouter un argument comme un tableau id_sonde dans ta structure.

…
id_sonde[1] = adresse sonde n°1
id_sonde[2] = adresse sonde n°2
id_sonde[3] = adresse sonde n°3
// etc etc
…

Merci J-M-L et aux autres
Ca marche bien!!