Partage
  • Partager sur Facebook
  • Partager sur Twitter

Création d'une bibliothèque input->output

22 janvier 2019 à 10:17:43

Bonjour,

Ayant découvert Arduino depuis quelques mois, je m’essaie progressivement aux différents composants dispo.

J’en suis au stade de l’infra rouge avec la télécommande fourni dans mon kit de démarrage.

Sur ce point aucune question particulière (pour l’instant) mais cela m’a donné une idée pour me faciliter la vie : Je souhaiterai créer une bibliothèque qui convertisse le code Hexa envoyé par la télécommande en une chaine de caractère.

Ainsi au lieu de gérer les Case par des codes Hexa, je piloterai directement par « Key1 »,  « Key2 » …..

Voilà pour l’objectif mais je n’en suis pas encore là.

Je viens de comprendre le principe des bibliothèques et la logique des fichiers .h et .cpp

Les exemples trouvés sur le net comme blink ou morse fonctionnent et je les ai même trituré un peu avec succès.

Je m’attaque maintenant à l’envoie d’une donnée (input) vers une library pour avoir en retour une donnée de sortie (output).

Je voudrais commencer par du simple : par exemple envoyer « 1 » et récupérer« a »ou envoyer un nombre pour récupérer son double.

Je voulais m’appuyer sur des libraries existantes.

J’ai donc trouvé la bibliothèque AudioFrequencyMeter (pour quelqu’un qui voulait faire simple me direz vous …)

Et en particulier cette partie du code :

.h

float getFrequency(void);

.cpp

float AudioFrequencyMeter::getFrequency()

{

float frequency = -1;

if (checkMaxAmp > amplitudeThreshold) {

frequency = (float)(sampleRate / period);

if ((frequency < minFrequency) || (frequency > maxFrequency)) {

frequency = -1;

}

}

return frequency;

}

Programme :

#include <AudioFrequencyMeter.h>

AudioFrequencyMeter meter;

void setup() {

// put your setup code here, to run once:

Serial.begin(115200);

Serial.println("started");

meter.setBandwidth(70.00, 1500);// Ignore frequency out of this range

meter.begin(A0, 45000);// Intialize A0 at sample rate of 45kHz

}

void loop() {

// put your main code here, to run repeatedly:

float frequency = meter.getFrequency();

if (frequency > 0)

{

Serial.print(frequency);

Serial.println(" Hz");

}

}

Problème : j’ai bien une donnée de sortie dans cette exemple mais pas de donnée d’entré.

J’ai donc essayé de modifier les programmes en gardant la même base mais, forcément si c’était aussi simple….

Voici où j’en suis :

.h

#ifndef DonneesExt_h

#define DonneesExt_h

#include "Arduino.h"

class DonneesExt

{

public:

int output(void int input);

private:

};

#endif

.cpp

#include "Arduino.h"

#include "DonneesExt.h"

int DonneesExt::output(int input)

{

int resultat;

resultat = (2 * input);

return resultat;

}

Programme :

#include <DonneesExt.h>

DonneesExt data;

int donnee;

void setup()

{

Serial.begin(9600);

}

void loop()

{

donnee = 4;

int resultat=data.output(donnee);

Serial.println(donnee);

Serial.println(resultat);

delay(1000);

}

J’obtiens à la compilation « erreur de compilation Arduino…. »

Pouvez-vous svp m’aider, me conseiller … ?

Est-ce que ma logique pour gérer l’input et l’output est bonne ?

Existe-t-il des bibliothèques gérant des données d’entrée et de sortie sur lesquelles je pourrain m’appuyer ? Je pensais à la library « math » mais je ne l’ai pas trouvé

Enfin, question subsidiaire, existe-t-il une méthode simple pour ouvrir les fichiers .h et .cpp dans l’IDE arduino pour les modifier. Pour ma part, j’en suis à les ouvrir dans le Notepad et faire un copier/coller ce qui est très fastidieux

Merci pour votre aide


PS: Désolé je n'ai pas réussi à mettre de quotes pour les parties programme :honte: 

  • Partager sur Facebook
  • Partager sur Twitter
22 janvier 2019 à 12:19:09

Reprenons les différents poins un par un.

***

Mettre des chaines de caractères sur tes touches n'est pas une bonne idée.

En effet, un microcontrôleur travaille beaucoup plus rapidement sur des nombres que sur des chaines de caractères, surtout si elles sont longue.

Si tu veux un code plus parlant, je te conseille d'utiliser les #define.

Exemple :

#define KEY_VOLUME_PLUS 0x34
#define KEY_VOLUME_MOINS 0x35

void loop() {

    key = IR.read();

    if ( key == KEY_VOLUME_PLUS ) {
        ...
    }

}

Grace à ces #define, tu peux utiliser KEY_VOLUME_PLUS dans le if de ton code, ce qui est plus parlant que de mettre un 0x34 qui ne veut rien dire.

Et coté Arduino, cela revient au même car le compilateur va automatiquement remplacer KEY_VOLUME_PLUS par 0x34 lors de la compilation, ce qui permet au microcontrôleur de travailler avec des nombres.

***

Pour ta lib input/ouput, l'erreur vient de cette ligne : int output(void int input);

Le mot clef void signifie "aucun paramètre" ou "aucun retour".

Donc c'est un peu contradictoire de mettre void et int en même temps.

