Go Down

Topic: [Programmation] initialisation tableau de structure PROGMEM [RÉSOLU] (Read 2440 times) previous topic - next topic

moricef

Apr 29, 2015, 07:24 pm Last Edit: May 04, 2015, 11:39 pm by moricef Reason: Modification du titre
Bonjour, j'ai déjà posté sur un sujet similaire concernant le même problème (http://forum.arduino.cc/index.php?topic=319033.0) mais un poil moins avancé. Il faut dire qu'après avoir écrit mon code en C je me retrouve un peu coincé dans l'IDE arduino.

Voici mon petit sketch :

Code: [Select]

#include <IRremote.h>

#include "StructTableauCommandes.h"

IRsend irsend;

const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState = 0;         // Variable pour enregistrer l'état du bouton-poussoir
byte bits = 32;
TabCom tabCom[TAILLE_MAX];


void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT); // Broche bouton-poussoir comme entrée
}

void initTableauCommandes() {
  
  TabCom tabCom[8] = {
    {"KEY_POWER"}, {"KEY_TV"}, {"KEY_VIDEO"}, {"KEY_AUDIO"}, 0x17BD, 0x179C, 0x1798, 0x1799};
}

void afficheLigneCommandes() {
  
  byte i = 0;
  
  Serial.println(tabCom[i].label); // On affiche le nom de la commande
  
  for (byte n = 0; n < 3; n++) {  // La commande est envoyée 3 fois de suite
  
    irsend.sendRC5(tabCom[i].value, bits);
  
    delay(40);
  }
}

void loop() {
  
  initTableauCommandes();
 
  buttonState = digitalRead(buttonPin); // Interrogation du bouton-poussoir
  
  byte i = 0;

  while (i < TAILLE_MAX) {

    if (buttonState == HIGH) { // Si le bouton-poussoir est appuyé
  
       afficheLigneCommandes();
  
    } ++i;
  }
}



Code: [Select]

/*
 * StructTableauCommandes.h
 *
 *  Created on: 23 avr. 2015
 *      Author: fab2
 */

#ifndef STRUCTTABLEAUCOMMANDES_H_
#define STRUCTTABLEAUCOMMANDES_H_

#define TAILLE_MAX 4

typedef struct TabCom {
char label[50];
unsigned long value;
} TabCom;

#endif /* STRUCTTABLEAUCOMMANDES_H_ */

J'avais pourtant un affichage du nom de la commande dans le moniteur série dans une version antérieure du sketch mais je n'arrivais pas à lire ligne par ligne la liste des commandes. Ici rien ne s'affiche et je ne suis même pas sûr que la code RC5 envoyé soit correct. En fait autant je comprenais ce que je codais en C autant avec arduino je ne comprends pas vraiment.
Quelqu'un peut-il m'aiguiller parce que là je sèche

tahitibob35

Je ne connais pas trop les structures, mais faudrait pas faire un truc du genre :
Code: [Select]
  TabCom tabCom[8] = {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799}};
}



fdufnews

L'Arduino c'est du C
La seule chose à comprendre c'est la structure setup() loop().
Par rapport à un programme C "standard" le code généré par l'IDE à cette structure
Code: [Select]
main(){
      setup();
      while(1){
          loop();
      }
}

Donc on voit que setup() est appelée une fois et ensuite on entre dans une boucle infinie qui exécute loop() en permanence.

Dans ton cas, il y a ça comme problèmes
initTableauCommandes() devrait être appelée dans setup()
i est locale à afficheLigneCommandes() donc tu lis toujours le premier élément du tableau d'ailleurs on se demande pourquoi tu ne passes pas i en argument à afficheLigneCommandes().
A mon sens le test du bouton devrait être en dehors du while pour que, une fois que l'on détecte un appui, on exécute la suite de commandes en salve (à moins que ce ne soit pas le comportement souhaité)

moricef

