Langage C, exemples accédant au port GPIO

Liens vers d'autres pages de ce site Web   En construction ... à venir, si j'ai le temps, l'énergie, ...

° Raspberry pi, un mini micro ordinateur
° Raspbian, le système d'exploitation par défaut du Raspberry pi
° RISC OS, un système d'exploitation non préemptif, rapide
° Ubuntu Mate, une alternative, pour rester proche de Ubuntu
° Python, exemples accédant au port GPIO
° Langage C, exemples accédant au port GPIO

Table des matières   Liens internes à cette page

00 Des informations sur le port GPIO et le langage C
01 Fait clignoter une LED
02 Fait clignoter 3 LEDs
03 Pour tester le clavier sans interruption du programme
04 Fait clignoter une LED avec arrêt lors d'une pression sur une touche
05 Fait clignoter 3 LEDs avec arrêt lors d'une pression sur une touche
06 Lecture de l'état d'un bouton
07 Lecture d'une photorésistance, sur un seul port GPIO, non standard.
08
09 NON TERMINÉ, à continuer une autre fois.

Des informations sur le port GPIO et le langage C   Top

Beaucoup d'informations et de liens sur des vidéos sur le langage C sont disponible sur ma page principale, concernant Raspberry pi.
° Des vidéos pour apprendre le langage C sur Raspberry pi
D'autres informations concernant le langage C sont disponibles sur ° ma page sur les extensions en langage C du Python.

Deux librairies C pour accéder au port GPIO :
1) bcm2835.h c.f. www.airspayce.com/mikem/bcm2835
2) wiring Pi non exploré par moi.

Je suppose que vous avez installé la librairie bcm2835.h pour accéder aux ports GPIO depuis le langage C.

Dans tous les cas, sous Linux, il faut avoir installé le compilateur gcc et les librairies qui vont avec.
sudo apt-get update
sudo apt-get install build-essential

Pour installer la librairie bcm2835 :
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.55.tar.gz
tar zxvf bcm2835-1.55.tar.gz
cd bcm2835-1.55
./configure
make
sudo make check
sudo make install

Je dois préciser que je travail sous GNU/Linux KUbuntu 16.04.
Pour d'autres systèmes d'exploitations, il faut faire des analogies.
Pour écrire et compiler mon code C, j'ai utilisé le logiciel libre Geany.
Plus d'information concernant Geany et gcc et g++.
J'ai également fait des essais avec Code Blocks.

La suite donne juste des exemples.
gpio01_led_blink.c   fait clignoter une LED   TOP
/*
gpio01_led_blink.c 
Fait clignoter une LED

Dans Geany, il faut aller dans :
Construire > Définir les commandes de construction
Compiler : gcc -Wall -c "%f" -l bcm2835 -lm
Construire : gcc -Wall -o "%e" "%f" -l bcm2835 -lm
Exécuter : sudo "./%e"
L'option -lm est utile si on utilise la librairie standard de math :
#include <math.h>
*/  
#include <stdio.h>  // se trouve dans /usr/include/c++/4.9/tr1
#include <bcm2835.h>  // se trouve dans /usr/local/include

#define pinOut 21

int main(int argc, char **argv) {
//===============================
// initialise the GPIO
if (!bcm2835_init()) return 1;

// indique que la PIN "pinOut" est en sortie
bcm2835_gpio_fsel(pinOut, BCM2835_GPIO_FSEL_OUTP);

unsigned int myDelay = 1000; // délais en [ms]. On aurait pu le déclarer : #define myDelay 1000

while (1) {
  bcm2835_gpio_set(pinOut); // allume la LED
  bcm2835_delay(myDelay);   // bcm_delayMicroseconds(utin64_t micros);  fait un delay en microsecondes.
  bcm2835_gpio_clr(pinOut); // éteint la LED
  bcm2835_delay(myDelay);
  }
} // main  
gpio01_led_blink blink
gpio01_led_blink.c
Le fil rouge est connecté au 3,3V de la carte Raspberry pi.
Surtout ne PAS connecter au 5,0 V, cela peut endommager le Raspberry pi, suivant les connexions à venir.
Dans cet exemple, cette connexion du fil (rouge) au 3,3 V n'est pas utilisé.
Le fil noir est connecté au GND (ground) de la carte Raspberry pi, qui représente le 0 V.
La résistance est de 220 Ohms. Code couleurs : rouge ; rouge ; brun.


