Go Down

Topic: Decoupage d'un tres long programme (Read 2350 times) previous topic - next topic

caape

bonjour,
je voudrais, pour une question de lisibilité, decouper mon programme en plusieurs fichiers.
Il y a pour ça les .h et .c vous allez me dire.
Oui mais ...
Je voudrais mettre mes fonctions dans des fichiers séparés suivant le mode d'utilisation du programme. Il y en a une 8aine pour l'instant plus des fichiers avec des #define, etc.
le problème est que quand il y a dans mes fonctions, un truc qui doit etre afficher sur le LCD, je dois importer le LiquidCrystal.h puis declarer avec "extern LiquidCrystal lcd;" dans chacun des fichiers. Ca fait beaucoup a faire surtout que j'utilise pas mal de classes.
Existe-t-il un moyen de "concatener" les fichiers avant compilation automatiquement comme ci il ce n'était qu'un seul ce qui serait plus simple a utiliser pour moi et surtout plus rapide?

Je ne connais pas bien le C.
je ne suis pas tres clair, desolé, pas facile a expliquer.
StandAlone domotique
Volet roulant en proto (Eclairage Salon SAM)(Capteur T°)(Pilotage via WEB + Mobile)(Sonnette)(Alarme)

Jean-François

En haut à droite de la fenêtre de l'Ide il y a une flèche qui part sur la droite, tu clique dessus et tu fais "new tab"... et tu as un nouveau fichier qui sera compilé en même temps que le premier.
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

caape

Merci
j'avais deja fait ça pour tester avec les .h et .c
Mais il faut faire les déclarations car ça me dit que mes variables ne sont pas déclarées donc non utilisable.
et j'en ai beaucoup a partager dans beaucoup de fichiers.
Pour l'instant, je fais tout dans un seul fichier, mais il fait 500km de long, c'est dur de m'y retrouver.
StandAlone domotique
Volet roulant en proto (Eclairage Salon SAM)(Capteur T°)(Pilotage via WEB + Mobile)(Sonnette)(Alarme)

68tjs

J'ai déjà donné la solution plusieurs fois.................grrrrrrrr

Regardez par vous même comment l'IDE procède :
les fichiers supplémentaires sont rangés en ordre alphabétique.
Ca devrait mettre la puce à l'oreille ?

Ensuite l'IDE les concatène dans l'ordre d'affichage donc alphabétique.
Ce qui fait que si vous avez créé un fichier "setup.ino" et un autre "loop.ino" il chargera loop avant setup et le compilateur plantera.

Rusez pour que le chef se soit vous et pas ce &$£!µ de logiciel.

Vous n'avez pas trouvé ?
Non alors :
A) créez votre fichier principal comme d'habitude.
B) dans l'ide créez un fichier supplémentaire que vous appellerez A_setup.ino puis créez le fichier B_loop.ino.
De cette façon c'est maintenant vous qui aller imposer l'ordre d'affichage.
Comme par miracle le compilateur retrouvera les informations dans le bon ordre et il cessera de vous engue£µ&.

Répéter l'opération autant de fois que nécessaire.
PS -> que du classique qui doit être connu : IDE 1.0 fichier extension *.ino , IDE jusqu'à 0.23 extension *.pde.

fdufnews

Quote
le problème est que quand il y a dans mes fonctions, un truc qui doit etre afficher sur le LCD,

C'est peut être le résultat d'un mauvais découpage des fonctions et de leur répartition dans des librairies.

Les fonctions liées à l'affichage sont des fonctions de niveau relativement élevées et donc il ne devrait pas y avoir beaucoup de fonctions (ou librairies) qui aient besoin d'accéder à l'afficheur directement.

Tu peux par exemple dans les fonctions de bas niveau avoir des paramètres (ou valeurs) dans des variables privées de la classe et tu implémentes une (ou des) méthode(s) qui permet(tent) à la boucle principale de récupérer ces valeurs pour les transmettre à la classe d'affichage. Ce type de fonctionnement simplifie la réutilisation des librairies en permettant leur réutilisation dans un autre contexte (un autre type d'affichage par exemple ou même carrément pas d'afficheur mais un stockage des résultats dans un fichier).

caape

Bonjour et désolé de repondre si tardivement, je n'ai plus trop le temps en ce moment mais merci pour les reponses.

"les fichiers supplémentaires sont rangés en ordre alphabétique" ---> C'est bon, ca marche mais il faut faire gaf au piège de la case. ("M" avant "b")

"C'est peut être le résultat d'un mauvais découpage des fonctions et de leur répartition dans des librairies." ---> C'est fort possible, je débute sur arduino et je n'ai pas fais grand chose en C/C++, encore moins avec plusieurs fichiers.

J'ai pour projet, un boitier qui controle un APN reflex avec plusieurs fonctions (intervallometre, détecteur de passage, détecteur de lumiere, détecteur de son, retardateur, HDR, Lightpainting, ...). Chaqu'une des fonctions étant activé depuis le menu principal. J'aurais voulu séparer les différentes fonctions dans des fichiers distincts. Ca, c'est résolu avec les noms de fichier par ordre alphabetique.
Pour le hardware, j'utilise un LCD 4x20 et un RotaryEncoder avec les librairies qui vont bien.
Je voudrais faire une nouvelle librairie "Keyboard" qui utilise la lib "RotaryEncoder" pour que dans le reste du programme je n'utilise que la mienne. Ceci afin de pouvoir modifier l'interface de saisie dans une autre version en ne modifiant que la librairie et pour utiliser des simples boutons sur une entrée analogique. (Je réfléchi déjà à une autre utilisation qui utiliserait plusieurs modules avec différent modes de saisie et de controle mais qui utiliserait en grande partie le meme code. donc gain de temps)
N'ayant pas trop de temps en ce moment, j'ai tout mis dans le fichier principal et ca marche bien comme ca.
Je reprendrais le prog quand j'aurais plus de temps et surtout plus de connaissance sur la création de librairie et sur le C/C++ en générale pour refaire ca plus proprement.
Si qu'elqu'un a des liens interressants sur la manière de faire correctement une librairie pour arduino, qu'il les partage avec nous.

Merci

Pour mon projet qui avance mais tres trop lentement
StandAlone domotique
Volet roulant en proto (Eclairage Salon SAM)(Capteur T°)(Pilotage via WEB + Mobile)(Sonnette)(Alarme)

68tjs

Quote
"M" avant "b"

<troll> Mauvaise habitude de Windosien : le code ascii de "M" est différent de celui de "m" donc pour l'avr-libc "M" ne peut pas être égal à "m". </troll>

moribond

@68tjs: j'ai du mal à comprendre ton raisonnement.

Pour ce qui est du problème exposé comme il est, je pense que la solution est la vision objet.
Il n'y a rien de mieux pour "clarifier" sa programmation.

Cela induit certainement une refonte du programme, pêtre difficile au début mais bénéfique à terme.

68tjs

Quote
@68tjs: j'ai du mal à comprendre ton raisonnement.

Je n'ai ni exprimé une opinion ni vanté une solution, j'ai juste répondu à la question qui était posée.
Le demandeur "demandait" une solution à l'intérieur de l'IDE arduino, j'en avais trouvé une, je lui en fait part.

Maintenant si je devais exprimer mon opinion de "technicien non programmeur", ce sera d'utiliser un ide non arduino et des fichiers d'en-tête *.h et des fichiers *.c. Cette solution me parait plus "solide" pour découper un programme car elle oblige à bien structurer ses idées, opération la plus délicate pour un débutant.

Quant au C et au C++ je constate qu'il semble y avoir un large consensus pour la programmation objet dans la programmation pure : je parle par exemple des programmes qui tournent sous Linux, Mac ou windows.

Par contre dans le domaine des micro-controleurs en dehors du projet Wiring (Arduino n'en est qu'un fork) je constate qu'un maximum d'utilisateurs programment en C.

Donc le néophyte que je suis se dit "il doit bien y avoir une raison ?"

Et quand le néophyte voit l'utilisation de la programmation objet pour faire ceci tiré des bibliothèques arduino :
fichier EEPROM.h
Code: [Select]

#ifndef EEPROM_h
#define EEPROM_h
#include <inttypes.h>
class EEPROMClass
{
  public:
    uint8_t read(int);
    void write(int, uint8_t);
};
extern EEPROMClass EEPROM;
#endif


Fichier EEPROM.cpp
Code: [Select]

#include <avr/eeprom.h>
#include "WConstants.h"
#include "EEPROM.h"
uint8_t EEPROMClass::read(int address)
{
   return eeprom_read_byte((unsigned char *) address);
}
void EEPROMClass::write(int address, uint8_t value)
{
   eeprom_write_byte((unsigned char *) address, value);
}
EEPROMClass EEPROM;


Tout cela pour utiliser deux fonctions de l'avr-libc qui se résument à :
Code: [Select]
void eeprom_write_byte (uint8_t *__p, uint8_t __value)
uint8_t  eeprom_read_byte (const uint8_t *__p)

Il se dit que:
1) l'avr_libc propose trois méthodes pour lire/écrire dans une eeprom : par octet, par mot de 2 octets et par block. L'arduino n'autorise que le mode octet et censure les 2 autres modes.
2) Utiliser la programmation objet dans ce cas c'est utiliser un marteau pilon pour enfoncer un clou.
La seule utilité qu'il voit, le néophyte, c'est de masquer l'utilisation d'un pointeur.

Ce n'est pas ma façon de voir je ne comprends pas encore les pointeurs mais j'attends un tuto pour me soigner    ( :smiley-mr-green: Osaka je piaffe).

moribond

Très bon exemple que j'avais également repéré et qui m'avait fait gagner 14 octets sur ma UNO.

Go Up