[Edit] : Merci aussi fdufnews, je viens seulement de voir ta réponse qui éclaire ma lanterne.

Je ne connais pas trop les structures, mais faudrait pas faire un truc du genre :
Code: [Select]
 TabCom tabCom[8] = {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799}};
}



Merci.
Effectivement le bon code RC5 s'affiche en remplissant le tableau de cette manière. Mais je coince toujours et encore pour la lecture ligne par ligne.

moricef

#4
Apr 30, 2015, 05:36 pm Last Edit: Apr 30, 2015, 09:14 pm by moricef Reason: ajout d'informations
Bien, j'ai un peu avancé mais pas là où je pensais :
Comme bien sûr ça coinçait dans la RAM pour rentrer la totalité de mon tableau, j'ai regardé du coté de PROGMEM et j'ai initialisé le tableau dans setup() comme fdufnews me l'a suggéré.
Mais je ne trouve toujours pas comment me dépatouiller de cette boucle infini qui me lit l'ensemble du tableau en salve  à chaque appui BP :smiley-confuse: .


Code: [Select]

#include <avr/pgmspace.h>

const int TAILLE_MAX = 47;

typedef struct TabCom {
 char label[20];
 int value;
} TabCom;

static const TabCom tabCom[TAILLE_MAX] PROGMEM = {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799},
    {"KEY_IMAGES", 0x179A}, {"KEY_INFO", 0x179B}, {"KEY_RADIO", 0x178C}, {"KEY_EXIT", 0x179F},
    {"KEY_MENU", 0x178D}, {"KEY_CHANNELDOWN", 0x1792}, {"KEY_MUTE", 0x178F}, {"KEY_UP", 0x1794},
    {"KEY_DOWN", 0x1795}, {"KEY_LEFT", 0x1796}, {"KEY_RIGHT", 0x1797}, {"KEY_OK", 0x17A5},
    {"KEY_VOLUMEUP", 0x1790}, {"KEY_VOLUMEDOWN", 0x1791}, {"KEY_CHANNELUP", 0x17A0},
    {"KEY_CHANNELDOWN", 0x17A1}, {"KEY_RECORD", 0x17B7}, {"KEY_STOP", 0x17B6}, {"KEY_REWIND", 0x17B2},
    {"KEY_FASTFORWARD", 0x17B4}, {"KEY_PLAY", 0x17B5}, {"KEY_AGAIN", 0x17A4}, {"KEY_NEXT", 0x179E},
    {"KEY_PAUSE ", 0x17B0}, {"KEY_1", 0x1781}, {"KEY_2", 0x1782}, {"KEY_3", 0x1783}, {"KEY_4", 0x1784},
    {"KEY_5", 0x1785}, {"KEY_6", 0x1786}, {"KEY_7", 0x1787}, {"KEY_8", 0x1788}, {"KEY_9", 0x1789},
    {"KEY_NUMERIC_STAR", 0x178A}, {"KEY_0", 0x1780}, {"KEY_NUMERIC_POUND", 0x178E}, {"KEY_RED", 0x178B},
    {"KEY_GREEN", 0x17AE}, {"KEY_YELLOW", 0x17B8}, {"KEY_BLUE", 0x17A9}, {"KEY_SUBTITLE", 0x178E},
    {"KEY_TEXT", 0x178A}, {"KEY_HOME", 0x17BB}
  };

char buffer[30];    // make sure this is large enough for the largest string it must hold

const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println ();
  for (byte i = 0; i < TAILLE_MAX; ++i) {
    TabCom unElement;
    memcpy_P (&unElement, &tabCom[i], sizeof unElement);
    /*Serial.println (unElement.label);
     for (byte i = 0; i < 3; i++)
    {
    
      Serial.println(unElement.value, HEX);
    
    }*/
  }
}