gpio02_allume_3_led.c   fait clignoter 3 LEDs   TOP
/*
gpio02_allume_3_led.c 
Fait clignoter trois LEDs, comme un compteur binaire.

Dans Geany, ne pas oublier d'aller dans : 
Construire > Définir les commandes de construction
Complier : gcc -Wall -c "%f" -l bcm2835
Construire : gcc -Wall -o "%e" "%f" -l bcm2835
Compiler : sudo "./%e" 
************************************************ */

// c.f. https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
#include <stdio.h>   // se trouve dans /usr/include/c++/4.9/tr1
#include <bcm2835.h> // se trouve dans /usr/local/include

#define p3 21
#define p2 20
#define p1 16

// nombre de LED utilisées
#define TROIS 3

#define myDelay 1000 // délais en [ms]

int nn = 0;
int kk = 0;

// Défini les pins utilisé
int anPins[TROIS]  = {p1, p2, p3}; 
int anState[TROIS+1] = { 0, 0, 0, 0}; // Tout éteint au départ

int main(int argc, char **argv) {
//===============================
// initialise the GPIO
if (!bcm2835_init()) return 1;

// indique que les PIN sont en sortie
for (kk=0; kk<TROIS; kk++) {
  bcm2835_gpio_fsel(anPins[kk], BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_clr(anPins[kk]);
  }

bcm2835_delay(myDelay);  // bcm_delayMicroseconds(utin64_t micros);  fait un delay en microsecondes.

nn = 0;
while (1) {
  nn++;
  if (nn >= 8) nn = 0; // boucle sur les 8 états de 3 bits.

  anState[0] = 1 - anState[0]; // Change d'état
  if (anState[0] == 0) bcm2835_gpio_clr(anPins[0]);
  else                 bcm2835_gpio_set(anPins[0]);

  for (kk=0; kk<TROIS-1; kk++) {
    if (anState[kk] == 0) {
      // La pin n°  kk  a eu changement de l'état 1 à l'état 0
      anState[kk+1] = 1 - anState[kk+1]; // Change d'état de la pin suivante

      if (anState[kk+1] == 0) bcm2835_gpio_clr(anPins[kk+1]);
      else                    bcm2835_gpio_set(anPins[kk+1]);
      }
    else {
      // La pin n°  kk  a eu changement de l'état 0 à l'état 1
      break; // sort de la boucle
      }
    }

  printf("%d\n", nn); // Pour des tests

  bcm2835_delay(myDelay);  // bcm_delayMicroseconds(utin64_t micros);  fait un delay en microsecondes.
  } // while (1)
} // main  

gpio02_allume_3_led blink
gpio02_allume_3_led.c
Montage similaire au précédent : gpio01_led_blink.c, avec deux LEDs de plus.


gpio03_kbhit_no_stop.c   Pour tester le clavier sans interruption du programme   TOP
/*
gpio03_kbhit_no_stop.c
Le but est de lire l'état du clavier, sans que le programme s'arrête.
Donc, si rien n'a été tapé au clavier et qu'une lecture clavier se fait,
la fonction standard  getchar()  retourne le caractère EOF, qui vaut -1. ou 255 sur 1 octet
N'utilise pas le port GPIO, c'est juste un exemple pour lire le clavier.
***********************************************************************/

#include <stdio.h>  // http://www.cplusplus.com/reference/cstdio/

// http://stackoverflow.com/questions/9547868/is-there-a-way-to-get-user-input-without-pressing-the-enter-key
// http://shtrom.ssji.net/skb/getc.html
// http://cui.unige.ch/~garg/systinfo/tips/unix/terminal.html
// Pour : tcgetattr(STDIN_FILENO, &old_tio);
#include <termios.h>
#include <fcntl.h> // Pour F_GETFL, O_NONBLOCK
#include <unistd.h>  // Pour STDIN_FILENO

// c.f. https://www.tutorialspoint.com/c_standard_library/time_h.htm
#include <time.h> // Uniquement pour le test03, pour ralentir

int kbhit(void) {
//===============
// Première méthode
struct termios old_tio, new_tio;
int ch;
int old_fnctl;

tcgetattr(STDIN_FILENO, &old_tio);  // get the terminal settings for stdin
new_tio = old_tio;  // we want to keep the old setting to restore them a the end

// disable canonical mode (buffered i/o) and local echo
new_tio.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);

old_fnctl = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl | O_NONBLOCK);

