lundi 21 juillet 2014

Junix

Bonjour à tous. Un petit article pour vous présenter le projet que j'ai mené lors de mon stage de fin d'étude et cette année au sein de la société Zig Zag Production.

J'ai développé avec l'aide d'un collègue un robot mobile Wifi pour faire de l'animation live.

Sans plus attendre, voici une photo :


Il a été réalisé entièrement au sein de l'atelier. C'est un robot mobile dédié à l'animation en temps réel. Il est télécommandé par un comédien déporté qui :
  • peut entendre et voir au travers de Junix ;
  • parler au travers de Junix avec un vocodeur ;
  • bien entendu, le déplacer grâce à ces deux chenilles motrices ;
  • bouger la tête de Junix suivant deux axes ;
  • lever / descendre la tête ;
  • et changer le style des yeux !
Voici une vidéo ou l'on voit Junix déambuler :




Maintenant je vais détailler son fonctionnement interne car je suppose que c'est ce qui vous intéresse. 

Voici un schéma bloc de l'architecture actuelle de Junix :



Petite précision : Les liaisons vidéo et audio sont indépendantes de ce système, elles sont gérées par des modules HF. 

Le Raspberry Pi gère l'interface Wifi et contrôle les actionneurs de Junix. Le système est découpé en modules I2C :
  • Un module qui sert à étendre le port d'entrée/sortie du Raspberry Pi ;
  • Un module contrôleur pour le vérin électrique de la tête ;
  • Un module qui gère les divers éléments de la tête.
Au niveau logiciel, j'ai développé un serveur UDP en C++ pour le Raspberry Pi qui écoute les ordres émis par le client. Ce serveur pilote les composants I2C du robot.

Quant au client, il a été développé en Java est se présente sous cette forme : 





C'était un rapide aperçu de la partie logiciel / électronique de Junix. Je vais vous présenter maintenant la CAO du robot. La plupart des pièces ont été imprimés avec une imprimante 3D Makerbot.

On commence par une vue éclatée :


La base mobile est constituée de 4 flasques en alu montées avec des entretoises en profilé alu également. Les chenilles sont amorties avec des silentbloc. On peut voir les 4 batteries lithium-ions qui aliment le tout.

Détails de la tête :



Il y a principalement des pièces imprimées. Les servomoteurs utilisées sont des Dynamixel Rx 28, ils offrent une fluidité de mouvement exceptionnelle. 

C'est tout pour le moment, et surtout, n’hésitez pas à poser des questions.




jeudi 23 janvier 2014

Suite fraiseuse CNC


Voici la la nouvelle 3D de ma fraiseuse, avec l'intégration des moteurs :



J'avais parlé de faire mes contrôleurs de moteur PAP mais finalement j'ai trouvé un kit sur Ebay (parmi les nombreux disponibles) avec les moteurs + les contrôleurs + les alimentations pour pas trop cher. Voici à quoi ressemble le kit :


lundi 2 septembre 2013

Contrôle d'un moteur pas à pas

Bonjour à tous,
Au début de mon projet de CNC, j'avais parlé d'acheter mes contrôleurs de moteur pas à pas sur internet. J'ai cependant changé d'avis et je vais plutôt les réaliser moi même car cela est plus intéressant et moins cher.

Pour cela j'ai utilisé le composant TB6600HG qui est un driver de moteur pas à pas et qui possède les caractéristiques suivantes :

  • Mode pas entier, demi-pas, 1/4, 1/8, 1/16
  • Tension d'alimentation maximale de 50 V
  • Courant maximal par phase 4.5 A

dimanche 5 mai 2013

Un programme plus simple pour contrôler l'axe d'imprimanrte

J'ai trouvé beaucoup plus simple que mon post précédent pour contrôler l'axe d'imprimante. J'utilise pour cela deux bibliothèques : Encoder et PID.

Le programme ci-dessous fait bouger l'axe de gauche à droite :


/*
* Contrôle d'un axe d'imprimante en utilisant les bibliothèques
* Encoder et Pid
*
*/


#include <Encoder.h>
#include <PID_v1.h>

const int pin_channelA = 2;  // codeur optique
const int pin_channelB = 3;  // codeur optique
const int pin_t1 = 10;       // moteur, pont en H
const int pin_t2 = 9;        // moteur, pont en H
double Setpoint, Input, Output;