void loop() {

 TabCom unElement;  
  buttonState = digitalRead(buttonPin);
  byte i = 0;

  if (buttonState == HIGH) {    
    Serial.println (unElement.label);
    
    for (byte i = 0; i < 3; i++) {
    
      Serial.println(unElement.value);
    }  
    
    }++i;
}

Or je veux qu'il me lise une SEULE ligne par appui BP, puis la suivante à l'appui BP suivant.
L'affichage dans la console série ne correspond pas à ce que j'en attends : loop() m'affiche toujours le même label, en l'occurrence le dernier de la liste sans le premier caractère et un nombre quelconque qui change à chaque appui BP. Le tout répété neuf fois :
Code: [Select]

EY_HOME
1024
1024
1024
(...)
EY_HOME
0
0
0
(...)
EY_HOME
58114
58114
58114
(...)

(J'ai remarqué que si je maintiens le BP appuyé, plus le nombre affiché est grand, plus le texte défile rapidement.)

tahitibob35

Il y a plusieurs trucs bizarres dans ton code... dont :
Dans loop, tu mets i à 0.
Puis à la fin de loop, tu incrémentes i.
Puis i repasse aussitôt à 0 au début de loop.
Donc l'incrémentation ne sert à rien....

moricef

Il y a plusieurs trucs bizarres dans ton code... dont :
Dans loop, tu mets i à 0.
Puis à la fin de loop, tu incrémentes i.
Puis i repasse aussitôt à 0 au début de loop.
Donc l'incrémentation ne sert à rien....
Tu as raison, je remplace aussitôt "byte i = 0;" par "byte i;". Mais le résultat reste le même.

Le problème est que je ne sais pas comment gérer cette boucle loop. Pour moi le seul intérêt est que dans loop il doit y avoir la surveillance de l'état du BP, un point c'est tout.
Seulement si je met dans une autre fonction que loop() quelque chose comme " si appui BP -->lecture de la première ligne du tableau, puis incrémentation de +1 de la ligne" et ça dans une boucle jusqu'à lecture de la totalité du tableau genre :  i<47, et bien forcément ça ne prend pas parce que ce n'est pas dans ce qui est considéré dans arduino comme la fonction principale j'ai nommé loop()!

J'imagine que c'est un problème de débutant, ce que je suis,  c'est donc étonnant que personne n'ait de solution à cette question. S'il y en a une, de solution ...

fdufnews

i en variable globale
Initialisée à 0 dans setup()
Ensuite tu incrémentes à chaque appui dans loop() et tu testes s'il y a débordement pour remettre la variable à zéro.

tahitibob35

Bon, c'est pas la solution complète (ce serait trop facile :P), mais ça va t'aider :


Code: [Select]
const int TAILLE_MAX = 47;

typedef struct TabCom {
char label[20];
int value;
} TabCom;

static const TabCom tabCom[TAILLE_MAX]  {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799},
    {"KEY_IMAGES", 0x179A}, {"KEY_INFO", 0x179B}, {"KEY_RADIO", 0x178C}, {"KEY_EXIT", 0x179F},
    {"KEY_MENU", 0x178D}, {"KEY_CHANNELDOWN", 0x1792}, {"KEY_MUTE", 0x178F}, {"KEY_UP", 0x1794},
    {"KEY_DOWN", 0x1795}, {"KEY_LEFT", 0x1796}, {"KEY_RIGHT", 0x1797}, {"KEY_OK", 0x17A5},
    {"KEY_VOLUMEUP", 0x1790}, {"KEY_VOLUMEDOWN", 0x1791}, {"KEY_CHANNELUP", 0x17A0},
    {"KEY_CHANNELDOWN", 0x17A1}, {"KEY_RECORD", 0x17B7}, {"KEY_STOP", 0x17B6}, {"KEY_REWIND", 0x17B2},
    {"KEY_FASTFORWARD", 0x17B4}, {"KEY_PLAY", 0x17B5}, {"KEY_AGAIN", 0x17A4}, {"KEY_NEXT", 0x179E},
    {"KEY_PAUSE ", 0x17B0}, {"KEY_1", 0x1781}, {"KEY_2", 0x1782}, {"KEY_3", 0x1783}, {"KEY_4", 0x1784},
    {"KEY_5", 0x1785}, {"KEY_6", 0x1786}, {"KEY_7", 0x1787}, {"KEY_8", 0x1788}, {"KEY_9", 0x1789},
    {"KEY_NUMERIC_STAR", 0x178A}, {"KEY_0", 0x1780}, {"KEY_NUMERIC_POUND", 0x178E}, {"KEY_RED", 0x178B},
    {"KEY_GREEN", 0x17AE}, {"KEY_YELLOW", 0x17B8}, {"KEY_BLUE", 0x17A9}, {"KEY_SUBTITLE", 0x178E},
    {"KEY_TEXT", 0x178A}, {"KEY_HOME", 0x17BB}
  };

char buffer[30];    // make sure this is large enough for the largest string it must hold

const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState = 0;

byte i = 0;

void setup()
{
  Serial.begin(9600);
}


void loop() {

  TabCom unElement;
  buttonState = digitalRead(buttonPin);
 
  Serial.print(tabCom[i].label);
  Serial.print(" : ");
  Serial.println(tabCom[i].value, HEX);
  delay(1000);
  ++i;
}

moricef

Bon visiblement c'est pas encore ça. Après discute sur l'IRC, il faut voir du coté des changements d'états du BP et des variables à renseigner

moricef

Voilà le résultat, encore imparfait, mais on s'approche :
Code: [Select]
#define TAILLE_MAX 4

typedef struct TabCom {
char label[20];
unsigned long value;
} TabCom;

IRsend irsend;

const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState;         // Variable pour enregistrer l'état du bouton-poussoir
byte buttonOldState = LOW;
byte bits = 32;
byte i = 0;
TabCom tabCom[4] = {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799}
  };

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT); // Broche bouton-poussoir comme entrée
  initTableauCommandes();
}

void initTableauCommandes() {
 
 
}

void loop() {
   
 
 
    buttonState = digitalRead(buttonPin); // Interrogation du bouton-poussoir
   
    if ((buttonState != buttonOldState) && (buttonState == HIGH)) {
   
       ++i;
    }
    buttonOldState = buttonState;   
   
      Serial.println(tabCom[i].label);
      for (int n=0; n<3; ++n) {
      Serial.println(tabCom[i].value, HEX);
      }
   
}

c'est juste pour la boucle loop(). J'ai bien un changement de ligne à chaque appui BP, mais je ne sais pas mettre le programme en paus een attendant le prochain appui BP - changement d'état. Faut-il passer par une interruption matérielle?

moricef

Voilà, c'est résolu et  c'était finalement simple, encore eut-il fallu y penser : sortir buttonOldState = buttonState; du bloc if. (merci à jackbot sur l'irc)

Code: [Select]

#include <IRremote.h>

#define TAILLE_MAX 4

typedef struct TabCom {
char label[20];
unsigned long value;
} TabCom;

IRsend irsend;

const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState;         // Variable pour enregistrer l'état du bouton-poussoir
byte buttonOldState = LOW;
//byte bits = 32;
byte i;
int lireLigne;

TabCom tabCom[4] = {
    {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799}
};

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT); // Broche bouton-poussoir comme entrée
  byte i = 0;
}

void loop() {
  
    while (i<TAILLE_MAX){
      
      buttonState = digitalRead(buttonPin); // Interrogation du bouton-poussoir
  
      if ((buttonState != buttonOldState) && (buttonState == HIGH)) {
    
Serial.println(tabCom[i].label);
      
for (int n = 0; n < 3; n++) {

 Serial.println(tabCom[i].value, HEX);
}
      
i++;

delay(200);
      }
      
      if (i == TAILLE_MAX) {

i=0;
      }
    }
 
    buttonOldState = buttonState;  
}

