Menu shield dfrobot

bonjour a tous,

alors voila, cela fait quelques jours maintenant que je bosse sur un thermostat pour une piece d'elevage de reptiles. Le but : gerer 8 terrariums via un Arduino et un shield LCD KEYPAD dfrobot (des sondes DS18B20 releves les températures et pilotes des relais).

J'ai donc chercher pas mal comment programmer le shield dfrobot, j'ai enfin trouver un tuto expliquant comment faire ce que je veux, je soucis, mes 7 premiers sous-menu affiche bien ce que je veux, mais pas le 8eme, qui est pourtant identique au 7 autres, juste le numero de sonde et du relais qui change. Si je programme ma sonde et mon relais N°8 sur n'importe quelle menu, c'est pareil, de meme que si je programme une autre sonde sur le menu N°8, sa fonctionne.

Je suis perdu la je comprend pas ce qu'il se passe. J'ai essayer de changer les noms de sondes/relais, … mais rien.

Je precise que dans mon code les 8 sondes sont chacunes leur bus One_Wire.

Si quelqu'un peut m'aider sa serait super.

Merci d'avance.

Je n'arrive pas a mettre mon code, celui depasse les 9000 caracteres, je le poste des que possible en 2 parties.

String menuItems[] = {"TERRARIUM 1", "TERRARIUM 2", "TERRARIUM 3", "TERRARIUM 4", "TERRARIUM 5", "TERRARIUM 6", "TERRARIUM 7", "TERRARIUM 8","  "};

// Navigation button variables
int readKey;
int savedDistance = 0;

// Menu control variables
int menuPage = 0;
int maxMenuPages = 9;
int cursorPosition = 0;

// Creates 3 custom characters for the menu display
byte downArrow[8] = {
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b10101, // * * *
  0b01110, //  ***
  0b00100  //   *
};

byte upArrow[8] = {
  0b00100, //   *
  0b01110, //  ***
  0b10101, // * * *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100, //   *
  0b00100  //   *
};

byte menuCursor[8] = {
  B01000, //  *
  B00100, //   *
  B00010, //    *
  B00001, //     *
  B00010, //    *
  B00100, //   *
  B01000, //  *
  B00000  //
};

    byte degres[8] = { // DECLARATION D'UN TABLEAU DE 8 OCTETS POUR LE CARACTERE DEGRES 
      B00111,  
      B00101, 
      B00111, 
      B00000, 
      B00000, 
      B00000, 
      B00000, 
    };

    byte trait[8]={ // DECLARATION D'UN TABLEAU DE 8 OCTETS POUR LE CARACTERE TRAIT 
      B00100,
      B00100,
      B00100,
      B00100,
      B00100,
      B00100,
      B00100,
      B00100
    };

    byte case_vide[8]={ // DECLARATION D'UN TABLEAU DE 8 OCTETS POUR LE CARACTERE CASE VIDE
      B00000,
      B00000,
      B00000,
      B00000,
      B00000,
      B00000,
      B00000,
      B00000,
    };
    

#include <Wire.h>
#include <LiquidCrystal.h>
#include <OneWire.h> // INCLURE LA LIBRAIRIE ONEWIRE
#include <DallasTemperature.h> // INCLURE LA LIBRAIRIE DALLAS TEMPERATURE
#include "RTClib.h" //INCLURE LA LIBRAIRIE RTCLIB (HORLOGE RTC)

RTC_DS1307 RTC; //CLASSE RTC_DS1307

