IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Adresses mémoires de variables "à la suite"


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 999
    Par défaut Adresses mémoires de variables "à la suite"
    Bonjour,

    Difficile de trouver un titre explicite pour ma question... Ce n'est pas très compliqué :

    Dans mon code je déclare plusieurs variables les unes à la suite des autres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    byte serverIP[] = { 192, 168, 123, 32 };
    IPAddress ip(192, 168, 123, 177);
    byte LumiereA = 205;
    byte LumiereB = 3;
    byte delayPingServer = 10;
    byte mac[]= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    Je voudrais que ces variables occupent un espace en RAM "contigu"

    Voici un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    [01][02][03][04][05][06][07][08][09][0A][0B][0C][0D][0E][0F][10][11]
    Les octets aux adresses 1 à 4 correspondent à serverIP[]
    Les octets aux adresses 5 à 8 correspondent à ip
    L'octet à l'adresse 9 correspond à LumiereA
    L'octet à l'adresse 0A correspond à LumiereB
    L'octet à l'adresse 0B correspond à delayPingServer
    Les octets aux adresses 0C à 11 correspondent à mac

    Vous allez me dire : pourquoi ?

    Dans mon programme je vais avoir besoin de copier ces variables depuis et vers l'EEPROM
    Je vais aussi avoir besoin de pouvoir les modifier avec une interface utilisateur.

    Actuellement je dois gérer l'affichage, la saisie et la copie avec pas mal d'instructions et de switch-case ce qui aboutit à un code volumineux.

    Si ces variables sont "à la suite", avec un pointeur je peux afficher, saisir et copier chaque octet de ce paquet de variable de façon plus efficace : par exemple pour tout copier ou tout affiche, une boucle for next avec une instruction suffit.

    Comment faire cela de façon fiable, c'est à dire être certain que le compilateur place ces variables à des adresses qui se suivent ?

    Je pense déclarer un buffer, et ensuite déclarer les variables en leur spécifiant une adresse relative dans ce buffer

    Merci

    A bientôt

  2. #2
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 999
    Par défaut
    Bonjour,

    j'ai trouvé une façon de faire ;

    cela nuit à la lisibilité du code mais il n'y a que 5 endroits dans le code qui sont impactés et uniquement dans le fichier INO donc ça reste acceptable, avec des commentaires explicatifs

    J'ai remplacé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    byte serverIP[4] = { 192, 168, 123, 32 };
    byte ip[4] = {192, 168, 123, 177};
    byte delayPingServer = 10;
    byte LumiereA = 205;
    byte LumiereB = 3;
    byte mac[6] = {0x12, 0x92, 0x0B, 0xAE, 0x75, 0xCA};
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    byte EepromParametres[17] = { 192, 168, 123, 32, 192, 168, 123, 177, 10, 205, 3, 0x12, 0x92, 0x0B, 0xAE, 0x75, 0xCA};
    //                             0    1    2   3    4    5    6    7   8    9  10   11    12    13    14    15    16
    //REMPLACER CES VARIABLES :    PAR :
    //byte serverIP[]           =  EepromParametres[]
    //byte ip[]                 =  EepromParametres[] + 4
    //byte delayPingServer      =  EepromParametres[8]
    //byte LumiereA             =  EepromParametres[9]
    //byte LumiereB             =  EepromParametres[10]
    //byte mac[6]               =  EepromParametres[] + 11
    // REMARQUE IMPORTANTE : serverIP[] et ip[] appartenant au même réseau, en pratique on ne stocke pas dans l'eeprom
    //                       les octets 0, 1 et 2 de EepromParametres[] qui sont respectivement identiques aux octets 4, 5 et 6
    Très concrètement, dans le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Ethernet.begin(mac, ip);
    delay(delayPingServer);
    devient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Ethernet.begin(EepromParametres+11, EepromParametres+4); //Ethernet.begin(mac, ip);
    delay(EepromParametres[8]);//delay(delayPingServer);
    Le résultat :
    - 162 octets de ROM de gagnés
    - 4 octets de RAM en plus pour les variables
    Et ce, juste avec la fonction d'affichage ; avec les fonctions d'édition et de copie, je m'attend à un gain d'au moins 500 octets ce qui n'est pas négligeable.

    Cette façon de faire correspond un peu à la façon de coder en assembleur, dans laquelle on doit choisir manuellement l'adresse de chaque variable au moment de la déclarer.
    En assembleur, en mettant "à la suite" les variables de façon judicieuses, on peut économiser beaucoup de ROM en appliquant un traitement à tout un ensemble de variables avec une boucle (envoi sur un port série, affichage...)

    Je ne met pas résolu car j'aimerais trouver le moyen, dans le code, de définir des "alias" pour continuer à utiliser 'ip' au lieu de 'EepromParametres+4'
    (j'ai essayé avec les instructions * et & utilisées pour les pointeurs, sans succès)

    A bientôt

  3. #3
    Membre Expert
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 017
    Par défaut
    Bonjour electroremy
    Citation Envoyé par electroremy Voir le message
    ... Dans mon programme je vais avoir besoin de copier ces variables depuis et vers l'EEPROM ...
    Il n'aurait pas été plus simple de mettre toutes ces variables dans une structure (structureVariables)?
    Pour la sauver en EEPROM :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EEPROM.put(adresseDeDepartEnEEPROM, structureVariables);
    Pour la restituer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EEPROM.get(adresseDeDepartEnEEPROM, structureVariables);
    Ainsi plus besoin de s'inquiéter où se trouvent les variables.

    Citation Envoyé par electroremy Voir le message
    Je ne met pas résolu car j'aimerais trouver le moyen, dans le code, de définir des "alias" pour continuer à utiliser 'ip' au lieu de 'EepromParametres+4'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define ip EepromParametres+4
    Cordialement
    jpbbricole

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 899
    Par défaut
    @JP a 100 fois raison, il faut grouper dans une structure avec le bénéfice qu’on peut faire en une seule commande un put() ou get() de la structure en EEPROM.

    Seule petite amélioration pour répondre à votre besoin de "contiguïté" c’est un attribut supplémentaire à rajouter à la structure pour lui dire de tout "packer" (compresser) sinon la norme n’impose pas au compilateur de vraiment minimiser l’espace occupé, ni d’ailleurs de ranger les données dans l’ordre de déclaration. Avec des bytes sur une architecture 8 bits, peu de risques mais Il peut décider de laisser des trous (par exemple pour optimiser la vitesse des accès en alignant les variables sur des multiples de la taille du bus de données. Sur un ESP vous pourriez avoir une structure qui n’est pas organisée de la même façon.)

    Dans ce cas on déclare
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     typedef struct __attribute__ ((packed)) tDonnees { // see http://www.catb.org/esr/structure-packing/#_structure_alignment_and_padding
      ....;
    };

  5. #5
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 252
    Par défaut
    Bonjour,
    Bravo jpbbricole et merci pour ce complément Jay M __attribute__ ((packed)), j'en prends bonne note car j'avais déjà été embêté avec une table MODBUS où je voulais que les données soient contiguës et je m'étais résigné à faire un tableau comme l'a fait electroremy.

    A+

  6. #6
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 999
    Par défaut
    Merci pour vos réponses de connaisseurs

    En effet la structure est la façon "propre" de gérer la chose, mais il faut être certain que le compilateur va tout stocker dans le bon ordre et sans "trous".

    Chose de moins en moins évidente, car plus le temps passe, plus l'embarqué devient puissant, plus il se rapproche du fonctionnement d'un ordinateur de bureau et plus il s'éloigne du hardware.

    Cela a ses avantages et ces inconvénients.

    La méthode "bourrin" à l'avantage de résister à d'éventuelles optimisations et évolutions futures du compilateur

    Je me méfie car si la contiguïté et l'ordre de stockage des éléments d'une structure ne fait pas partie des spécifications officielles du langage, cela a des chances de ne pas ou ne plus être respecté...

    Après quelques mois passés sur d'autres occupations, vous avez probablement deviné que je me suis remis sur mon projet domotique à base d'Arduino UNO, de shield Ethernet et d'écran tactile ILI9341

    Alors j'ai une bonne nouvelle : j'ai trouvé comment mettre les données de calibration de la librairie URTouch.h dans l'EEPROM de l'Arduino.

    Je suis en train de finaliser mon projet "interface homme machine" ; le résultat c'est un module écran/arduino/ethernet totalement autonome.

    Juste un programme à téléverser, vous le mettez en route, un menu de réglages permet de calibrer l'écran, de choisir l'adresse IP et tous les paramètres, tout est sauvé dans l'EEPROM.

    Plus besoin d'éditer un programme Arduino pour chaque module, à cause de la calibration de l'écran TFT mais aussi des paramètres réseaux.

    L'interface homme machine sera, en quelque sorte, un écran TFT tactile client HTTP "universel".

    J'ai développé mon propre protocole, compatible avec les normes TCP/IP et HTTP.
    Ce protocole permet de piloter l'interface (affichage texte et graphiques, orientation de l'écran, lecture/écriture E/S, ...) avec très peu d'octets.
    Il y a un contrôle de CRC et une gestion d'erreur assez complète, tout est fait pour que le système ne plante pas, même en cas d'erreur de transmission ou d’envoi de données incorrectes.
    Cela permet d'utiliser comme serveur un petit Arduino de faible puissance.
    Mais on peut utiliser comme serveur un PC (c'est ce que je fais pour les tests), un Raspberry PI... bref n'importe quel truc pouvant être programmé comme serveur HTTP.

    Cerise sur le gâteau : l'interface permet aussi de lire et d'écrire sur quelques broches d'entrée/sorties, et surtout une broche de "ping" permet au serveur de forcer le client à faire une requête.
    Le "ping" se fait sur changement d'état de la broche (passage de 0 à 5V ou de 5V à 0) ce qui élimine tout problème de synchronisme, de durée mini/maxi ou d'accusé de réception.
    Bon OK il faut un peut de câblage mais c'était prévu dès le départ, et de toute façon il faut un câble pour la connexion Ethernet et l'alimentation : 4 paires = 2 paires pour l'Ethernet + 1 paire pour l'alim + il reste deux fils pour le "ping" et le reset.

    Le gros avantage de mon projet d'interface homme machine est son caractère universel.
    L'application qu'on en fait dépend entièrement du serveur.
    J'ai un peut pensé l'interface comme si je concevais un composant ou un module dont l'utilisateur ne peut pas modifier la programmation interne.
    (bien sûr il pourra quand même c'est mieux)

    Ce que je veux dire, c'est que pour mettre à jour le système ou ajouter des fonctionnalités, on a seulement besoin de modifier le programme du serveur.
    Les cartes interface homme machine, qui peuvent être nombreuses, n'auront qu'à être programmées une seule fois, et toutes avec le même programme (puisque les paramètres se règlent directement depuis le menu réglage via l'écran tactile, réglages qu'on ne fait normalement qu'une seule fois)

    En effet je ne me voyais pas faire le tour de la maison pour mettre à jour toutes les cartes interface pour tester chaque nouvelle idée.

    A bientôt

  7. #7
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 899
    Par défaut
    Citation Envoyé par electroremy Voir le message
    En effet la structure est la façon "propre" de gérer la chose, mais il faut être certain que le compilateur va tout stocker dans le bon ordre et sans "trous".
    Dans l’absolu ce n’est pas super important sans doute: La structure est écrite et relue comme il faut.

    Les "trous" coûteront un peu de place et de temps à l’écriture, donc si ces deux facteurs ne sont pas critiques la structure reste la solution la plus efficace pour écrire un code simple, lisible et évolutif. S’ils sont critiques on peut jouer avec __attribute__ ((packed))

    NB: écrire en eeprom c’est lent mais une fois les trous écrits ils ne sont plus modifiés donc on ne paye pas le coût d’écriture avec put()

    Je me méfie car si la contiguïté et l'ordre de stockage des éléments d'une structure ne fait pas partie des spécifications officielles du langage, cela a des chances de ne pas ou ne plus être respecté...
    C’est vrai. Donc à prendre en compte.

    ——-

    Vous avez "réinventé" le VT100 pour micros controller en mode ethernet. C’était le mainframe qui décidait de l’interface

  8. #8
    Membre chevronné Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 999
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Vous avez "réinventé" le VT100 pour micros controller en mode ethernet. C’était le mainframe qui décidait de l’interface
    Hé oui, la vie est un éternel recommencement

    D'ailleurs le cloud c'est plus ou moins la même chose, les utilisateurs n'ont plus qu'un poste client, les données sont stockées sur un serveur lointain avec la bienveillance des gouvernements qui piochent dedans, sans parler de la location de logiciels qui est un véritable piège à cons mais c'est un autre sujet...

    Mon afficheur basé sur Arduino a des avantages par rapport à un VT100 et plus sérieusement par rapport à des écrans gérés par Raspberry PI :
    - une faible consommation électrique
    - un temps de démarrage court
    - une bonne réactivité
    - pas besoin de faire un arrêt "propre"
    Il faut dire que j'ai optimisé toutes les librairies (GFX, ILI9341, URTouch, Ethernet) déjà pour que ça tienne dans les 32ko de ROM et ensuite pour que ce soit rapide.

    J'utilise tous les jours une interface web dans un smartphone pour piloter un lecteur MP3 Raspberry Pi (distribution Moode Audio), c'est performant MAIS les lenteurs de l'interface sont pénibles :
    - il faut plusieurs secondes après mise en route pour que l'interface soit prête (pourtant c'est une distribution Linux dédiée, et dans les réglages j'ai désactivé un maximum de choses, comme la carte vidéo...)
    - il y a pas mal de latence après chaque action sur l'interface, et parfois ça demande plus de dix ou vingt seconde pour se "reconnecter" quand on a pas manipulé l'interface depuis quelques minutes
    - il faut éteindre proprement le Raspberry Pi via l'interface, attendre 15 secondes, et l'éteindre électriquement
    - parfois, ça plante, il faut alors faire un hard reset
    Moode Audio reste néanmoins une bonne solution, ce que j'apprécie c'est la possibilité de connecter le smartphone en bluetooth (en plus de l'interface web), ce qui permet d'envoyer des podcasts sur la chaine hifi.
    On a ainsi une solution audio / musicale qui allie le meilleur des deux mondes : la qualité d'une installation HiFi et la mobilité et l’ergonomie du smartphone.
    Quand on est habitué au son d'une vraie bonne chaine hifi, on ne peut pas utiliser d'enceinte connectée, surtout quand on voit le prix que ces machins coutent
    Dommage que les lenteurs de l'interface pénalisent l'ergonomie.

    Un Arduino est avant tout un microcontroleur ; c'est pas puissant mais quand c'est bien programmé c'est très réactif, bien plus qu'un ordinateur avec un OS multitâche.
    C'est aussi plus fiable ; un gros système multitâche est trop complexe pour être testé dans tous les cas de figure, il y aura toujours des bugs, sans parler des lenteurs, inévitables quand 50 processus se battent entre eux pour accéder au CPU, à la RAM et aux ressources.
    Un microcontrôleur faisant beaucoup moins de choses on peut arriver plus facilement à le fiabiliser.

    Je viens de finir d'intégrer la fameuse calibration , j'en ai bavé, l'auteur de URTouch est soit bordelique soit farceur

    Bonne nouvelle il reste 3,5 Ko de ROM de libre, du coup je vais en profiter pour inclure dans mon projet quelques fonctions bonus et notamment une deuxième police de caractères avec une meilleure définition, car la police 5 x 7 est assez moche et ne met pas en valeur les possibilités de l'écran tactile.

    Le projet final, en termes de performances, n'aura rien à envier aux luxueux écran domotique du commerce, il risque même d'être plus polyvalent et plus économe en courant.
    L'écran 2,8" est un peut petit mais rien n'empêche de prendre un plus grand, toujours basé sur l'ILI9341
    D'ailleurs par rapport à sa taille, la résolution est presque trop élevée, 320x240 pixels pour 2,8" ça fait des pixels très étroits, on est obligé de dessiner des motifs "épais" pour qu'ils soient bien visibles ce qui est presque dommage.

    A bientôt

Discussions similaires

  1. Voir l'adresse mémoire d'une variable dans Eclipse
    Par foreman dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 13/03/2013, 00h12
  2. Récupérer le contenu d'une variable quotée
    Par wayat91 dans le forum VBScript
    Réponses: 3
    Dernier message: 04/03/2011, 11h01
  3. Réponses: 2
    Dernier message: 19/02/2009, 12h15
  4. Variable et leur adresse mémoire, comment les utiliser ?
    Par snoopy69 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 19/02/2009, 12h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo