Bonjour, bonjour,
Je me suis mis a creer une sorte d'émulateur avec arduino, j'ai coder plusieurs jeux et la taille qu'occupe la memoire SRAM dans mon arduino mega est de 40%. Aujourd'hui je me suis mit a coder un nouveau jeu : un quizz sur le tableau periodique des elements !
Alors, dans le bout de code que vous retrouverez ci dessous, tout va pas mal lorsque on met tout en memoire SRAM. Facile et simple d'utilisation, ce n'est pourtant pas l'ideal car je souhaite utiliser l'espace pour d'autres choses. En gros je voudrais mettre mon tableau en memoire flash et bien entendu pouvoir le recuperer. Pour ce faire, vous pouvez voir dans mon code que j'utilise des fonctions pour recuperer les donnees dans des 'char' et les afficher ; mais lorsque j'execute ce programme, le lcd ecrit n'importe quoi, des caracteres bizzards et des points d'interrogations ou tout autres choses similaires. Alors ma question est simple : pourquoi et comment ?
Je vous mets la fonction qui utilise PROGMEM ci dessous, il est un peu compliqué, surtout au niveau des noms de variables (je suis pas très inspiré), si vous avez une question sur le code, n'hésitez SURTOUT pas car je sais qu'il n'est pas très compréhensible… Je precise que mon code entier est juste ENORME (8000 lignes .........) et qu'il est ici VRAIMENT EPURER, juste le necessaire, c'est pourquoi j'ai enlever les fonctions setup et loop et toutes les autres declarations mais je ne doute pas que vous le comprendrez bien ! Le voici justement :
// Ce tableau est un peu complique et ne necessite pas de mise en memoire flash a mon avis
// Description du tableau, lorsque le chiffre est un 1, cela signifie que l'element est solide a 0°c, un 2 : il est gazeux et un 3 : il est liquide !
const int type_elements[118] {
1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2
};
// Declaration de mon tableau a 3 dimensions, en constante, en char, et en PROGMEM !
// Tableau de données de la table périodique :
const char elements PROGMEM [118][2][15] = {
{"Hydrogene", "H"},
{"Helium", "He"},
{"Lithium", "Li"},
{"Beryllium", "Be"},
{"Bore", "B"},
{"Carbone", "C"},
{"Azote", "N"},
{"Oxygene", "O"},
{"Fluor", "F"},
{"Neon", "Ne"},
{"Sodium", "Na"},
{"Magnesium", "Mg"},
{"Aluminium", "Al"},
{"Silicium", "Si"},
{"Phosphore", "P"},
{"Soufre", "S"},
{"Chlore", "Cl"},
{"Argon", "Ar"},
{"Potassium", "K"},
{"Calcium", "Ca"},
{"Scandium", "Sc"},
{"Titane", "Ti"},
{"Vanadium", "V"},
{"Chrome", "Cr"},
{"Manganese", "Mn"},
{"Fer", "Fe"},
{"Cobalt", "Co"},
{"Nickel", "Ni"},
{"Cuivre", "Cu"},
{"Zinc", "Zn"},
{"Gallium", "Ga"},
{"Germanium", "Ge"},
{"Arsenic", "As"},
{"Selenium", "Se"},
{"Brome", "Br"},
{"Krypton", "Kr"},
{"Rubidium", "Rb"},
{"Strontium", "Sr"},
{"Yttrium", "Y"},
{"Zirconium", "Zr"},
{"Niobium", "Nb"},
{"Molybdene", "Mo"},
{"Technetium", "Tc"},
{"Ruthenium", "Ru"},
{"Rhodium", "Rh"},
{"Palladium", "Pd"},
{"Argent", "Ag"},
{"Cadmium", "Cd"},
{"Indium", "In"},
{"Etain", "Sn"},
{"Antimoine", "Sb"},
{"Tellure", "Te"},
{"Iode", "I"},
{"Xenon", "Xe"},
{"Cesium", "Cs"},
{"Baryum", "Ba"},
{"Lanthane", "La"},
{"Cerium", "Ce"},
{"Praseodyme", "Pr"},
{"Neodyme", "Nd"},
{"Promethium", "Pm"},
{"Samarium", "Sm"},
{"Europium", "Eu"},
{"Gadolipium", "Gd"},
{"Terbium", "Tb"},
{"Dysprosium", "Dy"},
{"Holmium", "Ho"},
{"Erbium", "Er"},
{"Thulium", "Tm"},
{"Ytterbium", "Yb"},
{"Lutecium", "Lu"},
{"Hafnium", "Hf"},
{"Tantale", "Ta"},
{"Tungstene", "W"},
{"Rhenium", "Re"},
{"Osmium", "Os"},
{"Iridium", "Ir"},
{"Platine", "Pt"},
{"Or", "Au"},
{"Mercure", "Hg"},
{"Thallium", "Tl"},
{"Plomb", "Pb"},
{"Bismuth", "Bi"},
{"Polonium", "Po"},
{"Astate", "At"},
{"Radon", "Rn"},
{"Francium", "Fr"},
{"Radium", "Ra"},
{"Actinium", "Ac"},
{"Thorium", "Th"},
{"Protactinium", "Pa"},
{"Uranium", "U"},
{"Neptunium", "Np"},
{"Plutonium", "Pu"},
{"Americium", "Am"},
{"Curium", "Cm"},
{"Berkelium", "Bk"},
{"Californium", "Cf"},
{"Einsteinium", "Es"},
{"Fermium", "Fm"},
{"Mendelevium", "Md"},
{"Nobelium", "No"},
{"Lawrencium", "Lr"},
{"Rutherfordium", "Rf"},
{"Dubnium", "Db"},
{"Seaborgium", "Sg"},
{"Bohrium", "Bh"},
{"Hassium", "Hs"},
{"Meitnerium", "Mt"},
{"Darmstadtium", "Ds"},
{"Roentgenium", "Rg"},
{"Copernicium", "Cn"},
{"Nihonium", "Nh"},
{"Flerovium", "Fl"},
{"Moscovium", "Mc"},
{"Livermorium", "Lv"},
{"Tennessine", "Ts"},
{"Oganesson", "Og"}
};
void periodique() {
char bonne_reponse[15] = "";
char reponse_fictive[15] = "";
char reponse_fictive2[15] = "";
lcd.clear();
lcd.setCursor(2, 0);
lcd.print(F("QUIZZ Periodique"));
lcd.setCursor(1, 1);
lcd.print(F("Trouvez la reponse"));
lcd.setCursor(3, 2);
lcd.print(F("AUX QUESTIONS"));
// Definir des numeros aleatoires pour les questions
// le randomSeed(analogRead(A0)); est declaré dans le setup pour des nombres pseudo aleatoire !
int ordre_reponse = random(0, 3);
int type_question = random(0, 10);
int demande_vrai = random(0, 118);
int demande_fausse = random(0, 118);
int demande_fausse2 = random(0, 118);
while (demande_fausse == demande_vrai) {
// Tourner pour que les propositions soient differentes
demande_fausse = random(0, 118);
}
while (demande_fausse2 == demande_vrai or demande_fausse2 == demande_fausse) {
// Tourner pour que les propositions soient differentes
demande_fausse2 = random(0, 118);
}
// Declaré les tableaux qui contiendront les infos du quizz periodique
// Désolé si le nom des variables n'est pas tres parlant :)
char vraie_nom[15] = "";
char vraie_symbole[15] = "";
char faux_nom[15] = "";
char faux_symbole[15] = "";
char faux_nom2[15] = "";
char faux_symbole2[15] = "";
int vrai_type = 0;
int faux_type = 0;
int faux_type2 = 0;
// Ci dessous, les differentes versions (avec/sans PROGMEM) (Avec char OU String)
/*
vraie_nom = elements[demande_vrai][0];
vraie_symbole = elements[demande_vrai][1];
faux_nom = elements[demande_fausse][0];
faux_symbole = elements[demande_fausse][1];
faux_nom2 = elements[demande_fausse2][0];
faux_symbole2 = elements[demande_fausse2][1];
*/
/*
strcpy(vraie_nom, elements[demande_vrai][0]);
strcpy(vraie_symbole, elements[demande_vrai][1]);
strcpy(faux_nom, elements[demande_fausse][0]);
strcpy(faux_symbole, elements[demande_fausse][1]);
strcpy(faux_nom2, elements[demande_fausse2][0]);
strcpy(faux_symbole2, elements[demande_fausse2][1]);
*/
strcpy_P(vraie_nom, (char*)pgm_read_word(&(elements[demande_vrai][0])));
strcpy_P(vraie_symbole, (char*)pgm_read_word(&(elements[demande_vrai][1])));
strcpy_P(faux_nom, (char*)pgm_read_word(&(elements[demande_fausse][0])));
strcpy_P(faux_symbole, (char*)pgm_read_word(&(elements[demande_fausse][1])));
strcpy_P(faux_nom2, (char*)pgm_read_word(&(elements[demande_fausse2][0])));
strcpy_P(faux_symbole2, (char*)pgm_read_word(&(elements[demande_fausse2][1])));
vrai_type = type_elements[demande_vrai - 1];
faux_type = type_elements[demande_fausse - 1];
faux_type2 = type_elements[demande_fausse2 - 1];
Serial.println(elements[demande_fausse2][1]);
///////////////////////////////////////////////////
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(F("A =>"));
lcd.setCursor(0, 2);
lcd.print(F("B =>"));
lcd.setCursor(0, 3);
lcd.print(F("C =>"));
// Ici, on pose la question sur l'element mais le type de question est definis par un random (plus haut)
// PS : Si il y a plusieurs conditions pour un meme resultat c'est pout les probabilités, je veux que ca tombe moins de fois sur la question de l'etat a 0°C par exemple...
if (type_question == 0 or type_question == 1) {
// symbole de l'element
strcpy(bonne_reponse, vraie_symbole);
strcpy(reponse_fictive, faux_symbole);
strcpy(reponse_fictive2, faux_symbole2);
lcd.setCursor(0, 0);
lcd.print(F("Quel symbole : "));
lcd.print(demande_vrai + 1);
} else if (type_question == 2 or type_question == 3) {
// numero de l'element
strcpy(bonne_reponse, char((demande_vrai + 1)));
strcpy(reponse_fictive, demande_fausse);
strcpy(reponse_fictive2, demande_fausse2);
lcd.setCursor(0, 0);
lcd.print(F("Quel numero : "));
lcd.print(vraie_symbole);
}
else if (type_question == 4) {
// Type d'element, gaz, liquide, solide ?
const char gaz[7] = "Gazeux";
const char liq[8] = "Liquide";
const char sol[7] = "Solide";
if (vrai_type == 1) {
strcpy(bonne_reponse, gaz);
strcpy(reponse_fictive, liq);
strcpy(reponse_fictive2, sol);
} else if (vrai_type == 2) {
strcpy(bonne_reponse, liq);
strcpy(reponse_fictive, gaz);
strcpy(reponse_fictive2, sol);
} else if (vrai_type == 3) {
strcpy(bonne_reponse, sol);
strcpy(reponse_fictive, gaz);
strcpy(reponse_fictive2, liq);
}
lcd.setCursor(0, 0);
lcd.print(F("Quel Etat a 0C ? "));
if (random(2) == 0) {
lcd.print((demande_vrai + 1));
} else {
lcd.print(vraie_symbole);
}
} else {
// nom de l'element
strcpy(bonne_reponse, vraie_nom );
strcpy(reponse_fictive, faux_nom);
strcpy(reponse_fictive2, faux_nom2);
lcd.setCursor(0, 0);
lcd.print(F("Quel nom : "));
if (random(2) == 0) {
lcd.print((demande_vrai + 1));
} else {
lcd.print(vraie_symbole);
}
}
char num_bonne_reponse = 'A';
if (ordre_reponse == 0) {
num_bonne_reponse = 'A';
lcd.setCursor(5, 1);
lcd.print(bonne_reponse);
lcd.setCursor(5, 2);
lcd.print(reponse_fictive);
lcd.setCursor(5, 3);
lcd.print(reponse_fictive2);
} else if (ordre_reponse == 1) {
num_bonne_reponse = 'B';
lcd.setCursor(5, 1);
lcd.print(reponse_fictive);
lcd.setCursor(5, 2);
lcd.print(bonne_reponse);
lcd.setCursor(5, 3);
lcd.print(reponse_fictive2);
} else {
num_bonne_reponse = 'C';
lcd.setCursor(5, 1);
lcd.print(reponse_fictive2);
lcd.setCursor(5, 2);
lcd.print(reponse_fictive);
lcd.setCursor(5, 3);
lcd.print(bonne_reponse);
}
char entre_users = presser_clavier(); // Fonction qui attends qu'on appuis sur le keypad et retourne sa valeur.
lcd.clear();
lcd.setCursor(0, 0);
if (entre_users == num_bonne_reponse) {
lcd.print(F("Bonne reponse !"));
rgb(0, 255, 0); // Fonction pour une LED rgb
playVictorySound(); // Fonction pour jouer un son sur un buzzer
} else {
lcd.print(F("Mauvaise reponse !"));
rgb(255, 0, 0); // Fonction pour une LED rgb
playDefeatSound(); // Fonction pour jouer un son sur un buzzer
}
rgb(0, 0, 0); // Fonction pour une LED rgb (eteindre apres le buzzer)
// Afficher la totalité des infos sur l'element :
lcd.setCursor(0, 1);
lcd.print(F("Nom : "));
lcd.print(vraie_nom);
lcd.setCursor(0, 2);
lcd.print(F("Numero ATOMIC : ")); // Ce n'est pas une faute d'orthographe (c'est un jeu de mot mais je vous epargne l'explication :) )
lcd.print(demande_vrai + 1); // Le + 1 pour ignorer le 0 du tableau
lcd.setCursor(0, 3);
lcd.print(F("Symbole : "));
lcd.print(vraie_symbole );
presser_clavier(); // Mme fonction decrite plus haut !
rgb(0, 0, 0);
periodique(); // Revenir a la fonction pour rejouer
}
Je note que je ne sais pas si les balises de code se sont mises alors j'espere que ce sera lisible...
En tout cas, merci a vous pour vos futures reponses !!!