Pages: [1]   Go Down
Author Topic: Monter une radiocommande avec arduino  (Read 1521 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 32
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Je suis débutant "débrouillé", et je voudrais utiliser un arduino Duemilanove, 1 joystick analogique, un bouton, et un ensemble de modules APC220 pour faire une radiocommande rudimentaire et communiquer avec un autre arduino.
Le but est de commander une tête robotisée pour prendre des photos.
Dans cette tête, j'ai un servo intact (pour le tilt) et un servo modifié pour une rotation 360° continue (pan).

Je ne pars pas de rien, j'ai déjà essayé une paire de code :
* côté Emetteur
Code:
#define idlezone 20
#define incmax 20
#define joymid 512
#define panspeed 40

int x=1;
int y=0;
int button_A= 5;
int button_B= 3;
int button_C= 4;
int LED=13;
int valx = 0;
int valy = 0;
byte Clicbouton = 0;
int bouton;

long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers



void setup()
{
  int i;
  for(i=3;i<=5;i++)
  pinMode(i, INPUT);
  pinMode(LED,OUTPUT);
  Serial.begin(9600);
}
void loop()
{
  int val;
  while(1)
  {
    // Lecture Joystick Tilt
    val=analogRead(x);
    if (val > joymid + idlezone){
      valx = map(val, joymid + idlezone, 1023, 0, incmax);
    }
    if (val < joymid - idlezone){
      valx = map(val, joymid - idlezone, 0, 0, incmax);
      valx = -valx;
    }
    if (val <= joymid + idlezone && val >= joymid - idlezone){
      valx = 0;
    }
    
    // Conversion Tilt en byte pour emission
    byte tilt = 50 + valx;  
    
    // Lecture Joystick Pan
    val=analogRead(y);
    if (val > joymid + idlezone){
      valy = map(val, joymid + idlezone, 1023, 0, panspeed);
    }
    if (val < joymid - idlezone){
      valy = map(val, joymid + idlezone, 0, 0, panspeed);
      valy = -valy;
    }    
    if (val >= joymid - idlezone && val <= joymid + idlezone){
      valy = 0;
    }
    
    // Conversion Pan en byte pour emission
    byte pan = 50 + valy;  
    
    // Lecture bouton 2 / déclenchement
    bouton = digitalRead(button_B);
    if(bouton == 0 && millis() - time > debounce)
     {
         Clicbouton = 10;
     }
    else Clicbouton = 0;
    
    // Envoi des données Tilt, puis Pan, puis bouton
    Serial.print(0xff, BYTE);
    Serial.print(tilt);
    Serial.print(pan);
    Serial.print(Clicbouton);    
  }
}

* côté Recepteur
Code:
#include <Servo.h>


#define servomin 1000
#define servomax 2000



#define panidle 1500
#define panspeed 20
#define Pan_pin 3
#define Tilt_pin 4
#define Clic_pin 13

int servox = 1500;
int x=1;
int y=0;
int val1;
int val2;
int val3;

int panpos = panidle;
Servo pan_servo;  // le servo PAN
Servo tilt_servo; //le servo TILT


//(¯`·.¸¸.-Déclenchement direct de l'APN Ricoh par USB-.¸¸.·´¯)
// Cette routine doit changer si on utilise un gentled ou autre...
void clicricoh(){
  digitalWrite(Clic_pin, HIGH);   // pin APN ON
  delay(30);                     // durée 30ms (half-press et focus)
  digitalWrite(Clic_pin, LOW);    // pin APN OFF
  delay(200);                    // pause
  digitalWrite(Clic_pin, HIGH);   // pin APN ON
  delay(150);                    // durée 150ms (full-press)
  digitalWrite(Clic_pin, LOW);    // pin APN OFF
  delay(100);                    // delai après photo 2s (a régler)
  digitalWrite(Clic_pin, HIGH);   // pin APN ON
  delay(30);                     // durée 30ms (release)
  digitalWrite(Clic_pin, LOW);    // pin APN OFF
  delay(30);                     // durée 30ms
  digitalWrite(Clic_pin, HIGH);   // pin APN ON
  delay(30);                     // durée 30ms
  digitalWrite(Clic_pin, LOW);    // pin APN OFF
}


void setup()
{
  pan_servo.attach(Pan_pin);                          
  tilt_servo.attach(Tilt_pin);                      
  pinMode(Clic_pin, OUTPUT);
  
  Serial.begin(9600);      
}



void loop()
{
  int val;
  while (Serial.available() >= 4) {
    if (Serial.read() == 0xff) {
       val1 = Serial.read();
       val2 = Serial.read();
       val3 = Serial.read();

    Serial.flush();

    val = val1 - 50;
    if (val > 0){  
      if (servox != servomax){
        servox = servox + val;
        if (servox > servomax) servox = servomax;
      }
     }
    if (val < 0){
      if (servox != servomin){
        servox = servox + val;
        if (servox < servomin) servox = servomin;
      }
    }  
    
    tilt_servo.writeMicroseconds(servox);
    delay (50);
    
    val = val2 - 50;
    if (val != 0){
      panpos = panidle + val;
    }
    else {
      panpos = panidle;
    }
    
    pan_servo.writeMicroseconds(panpos);
    // delay (50);
    
    if (val3 == 10){
      clicricoh();
      delay (50);
    }
   Serial.print(val1);
   Serial.print(" : ");
   Serial.print(val2);
   Serial.print(" : ");
   Serial.println(val3);
 
   }
 }
    
}


A priori ça fonctionne, mais le problème est double :
1 - j'ai un manque de réactivité (quand je relâche le joystick, j'ai les servo qui continuent un très court instant, mais l'arrêt n'est pas immédiat)
2 - quand je clique sur le bouton, au lieu d'avoir un signal de déclenchement, j'en ai systématiquement 2, et parfois j'ai une valeur de 50 qui se glisse parfois dans le flux.

Si vous avez une piste pour que j'améliore mon code, ou que je le modifie radicalement, je vous en remercie d'avance.

A+
JC
Logged

Sophia-Antipolis (06)
Offline Offline
God Member
*****
Karma: 4
Posts: 618
Rejoignez le club !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pour le bouton, c'est bien de mettre le debounce (anti-rebond) mais je ne vois pas la mise à jour de la variable time (time = millis()) ?
Logged

Sophia-Antipolis (06)
Offline Offline
God Member
*****
Karma: 4
Posts: 618
Rejoignez le club !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sinon, répartir les Serial.print au fur et à mesure de ta boucle ? Cela évitera de devoir attendre que le premier octet soit parti avant d'envoyer l'autre.

On pourrait penser sortir les déclarations de variable, mais je ne sais pas si tu gagneras beaucoup...

Quand ton projet sera bien avancé, tu es le bienvenu pour poster tes résultats sur notre site comme illustration des APC220.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 32
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oups pour la mise à jour de la variable time... Mais bon ça n'arrange pas mon bidule.

Sinon, je veux bien répartir mes Serial.print après chaque (ou avant chaque) instruction, ça peut rendre plus réactif... Mais du coup je me pose des questions :
En combien de temps peut s'exécuter ma boucle ? Est-ce qu'il est possible de réactualiser le buffer pour qu'au moment de la lecture ce soit la dernière trame qui est reçue qui est exécutée ?
Et donc finalement, est-ce que je n'ai pas un problème de synchronisation entre la périodicité d'envoi d'une trame, sa réception, et son interprétation ?

A+
JC

PS : pour les modules APC220, j'en suis plutôt content. Normalement, on branche et hop c'est comme si on avant des fils croisés entre RX et TX de chaque arduino. Personnellement, j'ai eu des soucis au début, car si les deux étaient bien réglés sur la même fréquence, il n'y avait pas de communication. J'ai du trouver un PC sous Win$$ et tatonner avec le logiciel de configuration... pour revenir au réglage initial qui a décidé de fonctionner... J'attends de faire mieux fonctionner mes deux arduinos avant de faire des tests de portée.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 32
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai suivi les conseils et ça marche un peu mieux. Par contre, j'ai encore une question... au cas où quelqu'un veuille bien y répondre :
Est-ce que ça vaut le coût que le récepteur envoie une réponse de réception de trame, ce qui synchroniserait l'envoi de la trame suivante ?

Et est-ce bien utile de tester la contenance du buffer (ici, pas de lecture tant qu'il n'y a pas 4 octets) ?

A+
JC
Logged

Pages: [1]   Go Up
Jump to: