Gestion des variables / array avec arduino et divers types

Bonjour ,
Comme je disais dans la présentation , je me lance dans un projet de gestionnaire d'aqua mais plus orienté "Fish room" que ceux déjà existants
Comme je n'en suis qu'au début , je suis au stade de vouloir gérer plusieurs températures via des ds18b20 et par la suites les alertes qui vont avec . le tout si possible d'une manière souple et évolutive.
Je préviens tout de suite , et c'est la que ça doit coincer : j'ai une approche très "php" , que je connais pas mal, de ce que je veux
Le souci c'est que avec l'arduino c'est très différent.

Donc en gros j'ai au départ mes adresses uint8_t des sondes onewire
je voulais faire une variable tableau[] du type :
array mes_sondes[] = ( adresse uint8_t , nom de la sonde , temp actuelle , temp min , temps max ...) (c'est un exemple très proche du php c'est juste pour expliquer l'idée)

(le but étant de pouvoir récupérer aisément liste de sondes avec les infos liées et de les traiter sondes par sondes
de pouvoir aussi modifier des données comme la temp min ou max pour les alertes)

donc je voulais stocker ça directement dans les variables , initialisé au lancement ou dans un / des fichiers sur carte sd ou en dernier recours dans l'eeprom ( je préfère pas )

Voila , en php cela ne me poserait aucuns soucis mais la je bloque sur les typages
questions :
peut on dans un array avoir plusieurs types de variables ? si oui comment ?

sinon es-ce une solution ou es-ce que c'est irréalisable sur arduino
Si vous avez des pistes je suis preneur

Merci d'avance

Aqua-Passion:
je voulais faire une variable tableau[] du type :
array mes_sondes[] = ( adresse uint8_t , nom de la sonde , temp actuelle , temp min , temps max ...)
...
peut on dans un array avoir plusieurs types de variables ? si oui comment ?

Ce que tu cherches s'appelle une structure :

typedef struct
{
  uint8_t adresse;
  char[10] nom_sonde;
  int temp_actuelle;
  int temp_min;
  int temps_max;
} MyStruct;

#define NB_ELEMENTS     10

MyStruct MyArray[NB_ELEMENTS];

void myFunction()
{
  int indice;

  MyArray[indice].addresse = ...;
}

sa me fais penser un projet que j'avais commencer pour une personne.. (abandonné plus de nouvelle de cette personne.) gestion aquarium eau de mer... avec démarrage ecumeur .. chauffage .. refroid.. produit.. pulseur... time nourriture.. niveau d'eau.. lumiere ..

Super , merci beaucoup , en effet je pouvais toujours chercher , je cherchais pas vraiment du bon coté
pourtant ça fait une paire de jours que je cherchais j'ai vu plein de choses mais j'ai jamais croise de structure
encore merci !

sinon avant de poursuivre mes recherches , toujours pour mes sondes
est il techniquement possible de récupérer/écrire ces infos dans un genre de fichier config sur carte sd ?

@Tealcoune Ah mince c'est dommage c'était un projet commun avec la personne ou une commande ?

Oui, sans problèmes

Avec la classe File et la fonction write( buf, len ) pour écrire et read( buf, len ) pour lire
Attention ca sera du binaire (pas lisible directement dans notepad)

Si tu veux quelque chose en ASCII, c'est faisable aussi. Pas compliquer à écrire mais un peu plus lourd a relire.

D'accord merci je vais faire des recherches et essayer de faire quelque chose
Je crierais au secours si je trouve pas

projet a peut près en commun.. j'étais surtout la en appui programmation... la recherche de solution c'étais le gars.. et il m'envoyé les composants pour faire la simulation ..

Ah ok , mince , c'est dommage que ça ai pas abouti :frowning:

Bon je coince encore surement à cause d'une subtilité:

j'ai un fichier par sonde avec les données de base
adresse ,nom, temp_min, temp_max
j'arrive à lire ça ligne par ligne
J'ai cru comprendre que ça mettait les données de la ligne dans le buffer -> file.readLn(textBuffer, 50);
donc a chaque ligne si je fais Serial.print(textBuffer); j'ai le contenu de la ligne qui s'affiche dans le moniteur série
mais si je veux faire un truc du genre "sonde[0].nom_sonde = textBuffer;"
je ne récupère plus la même info mais un chiffe

J'ai cru comprendre que textBuffer était un array
Mais j'ai retourné ça dans tous les sens

en ayant "nomdelasonde" sur une ligne
impossible de trouver le moyen de le faire passer dans sonde[0].nom_sonde qui est un char*

TextBuffer n'est pas un tableau de Char?
dans un code que j'avais fais pour lire les heures d'allumage et d'extinction des lumières d'aqua .. j'utiliser char cc = myFile.read(); // File myFile; en déclaration.

donc si ton sonde[0].nom_sonde est un Char, tu peux pas lui mettre un tableau de char.

Enfin si je me trompe pas .

Oui , d'après ce que j'ai compris TextBuffer est un tableau de Char
Mais je sais pas comment passer de ça a char pour mettre dans mon sonde[0].nom_sonde
J'ai essayé de bidouiller 2-3 trucs
à chaque fois sur l'ecran tft je tombe soit sur 26 soit sur des caractères étranges ou un carré plein soir vide
je dois tourner autour :-p

PHP et C sont très éloignés l'un de l'autre même si la syntaxe est similaire.

Donc je te suggère de partir de la base avant de bidouiller car certaines ne choses ne se font pas toutes seules comme en PHP (conversion de type, copie entre variables non-scalaires, ....).

Par exemple une chaîne de caractère en C est une suite de caractères placée dans un tableau de caractère et dont la fin est indiquée par un caractère de valeur 0 '\0'

char MaChaine[10] est un tableau de caractère pouvant comporter jusqu'à 10 caractères

char MaChaine[10] = "Hello"; crée une variable tableau de caractère et remplie les 6 premiers caractères avec les valeurs 'H', 'e', 'l', 'l', 'o' et '\0'

On n'a pas le droit de copier des chaines de caractères par le signe =
char MaChaine[10];
char MonAutreChaine[10] = "Hello";
MaChaine = MonAutreChaine; // Ca ne marche pas !

Il existe des bibliothèques standard qui vont permettre de faire cela.
Par exemple :

#include <string.h>
...
strcpy( MaChaine, MonAutreChaine );

ou mieux :

strncpy( MaChaine, MonAutreChaine, sizeof(MaChaine)-1 );

Bref, il y a beaucoup de chose a apprendre.

C'est pourquoi je te disait dans un message précédant que c'était plus facile de le faire en binaire en utilisant write( buffer, len) et readBytes( buffer, len) plutot qu'en ASCII.

Ah terrible , merci je n'avais pas saisi l'approche du C
ça fonctionne merci mais va falloir que je trouve un bouquin sur le C je pense

Le grand classique, celui avec lequel j'ai appris : http://www.amazon.fr/Le-langage-C-Norme-ANSI/dp/2100487345
C'est le C de base sans fioriture.
Attention, les exemples ne passeront pas tous sur Arduino car les fonctions d'affichage printf() n'existent pas.
Mais très bien avec la version gratuite de VisualC++ en utilisant le modèle "application console".

Merci

Désolé c'est encore moi
Je tourne encore en rond à un endroit
malgré mes recherches je ne voie pas

donc j'ai ma structure sondes

typedef struct
{
  uint8_t adresse[8];
  char* nom_sonde;
  float temp_actuelle;
  float temp_min;
  float temp_max;
} 
sondes_temp;

le fichier de configuration est lu par ligne et peuple les variables
mais je bloque pour l'adresse
0x28,0xC6,0x4D,0x21,0x04,0x00,0x00,0x57
J'ai voulu la décomposer en 8 pour remplir adresse
le résultat final devrait être équivalent à

sonde[0].adresse[0]= 0x28;      
 sonde[0].adresse[1]=      0xC6;
sonde[0].adresse[2]=      0x4D;
sonde[0].adresse[3]=      0x21;
sonde[0].adresse[4]=      0x04;
sonde[0].adresse[5]=      0x00;
sonde[0].adresse[6]=      0x00;
sonde[0].adresse[7]=      0x57;

(codé en dur)
mais une fois de plus je coince
le code qui décompose la ligne est

char *p = textBuffer;
char *str;
int itr= 0;
while ((str = strtok_r(p, ",", &p)) != NULL){

ensuite j'ai essayé des
sonde[0].adresse*= str;*
sonde[0].adresse=(uint8_t )(str);
ou encore
strcpy( sonde[0].adresse, (uint8_t )str );
mais je ne voie pas
j'ai changé les types
mais j'ai toujours des
"invalid conversion from 'uint8_t' to 'const char'"

ou
" cast from 'char*' to 'uint8_t' loses precision"

Bon j'ai fait une ou deux modifs :

typedef struct
{
  DeviceAddress adresse;
  char* nom_sonde;
  float temp_actuelle;
  float temp_min;
  float temp_max;
} 
sondes_temp;
              char *p = textBuffer;
              uint8_t *str;
              int itr= 0;
              while ((str = (uint8_t *)strtok_r(p, ",", &p)) != NULL){
                sonde[0].adresse[itr]= str;
                itr++;
              }

Mais maintenant j'ai
"invalid conversion from 'uint8_t*' to 'uint8_t'"
sur
"sonde[0].adresse[itr]= (uint8_t *)str;"

Vu que tu ne nous dis pas ce qu'est DeviceAddress , ca va pas être facile.

Fait attention avec les pointeurs.
Il faut vraiment que tu creuses le C et les pointeurs car c'est très différents de ce que tu a pu connaitre en PHP.
Un pointeur est une variable qui contient une adresse en mémoire. Il fautq ue cette adresse ait été allouée, que tu sot sure qu'il y ait quelque chose derrière et que ca ne va pas disparaître tout seul.

Par exemple tu crée une variable p qui pointe vers textBuffer. Qu'est-ce que textbBuffer ?
Supposons que tu as char textBuffer[10]
Dans ce cas textBuffer est un tableau de caractère. Il est alloué en mémoire et il existe.
Donc p pointe vers le 1er caractère de textBuffer
Ton usage de strtok_r() est syntaxiquement correct mais peut être fonctionnellement incorrect.
Il ne faut pas oublier que p va :

  • prendre des valeurs qui sont des adresses mémoires situées dans textBuffer
  • la fonction strtok_r modifie le contenu de textBuffer
  • tu va peut être réutiliser textBuffer plus loin dans ton code

sonde[0].adresse[itr]= str;
str est un pointeur sur char
Sans savoir de quoi est fait addresse, je ne peux pas conclure

Donne plus de code

J'ai un peu regardé sur le net mais pour les pointeurs mais c'est pas pratique de comprendre sur le net tout seul
pas encore eu le temps d'aller voir pour le bouquin je pense que je vais attendre le mois prochain pour l'acheter ce mois ci c'est un peu juste :-p

Je n'ai pas saisi si il était possible d'éviter d'utiliser les * ou de passer de char* à char pas exemple
depuis le début dès que j'essayais avec juste char j'ai des erreurs à la compilation

par exemple dans struct j'ai "char* nom_sonde;"
si j'essaye "char nom_sonde;" à la place j'ai une erreur à "myGLCD.print(sonde[0].nom_sonde,10,36);":
"invalid conversion from 'char' to 'const char*'"

sinon
DeviceAddress vient de
DallasTemperature.h :
"typedef uint8_t DeviceAddress[8];"

textbBuffer est une ligne de texte "file.readLn(textBuffer, 50);"
(tableau de caractère) normalement

file.readLn(buffer, bufSize);
Read the next line of text from an open text-file.
Parameters:
buffer: charArray to put the next line of text into
bufSize: size of buffer in bytes
Returns: Result as a word
Usage: res = file.readLn(st, 80); // Attempt to read the line of text and return it in st
Notes:
• The result will be the length of the textline that are returned
• If the buffer was to small it will be filled with all the text it could contain, and result will be BUFFER_OVERFLOW. It the end of the file was reached during the read result will be EOF
• Result can also be FILE_IS_EMPTY, ERROR_NO_FILE_OPEN or ERROR_WRONG_FILEMODE

Je vais essayer de mettre un peu plus de code concerné mais vu que c'est une une mise au point c'est un peu fouillis faut que je réorganise/ nettoie /commente le code

#include <Wire.h>
#include <tinyFAT.h>
#include <UTFT.h>
#include <UTFT_tinyFAT.h>
#include <ITDB02_Touch.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Timer.h>
#include <tinyFAT.h>
#include <String.h>

Timer t;


// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 8

int ledalert = 9;
int buzzer = 10;

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

int x, y;
int n = 1;


typedef struct
{
  DeviceAddress adresse;
  char* nom_sonde;
  float temp_actuelle;
  float temp_min;
  float temp_max;
} 
sondes_temp;

sondes_temp sonde[10];

// Declare which fonts we will be using
extern uint8_t SmallFont[];
extern uint8_t BigFont[];

...

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

....

byte res;
word result;
char textBuffer[81];

/***DEBUT SETUP *************************************************************************************************************************/
void setup(){
  Wire.begin();
  Serial.begin(9600);
  zero=0x00;
  dispHeure = String ();

  // initialize digital pin as output.
  pinMode(ledalert, OUTPUT);
  pinMode(buzzer, OUTPUT); 

  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.clrScr();

  file.initFAT();
  myGLCD.setFont(BigFont);

  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_MEDIUM);

  myGLCD.fillScr(255, 255, 255);
  myGLCD.setBackColor(153, 204, 255);
  myGLCD.loadBitmap(0, 0, 320, 240, "fond.raw");
  myGLCD.setColor(0, 0, 0);


  myGLCD.print("Carte Gestion bacs", CENTER, 5);
  myGLCD.setFont(SmallFont);


  // Start up the library
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(Tempad1, 10);
  sensors.setResolution(Tempad2, 10);

  int tickEvent = t.every(1000, getDateDs1307tolcd);

  getSondesInfos();
  //Chargement SD
  delay(1000);

}
/*FIN SETUP *************************************************************************************************************************/

/*DEBUT LOOP ************************************************************************************************************************/
void loop(){
  //rafraich timer
  t.update();

  temptolcd();

...

  myGLCD.print(String(freeRam()),280,200);
  delay(1000);

}

/*FIN LOOP ************************************************************************************************************************/

void temptolcd(){
  sensors.requestTemperatures();
  float thistemp = printTemperature((uint8_t*)sonde[0].adresse);
  sonde[0].temp_actuelle = thistemp;

  Serial.println(sonde[0].temp_actuelle); 


  myGLCD.print(sonde[0].nom_sonde,10,36); //

  myGLCD.printNumF( sonde[0].temp_actuelle,1,133,36); // temperature bac
  myGLCD.drawCircle(167,36,1); // Cercle degre bac   
  myGLCD.print("C",172,36); // "c" de temperature bac


  if (sonde[0].temp_actuelle > sonde[0].temp_max){
    myGLCD.loadBitmap(100, 26, 32, 32, "thermoal.raw");
    ledalertOn();
    buzzOn();
  }
  else if (sonde[0].temp_actuelle < sonde[0].temp_min){
    myGLCD.loadBitmap(100, 26, 32, 32, "thermof.raw");
    ledalertOn();
    buzzOn();
  }
  else {
    myGLCD.loadBitmap(100, 26, 32, 32, "thermo.raw");
    ledalertOff();
    buzzOff();
  }

  sensors.requestTemperatures();
  //lcd.print("Temp3: ");
  //printTemperature(Tempad2);
}

void buzzOn(){
  analogWrite(buzzer,128);
  delay(500);
  digitalWrite(buzzer, LOW);
  delay(500);
}

void buzzOff(){
  digitalWrite(buzzer, LOW);
}

void ledalertOn(){
  digitalWrite(ledalert, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(ledalert, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);   
}

void ledalertOff(){
  digitalWrite(ledalert, LOW);
}

...

float printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  if (tempC == -127.00) {
    Serial.println("Error getting temperature");
    printAddress(deviceAddress);
    return tempC;
  } 
  else {
   return tempC;
  }

}

void getSondesInfos()
{
  //sonde[0].adresse = {0x28,0xC6,0x4D,0x21,0x04,0x00,0x00,0x57};
  //sonde[0].nom_sonde = "Temp test";
  //sonde[0].temp_actuelle = 21;
  //sonde[0].temp_min = 10;
  //sonde[0].temp_max = 26; 
  int line=0;

  if (file.exists("temp1.txt"))
  {  
    res=file.openFile("temp1.txt", FILEMODE_TEXT_READ);
    if (res==NO_ERROR)
    {
      result=0;
      while ((result!=EOF) and (result!=FILE_IS_EMPTY))
      {
        line ++;
        result=file.readLn(textBuffer, 50);
        if (result!=FILE_IS_EMPTY)
        {
          if (result==BUFFER_OVERFLOW)
            Serial.print(textBuffer);
          else{

            if (line==2) {
              //Si ligne adresse
              Serial.println("ok 2 adr");
              char *p = textBuffer;
              uint8_t *str;
              int itr= 0;
              while ((str = (uint8_t *)strtok_r(p, ",", &p)) != NULL){ // delimiter is the semicolon
                Serial.print(itr);
                Serial.print("  :  ");
                Serial.print((char*)str);
                Serial.print("  ->  ");

                sonde[0].adresse[itr]= str;
                Serial.println((char*) sonde[0].adresse[itr]);
                itr++;
              }
            }
            else if (line==4) {
              //Si ligne nom sonde
              Serial.println("ok 4 nom");
              strcpy( sonde[0].nom_sonde, textBuffer );
            }

            Serial.print("Line :");
            Serial.println(line);
            Serial.println(textBuffer);
          }
        }
        else
          Serial.println("** ERROR: File is empty...");
      }
      Serial.println();
      file.closeFile();
    }
    else
    {
      switch(res)
      {
      case ERROR_ANOTHER_FILE_OPEN:
        Serial.println("** ERROR: Another file is already open...");
        break;
      default:
        Serial.print("** ERROR: ");
        Serial.println(res, HEX);
        break;
      }
    }
  }
  else{

    Serial.println("** ERROR: 'temp1.txt' does not exist...");
  }

  Serial.println("** sensor init...");
  printAddress(sonde[0].adresse);
  Serial.println("** sensor init... fin");
}

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 8) Serial.print("0");
    Serial.print(deviceAddress[i],HEX);
    Serial.print(" - ");
  }
}

J'ai enlevé des morceau c'était trop gros , ça ne passais pas

la ligne while ((str = (uint8_t *)strtok_r(p, ",", &p)) != NULL){
sert a décomposer la ligne texte de l'adresse :

0x28,0xC6,0x4D,0x21,0x04,0x00,0x00,0x57

dans le but de peupler la sonde dans cette optique:
sonde[0].adresse[0]= 0x28;
sonde[0].adresse[1]= 0xC6;
sonde[0].adresse[2]= 0x4D;
sonde[0].adresse[3]= 0x21;
sonde[0].adresse[4]= 0x04;
sonde[0].adresse[5]= 0x00;
sonde[0].adresse[6]= 0x00;
sonde[0].adresse[7]= 0x57;

j'avais peur de pas pouvoir rentrer directement du genre sonde[0].adresse = {0x28,0xC6,0x4D,0x21,0x04,0x00,0x00,0x57}; en récupérant la ligne
Je me suis peut être compliqué la vie