Pages: [1] 2   Go Down
Author Topic: Signal Rx pour l'arduino  (Read 1461 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour à toutes et à tous,

Voilà, je me présente, je suis nouveau sur ce forum, je suis en classe de Terminale S SI, et j'ai donc un projet à élaborer durant toute mon année.
Je suis actuellement en charge de la partie électronique et surtout logiciel de mon projet, qui consiste à créer une fonction de parck automatique pour une voiture RC.

Je m' explique; Une rangée de voitures sont positionnées le long d'une route, et il y a une place. Je pilote donc ma voiture radiocommandé avec la radio, puis, au moment ou je vois une place, je m'arrête un peu avant, et enclenche un mode automatique, et la voiture va alors détecter si la place disponible est suffisante ou si elle ne l'est pas. Dans le second cas, elle fera clignoter une led rouge, tendit que dans le cas ou il la place est suffisante, elle entamera le séquence de parck.
Pour commander mon servo de diréction, et mon moteur, j'utilise la librairie Servo.h, pas de problème en théorie. ( oui j'ai pas entamé les tests, que je vais faire à la rentrée )

Cependant, pour capter les signaux radio, et interpréter ce que dis le Rx aux différentes entrées de la carte arduino, bah je sais vraiment pas comment faire. J'ai fouiné sur le web, partout ou je pouvais, mais je ne comprend pas bien comment faut-il faire. Je suis encore débutant dans ce domaine donc vu la compéxité de la chose,trame ppm etc..., je pensais prendre un code existant et m'en inspirer.

Voilà, j’espère avoir été asses clair, donc si quelqu'un peux me dire comment interpréter les signaux d'un Rx pour faire varier par exemple l'angle d'un servo, je vous en serai reconnaissant.

Bonne soirée,
RoToR
Logged

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Si tu débute complètement à ce niveau, il faut déjà que tu intègre bien ce qu'est un signal servo :

C'est la durée du créneau "haut" qui donnera l'angle du servo :
1ms = A fond à gauche
1.5ms = Au milieu
2ms = A fond à droite

Il se trouve sur le fil blanc de la prise servo.

Pour débuter, je te conseille d'essayer de capter les différents signaux de ton Rx à l'aide de la commande pulseIn().
Ca devrait te permettre de débuter sereinement sans trop de complexité smiley-wink

EDIT : Un vieux bout de code qui traînait...
Code:
      Ch1Pos = pulseIn(2, HIGH, 20000);
      Ch2Pos = pulseIn(3, HIGH, 20000);
      Ch3Pos = pulseIn(4, HIGH, 20000);

Ici, je mesurais 3 canaux, branché sur les PIN 2,3 & 4 de l'arduino.
La commande pulseIn me renvoyait des milli-secondes, donc le résultat devait être entre environ entre 1000 & 2000 (avec une position milieu à environ 1500)
20000 c'est le timeout de la fonction en micro-secondes, si au bout 20ms le signal n'est pas HAUT, la commande redonne la main.
« Last Edit: March 03, 2013, 06:01:30 pm by UniseV » Logged

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 !

France
Offline Offline
Faraday Member
**
Karma: 52
Posts: 5341
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Tu perdrais moins de temps à faire ta propre télécommande avec un nRF24L01, un joystick et une seconde carte arduino que d'essayer d'interpréter des signaux de contrôle dont le format t'est inconnu.

Pour la mesure de distance tu as prévu quoi comme capteurs ?
Tu doit pouvoir utiliser des capteurs infrarouge Sharp moyennant un bon positionnement dans les coins de la voiture.
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tu perdrais moins de temps à faire ta propre télécommande avec un nRF24L01, un joystick et une seconde carte arduino que d'essayer d'interpréter des signaux de contrôle dont le format t'est inconnu.

Je ne suis pas de cet avis, l'avantage des signaux servo, c'est qu'il sont standardisé et connus, on peut ainsi interfacer facilement tout équipement RC (servo, contrôleur de moteur, récepteur...).

Je pense qu'il y a moins de travail à développer un programme qui écoute et numérise les signaux, plutôt que de concevoir la liaison dans sa globalité.

La librairie servo est un exemple d'interfaçage standard, et elle suffit dans bien des cas.

