Problème mémoire Arduino

Bonjour,

Suite a un soucis de Sram dans mon programme , je me suis renseigné et j'ai entendu parler de la fonction F() et PROGMEM de la bibliotheque <avr/pgmspace.h>, je les ai incorporé à mon code et j'ai réussi à récupérer la Sram qu'il me manquait. Le problème si je mets mes tableaux en PROGMEM je n'arrive plus à les utiliser alors que les autres marchent correctement. Je vous met le programme en lien mais pour etre plus clair, mon programme affiche une page html sur le client qui permet de piloter et d'envoyer avec la arduino des IR, problème : seul les IR sans le PROGMEM sont envoyées les autres ne sont pas send. Quel est le problème ? Y a-t-il un autre moyen ?

Thx !

IR_TV.ino (26.3 KB)

Tes tableaux ne sont pas bien déclarés si on suit la doc fournie :

While PROGMEM could be used on a single variable, it is really only worth the fuss if you have a larger block of data that needs to be stored, which is usually easiest in an array, (or another C data structure beyond our present discussion).
Using PROGMEM is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), also defined in the pgmspace.h library, to read the data from program memory back into SRAM, so we can do something useful with it.
As mentioned above, it is important to use the datatypes outlined in pgmspace.h. Some cryptic bugs are generated by using ordinary datatypes for program memory calls. Below is a list of variable types to use. Floating point numbers in program memory do not appear to be supported.
prog_char - a signed char (1 byte) -127 to 128
prog_uchar - an unsigned char (1 byte) 0 to 255
prog_int16_t - a signed int (2 bytes) -32,767 to 32,768
prog_uint16_t - an unsigned int (2 bytes) 0 to 65,535
prog_int32_t - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
prog_uint32_t - an unsigned long (4 bytes) 0 to 4,294,967,295

Source : PROGMEM - Arduino Reference

Salut,

Pas de code, pas de réponse :wink:

B@tto:
Source : PROGMEM - Arduino Reference

STOP !
La référence Arduino est la pire source d'informations qu'il soit qu'en on arrive dans du dév AVR-C bas niveau ...

Google "avr progmem" ->
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
"click" ->
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#gadb50761b9f19d45449445208778ee420
"click" ->

prog_char
Note: DEPRECATED

prog_int16_t
Note: DEPRECATED

prog_int32_t
Note: DEPRECATED

prog_int64_t
Note: DEPRECATED

prog_int8_t
Note: DEPRECATED

prog_uchar
Note: DEPRECATED

(...)

DEPRECATED

La team Arduino a encore frappé. On n'utilise plus les types prog_* depuis un bon moment déja.
Par contre les PROGMEM et le const sont obligatoire (voir lien n°1) :wink:

Faut mettre à jour ton tuto sur le LCD de Nokia 5110 alors :stuck_out_tongue:

B@tto:
Faut mettre à jour ton tuto sur le LCD de Nokia 5110 alors :stuck_out_tongue:

Ya pas que celui là qui mériterai une màjn mais j'ai pas le temps.

bonjour merci de vos réponses je vais potasser tout ça .

pour le :

Pas de code, pas de réponse

skywodd le code est en fichier téléchargeable dans mon lien . Il était trop imposant pour le taper direct et j'ai donc du l'upload.
cordialement

edit:
J'ai regardé les sites et je comprends mieux le progmem. Mais mon soucis persiste:
comme j'ai compris je declare mon tableau comme celà :

unsigned int S_pwr[68]PROGMEM={4600,4350,700,1550,650,1550,650,1600,650,450,650,450,650,450,650,450,700,400,700,1550,650,1550,650,1600,650,450,650,450,650,450,700,450,650,450,650,450,650,1550,700,450,650,450,650,450,650,450,650,450,700,400,650,1600,650,450,650,1550,650,1600,650,1550,650,1550,700,1550,650,1550,650};

puis je le récupére

irsend.sendRaw(pgm_read_float(&(S_pwr)),68,38);

le probléme j'ai utilisé les différent pgm_read_* maisj e ne trouve aucun qui me permetrait de lire un int ou un unsigned int et quand j'utilise le pgm_read_float ( le plus logique ) c'est ma fonction qui n'aprécie plus et qui ne veux pas de float
Je me suis dit ok c'est un float donc autant le retransformer en int et le probléme est réglé.