// Setting the LCD shields pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

    const int RELAIS_1=30; // RELAIS 1 SUR PIN 30
    const int RELAIS_2=31; // RELAIS 2 SUR PIN 31
    const int RELAIS_3=32; // RELAIS 3 SUR PIN 32
    const int RELAIS_4=33; // RELAIS 4 SUR PIN 33
    const int RELAIS_5=34; // RELAIS 5 SUR PIN 34
    const int RELAIS_6=35; // RELAIS 6 SUR PIN 35
    const int RELAIS_7=36; // RELAIS 7 SUR PIN 36
    const int RELAIS_8=37; // RELAIS 8 SUR PIN 37

    const int Cons_jour_terra_1 = 32;
    const int Cons_jour_terra_2 = 32;
    const int Cons_jour_terra_3 = 32;
    const int Cons_jour_terra_4 = 32;
    const int Cons_jour_terra_5 = 32;
    const int Cons_jour_terra_6 = 32;
    const int Cons_jour_terra_7 = 32;
    const int Cons_jour_terra_8 = 32;

    const int Cons_nuit_terra_1 = 29;
    const int Cons_nuit_terra_2 = 29;
    const int Cons_nuit_terra_3 = 29;
    const int Cons_nuit_terra_4 = 29;
    const int Cons_nuit_terra_5 = 29;
    const int Cons_nuit_terra_6 = 29;
    const int Cons_nuit_terra_7 = 29;
    const int Cons_nuit_terra_8 = 29;

        // DEFINITION DES PORTS BUS ONEWIRE
        
    #define ONE_WIRE_BUS_1 22 // BUS ONEWIRE SONDE 1 SUR PIN 22
    #define ONE_WIRE_BUS_2 23 // BUS ONEWIRE SONDE 2 SUR PIN 23
    #define ONE_WIRE_BUS_3 24 // BUS ONEWIRE SONDE 3 SUR PIN 24
    #define ONE_WIRE_BUS_4 25 // BUS ONEWIRE SONDE 4 SUR PIN 25
    #define ONE_WIRE_BUS_5 26 // BUS ONEWIRE SONDE 5 SUR PIN 26
    #define ONE_WIRE_BUS_6 27 // BUS ONEWIRE SONDE 6 SUR PIN 27
    #define ONE_WIRE_BUS_7 28 // BUS ONEWIRE SONDE 7 SUR PIN 28
    #define ONE_WIRE_BUS_8 29 // BUS ONEWIRE SONDE 8 SUR PIN 29
  

        // DEFINITION DES PORTS COMMUNICATIONS BUS ONEWIRE
        
    OneWire oneWire_1(ONE_WIRE_BUS_1); //BUS ONEWIRE_1 SUR ONEWIRE 1
    OneWire oneWire_2(ONE_WIRE_BUS_2); //BUS ONEWIRE_2 SUR ONEWIRE 2
    OneWire oneWire_3(ONE_WIRE_BUS_3); //BUS ONEWIRE_3 SUR ONEWIRE 3
    OneWire oneWire_4(ONE_WIRE_BUS_4); //BUS ONEWIRE_4 SUR ONEWIRE 4
    OneWire oneWire_5(ONE_WIRE_BUS_5); //BUS ONEWIRE_5 SUR ONEWIRE 5
    OneWire oneWire_6(ONE_WIRE_BUS_6); //BUS ONEWIRE_6 SUR ONEWIRE 6
    OneWire oneWire_7(ONE_WIRE_BUS_7); //BUS ONEWIRE_7 SUR ONEWIRE 7
    OneWire oneWire_8(ONE_WIRE_BUS_8); //BUS ONEWIRE_8 SUR ONEWIRE 8
    

        // DEFINITION DES NOMS DE PORTS ONEWIRE
        
    DallasTemperature sensors_1(&oneWire_1); // LA COMMANDE "SENSORS_1" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_1
    DallasTemperature sensors_2(&oneWire_2); // LA COMMANDE "SENSORS_2" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_2
    DallasTemperature sensors_3(&oneWire_3); // LA COMMANDE "SENSORS_3" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_3
    DallasTemperature sensors_4(&oneWire_4); // LA COMMANDE "SENSORS_4" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_4
    DallasTemperature sensors_5(&oneWire_5); // LA COMMANDE "SENSORS_5" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_5
    DallasTemperature sensors_6(&oneWire_6); // LA COMMANDE "SENSORS_6" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_6
    DallasTemperature sensors_7(&oneWire_7); // LA COMMANDE "SENSORS_7" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_7
    DallasTemperature sensors_8(&oneWire_8); // LA COMMANDE "SENSORS_8" LIRA LA TEMPERATURE SUR LE BUS ONEWIRE_8

