Go Down

Topic: [RESOLU] Créer ma première librairie... (PPMread) (Read 1 time) previous topic - next topic

UniseV

Feb 24, 2013, 08:22 pm Last Edit: Feb 26, 2013, 11:19 pm by UniseV Reason: 1
Bonjour,

Je voudrais créer ma première librairie et elle aura pour rôle de fournir les valeurs lues d'un récepteur de modélisme (au format PPM).

Pourquoi une librairie :

  • J'utilise très souvent ce code que j'ai déjà développé, sous forme de librairie ça le rendra facilement intégrable et désintégrable  ;)

  • Je le fais parfois évoluer, et c'est pénible de copier/coller mes évolution dans les différents projets



Mais voila, c'est ma première librairie, je viens de loin, alors je suis parti de l'exemple de la librairie Morse.h sur le site Arduino et je l'ai vidé de son contenu et renommé en PPMread, ça me donne déjà une coquille vide.

Le H :
Code: [Select]
/*
 PPMread.h - Library for reading PPM 6ch (negative modulated).
*/

#ifndef PPMread_h
#define PPMread_h

class PPMread
{
 public:
   PPMread(int pin);
   void begin();
   void read();
 private:
   int _pin;
};

#endif


Le CPP :
Code: [Select]
/*
 PPMread.cpp - Library for reading PPM 6ch (negative modulated).
*/

#include "PPMread.h"

PPMread::PPMread(int pin)
{
}

void PPMread::begin()
{
}

void PPMread::read()
{
}


Et ça devrait s'utiliser à peu près comme ça comme ça :

Code: [Select]
#include <PPMread.h>

PPMread ppm(13);

void setup()
{
 ppm.begin();
}

void loop()
{
 ppm.read();
}


Pour l'instant mon soucis, c'est que j'aimerai ne pas avoir de paramètre pin dans PPMread, le fameux 13 ne me sert à rien, peut-on s'en passer ?
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

B@tto

Oui oui pas de problème, vire les "int pin"
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

fdufnews

Tu as déclaré une variable _pin associé à ta classe.
Il suffit de l'initialiser dans le constructeur lorsque tu instancies ta classe (soit en passant la valeur en argument, soit en fixant une valeur par défaut). Ensuite les méthode que tu vas créer pourront utiliser cette variable directement et tu n'auras plus besoin de la passer en argument.

UniseV

Bha oui mais ça ne veut plus compiler si j'enlève le paramètre pin (dont je n'ai pas besoin) :



Voici le H :
Code: [Select]
/*
  PPMread.h - Library for reading PPM 6ch (negative modulated).
*/

#ifndef PPMread_h
#define PPMread_h

class PPMread
{
public:
  PPMread();
  void begin();
  void read();
private:
};

#endif

Et le CPP :
Code: [Select]
/*
  PPMread.cpp - Library for reading PPM 6ch (negative modulated).
*/

#include "PPMread.h"

PPMread::PPMread()
{
}

void PPMread::begin()
{
}

void PPMread::read()
{
}
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

Heloderma-kris

#4
Feb 25, 2013, 02:48 pm Last Edit: Feb 25, 2013, 02:51 pm by Heloderma-kris Reason: 1
juste une question pour mieux cerné ton souci ,
tu cherche toujours a utiliser la pin 13 ou tu change dans ton code a certaint endroit ?

car si c'est du definitif , j'imagine que dans ta fonction tu peut simplement metre
le 13 la ou tu a besoin et te passer de a variable _pin.

ou alors comme dit  fdufnews tu peut la rendre facultative lors de l'initialisation tu la declare dans le .h

comme cela je pense que ça doit marcher
Code: [Select]
PPMread::PPMread(int pin=13)
{
}


cela dit je suis pas sur d'avoir compris ton probleme!

UniseV

En fait je veux juste m'en débarrasser, je n'ai pas besoin de paramètre.

Ma librairie utilisera une fonction HARDWARE du PIN 8, donc je n'ai pas besoin de ce paramètre.
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

skywodd

Bonjour,

La déclaration de l'objet "ppm" dans ton code d'exemple est faux ;)

Code: [Select]
PPMread ppm();
et :
Code: [Select]
PPMread ppm;
Ce n'est pas la même chose ;)

Si ton constructeur n'as pas d'argument tu doit utiliser la seconde syntaxe.
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

UniseV

#7
Feb 25, 2013, 08:38 pm Last Edit: Feb 25, 2013, 08:40 pm by UniseV Reason: 1
Yes, ça compile, merci skywodd.

Je m'attaque donc maintenant aux "fonctions", et vous fait part de mon second problème :

J'ai alimenté la fonction begin avec le paramétrage du timer1 :
Code: [Select]
/*
 PPMread.cpp - Library for reading PPM 6ch (negative modulated).
*/

#include "PPMread.h"

PPMread::PPMread()
{
}

void PPMread::begin()
{
   // Timer1 setup
 TCCR1A=B00000000; // OCR2A/OCR2B : disconnected, Timer: normal mode
 TCCR1B=B00000010; // Falling edge CAPTUREPIN detection, Timer:normal mode, Prescaler=clk/8
 TIMSK1=B00100001; // Activate CAPTUREPIN interrupt & OVF interrupt
}

void PPMread::read()
{
}


Et ça coince encore à la compilation, ce coup-ci au niveau des regsitres HARD, mais aussi au niveau des valeurs binaires  :smiley-roll-blue: :



Pourtant je n'utilisais aucune librairie supplémentaire dans mon code...
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

B@tto

Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

UniseV

#9
Feb 25, 2013, 11:34 pm Last Edit: Feb 25, 2013, 11:51 pm by UniseV Reason: 1
Yesss ! Thank you, j'avai essayé avec #include "Arduino.h"... alors que c'est #include <Arduino.h>

Bon ça compile bien avec ça :

Code: [Select]
/*
 PPMread.cpp - Library for reading PPM 6ch (negative modulated).
*/

#include "PPMread.h"
#include <Arduino.h>

PPMread::PPMread()
{
}

// Données de capture du Rx
boolean endTrame=0,failsafe=0;
volatile unsigned int vchUp[8];
volatile unsigned int vchPos[6];
byte curEdge;


ISR(TIMER1_CAPT_vect)
{
 vchUp[curEdge]=ICR1; // Capture des timestamp 1 à 6
 curEdge++;
 if (curEdge>7) {     // A partie du 7ème...  
   TCNT1=0;           // RESET du counter pour éviter le FailSafe
   if ((vchUp[7]-vchUp[1]) > 30000) {  //Si la trame totale dépasse 15ms - Trame KO ou mauvaise synchro
     curEdge=0;            //Remise à 0 du compteur de fronts                      
   }
   else {                  //Sinon, une bonne trame est capturée, on calcule donc la valeur des canaux
     curEdge=1;
     for (int i=0;i<6;i++) {
       vchPos[i]=(vchUp[i+2]-vchUp[i+1]); //Mesure des canaux (diviser par 2 pour obtenir des µs)
     }
     endTrame=1;           // Pour dire à la MainLoop que de nouvelles valeurs sont disponibles
   }
 }
}

ISR(TIMER1_OVF_vect)
{
 failsafe=1;  // Le compteur a attends sa limite (32ms), on déclenche donc le FailSafe
}


void PPMread::begin()
{
   // Timer1 setup
 TCCR1A=B00000000; // OCR2A/OCR2B : disconnected, Timer: normal mode
 TCCR1B=B00000010; // Falling edge CAPTUREPIN detection, Timer:normal mode, Prescaler=clk/8
 TIMSK1=B00100001; // Activate CAPTUREPIN interrupt & OVF interrupt
}

void PPMread::read()
{
 
}


J'espère que mes interruptions vont être correctement prises en compte  :smiley-roll-blue:

J'attaque maintenant la dernière partie, la fonction read, qui va permettre au programme "utilisateur" de lire les données du Rx... et la ça se complique parce qu'avant de vouloir librariser le truc c'était géré sous forme de tableau :

Code: [Select]
 if (endTrame==1) {
   cli();
   for (int i=0;i<6;i++) {
     if (vchPos[i] > (cha[i]+ecart) || vchPos[i]< (cha[i]-ecart)) { // Si la nouvelle valeur dépasse l'hystérésis
     cha[i]=vchPos[i]; // Recopie les valeurs des canaux
     }
   }
   sei();
   endTrame=0;
   }


Et j'ai cru comprendre qu'on ne pouvait pas passer un tableau en retour d'une fonction... à votre avis quel est la meilleure façon de faire, sachant que cette fonction ne demande rien en entrée et qu'elle doit retourner 6 valeurs ?

Je précise que la simplicité d'utilisation doit surtout être du côté de l'utilisateur, donc ça peut être un peu tordu côté librairie mais il faut que ça reste simple côtré "main code".
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

fdufnews

Quote
à votre avis quel est la meilleure façon de faire, sachant que cette fonction ne demande rien en entrée et qu'elle doit retourner 6 valeurs

La fonction pourrait retourner un pointeur mais c'est généralement mal compris par l'utilisateur lambda et source de problèmes.
Le plus simple serait de passer en argument un pointeur sur un tableau déclaré par la fonction appelante.

UniseV

La fonction pourrait retourner un pointeur mais c'est généralement mal compris par l'utilisateur lambda et source de problèmes.

Ca obligerait en plus à développer dans le main code un "truc" pour lire la mémoire et saucissonner le contenu dans des variables...

Le plus simple serait de passer en argument un pointeur sur un tableau déclaré par la fonction appelante.


La fonction read, écrirait directement à l'emplacement mémoire indiqué, et mettrait à jour les variable du main code sans les connaitre, c'est l'idée ?
Dis-moi si j'ai bien compris, ça s'utiliserait comme ça :
Code: [Select]
unsigned int cha[6];
unsigned int* rxPoint=&cha[0];

void setup() {
}
void loop() {
  ppm.read(rxPoint)
}


??
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

UniseV

#12
Feb 26, 2013, 11:18 pm Last Edit: Feb 27, 2013, 11:41 pm by UniseV Reason: 1
Ça fonctionne, et j'en suis le premier étonné.

J'ai finalement fait évolué la fonction ppm.read() pour qu'elle renvoi une valeur 0, 1 ou 2 :

0 = Pas de nouvelles trame capturée depuis le dernier appel de la fonction
1 = Des nouvelles valeurs ont été mise à jour en mémoire
2 = Le signal radio est perdu, les donnée en mémoire sont figées

Un example d'utilisation :

Code: [Select]
#include <PPMread.h>          // On inclue la librairie

// Données du Rx
unsigned int cha[6];           // Les valeurs des canaux

PPMread ppm(&cha[0]);          // On lance l'instance, en fournissant le pointeur

void setup()
{
 Serial.begin(115200);        // On prepare la sortie série
 ppm.begin();                // On démarre la lecture PPM en arrière-plan
}

void loop()
{
 if (0 < ppm.read()){   // Si des nouvelles valeurs ou FAILSAFE
   if (1 < ppm.read()){   // Si FAILSAFE
     Serial.println("FAILSAFE");

   }
   else {               // Si des nouvelles valeurs, la variable est DEJA A JOUR
   for (int i=0; i < 6; i++){ // Imprimer les valeurs des canaux sur le port série
       Serial.print(cha[i]);
       Serial.print(";");
     }
     Serial.println(";");

   }
 }
}


Il me reste à nettoyer le code & imaginer un truc cloisonné au niveau des interruptions... merci à tous, j'avance à pas de géants grâce à ce forum.
EN: Libraries are my Gurus, they make me believe anything they want !
FR: Les librairies sont mes gourous, elles me font croire ce qu'elles veulent !

Go Up