[C] Comment écrire sur le port série (arduino) ?

Bonjour, je me suis lancé dans le développement d’un drone/quadcopter et j’aimerai pouvoir envoyer les données de mon joystick (manette de ps3 branchée à mon pc) à mon arduino. Je précise que je suis sous linux, plus précisément Debian.

En clair, j’essaye d’établir une liaison de ce type :

Pc → port série → arduino + module radio - - - - - > Arduino + module radio (quadcopter)

J’ai donc commencé par envoyer les valeurs de mon joystick à l’arduino via le serial, sans me préoccuper de la liaison radio. Mon problème est que certaines valeurs envoyées sont erronées. Exemple ici je tente d’envoyer les valeurs d’un axe de mon joystick (en le maintenant sur sa position la plus élevée (32767), et sachant que les valeurs que j’envoie sont comprises entre -32 767 et 32 767) :

Voici le code linux qui permet de récupérer les données de la manette (ce programme fonctionne parfaitement bien) et de les envoyer à l’Arduino branché au pc :

#include <stdio.h>
#ifdef __linux__
  #include <unistd.h>
  #include <fcntl.h>
  #include <termios.h>
#else
  #include <windows.h>
#endif
  
#include "libenjoy.h"
  
// This tels msvc to link agains winmm.lib. Pretty nasty though.
#pragma comment(lib, "winmm.lib")
  
int main()
{
    int fd; /* port file descriptor */
    char port[20] = "/dev/ttyUSB0"; /* port to connect to */
    speed_t baud = B115200; /* baud rate */
 
    int left_right = 0,  // Data we want to send
        back_front = 0,
        counterClockwise_clockwise = 0,
        down_up = 0,
        start = 0,
        takeoff = 0,
        land = 0; 
  
    libenjoy_context *ctx = libenjoy_init(); // initialize the library
    libenjoy_joy_info_list *info;
  
    // Updates internal list of joysticks. If you want auto-reconnect
    // after re-plugging the joystick, you should call this every 1s or so
    libenjoy_enumerate(ctx);
  
    // get list with available joysticks. structs are
    // typedef struct libenjoy_joy_info_list {
    //     uint32_t count;
    //     libenjoy_joy_info **list;
    // } libenjoy_joy_info_list;
    //
    // typedef struct libenjoy_joy_info {
    //     char *name;
    //     uint32_t id;
    //     char opened;
    // } libenjoy_joy_info;
    //
    // id is not linear (eg. you should not use vector or array),
    // and if you disconnect joystick and then plug it in again,
    // it should have the same ID
    info = libenjoy_get_info_list(ctx);
  
    if(info->count != 0) // just get the first joystick
    {
        libenjoy_joystick *joy;
        printf("Opening joystick %s...", info->list[0]->name);
        joy = libenjoy_open_joystick(ctx, info->list[0]->id);
        if(joy)
        {
            int counter = 0;
            libenjoy_event ev;
  
            printf ("\033[32mSuccess!\n\033[0m");
            printf("Press Enter to Continue");
            while(getchar() != '\n');
              
            fd = open(port, O_RDWR); /* connect to port */
            usleep(3500000); // Arduino's reboot
 
           /* set the other settings (in this case, 38400 8N1) */
            struct termios settings;
            tcgetattr(fd, &settings);
 
            cfsetospeed(&settings, baud); /* baud rate */
            settings.c_cflag &= ~PARENB; /* no parity */
            settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
            settings.c_cflag &= ~CSIZE;
            settings.c_cflag |= CS8 | CLOCAL; /* 8 bits */
            settings.c_lflag = ICANON; /* canonical mode */
            settings.c_oflag &= ~OPOST; /* raw output */
 
            tcsetattr(fd, TCSANOW, &settings); /* apply the settings */
            tcflush(fd, TCOFLUSH);
  
            while(1)
            {
                // Value data are not stored in library. if you want to use
                // them, you have to store them
  
                // That's right, only polling available
                while(libenjoy_poll(ctx, &ev))
                {
                    if(ev.type == LIBENJOY_EV_AXIS)
                    {
                        switch(ev.part_id)
                        {      
                        case 0:
                            left_right = ev.data;
                            break;
                        case 1:
                            back_front = -ev.data;
                            break;
                        case 2:
                            counterClockwise_clockwise = ev.data;
                            break;
                        case 3:
                            down_up = -ev.data;
                            break;
                        }
                    }
                      
                    if(ev.type == LIBENJOY_EV_BUTTON)
                    {
                        switch(ev.part_id)
                        {
                        case 3:
                            start = ev.data;
                            break;
                        case 12:
                            takeoff = ev.data;
                            break;
                        case 14:
                            land = ev.data;
                            break;
                        }
                    }
                      
                    //Writing to the file and separate digits
                    fprintf(fd,"%dA",down_up);
                    fprintf(fd,"%dB",counterClockwise_clockwise);
                    fprintf(fd,"%dC",back_front);
                    fprintf(fd,"%dD*",left_right);
 
                    fflush(fd);
 
                    printf("roll : %6d | pitch : %6d | yaw : %6d | throttle : %6d | start : %1d | takeoff : %1d | land %1d \n", left_right, back_front, counterClockwise_clockwise, down_up, start, takeoff, land);
                         
                }
#ifdef __linux
                usleep(50000);
#else
                Sleep(50);
#endif
                counter += 50;
                if(counter >= 1000)
                {
                    libenjoy_enumerate(ctx);
                    counter = 0;
                }
            }
  
            // Joystick is really closed in libenjoy_poll or libenjoy_close,
            // because closing it while libenjoy_poll is in process in another thread
            // could cause crash. Be sure to call libenjoy_poll(ctx, NULL); (yes,
            // you can use NULL as event) if you will not poll nor libenjoy_close
            // anytime soon.
              
            libenjoy_close_joystick(joy);
        }
        else
            printf("\033[31mFailed!\033[0m");
    }
    else
        printf("No joystick available\n");
  
    // Frees memory allocated by that joystick list. Do not forget it!
    libenjoy_free_info_list(info);
  
    // deallocates all memory used by lib. Do not forget this!
    // libenjoy_poll must not be called during or after this call
    libenjoy_close(ctx);
    
    close(fd); /* cleanup */
      
    return 0;
}

et voici le code de l’arduino connecté au pc via le serial :

http://pastebin.com/xeTTggNR

Bon j’ai testé le tout, sans la radio, à 38 400 bauds, il y avait beaucoup de valeurs erronées, puis j’ai essayé à 115 200 bauds (l’arduino était bien réglé à 115 200 aussi), il y en avait beaucoup moins, mais toujours un peu… Je ne sais pas si c’est possible de communiquer à plus de 115 200 bauds/s avec un Arduino, mais ça me semble pas très logique qu’il y ait moins d’erreurs à 115 200…

peut être qu’un autre programme envoie des données sur le port série ?

je ne sais pas si ça peut être un problème matériel :frowning:

Merci d’avance :frowning: Dites moi si je manque de précisions !

personne peut m'aider ? :(