salut

en attendant d'avoir la suite, premières remarques :

pourquoi définir un caractère "vide" ? il suffit d'envoyer un espace

pourquoi utiliser un bus par sonde pour les ds18b20 ? l'intéret du bus oneWire c'est quand même de pouvoir mettre toutes les sondes en // sur le même câble... enfin c'est vrai que comme ça pas besoin de se prendre la tête avec les adresses

si tu veux un exemple de menu fonctionnel sur un lcd 4*20,tu peux regarder dans mon projet thermalduino.La partie lecture/enregistrement des DS18b20 pourrait aussi t'être utile d'ailleurs

Voici la suite. J'ai resolu mon probleme initial, en fait, je ne sais pas pourquoi, mais le probleme venais de mon bus onewire 8 (donc sur le pin 29), j'ai tous decaller, et sa fonctionne.

Tu as l'air de bien connaitre, j'ai des bases un peu étendu si je puis dire, mais pas assez pour la suite du projet. Je souhaiterais pouvoir modifier les temperatures consignes direct dans les sous menu. J'ai trouver un programme qui le fait, mais je n'arrive pas a l'adapter a mon projet (dans le programme de base, le gars modifier l'heure, moi je veut modifier une temperature.

En te remerciant.

void setup() {

  // Initializes serial communication
  Serial.begin(9600);

  // Initializes and clears the LCD screen
  lcd.begin(16, 2);
  lcd.clear();

  RTC.begin();

  // Creates the byte for the 3 custom characters
  lcd.createChar(0, menuCursor);
  lcd.createChar(1, upArrow);
  lcd.createChar(2, downArrow);
  lcd.createChar(3,degres); // CREATION DU CARACTERE DEGRES
  lcd.createChar(4,trait); // CREATION DU CARACTERE TRAIT
  lcd.createChar(5,case_vide); // CREATION DU CARACTERE CASE VIDE
}

void loop() {
  mainMenuDraw();
  drawCursor();
  operateMainMenu();
}

// This function will generate the 2 menu items that can fit on the screen. They will change as you scroll through your menu. Up and down arrows will indicate your current menu position.
void mainMenuDraw() {
  Serial.print(menuPage);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print(menuItems[menuPage]);
  lcd.setCursor(1, 1);
  lcd.print(menuItems[menuPage + 1]);
  if (menuPage == 0) {
    lcd.setCursor(15, 1);
    lcd.write(byte(2));
  } else if (menuPage > 0 and menuPage < maxMenuPages) {
    lcd.setCursor(15, 1);
    lcd.write(byte(2));
    lcd.setCursor(15, 0);
    lcd.write(byte(1));
  } else if (menuPage == maxMenuPages) {
    lcd.setCursor(15, 0);
    lcd.write(byte(1));
  }
}