moricef

Je met mon sketch final avec PROGMEM  :
Code: [Select]
#include <IRremote.h>
#include <avr/pgmspace.h>

#define LABEL_SIZE 20

struct TabCom_STRUCT {
  char label[LABEL_SIZE];
  unsigned int value;
};

const TabCom_STRUCT tabCom_tab[] PROGMEM = {
  {"KEY_POWER", 0x17BD}, {"KEY_TV", 0x179C}, {"KEY_VIDEO", 0x1798}, {"KEY_AUDIO", 0x1799},
  {"KEY_IMAGES", 0x179A}, {"KEY_INFO", 0x179B}, {"KEY_RADIO", 0x178C}, {"KEY_EXIT", 0x179F},
  {"KEY_MENU", 0x178D}, {"KEY_CHANNELDOWN", 0x1792}, {"KEY_MUTE", 0x178F}, {"KEY_UP", 0x1794},
  {"KEY_DOWN", 0x1795}, {"KEY_LEFT", 0x1796}, {"KEY_RIGHT", 0x1797}, {"KEY_OK", 0x17A5},
  {"KEY_VOLUMEUP", 0x1790}, {"KEY_VOLUMEDOWN", 0x1791}, {"KEY_CHANNELUP", 0x17A0},
  {"KEY_CHANNELDOWN", 0x17A1}, {"KEY_RECORD", 0x17B7}, {"KEY_STOP", 0x17B6}, {"KEY_REWIND", 0x17B2},
  {"KEY_FASTFORWARD", 0x17B4}, {"KEY_PLAY", 0x17B5}, {"KEY_AGAIN", 0x17A4}, {"KEY_NEXT", 0x179E},
  {"KEY_PAUSE ", 0x17B0}, {"KEY_1", 0x1781}, {"KEY_2", 0x1782}, {"KEY_3", 0x1783}, {"KEY_4", 0x1784},
  {"KEY_5", 0x1785}, {"KEY_6", 0x1786}, {"KEY_7", 0x1787}, {"KEY_8", 0x1788}, {"KEY_9", 0x1789},
  {"KEY_NUMERIC_STAR", 0x178A}, {"KEY_0", 0x1780}, {"KEY_NUMERIC_POUND", 0x178E}, {"KEY_RED", 0x178B},
  {"KEY_GREEN", 0x17AE}, {"KEY_YELLOW", 0x17B8}, {"KEY_BLUE", 0x17A9}, {"KEY_SUBTITLE", 0x178E},
  {"KEY_TEXT", 0x178A}, {"KEY_HOME", 0x17BB}
};

char buffer_label[30];    // make sure this is large enough for the largest string it must hold
IRsend irsend;
const byte buttonPin = 2;           // Bouton-poussoir en broche 2
byte buttonState;
byte buttonOldState;
byte bits;
byte counter; // counter variable
unsigned long readValue;

void setup() {
  Serial.begin(9600);
  counter = 0;
  bits = 32;
  pinMode( buttonPin, INPUT_PULLUP);
}

void loop() {
  buttonState = digitalRead(buttonPin); // Interrogation du bouton-poussoir
 
  if (buttonState != buttonOldState) {
    buttonOldState = buttonState;
   
    if( buttonState == HIGH)
    {
      strcpy_P(buffer_label, tabCom_tab[counter].label);
      Serial.print(buffer_label);
      Serial.print(" ");
      readValue= pgm_read_word(&tabCom_tab[counter].value);
      Serial.print("0x");
      Serial.print(readValue, HEX);
      Serial.print(" ");
      Serial.println(bits);
      for (int n = 0; n < 3; n++) {
     
      irsend.sendRC5(readValue, bits);
      delay(40);

      }
      counter++;
      delay(200);
      if (counter >= sizeof(tabCom_tab) / sizeof(TabCom_STRUCT)) {
        counter = 0;

      }
    }
  }
}

Go Up