ch = getchar();

// Remet les valeurs par défaut de "stdin"
tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl);

// Si un caractère a été tapé retourne 1, sinon, retourne 0
if(ch != EOF) {
    ungetc(ch, stdin); // remet le caractère dans la file d'entrée.
    return 1;
  }

return 0;
} // kbhit

char kbhit2(void) {
//=================
// Deuxième méthode, qui me semble meilleure
struct termios old_tio, new_tio;
int ch;
int old_fnctl;

tcgetattr(STDIN_FILENO, &old_tio);  // get the terminal settings for stdin
new_tio = old_tio; // we want to keep the old setting to restore them at the end

// disable canonical mode (buffered i/o) and local echo
new_tio.c_lflag &=(~ICANON & ~ECHO);

tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
old_fnctl = fcntl(STDIN_FILENO, F_GETFL, 0);

// Pour que le programme ne s'arrête pas à l'instruction "getchar()"
fcntl(STDIN_FILENO, F_SETFL, old_fnctl | O_NONBLOCK);

ch = getchar();

// Remet les valeurs par défaut de "stdin"
tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl);

return ch;  // EOF == -1
//if(ch != EOF) return ch;
//return 0;
} // kbhit2

int test01(void) {
//==============
char chK;

printf("Pressez sur  q  pour quitter\n");
do {
  while(!kbhit()) {}
  chK = getchar();
  printf("%c", chK);
  } while (chK != 'q');

return 0;
} // test01

int test02(void) {
//==============
char chK;

printf("Pressez sur  q  pour quitter\n");
do {
  do { chK = kbhit2(); } while(chK == (char)EOF);
  printf("%c   EOF =%d", chK, EOF);
  } while (chK != 'q');

return 0;
} // test02

int test03(void) {
//================
// Encore un test.
struct termios old_tio, new_tio;
char chK;
int old_fnctl;
time_t timeLast, timeNow;
double vDiffTime;
long nCompte = 0; // compte le nombre de fois que le programme a bouclé en une seconde.
 
tcgetattr(STDIN_FILENO, &old_tio); // get the terminal settings for stdin
new_tio = old_tio; // we want to keep the old setting to restore them at the end

// disable canonical mode (buffered i/o) and local echo
new_tio.c_lflag &=(~ICANON & ~ECHO);

// set the new settings immediately
tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);

// Pour que le programme ne s'arrête pas à l'instruction "getchar()"
old_fnctl = fcntl(STDIN_FILENO, F_GETFL, 0); // Mémorise, pour les remettre à la fin
fcntl(STDIN_FILENO, F_SETFL, old_fnctl | O_NONBLOCK);

timeNow = clock(); // heure du processeur

do {
  chK = getchar();
  printf("Hello World,  nCompte=%ld\n", nCompte);

  // Attente de quelques dixièmes de secondes.
  timeLast = timeNow;
  nCompte = 0;
  do {
    nCompte++;
    timeNow = clock(); // heure du processeur
    vDiffTime = difftime(timeNow, timeLast); // Différence de temps en micro-secondes
    } while (vDiffTime < 1000000.0);

  } while (chK != 'q');

// restore the former settings
tcsetattr(STDIN_FILENO, TCSANOW,&old_tio);

// Remet les valeurs par défaut de "stdin"
tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl);

return 0; 
} // test03

int main(int argc, char **argv) {
//================================
return test02();
} // main

gpio04_led_blink_and_stop.c   Fait clignoter une LED avec arrêt lors d'une pression sur une touche   TOP
Test les touches "q" pour quitter, "p" pour "plus vite" et "m" pour "moins vite.
/*
gpio04_led_blink_and_stop.c 
Fait clignoter une LED
Fait varier la vitesse de clignotement,
suivant la touche du clavier pressée.
La touche "q" quitte le programme.

Dans Geany, ne pas oublier d'aller dans : 
Construire > Définir les commandes de construction
Complier : gcc -Wall -c "%f" -l bcm2835
Construire : gcc -Wall -o "%e" "%f" -l bcm2835
Compiler : sudo "./%e" 
************************************************ */

#include <stdio.h>   // se trouve dans /usr/include/c++/4.9/tr1
#include <bcm2835.h> // se trouve dans /usr/local/include

#include <termios.h> // Pour : tcgetattr(STDIN_FILENO, &old_tio);
#include <fcntl.h> // Pour F_GETFL, O_NONBLOCK
#include <unistd.h>  // Pour STDIN_FILENO

// c.f. https://www.tutorialspoint.com/c_standard_library/time_h.htm
#include <time.h> // Uniquement pour le test03, pour ralentir

#define pinOut 21

// Pour mémoriser les états standards d'entrée du clavier
struct termios old_tio, new_tio;
int old_fnctl;

int main(int argc, char **argv) {
//===============================
char chK; // Lecture d'une touche au clavier
unsigned int myDelay = 1000; // délais en [ms].

// initialise the GPIO
if (!bcm2835_init()) return 1;

tcgetattr(STDIN_FILENO, &old_tio);  // get the terminal settings for stdin
new_tio = old_tio; // we want to keep the old setting to restore them at the end

// disable canonical mode (buffered i/o) and local echo
new_tio.c_lflag &=(~ICANON & ~ECHO);

tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
old_fnctl = fcntl(STDIN_FILENO, F_GETFL, 0);

// Pour que le programme ne s'arrête pas à l'instruction "getchar()"
fcntl(STDIN_FILENO, F_SETFL, old_fnctl | O_NONBLOCK);

// indique que la PIN "pinOut" est en sortie
bcm2835_gpio_fsel(pinOut, BCM2835_GPIO_FSEL_OUTP);

printf("'p' augmente la fréquence de clignotement\n");
printf("'m' diminue la fréquence de clignotement\n");
printf("'q' quitte le programme\n");

while (1) {
  bcm2835_gpio_set(pinOut);
  bcm2835_delay(myDelay);  // bcm_delayMicroseconds(utin64_t micros);  fait un delay en microsecondes.
  bcm2835_gpio_clr(pinOut);
  bcm2835_delay(myDelay);
  
  chK = getchar() & (255-32); // Pour forcer les majuscules (vieux jeux)
  //if ((chK > 32) && (chK < 128)) printf("%d\n", chK);
  if (chK == 'Q') break;
  if (chK == 'M') {
    myDelay += 50; // diminue la fréquence
    printf("Delais = %d [ms]\n", myDelay);
    }
  if (chK == 'P') {
    myDelay -= 50; // augmente la fréquence
    if (myDelay < 50) myDelay = 50; // limite la vitesse de clignotement 
    printf("Delais = %d [ms]\n", myDelay);
    }
  } // while(1)
  
bcm2835_gpio_clr(pinOut); // éteint la LED

// Remet les valeurs par défaut de "stdin"
tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl);

return 0;
} // main  

gpio04_led_blink_and_stop blink
gpio04_led_blink_and_stop.c
Montage identique au : gpio02_allume_3_led.c.