// When called, this function will erase the current cursor and redraw it based on the cursorPosition and menuPage variables.
void drawCursor() {
  for (int x = 0; x < 2; x++) {     // Erases current cursor
    lcd.setCursor(0, x);
    lcd.print(" ");
  }

  // The menu is set up to be progressive (menuPage 0 = Item 1 & Item 2, menuPage 1 = Item 2 & Item 3, menuPage 2 = Item 3 & Item 4), so
  // in order to determine where the cursor should be you need to see if you are at an odd or even menu page and an odd or even cursor position.
  if (menuPage % 2 == 0) {
    if (cursorPosition % 2 == 0) {  // If the menu page is even and the cursor position is even that means the cursor should be on line 1
      lcd.setCursor(0, 0);
      lcd.write(byte(0));
    }
    if (cursorPosition % 2 != 0) {  // If the menu page is even and the cursor position is odd that means the cursor should be on line 2
      lcd.setCursor(0, 1);
      lcd.write(byte(0));
    }
  }
  if (menuPage % 2 != 0) {
    if (cursorPosition % 2 == 0) {  // If the menu page is odd and the cursor position is even that means the cursor should be on line 2
      lcd.setCursor(0, 1);
      lcd.write(byte(0));
    }
    if (cursorPosition % 2 != 0) {  // If the menu page is odd and the cursor position is odd that means the cursor should be on line 1
      lcd.setCursor(0, 0);
      lcd.write(byte(0));
    }
  }
}


void operateMainMenu() {
  int activeButton = 0;
  while (activeButton == 0) {
    int button;
    readKey = analogRead(0);
    if (readKey < 790) {
      delay(100);
      readKey = analogRead(0);
    }
    button = evaluateButton(readKey);
    switch (button) {
      case 0: // When button returns as 0 there is no action taken
        break;
      case 1:  // This case will execute if the "forward" button is pressed
        button = 0;
        switch (cursorPosition) { // The case that is selected here is dependent on which menu page you are on and where the cursor is.
          case 0:
            menuItem1();
            break;
          case 1:
            menuItem2();
            break;
          case 2:
            menuItem3();
            break;
          case 3:
            menuItem4();
            break;
          case 4:
            menuItem5();
            break;
          case 5:
            menuItem6();
            break;
          case 6:
            menuItem7();
            break;
          case 7:
            menuItem8();
            break;
        }
        activeButton = 1;
        mainMenuDraw();
        drawCursor();
        break;
      case 2:
        button = 0;
        if (menuPage == 0) {
          cursorPosition = cursorPosition - 1;
          cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
        }
        if (menuPage % 2 == 0 and cursorPosition % 2 == 0) {
          menuPage = menuPage - 1;
          menuPage = constrain(menuPage, 0, maxMenuPages);
        }

        if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
          menuPage = menuPage - 1;
          menuPage = constrain(menuPage, 0, maxMenuPages);
        }

        cursorPosition = cursorPosition - 1;
        cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));

        mainMenuDraw();
        drawCursor();
        activeButton = 1;
        break;
      case 3:
        button = 0;
        if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
          menuPage = menuPage + 1;
          menuPage = constrain(menuPage, 0, maxMenuPages);
        }

        if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
          menuPage = menuPage + 1;
          menuPage = constrain(menuPage, 0, maxMenuPages);
        }

        cursorPosition = cursorPosition + 1;
        cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
        mainMenuDraw();
        drawCursor();
        activeButton = 1;
        break;
    }
  }
}

// This function is called whenever a button press is evaluated. The LCD shield works by observing a voltage drop across the buttons all hooked up to A0.
int evaluateButton(int x) {
  int result = 0;
  if (x < 50) {
    result = 1; // right
  } else if (x < 195) {
    result = 2; // up
  } else if (x < 380) {
    result = 3; // down
  } else if (x < 790) {
    result = 4; // left
  }
  return result;
}

// If there are common usage instructions on more than 1 of your menu items you can call this function from the sub
// menus to make things a little more simplified. If you don't have common instructions or verbage on multiple menus
// I would just delete this void. You must also delete the drawInstructions()function calls from your sub menu functions.
void drawInstructions() {
  lcd.setCursor(0, 1); // Set cursor to the bottom line
  lcd.print("Use ");
  lcd.write(byte(1)); // Up arrow
  lcd.print("/");
  lcd.write(byte(2)); // Down arrow
  lcd.print(" buttons");
}

salut

et ton programme, là, il compile ? Avec ce que tu as posté ça ne me semble pas possible, il manque une partie des fonctions du menu... ou alors je bigle