Il te faudrait plutôt ce code là : int output(int input);

Pour faire plus générique, on a toujours : TypeRetour NomFonction( TypeArgument NomArgument, [...] );

Prenons l'exemple d'une fonction multiplication, celle-ci prend en paramètre 2 entiers (A et B) et renvoie un autre entier qui correspond au résultat.

Ce qui donne alors :

// Dans le .h :

int multiplier( int nbA, int nbB );


// Dans le .cpp :

int multiplier( int nbA, int nbB ) {
    int resultat = nbA * nbB;
    return resultat;
}


// Dans le code principal :

void loop() {

    int test = multiplier(4, 54);
    Serial.println(test);

}

***

Pour l'édition du code, en ce qui me concerne, je me sert exclusivement de Notepadd++ (qui apporte de la couleur).

Pour cela, il faut aller dans "Fichier / Préférence" puis cocher la case "Utiliser un éditeur externe".

Cela force Arduino à recharger les fichiers avant chaque compilation.

Ainsi, il te suffit simplement de sauvegarder tes fichiers (CTRL+S) avant de compiler (pas besoin de copier/coller).


  • Partager sur Facebook
  • Partager sur Twitter
22 janvier 2019 à 12:31:53

Merci pour cette réponse rapide.

Si le passage en chaine de caractère est une mauvaise idée je vais peut être abandonné mais pour ma culture et le défis je vais persévérer sur les Libraries.

Pour la partie input/output, tu me présentes cela comme un fonction.

La bibliothèque fonctionnerai exactement comme une fonction ?

Avec l'appel dans la partie .h et la fonction dans le .cpp ?

C'est aussi simple que ça  ! Mais c'est génial :)

Je teste ça ce soir

Merci aussi pour le "Utiliser un éditeur externe".

  • Partager sur Facebook
  • Partager sur Twitter
22 janvier 2019 à 17:34:07

Libre à toi de mettre ce que tu veux dans ta bibliothèque ;)

Si tu as envie de faire une bibliothèque qui contient uniquement des fonctions, c'est possible.

Mais en ce qui concerne Arduino, il est vrai que l'on voit beaucoup de fonction encapsulé dans des classes.

Cela permet d'avoir des fonctions avec le même nom sur différents objets.

Par exemple, grâce à des classes, on peut avoir une fonction println pour le Serial (pour afficher des données dans la console) et on pourrait aussi avoir une autre fonction println pour une classe Printer (pour afficher des données sur une imprimante).

Si tu n'as pas d'objet à créer (pour une classe utilitaire par exemple), tu peux utiliser des fonctions static.

Exemple:

// Dans le .h :

class Tools {

public:
    static int multiplier( int nbA, int nbB );

};
 
 
// Dans le .cpp :
 
int Tools::multiplier( int nbA, int nbB ) {
    int resultat = nbA * nbB;
    return resultat;
}
 
 
// Dans le code principal :
 
void loop() {
 
    int test = Tools::multiplier(4, 54);
    Serial.println(test);
 
}

Sans le static, il faudrait créer un objet et cela donnerait :

// Dans le .h :

class Tools {

public:
    int multiplier( int nbA, int nbB );

};
 
 
// Dans le .cpp :
 
int Tools::multiplier( int nbA, int nbB ) {
    int resultat = nbA * nbB;
    return resultat;
}
 
 
// Dans le code principal :

Tools objTools;

void loop() {
 
    int test = objTools.multiplier(4, 54);
    Serial.println(test);
 
}



  • Partager sur Facebook
  • Partager sur Twitter
23 janvier 2019 à 11:15:37

Merci beaucoup Lorrio.

Ca marche nickel.

Et Notepad++ est déjà adopté

Une autre petite question: quels sont les avantages et inconvénients d'une fonction static et d'une classe l'un par rapport à l'autre ?

  • Partager sur Facebook
  • Partager sur Twitter
23 janvier 2019 à 13:44:42

Une classe permet d'englober des attributs (variables) qui pourront être utilisée par la suite aux travers des objets créé.

Tandis qu'une fonction n'a pas accès aux attributs mais seulement aux paramètres.

Un petit exemple pour comprendre :

// Dans la lib :

class PinOut {

public:
    PinOut(int pin) { _pin = pin; }

public:
    write(int val) { digitalWrite(_pin, val); }

private:
    int _pin;

};

// Dans le code :

PinOut led(13);

void loop() {
    led.write(HIGH);
    delay(1000);
    led.write(LOW);
    delay(1000);
}

Grâce à l'attribut _pin, l'objet de cette classe PinOut peut retenir le numéro de la pin à affecter pour le write.

Tandis que si l'on utilise du static, on n'a pas accès aux attributs donc il faudrait mettre ce numéro comme argument à chaque appel.

// Dans la lib :

class PinOut {

public:
    PinOut() { }

public:
    write(int pin, int val) { digitalWrite(pin, val); }

};

// Dans le code :

void loop() {
    PinOut::write(13, HIGH);
    delay(1000);
    PinOut::write(13, LOW);
    delay(1000);
}

Mais Google sera te donner beaucoup plus d'avantages que moi ;)

Pour cela, il te suffit de chercher "avantages de la programmation orientée objet".

-
Edité par lorrio 23 janvier 2019 à 13:45:36

  • Partager sur Facebook
  • Partager sur Twitter