EDIT :  En revanche, je suis le premier à dire qu'il faudra changer ce standard qui commence à être dépassé  smiley-wink
« Last Edit: March 05, 2013, 04:51:12 am by UniseV » Logged

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 !

France
Offline Offline
Faraday Member
**
Karma: 52
Posts: 5341
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Je ne suis pas de cet avis, l'avantage des signeaux servo, c'est qu'il sont standardisé et connus, on peut ainsi interfacer facilement tout équipement RC (servo, controleur de moteur, récepteur...).
Est-ce qu'il est sûr que sa télécommande sort un signal RC "standard" ?
Si oui d'accord c'est la meilleur solution, sinon faut connaitre la forme du signal et voir comment il réagit.

Si c'est une voiture RC "grand publique" ya des chances que le contrôleur soit un truc made in chinois avec un circuit de sonnette de porte smiley-roll
(oui ça sent le vécu)
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bien vu Skywodd, il risque d'y avoir du retro-ingeneering.  smiley-cool

RoToRx88 : C'est quoi ta voiture RC ?
Logged

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 !

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wouah !
Alors euh, bonsoir tout le monde!

Merci bien pour toutes vos réponses aussi sympas les unes que les autres !
Merci à toi UniseV pour ton mini tuto.

Donc, ce que tu m'a montré et expliqué UniseV, je l'avais plus ou moins deviné les de mes tests, car c'était aproximativement les mêmes valeurs sur l'oscilloscope quand je le branchais sur un pin signal de mon Rx.

J'ai utilisé ton bout de code, et je m'en suis servi / adapté pour me faire un propre code qui lis donc 4 entrées de ma carte arduino Uno, et fais varier 4 servos en fonction. Tout marche relativement bien, puisqu'en effet, mes servos ont la tremblote ! Et je ne savais pas pourquoi, donc je me suis dis que j'allais afficher chaque valeur brute reçu lue par les entrées, dans le moniteur serial. Chose faite, j'ai un signal tout sale !

Voilà déjà mon code:
Code:
#include <Servo.h>


const int ch1 = A0, ch2 = A1, ch3 = A2, ch4 = A3;
Servo servoRouge1;
Servo servoRouge2;
Servo servoNoirPetit;
Servo servoNoirGros;


void setup()
{
  servoRouge1.attach(9);
  servoRouge2.attach(10);
  servoNoirPetit.attach(11);
  servoNoirGros.attach(6);
  pinMode(ch1, INPUT);
  pinMode(ch2, INPUT);
  pinMode(ch3, INPUT);
  pinMode(ch4, INPUT);
  Serial.begin(9600);
}


void loop()
{
  int posCh1 = pulseIn(ch1, HIGH, 20000);
  int posCh2 = pulseIn(ch2, HIGH, 20000);
  int posCh3 = pulseIn(ch3, HIGH, 20000);
  int posCh4 = pulseIn(ch4, HIGH, 20000);
 
  int posServoRouge1 = map(posCh1, 1000, 2000, 0, 180);
  int posServoRouge2 = map(posCh2, 1000, 2000, 0, 180);
  int posServoNoirPetit = map(posCh3, 1000, 2000, 0, 180);
  int posServoNoirGros = map(posCh4, 1000, 2000, 0, 180);
 
  servoRouge2.write(posServoRouge2);
  servoRouge1.write(posServoRouge1);
  servoNoirPetit.write(posServoNoirPetit);
  servoNoirGros.write(posServoNoirGros);

 
 affichage(posCh1,posCh2,posCh3,posCh4);
}



int affichage(int posCh1, int posCh2, int posCh3, int posCh4)
{
  Serial.print("Ch1: ");
  Serial.print(posCh1);
  Serial.print(" Ch2: ");
  Serial.print(posCh2);
  Serial.print(" Ch3: ");
  Serial.print(posCh3);
  Serial.print(" Ch4: ");
  Serial.println(posCh4);
  return 0;
}

Il ne doit surement pas être parfait, loin de la, mais il à déjà le mérite d'éxister...
Et voilà les valeurs des entrées: ( lien copié collé car prend trop de place dans le message )
http://www.heypasteit.com/clip/0PW6