salut,

il en manque encore un morceau, je n'arrive pas a la poster. Y a t'il un moyen pour poster de grands programmes sur le forum ?

Alors la, pour le moment, mon menu fonctionne, j'affiche mes sondes, mes consignes tous sa en fonction de l'heure? Par contre, j'ai créer un void Regul_temp, dans lequel j'ai mis mon programme pour piloter mes relais en fonction de la temperature, mais je n'arrive pas a afficher l'etat de mes relais dans mes sous menus (on off), ils restent toujours sur off. J'ai vu que cela venait du fait que mon void loop est composé de mainMenuDraw();
drawCursor();
operateMainMenu();
Regul_Temp();

Pourrais tu m'expliquer comment je pourrais faire pour avoir le retour d'etat de mes relais dans mes void menu_items s'il te plait.

En te remerciant.

Salut,

Bon, j'ai reussi a faire ce que je voulais (avoir mon retour d'état de mes relais dans mes sous menus). Maintenant, il ne me reste plus qu'a modifier les valeurs de consigne via mes BP.

En sachant que j'ai des consignes jour et des consignes nuit pour chaque terra, je pense qu'il vaudrait mieux faire un sous menu "Config. temp." ou je pourrais modifier tous les consignes pour tous les terras (page 1 consignes jour et nuit terra 1, page 2 consignes jour et nuit terra 2, ...).

Et la par contre, je bloque. Pourrais tu m'aiguiller sur la marche a suivre.

En te remerciant.

il faudrait que tu postes ton programme

si il est trop grand pour le coller dans le texte, joint le fichier .ino à ton message, tout simplement :wink:

Salut,

Voila, je poste mon programme, j'ai pris le temps de "ranger" un petit peu, pour que sa soit un peu plus clair. Il y a surement une meilleure solution que celle que j'ai employé (déjà, pour les DS18B20, mais aussi pour les données, on doit surement pouvoir les mettre en tableau, …).

Donc la, mon programme compile, mes températures consignes et reelles s'affichent, de meme que l'etat de mes relais (ON / OFF), bon, sur ce point, entre 31 et 32,5 degres, je n'ai pas de retour, je ne sais pas pourquoi, est ce du au fait que mes valeurs ne "bougent" pas dans les menus (il faut que je fasse retour et que je retourne sur le terrarium concerné pour voir la valeur actualisée).

Donc, maintenant, ce que je voudrais faire, c'est un menu dans le genre la

Terrarium 1 -> (affiche mes infos consigne/reelle/etat) -> reglage des consignes jour et nuit

et ce pour les 8 terrariums.

Pense tu que c'est possible (surement), et si oui, pourrais tu m'expliquer un peu comment faire stp.

Je ne demande pas qu'on me donne le programme tous fait, mais que l'on m'explique un peu, pour pouvoir le refaire la prochaine fois.

En te remerciant.

LCD_Shield_Menu.ino (27.3 KB)

bon je viens de lire vite fait ton code (mais vraiment vite fait, entre deux hurlements de la descendance...)

il y a un truc qui me gène : tu réalise les actions d'automatisme dans le menu.
Il me semble qu'il faudrait séparer ça : faire une ou des fonctions qui se chargent de l'automatisme, et laisser le menu s'occuper uniquement de l'affichage. Déja ça simplifirait le code.

ensuite oui pour l'organisation générale en effet tout ranger dans des tableaux serait mieux

une remarque aussi : pour tes consignes, tu utilise des unsigned int -->ça bouffe plein de mémoire pour une valeur qui sera toujours autour de 20, c'est dommage. Utilises plutôt des byte, tu utilisera un seul octet par variable.

Pour le reste, j'ai pas le temps ce soir de regarder plus en détail

