Ceci est une ancienne révision du document !
Table des matières
Emetteur pour transmission par led
Principe
Comme vous l'avez sans doute lu précédemment, nous allons chercher à créer un programme permettant de contrôler le clignotement d'une led pour transmettre des données aussi rapidement que possible.
Pour réaliser cet émetteur, nous allons nous travailler à la création interface qui va nous permettre de contrôler le gpio du raspberry et à la gestion des changements d'états de la led.
Développement
Interface avec le gpio
Comme vous l'avez compris, on va avoir besoin d'interagir avec le gpio du raspberry afin de faire, plus tard, clignoter une led.
En fait il est extrêmement simple d'allumer ou d'éteindre une led. Vous pouvez même vous y amusez directement depuis un shell, sans passer par aucun programme (notez simplement dans un coin de votre tête que j'ai travaillé sous Raspbian Lite, noyau version 4.14).
Tout d'abord, vous aurez besoin d'exporter la led via le pin du gpio sur lequel elle est connectée. En shell, vous aurez simplement à taper ceci:
echo numero_du_pin_de_la_led > /sys/class/gpio/export
Il vous faut maintenant paramétrer la direction de la led. Pour ce faire, il vous suffit de procéder ainsi:
echo "out" > /sys/class/gpio/gpioX/direction
où X est le numéro du pin où vous avez branché la led. Le principe simple et comme vous le voyez ce n'est vraiment pas compliqué !
Vous êtes maitenant prêts à allumer/éteindre la led, et le principe est le même:
echo V > /sys/class/gpio/gpioX/value
avec V qui peut valoir 1 pour éteindre la led ou 0 pour allumer la led (cela vous semble peut être contre intuitif, mais c'est comme ça) et X qui est toujours le numéro du pin de la led.
Quand vous aurez fini de jouer, vous devrez dé-exportez la led. Là aussi, c'est très simple:
echo numero_du_pin_de_la_led > /sys/class/gpio/unexport
Et voilà, le pin de la led est de nouveau “inactif”.
Tout va se passer de la même manière en C++ ! En effet, vous pouvez très bien ouvrir ces fichiers dans votre code pour y effectuer toutes les opérations dont je viens de vous parler, c'est comme ça que je vous recommande de procéder. J'ai personnellement choisi de créer une classe pour encapsuler ces opérations. Le code de cette classe est disponible sur mon github (fichiers ledcontroller.cpp/hpp) au cas où vous ne souhaiteriez pas tout réécrire vous même.
Je ne vais pas détailler ligne par ligne le code de l'interface dans ce tutoriel étant donné qu'il est très simple de développer une classe qui implémenterai ces opérations (à condition d'être familier avec le C++) et que ce n'est pas cette partie de l'émetteur qui présente le plus d'intérêt.
Dans tous les cas vous avez toutes les clés en main, soit pour comprendre le code que je met à votre disposition, soit pour développer votre propre interface, gardez simplement à l'esprit que tout va se passer de la même manière qu'avec les commandes shell ci-dessus.
Pour comprendre le code qui va suivre, je vais vous détailler ci-dessous les fonctions que j'ai implémenté dans mon interface que je vais utiliser pour la gestion de la led.
- LedController: le constructeur de notre classe, vous ne me verrez l'utiliser qu'avec un seul paramètre, qui sera le numéro du pin de la led.
- turnOn: une méthode de la classe LedController qui allume la led, si cette dernière est déjà allumée, rien ne se passe (cette fonction ne prend aucun paramètre).
- turnOff: une autre méthode de LedController qui éteint la led, si cette dernière est déjà éteinte, rien ne se passe (cette fonction ne prend aucun paramètre)
Si vous êtes arrivés jusqu'ici, vous êtes prêt à attaquer la partie amusante !
Les changements d'états de la led
Dans cette partie, nous allons écrire un main qui va utiliser notre API pour allumer/éteindre la led en fonction de la valeur de chaque bit de chaque caractère d'un message. Nous avons décidé d'utiliser des chaînes de caractères comme données à transmettre, simplement parce qu'il nous sera plus facile (selon nous) de visualiser les erreurs de bits sur des caractères que sur les valeurs des pixels d'une image ou tout autre type de données qu'on aurait pu transmettre.
En concevant le code que je vais vous présenter, j'ai prévu deux chaînes de caractères particulières qui agirait comme des commandes. Ces deux commandes sont /end pour terminer le programme proprement et libérer les ressources (ici, é-exporter le pin de la led), et /test qui envoie une séquence particulière de 0 et de 1 (qui sont en fait des “U”), parce que cette alternance cyclique de 0 et de 1 va nous permettre de visualiser d'éventuelles erreurs de synchronisation.
Voyons à quoi ressemble la boucle de notre main:
int main() { LedController lc(GPIO_PIN); std::string message; std::cout << "Waiting for a string to send: (\"/test\" to launch a sequence of 0 and 1, \"/end\" to end the program)" << std::endl; std::getline(std::cin, message); while(message != "/end") { std::cout << "Waiting for a string to send: " << std::endl; if(message == "/test") { transmit(lc, "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"); } else { transmit(lc, message); } std::cout << "Transfer complete.\n" << std::endl; } return ALL_GOOD; }
Sources du projet
Auteur: Sylvain Durand