irsend.sendRaw((int)pgm_read_float(&(S_pwr)),68,38);

La le programme me dit que je convertis un 'int' en un 'unsigned int*'...
dernier test , ok l int il veux pas c'est normale on va transformer le float en unsigned int alors :

irsend.sendRaw((unsigned int)pgm_read_float(&(S_pwr)),68,38);

et bien toujours pas là il me dit que je convertis un 'unsigned int' en 'unsigned int*'

Je cherche un peu et je me dis , " mais que veut dire cette '*' à la fin de unsigned int " et la je ne trouve pas de réponse a mon problème si quelqu'un a une idée ou saurait ou je me suis trompé

skywodd:

B@tto:
Faut mettre à jour ton tuto sur le LCD de Nokia 5110 alors :stuck_out_tongue:

Ya pas que celui là qui mériterai une màjn mais j'ai pas le temps.

Pour ça marche bien encore ! Mais du coup, vu que ces types sont déprécié, cela veut bien dire qu'à une époque ils étaient valables ? Donc que l'usage ou non de ces types est lié à la version de GCC ?

QuentinHbt:
J'ai regardé les sites et je comprends mieux le progmem. Mais mon soucis persiste:
comme j'ai compris je declare mon tableau comme celà :

unsigned int S_pwr[68]PROGMEM={4600,4350,700,1550,650,1550,650,1600,650,450,650,450,650,450,650,450,700,400,700,1550,650,1550,650,1600,650,450,650,450,650,450,700,450,650,450,650,450,650,1550,700,450,650,450,650,450,650,450,650,450,700,400,650,1600,650,450,650,1550,650,1600,650,1550,650,1550,700,1550,650,1550,650};

puis je le récupére

irsend.sendRaw(pgm_read_float(&(S_pwr)),68,38);

le probléme j'ai utilisé les différent pgm_read_* maisj e ne trouve aucun qui me permetrait de lire un int ou un unsigned int

Personnellement pour relire un int ou unsigned int j'utiliserais pgm_read_word qui semble quand même plus approprié.

et bien quand je fait le pgm_read_word j'ai l'erreur "invalid conversion from 'uint16_t' to 'unsigned int*'"

faut faire un cast pour redonner le bon type à la valeur

unsigned int toto;

toto = (unsigned int) pgm_read_word(la_variable_en_progmem);

j'ai testé et ai mis le test précédament , mais je l'ai refait avec une version plus claire :

unsigned int test = (unsigned int)pgm_read_word(&S_pwr);
 irsend.sendRaw(test,68,38);

et le résultat est le même:
"invalid conversion form 'unsigned int' to 'unsigned int*'"

toujours cette fameuse '*' dont je ne comprend pas le sens

L'erreur doit être ailleurs.
Je compile ce code sans problème (avec ou sans le cast):

#include <avr/pgmspace.h>

unsigned int S_pwr[68]PROGMEM={4600,4350,700,1550,650,1550,650,1600,650,450,650,450,650,450,650,\
450,700,400,700,1550,650,1550,650,1600,650,450,650,450,650,450,700,450,650,450,650,450,650,1550,\
700,450,650,450,650,450,650,450,650,450,700,400,650,1600,650,450,650,1550,650,1600,650,\
1550,650,1550,700,1550,650,1550,650};

void setup() {
  // put your setup code here, to run once:
  unsigned int toto = pgm_read_float(&(S_pwr));
}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

j'ai testé avec et sans et le probléme est bien à niveaux enfin je pense , ou cela vient de la fonction qui est trés sensible à la casse ou autres :confused:

en gros la convertion se passe bien mais le irsend lui demande un unsigned int* je pensse que le soucie vien ce là. mais je ne sait pas exactement pourquoi

QuentinHbt:
j'ai testé avec et sans et le probléme est bien à niveaux enfin je pense , ou cela vient de la fonction qui est trés sensible à la casse ou autres :confused:

Le C est sensible à la casse

QuentinHbt:
en gros la convertion se passe bien mais le irsend lui demande un unsigned int* je pensse que le soucie vien ce là. mais je ne sait pas exactement pourquoi