pour ce qui est de ranger les températures, consignes et paramètres en tableau,tu peux regarder ce que j'ai commencé dans le code de ce post #41
Une fois ça fini d'ailleurs tu aura un bon exemple de menu avec affichage et réglages,mais j'ai pas eu le temps ce WE
Ce code d'ailleurs devrait pouvoir être directement transposé à ton application, puisque le nombre de zones est paramétrable facilement, et comme justement tout est fait avec des tableaux, une seule modif agit pour toutes les zones

Salut

Merci de ta réponse.

J’ai essayer de créer un Void Regul_temp pour gérer mon automatisme, mais sa ne fonctionner pas et j’en avais pas de retour sur l’état de mes relais sur mon LCD.

D’accord, je vais regarder sa de près se soir, et je te tiens au courant.

Encore merci.

là à l'inverse si tu n'est pas sur le menu concerné, tu ne régules pas, je ne pense pas que ce soit la bonne solution...

poste ton programme avec la régulation séparée, on va voir ce qu'il est possible de faire pour que ça fonctionne

Salut,

Je viens de te le refaire vite fait (je l'avais effacé, j'ai tellement fais d'essai j'avais fait un peu de menage).
Je te le met en fichier joint.

Ah oui, si je suis pas sur le menu concerné, sa ne regule pas, je comprend maintenant. De meme que quand je suis sur les pages de mon menu, les valeurs des sondes se fige, pour les voir varier, je doit quitter le menu et y revenir.

Merci beaucoup du coup de main, parceque la, je suis pommé

LCD_Shield_Menu.ino (27.3 KB)

je regarde ça dès que j'ai un moment, ce soir ou demain

bon ben alors elle est où dans le code ta fonction regul_temp() ? à part un appel commenté dans la loop, le reste du code est toujours identique, avec tout dans le menu...

il faudrait que tu sépares clairement :

-la lecture des températures (créés une fonction pour ça appelée en début de loop() par exemple toutes les 2 ou 3 secondes, voir pour faire une tempo avec millis() pour cela, qui va lire les capteurs et mettre à jour des variables globales contenant les températures)
-la fonction de régulation qui va activer les relais en fonction des températures lues juste avant et des consignes
-l'affichage qui fera ce qu'il a à faire sans perturber le reste

actuellement dans ton code, tout est dans l'affichage, donc forcément si tu n'est pas sur la page de menu concernée, ben rien ne se passe

oui, ayant refait le code en vitesse, j'ai oublier de décommenter le ligne dans le loop

D'accord, je ne peux pas regarder ce Week-end, mais je me penche la dessus dès que possible.

Donc, si je comprend bien, mon code doit etre dans le genre la

Void loop

(relevée de temperature, via un void releve_temp placé en fin de prog par exemple)

(régulation, direct dans le loop)

(affichage, direct dans le loop)

C'est bien ca ?

En te remerciant.

décommenter la ligne si la fonction n'existe pas dans le code, ça ne sert à rien à part créer une erreur de compilation...

oui, enfin non, pas exactement. actuellement tu as une loop qui fait :

-affichage (et tout est dedans...)

l'idée c'est de faire :

-lecture capteurs
-regulation
-affichage

mais pas direct dans la loop, dans des fonctions séparées sinon le code va vite devenir un bazard illisible

Par exemple, sur la base de ce que tu as actuellement :

  void loop() {
          lectureTemperature();
          regulation();
          //partie affichage et menu	  
	  mainMenuDraw();
	  drawCursor();
	  operateMainMenu();
 
  }

pour que ça fonctionne, il faut que ta fonction lectureTemperature() mette à jour des variables globales avec les températures, pour que celles-ci soit disponibles pour les autres fonctions de régulation et affichage.

oui d'accord je vois pour l'architecture du programme, mais comment justement mettre a jour les variables des températures pour qu'elles soit dispo dans les autres fonctions ? C'est surtout la que je bloque…

Apres, la deuxieme problematique, c'est de pouvoir modifier les consignes jour et nuit pour les terras directement sur l'ecran.