[Résolu] Librairie maison

Super analyse Barbu!

Je regarde ce que tu as fait, et je vais voir pour KB_NOKEY, car je suis sous l'IDE22 (pas le courage de me mettre encore à la 1.0... Mais je pense que ça passera. (il va falloir que je mette en majuscule tous mes define (y'en a plein d'autres que j'ai pas mis pour ne pas alourdir mon post)? ou c'est juste une spécificité du 1.0? j'aime pas trop les majuscules en prog, je trouve que ça surcharge un peu trop...

A tout'!

C'est pas obligatoire, c'est un standard.

Il existe de nombreux standards de règle de codages.
Les règles de codages servent à ce que l'on identifie au 1er coup d'oeil les éléments. Suivants les règles on va pouvoir distinguer par exemple les variables globales des variables locales et des paramètres de fonctions. Distinguer les noms de types des noms de variables ou de fonctions, ...
Il en existe des tas différentes.

Mais il y au moins une règle sur laquelle tout le monde s'accorde de le début : les constantes en #define sont en MAJUSCULES.

Suivre une règle de codage, c'est un bon principe. Ca donne de la rigueur à ton code et ca aide à la relecture et à la maintenance ultérieure.
C'est comme l'indentation.
Le compilateur il s'en contrefiche de l'indentation.
Mais si tu indentes correctement ton code, tu sauras mieux le relire et le maintenir
Idem avec les règles de codages.

Et quand tu partages ton code soit pour l'offrir à la communauté soit pour poser une question sur le forum, c'est comme un post : si c'est mal écrit, cela ne donne pas envie de le lire et d'y répondre.

Yep!

Super fort Barbudor :wink:

Il faudrait aussi rappeler les règles pour les #includes.

Les guillements pour les libs crées dans le répertoire courant.
Les crochets pour les libs standards.

@+

Zoroastre.

Salut à vous deux.

Il faut que je vous avoue que j'ai fait l'impasse complète en prog à l'école (quel con... mais ça ne m'a pas empêché d'avoir mon BTS électro haut la main, car à l'époque en 95, la micro n'était pas trop importante). Je suis donc totalement autodidacte en prog. Je pensais que le C++ était juste du C avec quelque fonctionnalités en plus plus (la notion de x++, ++x par exemple), et que les deux pouvaient marcher ensemble...

De plus, selon les langages, l'un est sensible à la casse, pas l'autre, etc etc... et pour ce qui est des règles de de codage, je me contente juste de conserver des espacement de début de ligne dans les blocs pour retrouver facilement la fin du bloc, et j'ai tendance à nommer mes variables comme en basic (je crois) : "nom_de_la_variable" et non "nomDeLaVariable" comme il faudrait (je trouve la première forme plus lisible, c'est du perso)...

Pour revenir à ma lib maison, j'intègre les modifs et je teste ce matin même! Je suis sous IDE 0022, rappelons-le...

Merci encore à vous deux!

cinci

PS / EDIT :

In file included from C:\Program Files\arduino-0022\hardware\arduino\cores\arduino/WProgram.h:6,
from C:\Program Files\arduino-0022\libraries\MEGA_LCD_KB_debug/MEGA_LCD_KB_debug.h:8,
from C:\Program Files\arduino-0022\libraries\MEGA_LCD_KB_debug\MEGA_LCD_KB_debug.c:26:
c:/program files/arduino-0022/hardware/tools/avr/lib/gcc/../../avr/include/math.h:439: error: expected identifier or '(' before 'double'
c:/program files/arduino-0022/hardware/tools/avr/lib/gcc/../../avr/include/math.h:439: error: expected ')' before '>=' token

j'ai mis tout le bloc ci-dessous du .c en commentaire, et ça a compilé.

#include "Arduino.h"

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "wiring.h"
#endif

