sprintf bizarre

Bonjour,

J'aimerais avoir de l'aide car le menu que j'essai de mettre en place ne fonctionne pas et je ne vois pas pourquoi.

Voici le code :

#include <LiquidCrystal.h>
#include <JC_Button.h>

// LCD ----------------------------
#define D0 38
#define D1 39
#define D2 40
#define D3 41
#define D4 42
#define D5 43
#define D6 44
#define D7 45
#define E 46
#define RW 47
#define RS 48
#define BL A12

// Keyboard -----------------------
#define KBD0 31
#define KBD1 32
#define KBD2 33
#define KBD3 34
#define KBD4 35
#define KBD5 36
#define KBD6 37
#define KLED 30

// LCD
LiquidCrystal lcd(RS, RW, E, D0, D1, D2, D3, D4, D5, D6, D7);
bool inMenu = false;
byte enter[] = {B00000, B00000, B00101, B01001, B11111, B01000, B00100, B00000};      // 0x08
byte arrowUp[] = {B00000, B00100, B01110, B10101, B00100, B00100, B00100, B00000};    // 0x01
byte arrowDown[] = {B00000, B00100, B00100, B00100, B10101, B01110, B00100, B00000};  // 0x02
char lcdMenuLine1[20] = "";
char lcdMenuLine2[20] = "";
char lcdMenuLine3[20] = "";
char lcdMenuLine4[20] = "";

// Keyboard
Button s0(KBD0);
Button s1(KBD1);
Button s2(KBD2);
Button s3(KBD3);
Button s4(KBD4);
Button s5(KBD5);
Button s6(KBD6);

uint8_t pumpStartHour = 8;
uint8_t pumpMinWorkingHours = 4;

void mainMenu()
{
  byte timeout = 0;
  // Disable main LCD task
  inMenu = true;
  sprintf(lcdMenuLine1, "\x01=Set filter pump   ");
  // Clear LCD
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(lcdMenuLine1);
  lcd.setCursor(0,3);
  lcd.print("\x08=Quit");
  delay(100);
  do
  {
    // Read buttons
    s0.read();
    s1.read();
    s2.read();
    s3.read();
    s4.read();
    s5.read();
    s6.read();
    // s1 -> Set filter pump
    if (s1.wasPressed()) 
    {
      setFilterPumpMenu();
      s0.read();
      timeout = 0;
      delay(100);
    }
    
    delay(100);
    timeout++;
  }while ((!s0.wasPressed()) && (timeout < 100));
  inMenu = false;
  
  // EEPROM
  //EEPROM.writeDouble(addrPumpStartHour, 8);
  //EEPROM.writeDouble(addrPumpMinWorkingHours, 4);
  //EEPROM.writeDouble(addrTemperature1Calibration, 0.45);
}

void setFilterPumpMenu()
{
  byte timeout = 0;
  sprintf(lcdMenuLine1, "\x01=Set start time %02d ", pumpStartHour);
  sprintf(lcdMenuLine2, "\x02=Set min work %02d   ", pumpMinWorkingHours);
  // Clear LCD
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(lcdMenuLine1);
  lcd.setCursor(0,1);
  lcd.print(lcdMenuLine2);

  lcd.setCursor(0,3);
  lcd.print("\x08=Quit");
  delay(100);
  do
  {
    // Read buttons
    s0.read();
    s1.read();
    s2.read();
    s3.read();
    s4.read();
    s5.read();
    s6.read();
    // s1 -> Set start time
    if (s1.wasPressed()) 
    {
      setStartTimeFilterPumpMenu();
      timeout = 0;
    }
    // S2 -> Set min work
    if (s2.wasPressed()) 
    {
      setMinWorkingTimeFilterPumpMenu();
      timeout = 0;
    }
    delay(100);
    timeout++;
  }while ((!s0.wasPressed()) && (timeout < 100));
}

void setStartTimeFilterPumpMenu()
{
  
}

void setMinWorkingTimeFilterPumpMenu()
{
  
}


void setup() 
{
  // LCD
  lcd.createChar(0, enter);
  lcd.createChar(1, arrowUp);
  lcd.createChar(2, arrowDown);
  lcd.begin(20, 4);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Version 1.0b");
  lcd.setCursor(0,3);
  lcd.print("\x08=Menu");
  // Buttons
  s0.begin();
  s1.begin();
  s2.begin();
  s3.begin();
  s4.begin();
  s5.begin();
  s6.begin();
}

void loop() 
{
  // Read buttons
  s0.read();
  s1.read();
  s2.read();
  s3.read();
  s4.read();
  s5.read();
  s6.read();
  // Enter menu = S0
  if (s0.wasPressed())
  {
    mainMenu();
    digitalWrite(KLED, HIGH);
    delay(100);
    digitalWrite(KLED, LOW);
  }

  lcd.clear();
  lcd.setCursor(0,3);
  lcd.print("\x08=Menu");
  delay(100);
}

Le problème est que quand je vais dans le menu, il entre bien dans la méthode : setFilterPumpMenu() et je m'attends ici a voir les 2 premières lignes :

lcdMenuLine1
lcdMenuLine2

Mais je vois uniquement la ligne lcdMenuLine2. Je ne comprends pas pourquoi.

Une idée ?

Tes chaînes sont trop longues, elles font 20 caractères dans des variables pour lesquelles tu as réservé seulement 20 caractères. Il manque un octet pour mettre le terminateur.
Pourquoi mettre un espace à la fin de la chaîne?

Merci pour la réponse, j'ai mis 21 dans la déclaration : char lcdMenuLine1[21] = ""; et maintenant c'est bon.
Pouquoi avoir mis 20, c'est que mon afficheur LCD a 20 caractères de long, de cette manière j'efface le contenu précédent s'il y en avait.

Merci encore.

Il faut le faire dans toutes tes variables char lcdMenuLineX. Tu as le problème dans toutes tes chaînes.

oui, oui, c'est ce que j'ai fait.
Maintenant je m'opccupe du second problème qui est le "quit".
Lorsque je quitte je pensais revenir au menu n-1, mais là je reviens tout au début...

Lorsque tu sors de setFilterPumpMenu(), s0 est appuyé et la première chose que tu fais au niveau supérieur c'est de lire l'état de s0 qui est toujours appuyé donc tu quittes ta boucle et tu réinitialises ton menu.

Il faudrait tester que s0 a été relâché avant de quitter setFilterPumpMenu().

C'est bon, tout est réglé ça marche comme je veux maintenant.
Merci beaucoup.

De rien