gpio05_allume_3_led_and_stop.c   Fait clignoter une LED avec arrêt lors d'une pression sur une touche   TOP
Test les touches "q" pour quitter, "p" pour "plus vite" et "m" pour "moins vite.
/*
gpio05_allume_3_led_and_stop.c 
Fait clignoter trois LEDs, comme un compteur binaire.
Fait varier la vitesse de clignotement,
suivant la touche du clavier pressée.
La touche "q" quitte le programme.

Dans Geany, ne pas oublier d'aller dans : 
Construire > Définir les commandes de construction
Complier : gcc -Wall -c "%f" -l bcm2835
Construire : gcc -Wall -o "%e" "%f" -l bcm2835
Compiler : sudo "./%e" 
************************************************ */

// c.f. https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
#include <stdio.h>   // se trouve dans /usr/include/c++/4.9/tr1
#include <bcm2835.h> // se trouve dans /usr/local/include

#include <termios.h> // Pour : tcgetattr(STDIN_FILENO, &old_tio);
#include <fcntl.h> // Pour F_GETFL, O_NONBLOCK
#include <unistd.h>  // Pour STDIN_FILENO

// c.f. https://www.tutorialspoint.com/c_standard_library/time_h.htm
#include <time.h> 

#define p3 21
#define p2 20
#define p1 16

// nombre de LED utilisées
#define TROIS 3

int nn = 0;
int kk = 0;

// Défini les pins utilisé
int anPins[TROIS]  = {p1, p2, p3}; 
int anState[TROIS+1] = { 0, 0, 0, 0}; // Tout éteint au départ

// Pour mémoriser les états standards d'entrée du clavier
struct termios old_tio, new_tio;
int old_fnctl;

time_t timeLast, timeNow;
double vDiffTime;

char chK; // Pour la lecture du caractère tapé au clavier
unsigned int myDelay = 500000; // délais en [micro-s].

