Problème de lecture des données transmises par la radio
Sylvie50120
6 Messages
Le jeudi 16 septembre 2021 à 18:01:44
Je possède déjà un drone, un DJI F450 avec un module NAZA Lite. Ca marche, mais on ne sait pas vraiment ce qu'il y a dans le module de conduite...
J'ai découvert la série d'articles sur la construction d'un drone à base d'arduino qui me passionne ! J'apprécie d'autant plus qu'à la lecture, j'apprends beaucoup de choses sur la programmation de l'arduino.
Bon si j'écris, c'est que j'ai un problème ! Voilà :
Je suis les articles les uns après les autres, j'en suis à tester le lien entre la radiocommande et l'arduino. Ma configuration est la suivante :
- Une radio TARANIS X9D+
- Un récepteur X6R
- Un arduino NANO
- Le câblage reste identique à celui proposé dans l'article 6.
Lorsque je reprends le sketch de teste de la liaison entre radio et arduino, j'obtiens des valeurs totalement incohérentes par rapport aux valeurs que l'on devrait obtenir, comprises entre 1000 et 2000 : Les valeurs lues varient même sans mouvements sur les manches de la radio, les valeurs lues dépassent 50000...
Je croyais que le NANO pouvait remplacer un UNO quasi au pied levé... Existe-t-il des différences qui expliquent ces écarts ?
Merci pour votre aide
Alain
J'ai découvert la série d'articles sur la construction d'un drone à base d'arduino qui me passionne ! J'apprécie d'autant plus qu'à la lecture, j'apprends beaucoup de choses sur la programmation de l'arduino.
Bon si j'écris, c'est que j'ai un problème ! Voilà :
Je suis les articles les uns après les autres, j'en suis à tester le lien entre la radiocommande et l'arduino. Ma configuration est la suivante :
- Une radio TARANIS X9D+
- Un récepteur X6R
- Un arduino NANO
- Le câblage reste identique à celui proposé dans l'article 6.
Lorsque je reprends le sketch de teste de la liaison entre radio et arduino, j'obtiens des valeurs totalement incohérentes par rapport aux valeurs que l'on devrait obtenir, comprises entre 1000 et 2000 : Les valeurs lues varient même sans mouvements sur les manches de la radio, les valeurs lues dépassent 50000...
Je croyais que le NANO pouvait remplacer un UNO quasi au pied levé... Existe-t-il des différences qui expliquent ces écarts ?
Merci pour votre aide
Alain
Sylvie50120
6 Messages
Le vendredi 17 septembre 2021 à 17:25:43
J'apporte quelques précisions quant à mon problème, néanmoins cela ne m'aide vraiment pas à comprendre le problème que je rencontre. On y va :
- J'ai vérifié le bind du récepteur X6R avec la radio Taranis : c'est OK, le voyant est vert.
- Le programme sur la radio est on ne peut plus simple : ROLL sur voie 1 à 100%, PITCH sur voie 2 à 100%, THROTTLE sur voie 3 à 100%, et YAW sur voie 4 à 100%, on ne peut pas faire plus simple dans la Taranis lorsqu'on crée un nouveau modèle...
- J'ai raccordé au récepteur 4 servos Tower Pro SG90, sur voies 1, 2, 3, 4.
- On met sous tension et là, tous les servos fonctionnent, MAIS aucun de fait 0°-180° : l'amplitude de rotation n'est que de 80° (la mesure est faite "à l'oeil"). N'empêche, c'est clair que le débattement n'est que la moitier de ce que j'attendais !!!
Le dimanche 19 septembre 2021 à 15:27:40
Salut Alain,
L'Aruino Uno et l'Arduino Nano utilisent le même microcontrôleur, à savoir le ATMega328. Le code du chapitre 6 est donc censé fonctionner sur ces deux cartes.
Les servomoteurs ont une fréquence de fonctionnement qui leur est propre. Si elle n'est pas la même que celle de ta radiocommande/récepteur, ça peut expliquer cette amplitude réduite.
Il serait intéressant de trouver la datasheet de ta radiocommande/récepteur pour voir la fréquence de fonctionnement et la durée des impulsions qui sont censées être comprises entre 1000µs et 2000µs.
L'Aruino Uno et l'Arduino Nano utilisent le même microcontrôleur, à savoir le ATMega328. Le code du chapitre 6 est donc censé fonctionner sur ces deux cartes.
Les servomoteurs ont une fréquence de fonctionnement qui leur est propre. Si elle n'est pas la même que celle de ta radiocommande/récepteur, ça peut expliquer cette amplitude réduite.
Il serait intéressant de trouver la datasheet de ta radiocommande/récepteur pour voir la fréquence de fonctionnement et la durée des impulsions qui sont censées être comprises entre 1000µs et 2000µs.
Sylvie50120
6 Messages
Le dimanche 19 septembre 2021 à 18:17:02
Merci pour cette réponse.
Je reste vraiment dans l'expectative : la radio Taranis est assez compliquée à utiliser (pour moi en tous cas), mais je peux maintenant affirmer que la durée des impulsions est comprise entre 988µs et 2012µs (c'est affiché sur l'un des écrans de réglage de la radio...)....
Pour autant, je n'ai toujours aucun résultat probant !
Du point de vue montage :
Merci pour le temps que vous me consacrez !
Alain
Je reste vraiment dans l'expectative : la radio Taranis est assez compliquée à utiliser (pour moi en tous cas), mais je peux maintenant affirmer que la durée des impulsions est comprise entre 988µs et 2012µs (c'est affiché sur l'un des écrans de réglage de la radio...)....
Pour autant, je n'ai toujours aucun résultat probant !
Du point de vue montage :
- l'arduino UNO ou NANO (j'ai essayé avec les deux types de cartes !) sont raccordés au PC en USB
- Le récepteur radio est raccordé aux pins de l'arduino avec des fils de bread board. Le récepteur est alimenté par un bloc de 4 piles 1,5V. La masse de ce bloc de pile est relié au ground de l'arduino.
Merci pour le temps que vous me consacrez !
Alain
Sylvie50120
6 Messages
Le dimanche 19 septembre 2021 à 19:13:35
Re bonsoir !
En fait, j'avais des doutes quant au fonctionnement du couple radio-récepteur... J'ai donc programmé un sketch utilisant pulseIn afin de lire ce qui passe sur les pins 8, 9, 10, 11.
Le sketch est le suivant :
ET CA MARCHE !!!!!!!!!!!!!!! : j'ai bien des valeurs comprises entre 990 et 1990... mais il faut 45 millisecondes pour lire les 4 voies....
En fait, j'avais des doutes quant au fonctionnement du couple radio-récepteur... J'ai donc programmé un sketch utilisant pulseIn afin de lire ce qui passe sur les pins 8, 9, 10, 11.
Le sketch est le suivant :
#define canal1 8
#define canal2 9
#define canal3 10
#define canal4 11
int ch1, ch2, ch3, ch4;
unsigned long debut, duree;
void setup() {
// Démarrer la liaison série
Serial.begin(9600);
//Déclarer les canaux en entrée
pinMode(canal1, INPUT);
pinMode(canal2, INPUT);
pinMode(canal3, INPUT);
pinMode(canal4, INPUT);
}
void loop() {
debut = micros();
// Lire les 4 canaux
ch1 = pulseIn(canal1, HIGH, 25000);
ch2 = pulseIn(canal2, HIGH, 25000);
ch3 = pulseIn(canal3, HIGH, 25000);
ch4 = pulseIn(canal4, HIGH, 25000);
duree = micros() - debut;
// Affichage des lectures sur le terminal
Serial.print("Durée 4 pulseIn = ");
Serial.print(duree/1000);
Serial.print("ms");
Serial.print("\tCanal 1 = ");
Serial.print(ch1);
Serial.print("\tCanal 2 = ");
Serial.print(ch2);
Serial.print("\tCanal 3 = ");
Serial.print(ch3);
Serial.print("\tCanal 4 = ");
Serial.println(ch4);
}
ET CA MARCHE !!!!!!!!!!!!!!! : j'ai bien des valeurs comprises entre 990 et 1990... mais il faut 45 millisecondes pour lire les 4 voies....
Sylvie50120
6 Messages
Le dimanche 19 septembre 2021 à 20:08:11
Voici le code que j'essaye sans succès de faire tourner :
/*
* ================================================
* Alain 15 septembre 2021
* ================================================
* Sketch de test du lien entre arduino nano et
* la radio Taranis X9D
* ================================================
* Repris du site :
* https://www.firediy.fr/article/utiliser-sa-radiocommande-avec-un-arduino-drone-ch-6
* ================================================
*/
// Numérotation des canaux
#define CHANNEL1 0
#define CHANNEL2 1
#define CHANNEL3 2
#define CHANNEL4 3
// Définition des degrés de liberté du drone
#define YAW 0
#define PITCH 1
#define ROLL 2
#define THROTTLE 3
// Variables de gestion du temps
volatile unsigned long current_time;
volatile unsigned long timer[4];
// Etat précédent de chaque canal (HIGH ou LOW)
volatile byte previous_state[4] = {HIGH, HIGH, HIGH, HIGH};
// Durée de pulsation sur chaque canal en µs,
// la valeur doit être comprise entre 1000µs et 2000µs
volatile unsigned int pulse_duration[4] = {1500, 1500, 1000, 1500};
// Définition du mapping des 4 voies (association des commandes à un canal donné)
int mode_mapping[4];
void setup() {
// Ouvrir la liaison avec le terminal
Serial.begin(9600);
// Définition du mapping des contrôles : quelle commande
// est sur quel canal (correspond au mode 2 des radios)
mode_mapping[YAW] = CHANNEL4;
mode_mapping[PITCH] = CHANNEL2;
mode_mapping[ROLL] = CHANNEL1;
mode_mapping[THROTTLE] = CHANNEL3;
// Configuration des interruptions scrutées par le µC
// Placer le registre PCICR en scan du registre PCMSK0
PCICR |= (1 << PCIE0);
// Configurer les 4 interruptions
PCMSK0 |= (1 << PCINT0); // Place PCINT0 (digital pin 8) pour capter une interruption sur changement d'état
PCMSK0 |= (1 << PCINT1); // Place PCINT1 (digital pin 9) pour capter une interruption sur changement d'état
PCMSK0 |= (1 << PCINT2); // Place PCINT2 (digital pin 10) pour capter une interruption sur changement d'état
PCMSK0 |= (1 << PCINT3); // Place PCINT3 (digital pin 11) pour capter une interruption sur changement d'état
}
void loop() {
// Simplement recopier les canaux sur le terminal
dumpChannels();
}
/*
* Fonction de duplication de l'état des canux sur le terminal
*/
void dumpChannels(){
for (int i = CHANNEL1; i <= CHANNEL4; i++){
Serial.print("\tCanal ");
Serial.print(i+1);
Serial.print("\tPulse");
Serial.print(i+1);
Serial.print(" = ");
Serial.print(pulse_duration[i]);
}
Serial.print("\n");
}
/*
* Cette routine est appelée chaque fois que que l'entrée sur les pins 8, 9, 10, 11 change d'état
* On lit les signaux du récepteur pour obtenir les instructions de vol
*
* La routine doit aussi rapide que possible afin de ne pas perturber le programme principal
* Le truc est d'utiliser les registres des prts du µC pour lire l'état des pins.
* Faire (PINB & B00000001) est la même chose que faire digitalRead(8), avec l'avantage d'utiliser
* moins de temps CPU.
* C'est moins clair en programmation, mais bien plus efficace !
*/
ISR(PCINT0_vect){
// Lire le temps courant
current_time = micros();
//----------- Traitement du canal 1 ------------------------------------------------------------------------
if (PINB & B00000001) { // Le Pin 8 est-il à l'état HIGH ?
if (previous_state[CHANNEL1] == LOW) { // Pin 8 est passé de 0 à 1 (front montant)
previous_state[CHANNEL1] = HIGH; // Sauvegarder l'état courant du pin 8
timer[CHANNEL1] = current_time; // Démarrer le timer
}
} else if(previous_state[CHANNEL1] == HIGH) { // Pin 8 est passé de 1 à 0 (front descendant)
previous_state[CHANNEL1] == LOW; // Sauvegarder l'état courant du pin 8
pulse_duration[CHANNEL1] = current_time - timer[CHANNEL1]; // Stop timer et calcul pulse duration
}
//----------- Traitement du canal 2 ------------------------------------------------------------------------
if (PINB & B00000010) { // Le Pin 9 est-il à l'état HIGH ?
if (previous_state[CHANNEL2] == LOW) { // Pin 9 est passé de 0 à 1 (front montant)
previous_state[CHANNEL2] = HIGH; // Sauvegarder l'état courant du pin 9
timer[CHANNEL2] = current_time; // Démarrer le timer
}
} else if(previous_state[CHANNEL2] == HIGH) { // Pin 9 est passé de 1 à 0 (front descendant)
previous_state[CHANNEL2] == LOW; // Sauvegarder l'état courant du pin 9
pulse_duration[CHANNEL2] = current_time - timer[CHANNEL2]; // Stop timer et calcul pulse duration
}
//----------- Traitement du canal 3 ------------------------------------------------------------------------
if (PINB & B00000100) { // Le Pin 10 est-il à l'état HIGH ?
if (previous_state[CHANNEL3] == LOW) { // Pin 10 est passé de 0 à 1 (front montant)
previous_state[CHANNEL3] = HIGH; // Sauvegarder l'état courant du pin 10
timer[CHANNEL3] = current_time; // Démarrer le timer
}
} else if(previous_state[CHANNEL3] == HIGH) { // Pin 10 est passé de 1 à 0 (front descendant)
previous_state[CHANNEL3] == LOW; // Sauvegarder l'état courant du pin 8
pulse_duration[CHANNEL3] = current_time - timer[CHANNEL3]; // Stop timer et calcul pulse duration
}
//----------- Traitement du canal 4 ------------------------------------------------------------------------
if (PINB & B00001000) { // Le Pin 11 est-il à l'état HIGH ?
if (previous_state[CHANNEL4] == LOW) { // Pin 11 est passé de 0 à 1 (front montant)
previous_state[CHANNEL4] = HIGH; // Sauvegarder l'état courant du pin 11
timer[CHANNEL4] = current_time; // Démarrer le timer
}
} else if(previous_state[CHANNEL4] == HIGH) { // Pin 11 est passé de 1 à 0 (front descendant)
previous_state[CHANNEL4] == LOW; // Sauvegarder l'état courant du pin 11
pulse_duration[CHANNEL4] = current_time - timer[CHANNEL4]; // Stop timer et calcul pulse duration
}
}
Le jeudi 23 septembre 2021 à 08:24:05
Salut Alain, il y a une erreur dans ton Interrupt Sub Routine, dans les else. Au lieu d'y faire une affectation avec =, tu fais une comparaison avec == :
au lieu de :
Et là ça devrait fonctionner :)
previous_state[CHANNEL4] == LOW; // Sauvegarder l'état courant du pin 11
au lieu de :
previous_state[CHANNEL4] = LOW; // Sauvegarder l'état courant du pin 11
Et là ça devrait fonctionner :)