Passage avec classe

Bonjour,

Après "le salaire de la peur", "la famille Adams", voici un nouvel épisode de "Maman j'ai rétréci le code !"... (Private joke)

Bon, plus sérieusement, je suis en train de perdre les quelques poils que j'ai sur le haut du cailloux et pourtant mon code est... VIDE ! :disappointed_relieved:

J'essaie de faire une classe, histoire de gagner en lisibilité. Plusieurs problèmes m'oblige à revenir vous voir pour éclaircir ce qui ne va pas et du coup gagner aussi en lisibilité dans mon code. Le réduire, le synthétiser et pourquoi pas l'améliorer. Donc cette série de post, dans cete section me servira à ça dans tout mon projet de télécommande. J'ai pris un peu de recul et je me dis que je ne fais pas tant de mise à jour que ça. Tout bonnement par ce que c'est un joyeux B***** sans nom de près de 800 lignes de code ! peut-être qu'en découpant en classe, ça serais moins lourd à maintenir. Faut-il encore réussir à compiler.

Je développe principalement sous 2 type de carte. Pour mon projet (tant que j'ai les mains dans le cambouis, j'utilise des arduino 2560. Sinon la fameuse Uno et peut-être un jour, au niveau de la réception une nano... A voir pour cette dernière.

J'ai donc commencer par le plus simple et aussi le plus logique. La gestion de mon afficheur LCD par liaison I2C.
Avant, j'avais des fonctions qui travaille remarquablement bien. et qui resemble à ceci:

/* FONCTION initLCD */
void initLcd() {

//Initialisation de l'écran par I2C
Wire.begin(); //Amorce la connection sur SDA et SCL
Wire.beginTransmission(adresseLcd); //Appelle l'écran LCD
Wire.write((byte)0x00); //Assigne un null
Wire.write((byte)0x0C); //Effacer l'écran
Wire.write((byte)0x13); //Allume le rétro-éclairage
Wire.write((byte)0x04); //Ne pas afficher le curseur
Wire.endTransmission(); //Ferme la connexion sur SDA et SCL
}

/* FONCTION ecrireLcd */
void ecrireLcd(String texte, int positionEcran) {

//Initialisation de l'écran par I2C
Wire.begin(); //Amorce la connection sur SDA et SCL
Wire.beginTransmission(adresseLcd); //Appelle l'écran LCD
Wire.write((byte)0x00); //Assigne un null
Wire.write((byte)0x02); //Placer le curseur
Wire.write(positionEcran); //Sur l'écran
Wire.print(texte); //Ecrire un texte
Wire.endTransmission(); //Ferme la connexion sur SDA et SCL
}

/* FONCTION ecrireLcdChar */
void ecrireLcdChar(char texte[32], int positionEcran) {

//Initialisation de l'écran par I2C
Wire.begin(); //Amorce la connection sur SDA et SCL
Wire.beginTransmission(adresseLcd); //Appelle l'écran LCD
Wire.write((byte)0x00); //Assigne un null
Wire.write((byte)0x02); //Placer le curseur
Wire.write(positionEcran); //Sur l'écran
Wire.write(texte); //Ecrire un texte
Wire.endTransmission(); //Ferme la connexion sur SDA et SCL
}

/* FONCTION clearLcd() */
void clearLcd() {

//Initialisation de l'écran par I2C
Wire.begin(); //Amorce la connection sur SDA et SCL
Wire.beginTransmission(adresseLcd); //Appelle l'écran LCD
Wire.write((byte)0x00); //Assigne un null
Wire.write((byte)0x0C); //Effacer l'écran
Wire.endTransmission(); //Ferme la connexion sur SDA et SCL
}

/* FONCTION clearCol() */
void clearCol(int col) {
//Effacer la colonne
Wire.begin(); //Amorce la connection sur SDA et SCL
Wire.beginTransmission(adresseLcd); //Appelle l'écran LCD
Wire.write((byte)0x00); //Assigne un null
Wire.write((byte)0x02); //Placer le curseur
Wire.write(col); //Sur l'écran
Wire.write((byte)0x11); //Effacer l'écran
Wire.endTransmission(); //Ferme la connexion sur SDA et SCL
}

J'aimerais bien en faire une classe. Pour ce faire, j'ai créer un répertoire dans les librairies. J'y ai collé deux fichiers, un LcdI2C.h et un LcdI2C.cpp. Mon .h ressemble à:

#ifndef LcdI2C_h
#define LcdI2C_h

#include <Arduino.h>
#include <Wire.h>

class LcdI2C {
	public:
		LcdI2C();
		
		void initLcd();
};

#endif

Et mon .cpp à:

/*

*/

#include "LcdI2C.h"

//Constructeur
LcdI2C::LcdI2C() {
	//addrComponent = adresseLCD;
}

/* initLcd */
void LcdI2C::initLcd() {
	Wire.begin();	//Start bit
	Wire.beginTransmission((byte)0x63); //Appel carte
	Wire.write((byte)0x00);	//Null
	Wire.write((byte)0x0C);	//Effacer l'écran
	Wire.write((byte)0x13);	//Allumer le rétro éclairage
	Wire.write((byte)0x04);	//Ne pas afficher le curseur
	Wire.endTransmission();	//Fin de communication I2C
}

Enfin mon programme principal (vide pour le moment) :

#include "LcdI2C.h"

void setup() {

}

void loop() {

}

Vous allez me dire que jusque là, c'est très vide et pourtant; quand je compile, j'obtiens ce message d'erreur :sweat_smile:

/home/alexandre/Install/arduino-1.0.3/libraries/LcdI2C/LcdI2C.cpp: In member function ‘void LcdI2C::initLcd()’:
/home/alexandre/Install/arduino-1.0.3/libraries/LcdI2C/LcdI2C.cpp:14: error: ‘Wire’ was not declared in this scope

Si je comprends bien, le chemin vers Wire.h n'est pas trouvé. J'ai pas vraiment trouver de solution à ce problème et pourtant, il faudra bien car sans ça impossible de mettre en classe !

Voila, je m'en remet à vos commentaire, je vais d'abord résoudre ce problème avant de continuer mon code.
Merci pour vos indications.

Tu as mal interprété l'erreur : il faut lire "dans le fichier Lcdi2C.cpp, dans la fonction initLcd(), Wire n'a pas été déclaré". Tu as simplement oublié de faire un #include <wire.h>

Non, déjà tester de rajouter #include <Wire.h> dans le .cpp.

La seule chose qui fonctionne, sans que je ne comprenne pourquoi, c'est quand j'ai #include <Wire.h> dans le .h et dans mon source. Mais rien dans le .cpp. C'est pas logique puisque on est cencé déclarer ça dans le .h. C'est d'autant plus bizarre que le source ne contient pour le moment aucune instruction de type Wire. Ce sera différent plus tard !!

Le fonctionnement de l'IDE Arduino est très spécial.

Même si tu n'utilises pas Wire.h dans ton INO, a partir du moment où tu t'en sert dans un sous fichier c/cpp séparé ou dans une lib, tu dois mettre le #include dans le INO.

Le problème est que l'IDE Arduino ne compile pas les sources là où ils sont
Il les recopie dans un repertoire temporaire pour ne pas s'emm... a gérer des chemins d'include (ce que les "vrais" IDE savent très bien faire mais pas les rigolos qui ont fait l'IDE Arduino)
Si tu n'as pas #include Wire.h dans ton INO, la Lib Wire ne vas pas être ajouté à ton projet

barbudor:
Le fonctionnement de l'IDE Arduino est très spécial.

Je confirme !

barbudor:
Le problème est que l'IDE Arduino ne compile pas les sources là où ils sont
Il les recopie dans un repertoire temporaire pour ne pas s'emm... a gérer des chemins d'include (ce que les "vrais" IDE savent très bien faire mais pas les rigolos qui ont fait l'IDE Arduino)
Si tu n'as pas #include Wire.h dans ton INO, la Lib Wire ne vas pas être ajouté à ton projet

Ah donc on à affaire à des rigolos !! Et bien... Dire que je prenais Arduino pour un truc sérieux... Je vais peut-être revenir à lâge de pierre avec des pics mais au moins ils ne sont pas rigolos eux ! A quand un vraie IDE qui sache faire ce que font les pros ? Mieux une intégration dans une ide standard capable de gérer et l'ardino et la compilation ! Bref, vaste débat !!

Je reviens à la charge. Avant de faire mes classe j'avais écrit:

#define adresseLcd 0x63

void setup() {
initLcd();
}

Je pense passé par le constructeur tel que :

#define adresseLcd 0x63

void setup() {
   Obj LCD = new Obj(adresseLcd);
      LCD.ecrire("message", 01);
}

Bon, déjà il faut que je comprenne comment faire passer mon 0x63 sans conversion. Si quelqu'un à une idée.

Geeks:
Ah donc on à affaire à des rigolos !! Et bien... Dire que je prenais Arduino pour un truc sérieux... Je vais peut-être revenir à lâge de pierre avec des pics mais au moins ils ne sont pas rigolos eux ! A quand un vraie IDE qui sache faire ce que font les pros ? Mieux une intégration dans une ide standard capable de gérer et l'ardino et la compilation ! Bref, vaste débat !!

Non on a affaire à des profs de design qui ont voulu créer un environnement simple (voire simpliste) pour permettre à des étudiants de développer simplement du code pour leurs projets artistiques numériques (si j'ai bien retenu l'histoire).

Pour du dév plus "sérieux", l'environnement existe déjà, c'est AVR Studio, d'Atmel. C'est ce que j'utilise la plupart du temps.

Ah donc il existe bien un IDE. Ouf XD

Bon, par contre est-il dispo sous Linux débian ? Ensuite pour Windaube ? (J'utilise les deux environnement en général pour mes projets en fonction des composants nécessaire. La carte SD par exemple uniquement sur Windows sinon c'est pas reconnu par la shield j'ai pas pigée pourquoi).. Bref je cherche une vraie edi :slight_smile:

Ceci dit, tel que c'est installé ça fonctionne pas trop mal à part quelques points cités au dessus.

Bon, comme j'ai dit je cherche toujours à faire passé mes infos dans le constructeur...

Voila, je poursuit un peu.

Geeks:
Ah donc on à affaire à des rigolos !! Et bien... Dire que je prenais Arduino pour un truc sérieux... Je vais peut-être revenir à lâge de pierre avec des pics mais au moins ils ne sont pas rigolos eux ! A quand un vraie IDE qui sache faire ce que font les pros ? Mieux une intégration dans une ide standard capable de gérer et l'ardino et la compilation ! Bref, vaste débat !!

Arduino c'est pas juste un ide ...
C'est une carte électronique, des shields, breakout, ... bref plein de trucs hardware.
Une communauté, un compilateur et une couche d'abstraction hardware opensource :wink:

Concernant les PIC, sans vouloir lancer un débat sans fin "AVR vs PIC", le jour où mplab supportera 1% des fonctions de base d'un "vrai" ide comme eclipse ou netbeans les poules auront des dentiers :grin:

Surtout que (justement) Eclipse, AVR studio ou encore Code::Blocks (même si c'est pas le meilleur ide du monde à mes yeux) supportent avr-gcc et donc par extension le core arduino :wink:

patg_:
Non on a affaire à des profs de design qui ont voulu créer un environnement simple (voire simpliste) pour permettre à des étudiants de développer simplement du code pour leurs projets artistiques numériques (si j'ai bien retenu l'histoire).

+1 c'est même étonnant qu'il ai pu arriver jusqu'à ce qu'on connait d'arduino aujourd'hui.
Certaines de leurs décisions reflètent leurs manque de connaissance dans certain sujet software/hardware mais bon ...
Si il laissait la communauté donner son avis sur certain point ça ferait pas de mal :zipper_mouth_face:

patg_:
Pour du dév plus "sérieux", l'environnement existe déjà, c'est AVR Studio, d'Atmel. C'est ce que j'utilise la plupart du temps.

AVR studio pour windows ou Eclipse CDT + un peu de config (c'est vite fait, et c'est moins contraignant que AVR studio pour les màj) sous linux, mac et windows

Geeks:
La carte SD par exemple uniquement sur Windows sinon c'est pas reconnu par la shield j'ai pas pigée pourquoi)..

Elle doit être formaté en FAT(16 ou 32) pour fonctionner, le format EXT2/3/4 n'est pas supporté par la librairie sdFatLib (qui porte bien son nom).

Geeks:
Bref je cherche une vraie edi :slight_smile:

Si tu cherches un vrai ide installe AVR Studio et apprend directement à coder en "vrai" C/C++ pour AVR.
Arduino c'est bien pour débuter, mais si tu cherches déjà la petite bête avec l'ide autant savoir ce que tu peut faire <avr/io.h> :wink:

Geeks:
Bon, comme j'ai dit je cherche toujours à faire passé mes infos dans le constructeur...

A noter qu'au final ça reste quand même du C/C++ compilé avec gcc.
Donc à pars quelques petit trucs particulier de la avr-libc le reste c'est exactement comme de la programmation sur ordi, l'ide arduino ne touche à rien à ce niveau là :wink:

Ok pour tout ça.

Bon, pour moi, connaissant pas éclipse. Enfin si je l'ai essayé, je l'ai vite abandonné n'y trouvant pas de confort ! Donc je vais resté sur mon geany en éditeur externe et l'ide pour ce qui est de la compilation.

Par contre j'arrive pas à passer au constructeur mon 0x63...

Personne n'a une piste ?

Geeks:
Bon, pour moi, connaissant pas éclipse. Enfin si je l'ai essayé, je l'ai vite abandonné n'y trouvant pas de confort ! Donc je vais resté sur mon geany en éditeur externe et l'ide pour ce qui est de la compilation.

Je supporte pas geany perso, je le place au même niveau que Code::Blocks ...

Eclipse c'est un logiciel très (trop ?) complet.
Il est fait pour des dév Java et/ou C/C++ ayant au moins du dual screen, une machine de puissance respectable et surtout un besoin constant des fonctions de développement rapide qu'offre eclipse (auto-implémentation des prototypes, détection d'erreurs avant compilation, documentation + mise en forme, getter/setter auto, ...).
Essaye netbeans, c'est un peu plus "user friendly" mais le plugin C/C++ est pas encore super stable d'âpres ce que j'ai pu voir.

Geeks:
Par contre j'arrive pas à passer au constructeur mon 0x63...

Personne n'a une piste ?

Un indice :

class MaClasse {
protected:
    int mToto;

public:
    MaClasse(int toto);
};

MaClasse::MaClasse(int toto) :
   mToto(toto) {
}

Merde, j'ai lancé un troll de la mort.
Désolé, je le ferait plus. :smiley:

Geeks:
Je reviens à la charge. Avant de faire mes classe j'avais écrit:

Ah, t'as fait tes classes où ?
Moi j'étais dans l'Infanterie de Montage à Vars.
:grin:

#define adresseLcd 0x63

void setup() {
  Obj LCD = new Obj(adresseLcd);
      LCD.ecrire("message", 01);
}



Bon, déjà il faut que je comprenne comment faire passer mon 0x63 sans conversion. Si quelqu'un à une idée.

Je ne vois pas de problème dans le code ci-dessus
Qu’appelles tu un problème de conversion.

Par ailleurs sache que l'allocation dynamique marche très mal dans Arduino faute à la vielle chaîne de compilation utilisée.
J'ai upgradé le mien au dernier WinAVR qui n'est pas la dernière version de avr-gcc mais qui marche mieux avec les alloc dynamiques.
Apparemment l'intégration des dernières versions d'avr-gcc poserait pas mal de problème de compatibilité....

Donc je recommande fortement :

#define adresseLcd 0x63

Obj LCD(adresseLcd);

void setup() {
      LCD.ecrire("message", 01);
}

Ah ben voila, j'y suis arrivé 8)

Merci beaucoup.

Bon alors voila ce que ça donne vite fais...

Le .h:

#ifndef LcdI2C_h
#define LcdI2C_h

#include <Arduino.h>
#include <Wire.h>

class LcdI2C {
	public:
		LcdI2C(char adresseLcd);
		
		void init();
		void ecrire(char* saisie, int posEcran);
		void clear();
		void clearCol(int colEcran);
		
	private:
		char addrComponent;
};

#endif

Le .cpp:

#include "LcdI2C.h"

//Constructeur
LcdI2C::LcdI2C(char adresseLcd) {
	addrComponent = adresseLcd;
}

/* init */
void LcdI2C::init() {
	Wire.begin();	//Start bit
	Wire.beginTransmission(addrComponent); //Appel carte
	Wire.write((byte)0x00);	//Null
	Wire.write((byte)0x0C);	//Effacer l'écran
	Wire.write((byte)0x13);	//Allumer le rétro éclairage
	Wire.write((byte)0x04);	//Ne pas afficher le curseur
	Wire.endTransmission();	//Fin de communication I2C
}

/* ecrire */
void LcdI2C::ecrire(char* saisie, int posEcran) {
	Wire.begin();	//Start bit
	Wire.beginTransmission(addrComponent); //Appel carte
	Wire.write((byte)0x00);	//Null
	Wire.write((byte)0x02);	//Placer le curseur à
	Wire.write(posEcran);	//Numéro de matrice 1 - 80
	Wire.print(saisie);		//Texte sur écran
	Wire.endTransmission();	//Fin de communication I2C
}

Le source :

/* INC */
#include <Wire.h>
#include <SD.h>
#include <LcdI2C.h>

/* DEFINITIONs */
#define addresseLcdI2c 0x63	//Adresse ecran LCD sur I2C

/* CREATION OBJ GLOBAUX */
LcdI2C ecran(addresseLcdI2c); //Ecran

void setup() {
	
	Serial.begin(9600);		//Port série de dépannage
	Serial1.begin(9600); 	//Port série du modem
	
	ecran.init();	//Initialisation
	
	ecran.ecrire("Telecommande 433Mhz", 01);	//Ecrire
	ecran.ecrire("Version 1.0", 24);	//Ecrire
	ecran.ecrire("Bonjour", 66);	//Ecrire
	
	delay(1500);
	
	//Initialiser la carte SD
	if(initSD()) {
		
	}
}

Bon ben maintenant que j'ai la base, il faut que je continue.

A propos, t'a vue pour écrire dans le Lcd j'ai virer le String pour un char* conseillé par un ami XD

barbudor:
Par ailleurs sache que l'allocation dynamique marche très mal dans Arduino faute à la vielle chaîne de compilation utilisée.
J'ai upgradé le mien au dernier WinAVR qui n'est pas la dernière version de avr-gcc mais qui marche mieux avec les alloc dynamiques.
Apparemment l'intégration des dernières versions d'avr-gcc poserait pas mal de problème de compatibilité....

A noter que WinAVR est désormais mort et enterré, son successeur c'est "MHV AVR tools" :
http://www.makehackvoid.com/project/mhvavrtools

Ça fait toujours plaisir d'avoir un GCC 4.7.2 au lieu d'un vieux 4.4.x :grin:

skywodd:
A noter que WinAVR est désormais mort et enterré, son successeur c'est "MHV AVR tools" :
http://www.makehackvoid.com/project/mhvavrtools

Ça fait toujours plaisir d'avoir un GCC 4.7.2 au lieu d'un vieux 4.4.x :grin:

Et tu as essayé d'upgrader l'env. Arduino avec ?

barbudor:
Et tu as essayé d'upgrader l'env. Arduino avec ?

Pas encore mais ça ne saurait tarder :grin:

La version de l'IDE sous linux (debian) est modifiée. La modification consiste à ne pas utiliser les programmes fournis par l'IDE officielle Arduino (gcc-avr, avrdude, etc) mais ceux présent sur les dépots de la distribution et en distib "testing" cela fait belle lurette qu'avec l'IDE revu par Debian c'est gcc-avr 4.7.2.

Qui a dit que Linux est souvent à la ramasse ?

Et donc tu n'as aucun problème pour compiler de l'Arduino avec avr-gcc 4.7 ?
Je croyais qu'il y avait pas mal de problèmes et qu'il fallait reprendre le code du core et de certaines lib

Moi non :grin:, mais le mainteneur du paquet Scott Howard en eu lui je crois :~ .
Il a du mettre les mains dans le cambouis pour que ça marche.

Si tu veux faire des comparaisons dans les fichiers tu peux télécharger le paquet ici :
http://packages.debian.org/wheezy/arduino
et
http://packages.debian.org/wheezy/arduino-core
(l'IDE est coupée en deux : l'IDE d'un coté, les bibliothèques de l'autre)
Les paquets s'ouvrent comme une archive.

En Testing et SID c'est toujours la version 1.01. La version 1.03 est toujours en Experimental.

edit :
Stable = squeeze
Testing = wheezy
Sid et experimental : les noms ne change pas.
Ubuntu est basé sur un mix Testing/SID avec une correction des bugs limitée aux deux seules architectures i386 et AMD64

Et bien, j'en apprends tous les jours !!!

Donc, si je résume, il faudrais que je prenne la version fourni par Ubuntu car elle emploie une librairie à jour !! Et ben...

Bon, je reviens avec classe sur un besoin d'info sur les classes. J'en voie au fond de la classe qui ronflent !!! (Private joke)

Bien, le problème est le suivant. Je suis en train de gérer un FailSafe. En gris si divers cas se présentent, je fait diverses opération de sauvegarde du matériel. Un submersible, sans réception, c'est un peu comme un objet pouvant devenir assez instable. Il convient donc de géré certains cas en fonction. J'ai une terrible idée, faire une classe pour géré certains cas. Ainsi:

Est-il possible de transmettre en paramettre à une classe, la fonction externe à exécuté ?

Exemple théorique de ce que je voudrais faire :

/* Création objet global*/
FailSafe failReception(safeReception);
FailSafe failEtanche(safeEtanche);

void loop() {
   /* utilisation objet
   failReception.test();
   failEtanche.test();
}
 
/* Safe */
void safeReception() {
   //Options de sauvegarde sur problème radio
   //Couper les moteurs
   //Si on a attendu 200 passage
      //Lancer le safeEtanche();
   //Sinon, incrémenter un passage
}

/* Safe */
void safeEtanche() {
   //Options de sauvegarde sur problème de voie d'eau
   //Couper les moteurs
   //Mettre en marche la pompe
   //Faire clignoter les lumières
}

Voila, le but est assez compréhensible, je gère divers cas et diverses tests sur la base de flags gérér dans la classe. Ainsi je simplifie mon code principal. Seulement, j'aimerais savoir si on peut éventuellement accéder à une fonction externe de la classe.

Merci pour vos indications.

Donc, si je résume, il faudrais que je prenne la version fourni par Ubuntu car elle emploie une librairie à jour

Je n'ai avancé que du factuel, quant à assurer que cela fonctionnera avec gcc-acr 4.72 je n'irais pas jusqu'a affirmer dur comme fer que ce sera vrai
: je précise que je ne fais que programoter juste ce qu'il faut pour entretenir mes neuronnes qui maintenant sont plus près de 70 que de 60.
Quant à passer sur Ubuntu : oui mais juste pour voir dans le cas où tu ne connaîtrais pas Debian.
Perso j'ai commencé avec Mandrake qui est partie en sucette peu après, j'ai donc regardé du coté d'Ubuntu qui venait de sortir et dont on disait le plus grand bien.
Que neni ! J'avais gouté à la liberté avec Mandrake et avec Ubuntu j'avais l'impression de retourner sous Windows , c'est d'ailleurs le but recherché : ne pas dépayser les arrivants de windows. Mon pseudo en dit long : "il est interdit d'interdire" et je ne supporte pas qu'on décide à ma place qu'il ne faut pas de compte root et qu'on m'oblige à utiliser "sudo" à la place de "su" : c'est moi seul qui décide des conneries que je fais et que j'assume et non pas un quelquonque éditeur.
Je suis vite passé sur Debian et depuis j'y suis resté.
Et pourquoi utiliser une copie alors qu'on peut utiliser l'original ?