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 :

Teensy LC GPIO touch et LED


Sujet :

Arduino

  1. #1
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut Teensy LC GPIO touch et LED
    Bonjour,

    J'ai essayé de faire un programme pour allumer une led dès que je touche un GPIO touch du Teensy LC hors quand je téléverse le programme dans la Teensy LC, la led s'allume direct et ne s'éteint jamais même quand je touche le GPIO touch. Je pense que mon programme est faux, puis-je avoir de l'aide pour le réussir? merci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int ledPin = 11;
    int touchPin = touchRead(1);
    const int threshold = 30;
     
     
    void setup() {
      Serial.begin(9600);
      // initialize the digital pin as an output.
      pinMode(ledPin, OUTPUT);
      pinMode(touchPin, OUTPUT);
    }
    void loop() {
      { touchPin = touchRead(1);
        Serial.print(touchPin);
        if (touchPin < threshold)
        digitalWrite(ledPin, LOW);   // set the LED on
        else (touchPin > threshold);
        digitalWrite(ledPin, HIGH);
      }
    }

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    à mon avis ça ce n'est pas bon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     pinMode(touchPin, OUTPUT);
    vous avez une pin en entrée.
    si je me souviens bien, il ne faut rien mettre du tout

    Si vous faites tourner ce code et regardez la console série à 115200 bauds, ça vous dit quoi?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const uint8_t touchPin = 1; 
     
    void setup() {
      Serial.begin(115200); 
    }
     
    void loop() {
      Serial.println(touchRead(touchPin)); 
      delay(100); 
    }

  3. #3
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Bonsoir ,

    Comment ça il ne faut rien mettre dutout ?

    Ca me donne ça, le rouge c'est quand je touche pas et le orange quand je touche.

    Nom : Capture d’écran (197)_LI.jpg