et ça marche. Bon, faudrait un tuto un peu plus clair que ce qu'on trouve avec la lib Morse sur la façon de passer d'un prog à une lib, car j'aime pas trop ne pas comprendre ce que je fais, comme dans le cas présent. S'il le faut, je passerai au 1.0...

Super_Cinci:
Je pensais que le C++ était juste du C avec quelque fonctionnalités en plus plus (la notion de x++, ++x par exemple), et que les deux pouvaient marcher ensemble...

Oui et non.
Le C++ fait beaucoup plus que d'ajouter 2..3 fonctionnalités. En tout pas cas celles que tu cite : ++x et x++ existent depuis le début en C.
Mais la surcharge de fonctions que j'ai expliqué est un ajout qui impose un traitement différent sur les noms de fonctions.
Cela n'empêche pas de mélanger les 2, ils restent totalement compatible et la plupart du temps c'est transparent.
En dehors de la programmation objet, des templates etc ... le C++ ajoute au C :

  • la surcharge des fonctions et des opérateurs
  • la possibilité de déclarer des variables locales n'importe où et pas seulement en début de block.

La plupart du temps, je code dans un fichier CPP pour bénéficier sans m'en rendre compte des ajouts du C++ même si je ne fais pas de classes ou autre fonctionnalités purement C++.

De plus, selon les langages, l'un est sensible à la casse, pas l'autre, etc etc...

Tat le C que le C++ sont sensibles à la casse.

j'ai tendance à nommer mes variables comme en basic (je crois) : "nom_de_la_variable" et non "nomDeLaVariable" comme il faudrait

Il n'y a pas de "comme il faudrait". Ta règle est tout a fait valable que ce soit en C ou en Basic de même que l'inverse.
A part les define en majuscules qui est une règle de fait, toutes les règles sont possibles. En avoir une c'est mieux que ne pas en avoir.

j'ai mis tout le bloc ci-dessous du .c en commentaire, et ça a compilé.

#include "Arduino.h"

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "wiring.h"
#endif

Arduino.h ne devrait être présent qu'une fois? j'ai merdé.
Essaye en enlevant juste le 1er #include Arduino.h et en gardant ce qui est entre #if ... #endif