Et à des moments, ca redeviens '' propre '' et les servos n'ont plus la tremblote: ( idem pour le lien

http://www.heypasteit.com/clip/0PW8

Alors je vois pas de quoi cela peut venir... Surtout que cette radio, c'est la miène perso, que j'utilise pour mon quadricopter, et elle est nikel, aucun soucis !
J'attend de voir à la rentrée, avec le matos du lycée ce que celà donne.

Et tu vois skywodd, j'ai mis moins de temps que ce que tu pensais non ? ( enfin c'est une ébauche on est d'accord, c'est pas fini, mais sur le principe, ca fonctionne ! )
Sinon pour les capteurs, oui tu as raison, on utilise un sharp 2Y0A02 et deux sharp 2Y0D21.
Ducoup, vu les mesures faites en cours à l'oscillo, ca a l'air d'être une radio RC standard donc avec le même signal que celle que j'ai pour mon quadricopter.
Pour info c'est une turnigy ch9x:  http://www.hobbyking.com/hobbyking/store/__8991__Turnigy_9X_9Ch_Transmitter_w_Module_8ch_Receiver_Mode_1_v2_Firmware_.html

Voilà, je crois avoir fait le tour de tout ce que j'ai fais depuis ses deux jours,
Alors si vous avez besoins d'autres infos, je suis open ! Ca commence a fonctionner, ca fais plaisir !

PS: Quand à la ref. exacte de la voiture et de la radio du lycée, bah ca sera à la rentrée, car je les aient pas pris pour les vacances !

Bonne soirée,
RoToR
Logged

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tu devrais lire ça :
http://www.rcgroups.com/forums/showthread.php?t=1648040

Je pense qu'à 6 mois d'écart on fait exactement la même chose.

Si tu as réussi a capter et générer des signaux servo c'est déjà un très bon début.

La première amélioration que tu peux apporter, c'est de te débarrasser des pulseIn maintenant que tu as compris et appliqué le principe général.
La commande pulseIn bloque ton code pendant qu'elle "écoute" les signaux haut... c'est donc 4ms à 8ms qui partent à la poubelle toute les 22.5ms et en plus de ça, elle est assez imprécise et peut perturber le fonctionnement de la librairie Servo.

L'idée c'est d'utiliser les interruptions de l'ATmega328P, il est très puissant et très intéressant à ce niveau-là.

De mon côté je m'étais inspiré du travail de Duane B :
http://rcarduino.blogspot.fr/2012/01/how-to-read-rc-receiver-with.html
Et j'aivais fait ça :
http://www.rcgroups.com/forums/showpost.php?p=21863238&postcount=16
Attention, c'est une usine à GAZ qui est optimisée pour utiliser les plus petites interruptions possibles et qui détecte automatiquement l'ordre des canaux de ton Rx, avec Turnigy ça devrait fonctionner  smiley-wink

EDIT : J'utilise la même radio que toi, mais avec le récepteur 6 voies, car il crache du PPM sur la prise BAT.
« Last Edit: March 06, 2013, 06:16:48 pm by UniseV » Logged

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 !

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Quand tu dis
Quote
L'idée c'est d'utiliser les interruptions de l'ATmega328P, il est très puissant et très intéressant à ce niveau-là.
ca veux dire quoi ? J'y comprend rien, je suis allé voir les différents liens que tu as donné, mais je comprend pas grand chose smiley-sad Parce que à la limite si j'ai 8ms qui passent à la trappe, c'est pas bien grave si ? J'ai pas besoin d'un temps de réaction ultra rapide. Juste éviter que mes servos dansent dans tout les sens sans que je touche à quoi que ce soit ! Ducoup je pensais mettre un condo entre chaque sorties de mon Rx et les entrées de la carte arduino, mais ca va filter que si les valeurs décroissent, mais pas si elles augmentent... Donc j'me suis dis, je vais faire une boucle pour chaque voix, qui vérifie si il y a une variation de 10 ou 20, et ne fais aucun changement de variable, mais si on à une valeurs supérieur à 100, alors la on change pour donner un nouvel angle. Vous en pensez quoi ?

Parce que c'est dingue comme il peut y avoir des fluctuations sans raison... Je vois pas de quoi ca peut venir !

