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 :
/*
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
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.
Yesss ! Thank you, j'avai essayé avec #include "Arduino.h"... alors que c'est #include<Arduino.h>
Bon ça compile bien avec ça :
/*
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
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 :
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".
à 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.
fdufnews:
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...
fdufnews:
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 :
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 :
#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.