Ce n'est pas temps le problème de passer d'un programme à une lib (les Lib Arduino n'étant pas de vrai lib) que le problème de tous les changements entre la version 022 et la version 1.0.
Perso je ne vois aucune raison de rester dans une vielle version alors que plusieurs problèmes ont été corrigés dans la lib core Arduino dans la v1.0.
Il vaut mieux avoir la 1.0(.1) et apprendre à migrer les exemples vers cette version plutôt que garder une version obsolète.

Bonjour,
J'ai tapé les éléments et les ai placés comme me l'a conseillé barbudor (merci).
J'ai étudié la biblio. LiquidCristal pour attribuer les broches mais comme ça ne compilait pas,
j'ai remplacé les "unit8_t" par "int" mais ça fait juste disparaître les "unit8_t was not declared in this scope".
Il ne colorie pas les appellations de "keywords.txt".
Il me dit que HIGH, LOW et mes constantes ne sont pas définies.
Est-ce qu'il faut mettre les fichiers dans la position classique pour que ça compile ?
J'ai mis le contenu de mon dossier. Je sais que pour l'exemple il porte mal son nom mais j'ai changé d'idée en cours de route.

Merci de votre aide !

keywords.txt (479 Bytes)

numLED.cpp (3.44 KB)

numLED.h (310 Bytes)

numLEDserial.ino (122 Bytes)

Pour la coloration syntaxique, cela est normal, cela est du a l'extension txt.

Pour ce qui est de ta librairie "Numled", je pense qu'elle ne devrai pas être dans ton dossier mais dans le dossier ou sont toutes tes librairies. N'oublie pas de nommer correctement ton dossier ou tu mets tes deux fichiers cpp et h.

Ensuite plusieurs remarques :

  • Dans ton fichier INO tu n'inclus pas ta librarie numLED
  • Dans ton INO tu écris : numLED.begin(9,2,3,4,5,6,7);
    Cela suppose que tu utilise un objet numLED mais il n'est pas déclaré !!

Ensuite suggestion dans ton switch case de la fonction write tu écris :

 case 0:
      digitalWrite(h, HIGH);
      digitalWrite(hg, HIGH);
      digitalWrite(hd, HIGH);
      digitalWrite(m, LOW);
      digitalWrite(bg, HIGH);
      digitalWrite(bd, HIGH);
      digitalWrite(b, HIGH);
    case 1:
      digitalWrite(h, LOW);
      digitalWrite(hg, LOW);
      digitalWrite(hd, HIGH);
      digitalWrite(m, LOW);
      digitalWrite(bg, LOW);
      digitalWrite(bd, HIGH);
      digitalWrite(b, LOW);

vu le nombre de LOW par rapport au HIGH je mettrais tout a HIGH et dans les CASE je mettrais la valeur nécéssaire a LOW tu diviseras la taille de ton SWITCH par trois.

Ensuite tu écris :

void numLED::draw(int eh, int ehg, int egd, int em, int ebg, int ebd, int eb) {
  if((eh) == 1) {
    digitalWrite(h, HIGH);
  }
  if((eh) == 0) {
    digitalWrite(h, LOW);
  }
  if((ehg) == 1) {
    digitalWrite(hg, HIGH);
  }
  if((ehg) == 0) {
    digitalWrite(hg, LOW);
  }
  if((ehd) == 1) {
    digitalWrite(hd, HIGH);
  }
  if((ehd) == 0) {
    digitalWrite(hd, LOW);
  }
  if((em) == 1) {
    digitalWrite(m, HIGH);
  }
  if((em) == 0) {
    digitalWrite(m, LOW);
  }
  if((ebg) == 1) {
    digitalWrite(bg, HIGH);
  }
  if((ebg) == 0) {
    digitalWrite(bg, LOW);
  }
  if((ebd) == 1) {
    digitalWrite(bd, HIGH);
  }
  if((ebd) == 0) {
    digitalWrite(bd, LOW);
  }
  if((eb) == 1) {
    digitalWrite(b, HIGH);
  }
  if((eb) == 0) {
    digitalWrite(b, LOW);
  }
}

tu pourrais le remplacer par :

void numLED::draw(int eh, int ehg, int egd, int em, int ebg, int ebd, int eb) {
    digitalWrite( h  , eh  );
    digitalWrite( hg, ehg );
    digitalWrite( hd, ehd );
    digitalWrite( m, em  );
    digitalWrite( bg, ebg );
    digitalWrite( bd, ebd );
    digitalWrite( b  , eb  );
}

En effet LOW=0 et HIGH=1

Privilégie :

 if( eb == 1)  digitalWrite( b, HIGH );
 else             digitalWrite( b, LOW );

à

 if((eb) == 1) {
    digitalWrite(b, HIGH);
  }
  if((eb) == 0) {
    digitalWrite(b, LOW);
  }

Sa évite de faire le test deux fois.

Comme il t'a été dit précédemment fais déjà un code qui marche sans faire de librairie optimise le, et personnellement quand je vois le contenu de ta librairie, je ne la trouve vraiment pas nécessaire.

Bonjour,

numero_744:
j'ai remplacé les "unit8_t" par "int" mais ça fait fuste disparaître les "unit8_t was not declared in this scope".

Il faut inclure <stdint.h> pour avoir ces types "dure" :wink:
Remplacer un uint8_t (8 bits non signé) par un int (16 bits signé) quand ce n'est pas nécéssaire est un non-sens car cela ralenti ton programme pour rien et le rend consommateur de ram inutilement :wink:

numero_744:
Il ne colorie pas les appellations de "keywords.txt".

Il faut que le fichier keywords.txt comporte des fins de lignes UNIX (soit \n) et non "windows" (soit \r\n).
Avec notepad++ il suffit de faire édition -> convertir les fin de lignes -> format UNIX.

numero_744:
Il me dit que HIGH, LOW et mes constantes ne sont pas définies.

Essaye :

#include "Arduino.h"

->

#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

--

Au sujet de ton code :

  1. Tes fonctions write(), clear(), draw() ne peuvent pas compiler, elle ont besoin de variables qui n'existe pas dans leur contexte.
    Tu doit mettre les variables hg, hd, m, ... en tant que membre de ta classe et les initialiser dans le constructeur.

  2. Les int -> uint8_t + #include <stdint.h>

  3. Dans la fonction draw() :

if((eh) == 1) {
    digitalWrite(h, HIGH);
  }
  if((eh) == 0) {
    digitalWrite(h, LOW);
  }

Par définition : HIGH = 1, LOW = 0, donc il suffit d'écrire :

digitalWrite(h, eh);
  1. Dans clear() et write(), pourquoi réinventer la roue, ta fonction draw() existe il suffit de l'appeler :wink:
void numLED::clear() {
  draw(LOW, LOW, LOW, LOW, LOW, LOW, LOW);
}
  1. Dans write() :
    Il manque les break; à la fin de chaque case !

-> J'ai fait un zip avec toute les modif :wink:

numLED.zip (1.06 KB)

Bonjour et merci, Blizzard27 et skywood.
Une question chacun :

  • Blizzard27 :
    Qu'est-ce que déclarer ?

Blizzard27:
Cela suppose que tu utilise un objet numLED mais il n'est pas déclaré !!

int ... = ...; ?

  • skywood :
    Cela ne compile pas mais dois-je changer
class numLED : public Pruint8_t {

en

class numLED : public Print8_t {

?
(As-tu compilé avec un exemple comme :

void setup() {
  numLED.begin(8,2,3,4,5,6,7);
}

void loop() {
  for(int a = 0; a <= 9; a++) {
    numLED.write();
  }
}

Merci encore !!!

Qu'est-ce que déclarer ?

Tout comme une variable, il faut déclarer un objet. Un objet va disposer des différentes variables et fonctions de ta classe. Ta classe s’appelle "numLED".
Il faut donc que tu écrives dans ton fichier principale quelque chose dans ce genre:

//Déclaration de l'objet
numLED monobjet;

void setup() {
  monobjet.begin(8,2,3,4,5,6,7);
}

void loop() {
  for(int a = 0; a <= 9; a++) {
    monobjet.write();
  }
}

J'ai fais quelques modif et chez moi cela compile :

Programme principal :

#include <numLED.h>
//Déclaration de l'objet
numLED monobjet;

void setup() {
  monobjet.begin(8,2,3,4,5,6,7);
}

void loop() {
  for(int a = 0; a <= 9; a++) {
    monobjet.write(a);
  }
}

numLED.h

//numLED.h

#ifndef numLED_h
#define numLED_h

class numLED 
{   
    public:
        void begin(int h, int hg, int hd, int m, int bg, int bd, int b);
        void write(int chiffre);
        void clear();
        void draw(int eh, int ehg, int egd, int em, int ebg, int ebd, int eb);
        int h; 
        int hg; 
        int hd; 
        int m;
        int bg; 
        int bd; 
        int b;

};
#endif

numLED.cpp

//numLED.cpp
#include <stdint.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include "numLED.h"
               
void numLED::begin(int h, int hg, int hd, int m, int bg, int bd, int b){
  pinMode(h, OUTPUT);
  pinMode(hg, OUTPUT);
  pinMode(hd, OUTPUT);
  pinMode(m, OUTPUT);
  pinMode(bg, OUTPUT);
  pinMode(bd, OUTPUT);
  pinMode(b, OUTPUT);
}

void numLED::write(int chiffre) {
  switch (chiffre) {
    case 0: draw(HIGH, HIGH, HIGH, LOW , HIGH, HIGH, HIGH); break;	  
    case 1: draw(LOW , LOW , HIGH, LOW , LOW , HIGH, LOW ); break; 
    case 2: draw(HIGH, LOW , HIGH, HIGH, HIGH, LOW , HIGH); break;
    case 3: draw(HIGH, LOW , HIGH, HIGH, LOW , HIGH, HIGH); break;
    case 4: draw(LOW , HIGH, HIGH, HIGH, LOW , HIGH, LOW ); break;	  
    case 5: draw(HIGH, HIGH, LOW , HIGH, LOW , HIGH, HIGH); break;
    case 6: draw(HIGH, HIGH, LOW , HIGH, HIGH, HIGH, HIGH); break;
    case 7: draw(HIGH, LOW , HIGH, LOW , LOW , HIGH, LOW ); break;
    case 8: draw(HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH); break;  
    case 9: draw(HIGH, HIGH, HIGH, HIGH, LOW , HIGH, HIGH); break;
  }
}

void numLED::clear(void) {
  draw(LOW, LOW, LOW, LOW, LOW, LOW, LOW);
}

void numLED::draw(int eh, int ehg, int egd, int em, int ebg, int ebd, int eb) {
  digitalWrite(h  , eh );
  digitalWrite(hg , ehg);
  digitalWrite(hd , egd);
  digitalWrite(m  , em );
  digitalWrite(bg , ebg);
  digitalWrite(bd , ebd);
  digitalWrite(b  , eb );
}

Peut-on mettre la définition dans le *.h ?
Est-ce que la laisser en dehors de la bibliothèque a des avantages (comme utiliser plusieurs afficheurs) ?
Il me dit que void numLED::Write(int) est protegé.

Cela n'a pas beaucoup d'utilité, je le sais...
C'est juste un exemple simple pour apprendre.

Si tu veux utiliser plusieurs afficheurs du instancie deux objets différents par contre il faut que tu rajoute un constructeur dans ta classe qui va te permettre de paramètrer les PIN des afficheurs ensuite cela fonctionnera comme cela :

#include <numLED.h>
//Déclaration de l'objet
numLED Afficheur1(configuration);
numLED Afficheur2(configuration);

void setup() {
Afficheur1.begin(8,2,3,4,5,6,7);
Afficheur2.begin(8,2,3,4,5,6,7);
}

Mais a mon humble avis tu pars dans

void loop() {
for(int a = 0; a <= 9; a++) {
monobjet.write(a);
}
}

Mais un mon humble avis tu pars dans des notions qui ne sont que secondaires vu ton niveau en programmation, commence déjà par bien maitrisé le C j'ai envie de dire avant de rentrer dans les détails du C++ avant toutes ces subtilités que moi même je ne maîtrise pas très bien héritage, classes amies, polymorphisme, surchage de fonction, ... tu auras bien le temps de t'amuser avec cela par la suite, mais tu peu très bien coder en ignorant complètement ces notions. Certes il arrive un moment ou il faut se pencher dessus mais je ne pense pas que tu sois rendu a ce stade.

numero_744:
Cela ne compile pas mais dois-je changer

class numLED : public Pruint8_t {

en

class numLED : public Print8_t {

?

Oups ! Petite boulette dans mon CTRL+F remplacer "int" -> "uint8_t".

Le bon code est :

class numLED : public Print {

numero_744:
(As-tu compilé avec un exemple comme :
(...)

Non, habituellement je le fait, sauf cette fois ci par manque de temps.

numero_744:
Peut-on mettre la définition dans le *.h ?

Qu'entends tu par "définition" (qu'on parle bien de la même chose) ?

numero_744:
Il me dit que void numLED::Write(int) est protegé.

Si tu veut que ta classe hérite de la classe Print il faut que write soit "virtual" et respecte le prototype suivant :

virtual size_t write(uint8_t);

(En entrée un uint8_t qui est un caractére ou une valeur binaire et en sortie le nombre de caractére écrit soit 1)

Avant de partir dans des héritages de classe virtuelle tu devrais approfondir tes bases en C :wink:

Ps Blizzard27: quitte à inclure <stdint.h> autant utiliser des uint8_t et non des int.
PPs Blizzard27: par convention en C++ les membres d'une classe sont private ou protected -> principe d'encapsulation.

Merci à tous !!!
Je peux maintenant faire des bibliothèques.
J'ai gardé int car même en entrant la bonne bibliothèque ça ne compilait pas.

Voila un petit résumé de mon procédé :

créer 3 fichiers dans un dossier xExemple :

  • xExemple
  • xExemple.ino
  • xh
  • xh.ino
  • xcpp
  • xcpp.ino

modifier :

  • xExemple.ino
  • x.h
  • x.cpp

ouvrir xExemple.ino et dans l'onglet x.h entrer :

#ifndef
#define x_h

#include "Arduino.h" //Ou autre selon version
class x
{
  public :
    les fonctions
  private :
    les variables et constantes
};

#endif

puis entrer dans l'onglet x.cpp :

#include "Arduino.h"
#include "x.h"

x::x(int pin) { //cette partie se note x(int pin); dans le x.h elle sert à dire comment entrer les y.fonction(); dans le x.ino
//profitez-en pour définir les voies et les paramétrer
  _pin = pin; //définissez _pin dans private : de x.h et cette ligne sert à utiliser pin dans d'autres fonctions sous _pin
}

void x::fonction1() { //se note void fonction1(); dans x.h
  digitalWrite(_pin, HIGH); //agit sur la broche définie précédemment comme on le souhaite
  delay(1000);
  digitalWrite(_pin, LOW);
}

void x::fonction2(int etat) { //se note void fonction2(int etat); dans x.h
if(etat == 1) {
  digitalWrite(_pin, HIGH);
}
else {
  digitalWrite(_pin, LOW);
}

entrer dans l'onglet xExemple.ino :

#include "x.h"

x y(13); //Définit la broche et nomme "y" l'objet rattaché à la biblio. x (un objet peut être une ensemble de LEDs)

void setup() {
  y.fonction1(); //allume 1" la LED 13 et l'éteint
}

void loop() {
  y.fonction2(1); //allume la LED 13
  delay(3000); //pendant 3"
  y.fonction2(0); //et l'éteint
  delay(10000); //pendant 10"
}

Si ça compile, créez le dossier x dans librairies et mettez-y x.h et x.cpp
Remplacer dans x.ino #include "x.h" par #include <x.h>
Vous pouvez mettre xExemple.ino dans le un dossier "exemples" placé dans le dossier contenant x.h et x.cpp

Pour utiliser une fonction d'une bibliothèque par cette même bibliothèque :
x::fonction();

Salut !
Voici un petit cadeau : une librairie morse nommée "sMorse" avec deux exemples qui vous aideront mieux à la comprendre que je ne peux vous l'expliquer...
Il y a de 'A' à 'Z', de '0' à '9', ' ' et '.'

!!! : n'entrez qu'en majuscules avec un guillemet unique de chaque côté et un par un.

Salut au second sens !

sMorse.zip (3.39 KB)

Bonjour, je relance cette discussion car j'ai un problème :

error: void value not ignored as it ought to be

Qu'est-ce que cela signifie ?
Merci !

C'est généralement plus efficace de donner tout le contexte : copie complète de la fenêtre de compilation et eventuellement le sketch.

Mais dans ton cas je suppose que tu cherches à utiliser le retour d'une fonction void genre :

void toto()
{
}

a = toto();

Merci barbudor pour ta réponse.
C'est tout ce qu'il renvoie en précisant le lieu de l'erreur.
Je cherche bien à renvoyer une valeur :

void bibliotheque::fonction() {
  return valeur_enregistree;
}