Punaise je n'avais pas vu le *
irsend veut un pointeur sur la variable et non pas une valeur.
Du coup il faut rapatrier le tableau pour le passer en argument à irsend. Il doit falloir utiliser quelque chose comme memcpy_P pour transférer le tableau en RAM avant d'appeler irsend. A faire confirmer par les habitués de PROGMEM

Oue bien ce que je penssait pour la casse et le c (dsl sa fait 2 semaine que je suis sur le langage ^^)

Pour le pointage vas faloire que je regarde un peut cette fonction pour bien conprendre mais j'ai peur quand m'amuser a enlever et remetre les tableau dans la sram lle sature carle soucie c'est que le programme est gourment en sram.
Oui si quelqu'un si connait bien en PRGMEM se serait intéressent

Si tu as placé plusieurs tableaux en zone programme tu as de toutes les façons gagné de la place en RAM.
Une solution c'est de créer un tableau fourre-tout de la taille maximum dont tu auras besoin pour relire le plus gros de tes tableaux.
Ce tableau fourre-tout doit être de type void et tu typeras son contenu par un cast au moment de l'utiliser.

Bonjour,
première question : es-tu vraiment certains d'avoir besoin d'envoyer des trames raw et que ta télécommande ne correspond à aucun protocole géré par la librairie ? Parce que les protocoles connus sont nettement moins gourmands en ressources mémoire pour le stockage.

Si on suppose que la réponse est oui:
Deuxio : je suppose que tu as "mesuré" ces codes avec la librairie IrRemote elle-même. Or il me semble (mais je peux me tromper) que beaucoup des valeurs mesurées ne diffère que de "l'erreur de mesure". Ce qui veux dire que :

  • 450?400= 400
  • 650?700=700
  • 1500?1550?1600=1550

Je suis presque certains (mais il faut que tu vérifie bien sûr) que tes trames fonctionneront encore si tu les "nettoie" de cette façon.

Et si effectivement ça fonctionne, tu remarquera qu'en fait le début de tes trames est toujours identique : je n'ai pas regardé en détail mais au bas mot je dirais qu'au minimum les 30 premières données de chaque trames sont similaires. Du coup, au lieu de stocker des trames complètes, tu n'en as que la moitié plus un entête constant. Que ce sois en RAM ou en Flash, la mémoire nécessaire est quasiment divisée par deux.

Pour aller plus loin, on peux même constater que tu n'es pas obligé de stocker ces valeurs dans des int (16 bits) : si tu les divises par 10, toutes tiennent dans des uint8_t (sauf les 2 premières, mais elles peuvent être traitées à part), et du coup tu as encore divisé l'espace de stockage nécessaire par 2.

Ça donnerai un peu ça:


réserver en RAM un tableau de uint16_t de 68 éléments,
    initialiser le premier à 4600 et le second à 4350.

envoi(): 
  en commençant à l'index 2 du tableau:
    récupérer depuis la mémoire Flash les données de l'entête [u]une par une[/u]
    les multiplier par 10
    les stocker à l'index correspondant dans le tableau

    idem pour la suite, mais en utilisant les données propres à chaque trame.

Voilà, j'espère que c'est clair, j'ai comme un doute. En tout cas en faisant ça, tu perds un peu en rapidité d'exécution (mais je ne pense pas que ce sois un problème ici), en revanche tu divises ton empreinte mémoire quasiment par 3, et ça c'est loin d'être négligeable.

merci pour ces postes ,

fdufnews sa peut etre une idée je peux essayer.

haifger, je suis sur une télé samsung et la bibliothèque irremote ne les a pas , sauf erreur de ma part donc je suis obligé d'utiliser le raw enfin je crois. Après sur le mesuré non , je ne m'y connais pas du tout en infra rouge on ma demandé de réaliser un programme et je fais au mieux de mes capacités ^^ . Donc je ne sais pas du tout . Par contre je vais essayer ton idée.

je vous donnerai le retour demain après midi

cordialement.

Tu devrait aller voir là pour les codes de télécommandes: Index of /remotes

Oui je suis déjà allé sur ce site et trouvé le code, le problème c'est que irremote ne gère pas les code samsung sauf erreur de ma part