int main(int argc, char **argv) {
//================================
int nLoop = 1; // Mis à zéro pour arrêt du programme

// initialise the GPIO
if (!bcm2835_init()) return 1;

tcgetattr(STDIN_FILENO, &old_tio);  // get the terminal settings for stdin
new_tio = old_tio; // we want to keep the old setting to restore them at the end

// disable canonical mode (buffered i/o) and local echo
new_tio.c_lflag &=(~ICANON & ~ECHO);

tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
old_fnctl = fcntl(STDIN_FILENO, F_GETFL, 0);

// Pour que le programme ne s'arrête pas à l'instruction "getchar()"
fcntl(STDIN_FILENO, F_SETFL, old_fnctl | O_NONBLOCK);

// indique que les PIN sont en sortie
for (kk=0; kk<TROIS; kk++) {
  bcm2835_gpio_fsel(anPins[kk], BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_clr(anPins[kk]);
  }

printf("'p' augmente la fréquence de clignotement\n");
printf("'m' diminue la fréquence de clignotement\n");
printf("'q' quitte le programme\n");

timeNow = clock(); // heure du processeur

nn = 0;
while (nLoop) {
  nn++;
  if (nn >= 8) nn = 0; // boucle sur les 8 états de 3 bits.

  anState[0] = 1 - anState[0]; // Change d'état
  if (anState[0] == 0) bcm2835_gpio_clr(anPins[0]);
  else                 bcm2835_gpio_set(anPins[0]);

  for (kk=0; kk<TROIS-1; kk++) {
    if (anState[kk] == 0) {
      // La pin n°  kk  a eu changement de l'état 1 à l'état 0
      anState[kk+1] = 1 - anState[kk+1]; // Change d'état de la pin suivante

      if (anState[kk+1] == 0) bcm2835_gpio_clr(anPins[kk+1]);
      else                    bcm2835_gpio_set(anPins[kk+1]);
      }
    else {
      // La pin n°  kk  a eu changement de l'état 0 à l'état 1
      break; // sort de la boucle
      }
    }

  //printf("%d\n", nn); // Pour des tests
    
  // Attente, avec lecture imédiate du clavier
  timeLast = timeNow;
  do {
    chK = getchar() & (255-32); // Pour forcer les majuscules (vieux jeux)
    if (chK == 'Q') nLoop = 0; // Arrêt
    if (chK == 'M') {
      myDelay += 10000; // diminue la fréquence
      printf("Delais = %6.1f [ms]\n", myDelay/1000.0);
      }
    if (chK == 'P') {
      myDelay -= 10000; // augmente la fréquence
      if (myDelay < 10000) myDelay = 10000; // limite la vitesse de clignotement 
      printf("Delais = %6.1f [ms]\n", myDelay/1000.0);
      }

    timeNow = clock(); // heure du processeur
    vDiffTime = difftime(timeNow, timeLast); // Différence de temps en micro-secondes
    } while ((vDiffTime < myDelay) && (nLoop));
  
  } // while (1)
  
// éteint les LEDs
for (kk=0; kk<TROIS; kk++) bcm2835_gpio_clr(anPins[kk]);

// Remet les valeurs par défaut de "stdin"
tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
fcntl(STDIN_FILENO, F_SETFL, old_fnctl);

return 0;
} // main  

gpio05_allume_3_led_and_stop blink
gpio05_allume_3_led_and_stop.c
Montage similaire au précédent : gpio02_allume_3_led.c, avec deux LEDs de plus.


gpio06_input.c   lecture de l'état d'un bouton   TOP
/*
gpio06_input.c
Lit une entrée de l'état d'un bouton
*/  
#include <stdio.h>  // se trouve dans /usr/include/c++/4.9/tr1
#include <bcm2835.h>  // se trouve dans /usr/local/include

#define pinOut 19
#define pinIn  26
#define pinIn2  27

int main(int argc, char **argv) {
//===============================
// initialise the GPIO
if (!bcm2835_init()) return 1;

bcm2835_gpio_fsel(pinOut, BCM2835_GPIO_FSEL_OUTP); // indique que la PIN "pinOut" est en sortie
bcm2835_gpio_fsel(pinIn, BCM2835_GPIO_FSEL_INPT);  // indique que la PIN "pinIn" est en entrée
//bcm2835_gpio_set_pud(pinIn, BCM2835_GPIO_PUD_UP);  // Enable pull-up, par défaut, l'état de la PIN est UP

// Si la pinIn a été mise à 0, un flag est mis on.
// bcm2835_gpio_set_len(pinIn);  // Enable low detect on pinIn  
// bcm2835_gpio_set_hen(pinIn);  // Enable high detect on pinIn 


unsigned int myDelay = 1000; // délais en [ms]. On aurait pu le déclarer : #define myDelay 1000

while (1) {
//  if ((bcm2835_gpio_eds(pinIn) == 1) || (bcm2835_gpio_lev(pinIn2) == 1)) {
  if (bcm2835_gpio_lev(pinIn) == 1) {
    // Le bouton est pressé
    printf("Allume la LED\n");
    bcm2835_gpio_set(pinOut); // allume la LED
    bcm2835_delay(myDelay);   // bcm_delayMicroseconds(utin64_t micros);  fait un delay en microsecondes.
    bcm2835_gpio_clr(pinOut); // éteint la LED
    } // if
  } // while
} // main

gpio06_input blink
gpio06_input.c
Le fil rouge est connecté au 3,3V de la carte Raspberry pi.
Surtout ne PAS connecter au 5,0 V, cela peut endommager le Raspberry pi, suivant les connexions à venir.
Dans cet exemple, cette connexion du fil (rouge) au 3,3 V est utilisé.
Le fil noir est connecté au GND (ground) de la carte Raspberry pi, qui représente le 0 V.
Il y a une résistance est de 220 Ohms. Code couleurs : rouge ; rouge ; brun.
Il y a une résistance est de 10'000 Ohms. Code couleurs : brun ; noir ; orange.


gpio07_lecture_photo_resistance.c   Lecture d'une photorésistance, sur un seul port GPIO, non standard   TOP



gpio01_allume_led.c   LED   TOP



gpio9.c   LED   TOP



gpio10.c   LED   TOP




Plan du Site : Home   arrow   Raspberry pi   arrow   cgpio.html ( = http://www.juggling.ch/gisin/raspberrypi/cgpio.html )


Page mise à jour le 24 février 2018 par Bernard Gisin     ( Envoyer un e-mail )
Hébergement par : www.infomaniak.ch