Affichages : 209
Taille : 675,2 Ko

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Rien mettre du tout comme pinMode()

    Donc ça fonctionne bien - on voit bien quand vous touchez ou pas

  5. #5
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 317
    Points : 4 124
    Points
    4 124
    Par défaut Simplifier
    Bonjour,

    Le code initial ne peut pas fonctionner (en outre pourquoi autant d'accoladses et aussi peu d'indentations ?) :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void loop() {
       touchPin = touchRead(1);
       Serial.print(touchPin);
       if (touchPin < threshold)
          digitalWrite(ledPin, LOW);   // set the LED on
       else (touchPin > threshold);    // ??? (touchPin > threshold); ne sert à rien mais termine les tests
       digitalWrite(ledPin, HIGH);     // Sera donc toujours exécutée ! Led éteinte (le temps entre allumage/extinction très court
    }

    Plutôt écrire quelque chose comme :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void loop() {
       touchPin = touchRead(1);       // touchPin devrait plutôt s'appeler touchVal
       Serial.print(touchPin);
       digitalWrite(ledPin, touchPin > threshold);   // touchPin > threshold == 1 si vrai (led éteinte) et == 0 si faux (led allumée)
    }

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    digitalWrite(ledPin, touchPin > threshold);   // touchPin > threshold == 1 si vrai (led éteinte) et == 0 si faux (led allumée)
    pour le respect des types et des API documentées on préfèrera écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     digitalWrite(ledPin, touchPin > threshold ? HIGH : LOW);



  7. #7
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Bonjour,

    J'ai testé avec touchPin et touchVal mais ca me met comme erreur pour les deux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Code_moi_2: In function 'void loop()':
    Code_moi_2:11: error: assignment of read-only variable 'touchPin'
         touchPin = touchRead(1);
     
                  ^
     
    assignment of read-only variable 'touchPin'
    Et je dois aussi enlever les pinMode() ?

  8. #8
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 317
    Points : 4 124
    Points
    4 124
    Par défaut Mille façons de tondre un œuf
    Bonjour,

    Dans la déclaration, il faut juste écrire :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int touchVal;   // Pourrait être également déclarée dans loop() puisqu'il ne sert que là.
    const int touchPin = 1;
    ...
    Et dans loop():
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void loop() {
       touchVal = touchRead(touchPin);       // touchPin devrait plutôt s'appeler touchVal
       Serial.print(touchVal);
       digitalWrite(ledPin, touchVal > threshold);   // touchPin > threshold == 1 si vrai (led éteinte) et == 0 si faux (led allumée)
    }

    En ce qui concerne l'écriture proposée par Jay, cela se discute. Il n'y a pas de problème de type car HIGH et LOW ne sont pas des types mais des alias. Pour la bonne compréhension, l'écriture de Jay est nettement préférable. Pour l'efficacité, l'écriture élidée sera certainement traduite par un code plus efficient (à vérifier selon l'optimisation du compilateur). Pour moi, c'est un choix de style que chacun fait selon ses goûts et objectifs .

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  9. #9
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Citation Envoyé par Guesset Voir le message
    En ce qui concerne l'écriture proposée par Jay, cela se discute. Il n'y a pas de problème de type car HIGH et LOW ne sont pas des types mais des alias. Pour la bonne compréhension, l'écriture de Jay est nettement préférable. Pour l'efficacité, l'écriture élidée sera certainement traduite par un code plus efficient (à vérifier selon l'optimisation du compilateur). Pour moi, c'est un choix de style que chacun fait selon ses goûts et objectifs .
    Bien sûr ça se discute parce que votre code va fonctionner

    voici les points à prendre en compte:

    HIGH et LOW sont des #define pour des valeurs (1 et 0) donc par défaut en C++ ce sont des int. Ils sont donc typés.

    Votre code dépend du fait que HIGH c'est l'entier 1 et LOW c'est l'entier 0, ce qui n'est pas dans la documentation officielle. l'API ne mentionne que l'usage de HIGH et LOW => Vous dépendez de l'implémentation, ce n'est jamais bien pour le futur.

    Je pense que vous venez du C (comme moi) et ça influence
    En C, il n'y a pas de vrai booléen. le résultat d'un test c'est 1 ou 0 comme valeur de vérité,. Mais en C++ (notre compilateur) ce n'est plus vrai. true et false sont des types à part entière. Donc vous appelez digitalWrite() avec un type booléen formel comme paramètre. Comme la fonction digitalWrite() attend un octet non signé (uint8_t) le compilateur applique une règle officielle de conversion implicite qui transforme true en l'entier 1 et false en l'entier 0 (2 ou 4 octets suivant la plateforme) puis prend ensuite l'octet de poids faible puisque c'est la norme de promotion vers un type de taille inférieure signé. Donc le compilateur va générer du code pour tout cela (puis l'optimiseur va nettoyer). On se retrouve donc dans la même situation que si on avait écrit le test nous même au niveau du code.

    En parlant du futur, il y a une proposition dans le Arduino Core pour transformer HIGH et LOW en enum (qui est un type à part entière en C++).
    Si cela était adopté il n'y aurait plus de promotion automatique entre un type énuméré PinStatus et un byte et le compilateur C++ (surtout sur machines 32 bits où les flags de compilation sont moins permissifs) se refuse à le faire. (cette proposition a reçu beaucoup d'opposition parce que justement ça fait planter la compilation de nombreux programmes qui ont pris votre raccourci)

    donc pour toutes ces raisons, en plus de la lisibilité et maintenabilité, je préfère

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    digitalWrite(ledPin, touchPin > threshold ? HIGH : LOW);

    PS: et si vous voulez faire un test, essayez ce code en commentant l'une ou l'autre des lignes avec digitalWrite

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void setup() {
      pinMode(13, OUTPUT);
      bool b = analogRead(A0) > 512; // pour éviter les optimisations du compilateur
      // digitalWrite(13, b);
      digitalWrite(13, b ? HIGH : LOW);
    }
     
    void loop() {}
    vous verrez que le code généré prend la même place mémoire. 760 octets de flash et 9 octets de SRAM sur UNO.

  10. #10
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Bonjour,

    Dans la déclaration, il faut juste écrire :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int touchVal;   // Pourrait être également déclarée dans loop() puisqu'il ne sert que là.
    const int touchPin = 1;
    ...
    Et dans loop():
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void loop() {
       touchVal = touchRead(touchPin);       // touchPin devrait plutôt s'appeler touchVal
       Serial.print(touchVal);
       digitalWrite(ledPin, touchVal > threshold);   // touchPin > threshold == 1 si vrai (led éteinte) et == 0 si faux (led allumée)
    }

    En ce qui concerne l'écriture proposée par Jay, cela se discute. Il n'y a pas de problème de type car HIGH et LOW ne sont pas des types mais des alias. Pour la bonne compréhension, l'écriture de Jay est nettement préférable. Pour l'efficacité, l'écriture élidée sera certainement traduite par un code plus efficient (à vérifier selon l'optimisation du compilateur). Pour moi, c'est un choix de style que chacun fait selon ses goûts et objectifs .

    Salutations
    Effectivement vôtre code fonctionne,et c'est intéressant d'apprendre tout ça et donc quand je touche ça détecte dans le moniteur série et je vous en remercie à tout les deux mais le but premier que je voulais c'était que la led s'allume quand on touche et ça ne fonctionne pas, manque-t-il quelque chose?

  11. #11
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Citation Envoyé par JPP3939 Voir le message
    mais le but premier que je voulais c'était que la led s'allume quand on touche et ça ne fonctionne pas, manque-t-il quelque chose?
    avez vous bien mis le pinMode en OUTPUT dans le setup pour la LED?

    postez le code qui "ne fonctionne pas"

  12. #12
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int ledPin = 7;
    const int touchPin = 1;
    int touchVal;
    const int threshold = 30;
     
     
    void setup() {
      Serial.begin(115200);
      pinMode(ledPin, OUTPUT);
    }
    void loop() {
     
        touchVal = touchRead(touchPin);
        Serial.print(touchVal);
        digitalWrite(ledPin, touchVal > threshold);   // set the LED on
     
    }
    Oui mais le truc c'est que c'est toujours le même problème, quand je téléverse le programme sur la carte, la led est continuellement allumée. et quand je touche rien ne se passe

  13. #13
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut C'est Bon!
    Okay j'ai trouvé le problème! le threshold était trop faible je l'ai juste augmenté et ca fonctionne maintenant! Mon objectif est de faire fonctionner une deuxième led ! je reviens vers vous pour vous dire si j'ai réussi ! MERCI beaucoup !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const int threshold =2300;

  14. #14
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Citation Envoyé par JPP3939 Voir le message
    Okay j'ai trouvé le problème! le threshold était trop faible



    Oui c'est pour cela que je vous avais fait imprimer la valeur lue
    Dans la copie d'écran que vous avez postée on voit que vous êtes en dessous de 1000 quand il n'y a pas d'appui et au dessus de 2000 quand il y en a un

  15. #15
    Futur Membre du Club
    Femme Profil pro
    sans emploi
    Inscrit en
    Décembre 2021
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2021
    Messages : 18
    Points : 6
    Points
    6
    Par défaut
    Oui maintenant je comprends mieux J'ai réussi à le faire fonctionner avec plusieurs leds c'est top ! Sinon vous savez comment on nomme le fait que la led s'allume avant qu'on touche complètement le capteur ? Bonne fin de week-end !

  16. #16
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    bravo !

    bonne soirée

  17. #17
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 317
    Points : 4 124
    Points
    4 124
    Par défaut Honteux et fier
    Bonsoir Jay,

    Je ne crois pas que nous serons d'accord mais cela ne doit pas empêcher de présenter nos arguments .

    Citation Envoyé par Jay M Voir le message
    HIGH et LOW sont des #define pour des valeurs (1 et 0) donc par défaut en C++ ce sont des int. Ils sont donc typés...
    Si j'écris : byte a = 1; le compilateur ne passera pas par la case "1 est un entier" avant de se raviser à l'optimisation. Or écrire byte a = HIGH; sera traduit avant compilation en byte a = 1; (même si le préprocesseur est maintenant souvent intégré au compilateur son travail reste en amont). En fait les alias prennent le type nécessaire s'il peut être déduit du contexte par le compilateur (par exemple au travers des déclarations des types des arguments d'une fonction). Trois lignes plus loin, il peut apparaître sous un autre type.
    C'est en cela qu'il n'est pas typé car ce n'est pas une variable mais une chaine de caractères (au sens où le code source est une chaîne de caractères) qui sera remplacée par une autre (ici "0" ou "1").

    Faire de HIGH et LOW une énumération de type enum Status_t{LOW, HIGH}, pourquoi pas si le gain n'est pas seulement de bloquer certaines compilations.

    Je pense que la différence d'approche est le degré d'abstraction recherché. Pour ma part, sur des microcontrôleurs je ne suis pas favorable à des abstractions élevées car elles tendent à augmenter la charge sur des machines limitées en ressources (string me paraît un bon exemple). Par ailleurs, il me semble que quelqu'un qui commence en pensant aux états binaires pourra plus facilement s'abstraire des facilités Arduino pour, par exemple, piloter directement des registres du microcontrôleur.

    En résumé, je ne fais pas des bonds en voyant le code d'affectation conditionnelle mais je garde mes mauvaises habitudes .

    Salut
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  18. #18
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    Salut

    En fait je crois qu'on est d'accord sur le fond:

    Comme l'avait dit Donald Knuth (en reprenant Tony Hoare) "Premature Optimization Is the Root of All Evil" (même s'il ne faut pas non plus faire n'importe quoi sous prétexte que l'on optimisera plus tard).

    Bien sûr lorsqu'on développe pour micro-contrôleur souvent il faut faire attention à la mémoire et au temps d'exécution. Si l'écriture "correcte" n'était pas assez rapide ou trop gourmande en mémoire parce que l'optimiseur n'a pas "vu" comment faire, alors bien sûr on peut prendre des optimisations quand on sait ce que l'on fait. Mais dans ce cas avant de dépendre d'effets de bords sur HIGH et LOW, je pense que j'enlèverai l'appel à digitalWrite() pour utiliser directement les PORTS...

    En pratique on est d'accord sur le fait que votre approche fonctionne aujourd'hui et sans doute encore pour longtemps vu les dépendances et l'historique qui entraineraient des conséquences sur de nombreux codes si cela venait à être modifié.

    Là où on n'est peut-être pas d'accord c'est plus conceptuel et un respect des bonnes pratiques: Comme le C++ est beaucoup plus typé que le langage C (et que ce typage fort est de plus en plus imposé par les compilateurs), essayer de respecter la cohérence des types en C++ est pour moi important pour éviter des soucis dans le futur et former "les apprentis développeurs" aux bonnes pratiques. Par exemple utiliser des effets de bords (la dépendance à des valeurs non documentées si ce n'est en regardant dans le code) n'est pas considéré comme une bonne pratique. C'est pour cela qu'ici je ne le recommanderai pas votre raccourci dans un code qui a vocation d'exemple pour un débutant.


    ----------------------------------------

    Sinon long débat sur votre point

    Si j'écris : byte a = 1; le compilateur ne passera pas par la case "1 est un entier" avant de se raviser à l'optimisation.
    Je pense qu'on est d'accord mais ça dépend de ce que vous entendez par là.

    Si vous voulez dire qu'il ne génère pas le code tout de suite avec un entier puis ensuite génère encore plus de code pour transformer les 2 ou 4 octets en 1 seul octets et espérer que l'optimiseur ensuite fasse le ménage, on est d'accord.

    Schématiquement le compilateur (le parser) va d'abord évaluer l'expression et bâtir un arbre de représentation. l'opération est '=' avec 2 feuilles à gauche et à droite.
    Le compilateur évalue d'abord la feuille de droite. il n'y a pas d'opération à droite et voit une rvalue (techniquement une constante littérale de type entier), donc pour le moment il la conserve comme rvalue typée. Ensuite il regarde à gauche et comme c'est une affectation attend une lvalue (un endroit en mémoire), ici c'est simple, on a une variable donc directement la lvalue.

    Cet arbre n'est pas OK tel quel puisque le type sous jacent de la rvalue n'est pas identique à celui de la lvalue. Le compilateur déclenche donc ses règles de conversion implicites. La règle dit que le programme ne peut compiler que s'il existe une séquence de conversion implicite non ambiguë du premier type vers le second type. Ici le compilateur applique la règle dite de "Lvalue to rvalue conversion" et commence par regarder la règle de "Numeric promotions". Mais ici comme le type à droite est "plus petit" que le type à gauche, il appliquera la règle de "Numeric conversions" qui peut conduire à de la perte d'information et modification de la valeur. Le compilateur - au vu des types - détecte que la règle applicable est la suivante:
    If the destination type is unsigned, the resulting value is the smallest unsigned value equal to the source value modulo 2n where n is the number of bits used to represent the destination type.
    Comme on a une rvalue de type littéral sur 2 octets, le compilateur sait prendre tout seul l'octet de poids faible (il connait directement la valeur) et génère le code d'affectation à la mémoire associée à la lvalue a dont il connait aussi l'adresse. Si ce n'était pas un littéral mais une autre variable, il aurait aussi su aller chercher uniquement l'octet correspondant au poids faible donc sans appliquer de masque non plus. Si c'était un calcul, il aurait une représentation dans un ou plusieurs registres du résultat du calcul et saurait quel est l'octet là encore qui représente le poids faible et donc n'affecterait que celui là.

    Quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    digitalWrite(ledPin, touchVal > threshold);
    ce sont d'autres règles qui s'appliquent:

    le compilateur doit évaluer les paramètres à mettre sur la pile pour appeler la fonction.
    il voit `touchVal > threshold` et donc c'est une opération transitoire de type rvalue (pas de mémoire associée). L'arbre correspond à un opérateur '>' et deux lvalue. le type du résultat, porté par le noeud du graphe lié au >, est une rvalue de type booléen.

    le compilateur sait qu'il doit générer un test et disposera dans un registre transitoire du booléen vrai ou faux.

    Il voit ensuite que cette rvalue doit être affectée sur la pile à une lvalue de type uint8_t. Il n'y a pas égalité de type donc il doit faire appel aux "Implicit conversions" et ce coup ci la règle qui s'applique n'est plus une transformation numérique mais une règle d'abord spécifique aux booléens qui dit
    the type bool can be converted to int with the value false becoming ​0​ and true becoming 1
    donc il sait obtenir un type entier (une rvalue de type littéral) et ensuite il sait transformer (par la même règle que la règle précédente) cet entier sur plusieurs octets en un seul octet en prenant l'octet de poids faible.

    C'est ce qu'il fait et vous avez donc 0 ou 1 sur la pile, sous forme d'un seul octet et votre code fonctionne parce que "par chance" HIGH c'est 1 et LOW c'est 0.

    dans ma version plus compliquée des choses avec l'opérateur ternaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    touchPin > threshold ? HIGH : LOW
    l'arbre d'évaluation est plus compliqué: il a comme racine l'opérateur ternaire et attend à gauche un booléen et à droite deux expressions.

    Je vous passe le cheminement des conversions et règles appliquées par le compilateur, elles sont identiques à celles que l'on a vu plus haut, mais comme les expressions que l'on retourne suivant le booléen sont aussi des constantes littérales, là c'est l'optimiseur qui va faire son travail et identifier que le résultat est équivalent à celui de la promotion du booléen. L'optimiseur va aussi aller plus loin et in-liner la fonction digitalWrite() sans doute plutôt que de faire un appel d'ailleurs

    bref - si vous avez la variable (lvalue) b de type booléen en mémoire à l'adresse 0x100 et que vous faites ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    digitalWrite(13, b ? HIGH : LOW);
    , l'assembleur généré pour le second paramètre sera simplement similaire à un c'est à dire que l'on va chercher un octet en mémoire qui est simplement l'octet reprenant b. c'est ce registre qui sera ensuite utilisé

    Même coût informatiquement parlant, mais une version est plus "maintenable" et lisible que l'autre à mon avis et donc devrait avoir la préférence du développeur.

  19. #19
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 317
    Points : 4 124
    Points
    4 124
    Par défaut That's all folks !
    Bonjour,

    Nous sortons un peu du sujet initial aussi je m'arrêterai là.

    Que le compilateur fasse sa cuisine n'a pas tellement d'importance. Deux compilateurs différents respectant la même version du langage à traiter auront des résultats identiques (pour peu qu'ils soient de même qualité). Ceci indépendamment d'une représentation interne différente (par exemple avec des entiers internes sous 64 bits ou 32 bits). Je peux écrire un compilateur dans n'importe quel langage pour n'importe quelle cible. Son propre code n'est pas assujetti au langage cible tant qu'il fournit ce qu'on attend de lui (il y a des outils de développement de compilateurs ou translateurs qui peuvent générer du java ou du c indifféremment). Ainsi en est-il du typage interne.

    Ceci étant, je respecte le code proposé et l'attachement à la forme.

    Salut.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  20. #20
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 685
    Points : 5 328
    Points
    5 328
    Par défaut
    oui on s'éloigne

    je respecte le code proposé et l'attachement à la forme
    C'était ce que je voulais dire
    si on veut ne pas dépendre de constantes "non documentées", c'est mieux

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/05/2020, 19h47
  2. Simuler appui touche clavier sur GPIO
    Par molochlebanni dans le forum Raspberry Pi
    Réponses: 4
    Dernier message: 27/06/2018, 15h32
  3. [VB6] Touche impr écran
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 12/11/2002, 08h38
  4. Cherche Nom des touches du clavier
    Par juan64 dans le forum C++Builder
    Réponses: 8
    Dernier message: 23/07/2002, 20h11
  5. Shortcut avec plusieurs touches
    Par scorpiwolf dans le forum C++Builder
    Réponses: 4
    Dernier message: 06/07/2002, 16h57

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