Encoder encoder(pin_channelA, pin_channelB);
PID myPID(&Input, &Output, &Setpoint, 6.4, 0.32, 0.00064, DIRECT);

unsigned long time;
unsigned long last_time = 0;
int cons = 1;
int val = 1;

void setup() {
  myPID.SetMode(AUTOMATIC);  // demarrer Pid
  pinMode(pin_t1, OUTPUT);
  pinMode(pin_t2, OUTPUT);
  myPID.SetSampleTime(1);
  myPID.SetOutputLimits(-255, 255);
  Output = 0;
}

void loop() {
  Input = encoder.read() + cons;  // En entrée du Pid : valeur du codeur + consigne
  myPID.Compute();
  if (Output > 0) {  // sens avant
    analogWrite(pin_t1, Output);
    digitalWrite(pin_t2, LOW);
  }
  else if (Output < 0){  // sens arrière
    analogWrite(pin_t2, -Output);
    digitalWrite(pin_t1, LOW);
  }
  else {  // arrêt
    digitalWrite(pin_t1, LOW);
    digitalWrite(pin_t2, LOW);
  }

  // on incrémente ou décremente la consigne toute les 2 ms
  time = millis();
  if (time-last_time > 2) {
    cons+=val;
    if (cons>500)
      val=-1;
    if (cons==0)
      val = 1;
    last_time = time;
  }
}

vendredi 21 décembre 2012

lundi 26 novembre 2012

Commande des pièces

J'ai bien avancé ces derniers temps, j'ai commandé et reçu les pièces pour construire la structure et les guidages :

Les éléments de guidage viennent de chez "linearmotionbearings2008" sur Ebay. La qualité est bonne dans l'ensemble, certaines pièces ont un peu de rouille.
Voici les tubes en acier commandés chez "leboutte" en Belgique. Les prix sont très correct.


J'ai aussi reçu les tôles métalliques commandées chez "lametallerie" mais je n'ai pas fait encore de photo.
Vous pouvez trouver un récapitulatif des pièces que j'utilise dans mes documents Google sous le nom "Liste pièces".

jeudi 1 novembre 2012

Modélisation CNC finale

Voici la modélisation de ma CNC dans sa version finale :
J'ai simplifié la structure au maximum. Toutes les pièces utilisées sont issues des fournisseurs suivants :

  • linearmotionbearings2008 sur Ebay pour les éléments de guidage et d'entrainement;
  • leboutte.fr pour les tubes en acier;
  • cnc-plus.de pour la tête de fraisage et son support;
  • je ne sais pas encore pour les moteurs.

J'ai mis ma modélisation à votre disposition sur mon Google Document. Vous pouvez y accéder en cliquant sur l'onglet "Documents" de mon blog.

mardi 16 octobre 2012

2ème modélisation

Je continue mes recherches sur la conception de ma CNC. J'ai largement réduit la hauteur du portique afin de diminuer les moments crées lors de l'usinage sur les glissières. 


De plus, j'ai commencé à regarder du coté de la commande. Il existe de nombreux kits avec des moteurs pas à pas, le driver pour les contrôler et l'alimentation. Je pense me tourner vers ce genre de solution qu'on peut trouver facilement sur Ebay.

vendredi 21 septembre 2012

Fraiseuse : 1ere modélisation

Voici une première vue Solidworks de à quoi pourrait ressembler la fraiseuse :
Pour les éléments de guidage linéaire, je me suis basé sur les pièces de la boutique Ebay "linearmotionbearings2008". D'après les avis trouvés sur le net le rapport qualité/prix est plutôt bon pour les vis à billes et les rails. Les dimensions des tubes rectangulaires en acier proviennent du site Leboutte, le support de moteur de broche de CNC-Plus.
J'ai choisi d'utiliser des vis à billes car le jeu est très faible par rapport à un entrainement pignon-courroie ou vis-écrou. De plus avec un entrainement pignon-courroie ou vis-écrou, il faudrait prévoir un système de rattrapage de jeu et un réducteur pour le moteur. Donc je pense que niveau prix on s'y retrouve au final...
Cette modélisation est loin d'être la machine finale, elle sert juste à me faire réfléchir sur l'agencement des composants et la rigidité de la structure. Plusieurs autres modélisations vont suivre.

mardi 18 septembre 2012

Construction d'une mini fraiseuse

Pour commencer cette nouvelle année scolaire en beauté et comme j'ai pas mal de temps libre, j'ai décidé de m'attaquer à un projet de construction d'une mini fraiseuse amateur. Ce genre de fraiseuse est plus communément appelé CNC (machine à commande numérique). Si vous me demandez pourquoi je souhaite construire une fraiseuse, je vous réponds que c'est une bonne façon de relier ma passion pour le maquettiste et la robotique. En effet avec cette mini fraiseuse je pourrai usiner des pièces en polystyrène ou en bois afin de compléter mes maquettes.

J'ai passé de nombreuses heures à naviguer sur le web afin de voir ce qui se faisait et repérer les difficultés rencontrées par les autres amateurs. Les sites "Usinages", "CNCLoisirs" et "CNCZone" m'ont été d'une grande aide.

Mes attentes concernant ma machine sont les suivantes :
  • 3 axes
  • espace de travail d'environ 350x350x40
  • vitesse d'avance : pas d'importance pour moi sans tomber dans l’excès
  • matière usinable : principalement des matériaux mous mais aussi de l'aluminium 
  • précision de l'usinage : inférieure à 1/10 de mm
  • encombrement : pas de contrainte
  • poids : portable par deux êtres humains 
  • prix : bien évidement le moins cher possible sans négliger les performances
J'ai dressé une liste des fournisseurs susceptibles de m'intéresser en fonction de leurs prix et de leurs pays afin de ne pas payer des frais de transports trop important. Voici la liste. Cela m'a permis de commencer à réfléchir sur les pièces que je vais utiliser en faisant des modélisations sur Solidworks. Donc dans le prochain post qui va arriver bientôt, je mettrai des images des premières vues Solidworks et j'expliquerai mes premiers choix concernant les pièces.

mardi 14 juin 2011

FOX Board : I2C

Pour utiliser l'I2C sur la Foxboard assurez-vous d'avoir la dernière version du noyau linux.
On va accéder aux périphériques I2C via l'interface /dev. Il faut d’abord charger le module i2c-dev.

Chaque périphérique I2C est assigné à un nombre entre 0 et 255 (je l’appellerai n dans la suite). Pour voir la liste des périphériques I2C installer "i2c-tools" et tapez la commande "i2cdetect -l":
debarm:~# apt-get install i2c-tools
debarm:~# i2cdetect -l
i2c-0   i2c             i2c-gpio-1                              I2C adapter


Les périphériques I2C sont représentés par des fichiers de périphérique en mode caractère avec 89 comme numéro majeur et n comme numéro mineur. On peut les trouver dans /dev.
Ils doivent être nommés "i2c-n". On peut en créer un manuellement :
debarm:~# mknod /dev/i2c-0 c 89 0

Pour travailler avec l'I2C il faut inclure la bibliothèque "linex/i2c-dev.h"  distribuée avec i2c-tools.

Voici une classe qui permet d'utiliser facilement l'I2C sur la fox, il faut lui donner l'adresse du périphérique et le numéro du périphérique (n). Si le fichier /dev/i2c-n n’existe pas, il est automatiquement créé.


I2C_Device.h :
/*
 * I2C_Device.h
 *
 *  Created on: 14 juin 2011
 *      Author: Eliott
 */

#ifndef I2C_DEVICE_H_
#define I2C_DEVICE_H_

#include "linux/i2c-dev.h" // a copier de la fox : /usr/include/linux et aussi types.h
#include <sys/ioctl.h>
#include <iostream>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>

using namespace std;

class I2C_Device {
public:
    I2C_Device(unsigned char slave_adress,int numero_device);
    ~I2C_Device();

protected :
    void writeNBytes(char bytes[],int n);
    void readNBytes( char bytes[],int n);

private :
    int device;
};

#endif /* I2C_DEVICE_H_ */


I2C_Device.cpp :
#include "I2C_Device.h"



I2C_Device::I2C_Device(unsigned char slave_adress,int numero_device) {
    char filename[20];
    sprintf(filename,"/dev/i2c-%d",numero_device);
    device = open(filename, O_RDWR);
    if (device < 0) { // si le fichier device n'existe pas
        cout<<"ERROR : "<<filename<<" n'existe pas, creation..."<<endl;
        char commande[40];
        sprintf(commande,"mknod /dev/i2c-%d c 89 0",numero_device);
        system(commande); // on le creer avec mknod
        usleep(1000);
        device = open(filename, O_RDWR);
        if (device < 0) { // on l'ouvre et c'est bon
            cout<<"ERROR : open"<<endl;
            exit(1);
        }
    }

    if (ioctl(device, I2C_SLAVE, slave_adress) < 0) {
        cout<<"ERROR : ioctl"<<endl;
        exit(1);
    }
}
//***********************************************************************

I2C_Device::~I2C_Device() {
    close(device);
}
//***********************************************************************
void I2C_Device::writeNBytes(char bytes[],int n){
    if (write(device, bytes, n) !=n) {
        cout<<"ERROR : write"<<endl;
    }
}
//***********************************************************************
void I2C_Device::readNBytes(char bytes[],int n){
    if ((read(device,bytes,n))!=n) {
        cout<<"ERROR : read"<<endl;
    }
}

lundi 13 juin 2011

FOX Board : Timer

J'ai eu besoin d'une classe gérant un timer sur la FOXBoard pour faire des lectures périodiques d'un gyroscope.
J'ai utilisé la fonction gettimeofday() de /sys/time.h qui a une precision supérieure à clock().
On peut définir une fonction à appeler périodiquement. Elle doit être du type : void fonction(void* data)

Cette classe utilise la bibliothèque pthread qui est normalement déjà installé sur la Fox. Il faut juste signaler à Eclipse qu'on l'utilise : Project->Properties->C/C++ General->Path and Symbols->Librairies->Add "pthread"

Timer.h :
/*
 * Timer.h
 *
 *  Created on: 12 juin 2011
 *      Author: Eliott
 */

#ifndef TIMER_H_
#define TIMER_H_

#include <sys/time.h>
#include <iostream>
#include "pthread.h"

class Timer {
public:

    Timer(int wait); // wait en ms

    void setCall(void(*fonction)(void*),void* arg); // fonction à appeler périodiquement
    void start();
    void stop();

private :
    static void* callRun(void* data);
    void run();

    int wait;
    void(*fonction)(void*);
    void* arg;
    struct timeval start_t, end_t;
    pthread_t thread;
};

#endif /* TIMER_H_ */


Timer.cpp :
#include "Timer.h"


Timer::Timer(int wait) {
    this->wait=wait;
    thread=0;
}
//****************************************************************************
void Timer::setCall(void(*fonction)(void*),void* arg){
    this->fonction = fonction;
    this->arg =arg;
}
//****************************************************************************
void Timer::start(){
    if(thread==0)
        pthread_create(&thread,NULL,callRun,this);
}
//****************************************************************************
void* Timer::callRun(void* data){
    Timer *t = reinterpret_cast<Timer*>(data);
    t->run();
    return NULL;
}
//****************************************************************************
void Timer::stop(){
    if(thread!=0){
        pthread_cancel(thread);
        thread=0;
    }
}
//****************************************************************************
void Timer::run(){
    double temps;
    while(1){
        gettimeofday(&start_t, NULL); // Récupération temps début
        if(fonction!=NULL) fonction(arg); // appel de la fonction définie par setCall
        temps=0;
        while(temps<wait){
            gettimeofday(&end_t, NULL); // Récupération temps fin
            temps = (end_t.tv_usec-start_t.tv_usec+2)/1000;
            temps += (end_t.tv_sec-start_t.tv_sec)*1000;
        }
    }
}


Voici un main d'exemple qui affiche un compteur toute les 10 ms pendant 30 secondes.
On doit donc avoir 3000 affichages à la fin.
main.cpp :
#include "Timer.h"
#include <iostream>
using namespace std;

// afficher le compteur et l'incrementer
void afficher(void *data){
 cout<<(*(int*)data)++<<endl;
}


int main(void) {
 int compteur = 0;
 Timer timer(10);
 timer.setCall(afficher,&compteur);

 timer.start();
 sleep(30);
 timer.stop();

 return 0;
}

vendredi 10 juin 2011

FOX Board G20 en C++ : Entrées numériques

Je continue avec une classe pour les entrées numériques.
Même principe que précédemment : on écrit "in" dans le fichier direction et on lit le fichier value.  


DigitalInput.h :
/*
 * DigitalOutput.h
 *
 *  Created on: 6 juin 2011
 *      Author: Eliott
 */

#ifndef DIGITALOUTPUT_H_
#define DIGITALOUTPUT_H_

#include <fstream>
#include <iostream>
#include <sstream>

using namespace std;

class DigitalOutput {
public:
    DigitalOutput(int pin);

    void write(unsigned int value);
    void toggle();

private:
    int pin;
    int etat;
    string racine;
};

#endif /* DIGITALOUTPUT_H_ */

DigitalInput.cpp :
#include "DigitalInput.h"

DigitalInput::DigitalInput(int pin) {
    FILE *file=NULL;

    this->pin = pin;
    file = fopen("/sys/class/gpio/export","a");
    if (file==NULL){
        cout << "Erreur ouverture fichier : /sys/class/gpio/export"<<endl;
        return;
    }
    fprintf(file,"%d",this->pin);   // on exporte la pin
    fclose(file);

    // nom de la racine du nouveau fichier
    ostringstream ss;
    ss << this->pin;
    this->racine = "/sys/class/gpio/gpio" + ss.str() ;
    this->racine += "/";

    // direction du port
    file = fopen((this->racine + "direction").c_str(),"w+");
    if (file==NULL){
        cout << "Erreur ouverture fichier : "<<this->racine + "direction"<<endl;
        return;
    }
    fprintf(file,"in");
    fclose(file);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
unsigned int DigitalInput::read(){
    FILE *file=NULL;

    file = fopen((this->racine+"value").c_str(),"r");
    if(file==NULL){
        cout<<"Erreur ouverture fichier : "<<this->racine + "value"<<endl;
        return 0;
    }
    fscanf(file,"%d",&this->etat);

    fclose(file);

    return this->etat;
}







Exemple : !bouton sur PB18 et bouton sur PB19

main.cpp :
#include "DigitalInput.h"
#include "DigitalOutput.h"
#include "Foxboard.h"

int main(void) {
    DigitalOutput led1(foxboard::PB18), led2(foxboard::PB19);
    DigitalInput bouton(foxboard::PB0);
    unsigned int value;

    while(true){
        value = bouton.read();
        led1.write(!value);
        led2.write(value);
    }

    return 0;
}

FOX Board G20 en C++ : Sorties numériques

On va commencer par la class DigitalOutput pour manipuler une sortie en mode numérique.
Pour pouvoir utiliser une patte il faut d'abord l'exporter en écrivant son identifiant dans le fichier /sys/class/gpio/export.

Un nouveau dossier est créé : /sys/class/gpio/gpio"identifiant"
On utilise ensuite les fichiers direction pour définir le sens de la patte (out ou in) et value pour définir la valeur de la patte (0 ou 1).

Voici les identifiants des différentes E/S regroupés dans un espace de nom :



foxboard.h :
#ifndef FOXBOARD_H_
#define FOXBOARD_H_

namespace foxboard {
    static const int PB18 = 82;
    static const int PB19 = 83;
    static const int PB16 = 80;
    static const int PB17 = 81;
    static const int PB2 = 66;
    static const int PB3 = 67;
    static const int PB0 = 64;
    static const int PB1 = 65;
    static const int PC14 = 110;
    static const int PC15 = 111;
    static const int PC12 = 108;
    static const int PC13 = 109;
    static const int PC9 = 105;
    static const int PC10 = 106;
    static const int PC7 = 103;
    static const int PC8 = 104;
    static const int PC5 = 101;
    static const int PC6 = 102;
    static const int PB9 = 73;
    static const int PB8 = 72;
    static const int PB23 = 87;
    static const int PB22 = 86;
    static const int PB25 = 89;
    static const int PB24 = 88;
    static const int PA28 = 60;
    static const int PA27 = 59;
    static const int PA26 = 58;
    static const int PA25 = 57;
    static const int PB28 = 92;
    static const int PB7 = 71;
    static const int PB6 = 70;
    static const int PB29 = 93;
    static const int PB26 = 90;
    static const int PB5 = 69;
    static const int PB4 = 68;
    static const int PB27 = 91;
    static const int PB11 = 75;
    static const int PB10 = 74;
    static const int PB13 = 77;
    static const int PB12 = 76;
    static const int PB21 = 85;
    static const int PB20 = 84;
    static const int PB31 = 95;
    static const int PB30 = 94;
    static const int PA31 = 63;
    static const int PA30 = 62;
    static const int PA6 = 38;
    static const int PA7 = 39;
    static const int PA9 = 41;
    static const int PC3 = 99;
    static const int PC2 = 98;
    static const int PC1 = 97;
    static const int PC0 = 96;
    static const int PA24 = 56;
    static const int PA23 = 55;
    static const int PA10 = 42;
    static const int PA22 = 54;
    static const int PA11 = 43;
}

#endif /* FOXBOARD_H_ */


DigitalOutput.h :
#ifndef DIGITALOUTPUT_H_
#define DIGITALOUTPUT_H_

#include <fstream>
#include <iostream>
#include <sstream>

using namespace std;

class DigitalOutput {
public:
    DigitalOutput(int pin);

    void write(unsigned int value);
    void toggle();

private:
    int pin;
    int etat;
    string racine;
};

#endif /* DIGITALOUTPUT_H_ */

DigitalOutput.cpp :
#include "DigitalOutput.h"

DigitalOutput::DigitalOutput(int pin) {
    FILE *file=NULL;

    this->etat=0;
    this->pin = pin;
    file = fopen("/sys/class/gpio/export","a");
    if (file==NULL){
        cout << "Erreur ouverture fichier : /sys/class/gpio/export"<<endl;
        return;
    }
    fprintf(file,"%d",this->pin);     // on exporte la pin
    fclose(file);

    // nom de la racine du nouveau fichier
    ostringstream ss;
    ss << this->pin;
    this->racine = "/sys/class/gpio/gpio" + ss.str() ;
    this->racine += "/";

    // direction du port
    file = fopen((this->racine + "direction").c_str(),"w+");
    if (file==NULL){
        cout << "Erreur ouverture fichier : "<<this->racine + "direction"<<endl;
        return;
    }
    fprintf(file,"out");
    fclose(file);

    write(0);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void DigitalOutput::write(unsigned int value){
    FILE *file=NULL;

    file = fopen((this->racine+"value").c_str(),"w+");
    if(file==NULL){
        cout<<"Erreur ouverture fichier : "<<this->racine + "value"<<endl;
        return;
    }
    fprintf(file,"%d",value);
    this->etat = value;

    fclose(file);
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void DigitalOutput::toggle(void){
    write(!this->etat);
}


Exemple : Clignotement d'une led sur PB18

main.cpp :
#include "DigitalOutput.h"
#include "Foxboard.h"

int main(void) {
    DigitalOutput led(foxboard::PB18);

    while(true){
        usleep(500*1000);  // pause de 500 ms
        led.toggle();      // inverser état
    }

    return 0;
}

jeudi 9 juin 2011

FOX Board G20 en C++ : Mise en route

J'avais depuis un certain temps une FOX Board G20 dans mon placard, je l'ai ressortit et j'ai commencé à coder une petite bibliothèque en c++ pour manipuler les entrées/sorties.

La FOX Board G20 est un ordinateur embarqué développé par ACME Systems. Il est cadencé à 400Mhz et tourne sous linux. Plusieurs distributions de linux sont disponibles pour la carte comme Debian ou Gentoo. Pour ma part j'utilise Debian.

Site du constructeur : http://www.acmesystems.it/
Wiki : http://foxg20.acmesystems.it/doku.php




Je développe avec Eclipse sous Windows. Vous pouvez suivre cet article pour installer un cross compiler ce qui va vous permettre de compiler le code directement sur votre machine.

Pour manipuler les entrées/sorties de la carte on utilise l'interface sysfs. Cette interface nous permet par l'intermédiaire d'un système de fichier de contrôler et de récupérer des informations sur l'état des ports de la carte.

Une fois le programme compilé, vous trouverez dans le dossier de votre projet dans Debug un fichier .elf. Copier ce fichier sur la foxboard dans root/programmes par exemple.
Pour l'éxecuter : ./fox.elf