Bonne journée,
RoToR
Logged

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Les jitters viennent de plusieurs facteurs :
Certain sont en entrée à cause la commande PulseIn()
D'autre sont en sortie à cause de la librairie Servo.

Tu peux les filtrer grossièrement, ça dépend de la valeur de ton écart, personnelement je le fais pour des écarts de 2/3µs max.

Pour faire simple au sujet des interruptions :
Un interruption c'est un évènement qui déclenche une "pause" dans ta loop().
Par exemple, un évènement d'interruption pourrait être : quand le PIN8 passe de LOW à HIGH.
Après hors de ta boucle, tu écris un code (un peu comme une fonction) qui sera joué à chaque fois que l'évènement intervient.

Quand le code d'interruption a terminé d'être joué, l'Arduino va retourner dans la loop() et revenir exactement là ou il en était.

C'est un peu la base du multi-tâches.

EDIT : J'utilisais la librairie suivante :
http://code.google.com/p/arduino-pinchangeint/downloads/detail?name=pinchangeint-v1.72.zip&can=2&q=

Voici un exemple plutôt simple qui vient avec :
Code:
#include <PinChangeInt.h>

#define PIN1 2
#define PIN2 3
#define PIN3 4

uint8_t latest_interrupted_pin;
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins

void quicfunc() {
  latest_interrupted_pin=PCintPort::arduinoPin;
  interrupt_count[latest_interrupted_pin]++;
};

void pin3func() {
  Serial.print("Pin "); Serial.print(PIN3, DEC); Serial.println("!");
}

void setup() {
  pinMode(PIN1, INPUT); digitalWrite(PIN1, HIGH);
  PCintPort::attachInterrupt(PIN1, &quicfunc, FALLING);  // add more attachInterrupt code as required
  pinMode(PIN2, INPUT); digitalWrite(PIN2, HIGH);
  PCintPort::attachInterrupt(PIN2, &quicfunc, FALLING);
  pinMode(PIN3, INPUT); digitalWrite(PIN3, HIGH);
  PCintPort::attachInterrupt(PIN3, &pin3func, CHANGE);
  Serial.begin(115200);
  Serial.println("---------------------------------------");
}

uint8_t i;
void loop() {
  uint8_t count;
  Serial.print(".");
  delay(1000);
  for (i=0; i < 20; i++) {
    if (interrupt_count[i] != 0) {
      count=interrupt_count[i];
      interrupt_count[i]=0;
      Serial.print("Count for pin ");
      if (i < 14) {
        Serial.print("D");
        Serial.print(i, DEC);
      } else {
        Serial.print("A");
        Serial.print(i-14, DEC);
      }
      Serial.print(" is ");
      Serial.println(count, DEC);
    }
  }
}
« Last Edit: March 09, 2013, 04:48:55 am by UniseV » Logged

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 !

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour !

Bon mon code est, même amélioré, catastrophique... Ducoup j'ai essayé de comprendre le tiens, mais je n'y arrive pas smiley-sad
En plus, quand je compile, en aillant mis dans mon dossier librairies la librairie que tu m'a donné, il plante à cette ligne
Code:
  latest_interrupted_pin=PCintPort::arduinoPin;
Je vois pas a quoi cela peut correspondre donc j'ai du mal à essayer de debuger le chmilblik !

Et... Je croyais que l'arduino n'est pas multi-tâches, mais mono tâche... smiley-sad J'suis perdu la, si vous pouviez éclairer ma lanterne ! smiley-wink

Oh et dernière chose, mon Rx au lycée fontionne comme le miens, donc c'est bien du vrai matos RC avec un PPM et non pas une sonnerie de porte !

Bonne journée,
RoToR
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hello,

une interruption porte bien son nom. Elle interrompt le déroulement "normal" du programme lorsque le besoin intervient.
Par exemple lorsque tu veux gérer un bouton. Dans un déroulement normal tu va coder la détection de l'appui sur le bouton avec des boucles et/ou des conditions. quelque chose du genre :

Code:
loop() {
...
si (bouton appuyé) alors allumer la led;
...
}

Dans cet exemple, le test se fait à chaque cycle : à chaque boucle.

Dans le cas des interruptions, le programme déroule le code tant qu'un évènement n'intervient pas. si l'évènement intervient, on arrête le déroulement du programme, on exécute le code à exécuter lorsque cet évènement est détecté, puis on retourne là ou le programme s'était arrêté.

Code:
loop() {
...
...
}

interruption1() {
allumer la led;
}

En clair : en temps normal on teste si un évènement se produit et dans le cas positif on déclenche une action. Dans le cas des interruptions c'est l'apparition de l'évènement en lui même qui déclenche l'action.
Logged

Paris
Offline Offline
Sr. Member
****
Karma: 1
Posts: 366
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour !

Bon mon code est, même amélioré, catastrophique... Ducoup j'ai essayé de comprendre le tiens, mais je n'y arrive pas smiley-sad
En plus, quand je compile, en aillant mis dans mon dossier librairies la librairie que tu m'a donné, il plante à cette ligne
Code:
  latest_interrupted_pin=PCintPort::arduinoPin;
Je vois pas a quoi cela peut correspondre donc j'ai du mal à essayer de debuger le chmilblik !
Je te confirme qu'il ne trouve pas la librairie PinChangeInt, si elle est correctement installée, tu dois avoir le fichier suivant dans ton répertoire Arduino :

arduino-1.0.3\libraries\PinChangeInt\PinChangeInt.h

Sinon il faut que tu télécharge le fichier de mon message précédent et que tu installe correctement la librairie  smiley-wink

Et... Je croyais que l'arduino n'est pas multi-tâches, mais mono tâche... smiley-sad J'suis perdu la, si vous pouviez éclairer ma lanterne ! smiley-wink

Il est mono-tâche, car il ne va faire qu'une seule chose à la fois.
Mais il est multi-tâche car il est capable d'arrêter ce qu'il est en train de faire pour traiter une interruption et revenir ensuite sur son travail en cours  smiley-wink

Oh et dernière chose, mon Rx au lycée fontionne comme le miens, donc c'est bien du vrai matos RC avec un PPM et non pas une sonnerie de porte !
Rappel :
PPM : tout les signaux sur un seul fil
A mon avis tu voulais dire "PWM servo"  smiley-wink
Logged

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 !

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey la compagnie !

Excusez du retard j'ai pas mal été occupé ces derniers temps !
Bon ca a avancé un chouilla mon histoire ! Et ca marche pas trop mal en plus ! héhé   smiley-lol
Bref donc enfait, sur mon Rx, j'avais relié qu'une seule broche du Rx à l'alim et à la masse, et je ne connectais à mon arduino uniquement le broche Rx du signal... ( oui on je fais comme ca avec mon quadricopter et ca marche bien )
Mais la était mon erreur ! J'ai essayé de relier toutes les masses du Rx avec celle de l'arduino... Et la miracle !!!! Ca fonctionne, plus aucune interférences smiley-grin

Sinon je voudrai revenir sur ton histoire d'interruptions matérielle UniseV !
Je vois pas la différence entre exécuter un code d'un coup ou alors de le stopper pour aller chercher ce code dans un autre fichier... Quelle est la différence, on perd toujours autant de temps, car les actions de lecture avec pulseIn() ne se font toujours pas de façon simultanée ?! Donc si tu pouvais éclairer ma lanterne parce que la je vois pas la différence smiley-sad

J'ai projet cet aprèm en cours, je vous tiens au courent ce soir des améliorations !

Bonne journée,
RoToR
Logged

Ales
Offline Offline
Faraday Member
**
Karma: 29
Posts: 3174
Do or DIY
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Parce que tu veux utiliser pulseIn() ... Si tu utilises des interruptions à la place de pulseIn() les temps seront considérablement réduits. Principe :
- Première interruption : enregistrement de micros() dans une variable Temps1
- Sortie d’interruption le code reprend la où il s'était arrêté et suit son cours normal
- Deuxième interruption : nouvel enregistrement de micros() dans une variable Temps2 et levée d'un drapeau Flag.
- Sortie d’interruption le code reprend la où il s'était arrêté et suit son cours normal.
- Dans ton code il y a un if(Flag==True) { CalculPulse() } qui fait le calcul Temps2-Temps1

Voila, pas de temps mort smiley-wink
Logged


Pages: [1] 2   Go Up
Jump to: