Dans l'article précédent nous vous avons présenté la bibliothèque que nous avons mise en place pour le contrôle des moteurs. Ces dernières semaines nous avons travaillé sur les émetteur/récepteur radio. Maintenant que notre bibliothèque est au point nous pouvons vous la présenter au travers cet article.
Tout d'abord, voici une photo du composant en question. Tel qu'attendus, ils sont assez petits pour obtenir la dimension que nous désirons pour le drone.
Ces composants, fabriqués par Nordic Semiconductor sont assez répandus dans la communauté d'Arduino. Ainsi une large gamme d'exemples est disponible sur Internet et de nombreuse bibliothèques pour la manipulation de ce composant sont mises à disposition librement (notamment sur GitHub). Nous avons alors profité du succès de ce composant en basant notre bibliothèque sur RadioHead, une bibliothèque proposée par Paul Stoffregen.
Nous représentons un transmetteur par une instance de la classe Communication. Voici la déclaration de cette classe :
#include <SPI.h>
#include <RH_NRF24.h>
class Communication {
private:
RH_NRF24 _nrf24;
public:
Communication(int pin1, int pin2);
bool initRadio();
bool sendMsg(uint8_t* data, uint8_t len, uint8_t channel);
bool receiveMsg(uint8_t* data, uint8_t len, uint8_t channel);
};
Comme vous pouvez le voir cette classe reste très minimaliste. Elle ne propose qu'un attribut et trois méthodes. L'attribut représente le composent et il provient de la bibliothèque Radiohead. C'est à l'aide de cet attribut et des méthodes que nous avons écrites que nous allons assurer la communication entre le drone et le serveur. La première méthode, initRadio(), se charge de tester l'état du composant en vérifiant la bonne initialisation, son canal, sa vitesse et sa puissance de transmission. Suivant ces différentes valeurs le composant pourra être considéré (ou pas) comme prêt à être utilisé.
bool Communication::initRadio() {
bool state = true;
if(!_nrf24.init())
state = false;
if(!_nrf24.setChannel(1))
state = false;
if(!_nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
state = false;
return state;
}
Les deux autres méthodes se chargent de l'envoie et de la réception de données et ne possèdent rien de particulier.
Plus concrètement, les messages que nous comptons envoyer seront de deux types :
Les messages de type serveur, seront de simples tableaux d'entiers de taille 4. Ils permettront donc d'envoyer une position cible (c'est-à-dire trois composantes : x, y et z) à un drone. Les messages de type drone, seront quant à eux des tableaux d'entiers de taille 11. Un tableau contiendra donc le numéro du drone (channel), une position (encore une fois x, y et z) et les valeurs obtenues par les six capteurs à ultrasons.
Quel que soit le type du message, on se réserve un entier supplémentaire dans le tableau, pour communiquer des codes entre le serveur et les drones. Ces codes pourront représenter des codes des erreurs, des informations sur l'état du drone et alors des ordres bien spécifiques. Par exemple si le serveur envoyait la valeur 0, cela pourrait dire au drone "Retourne à la base". Ou bien si le drone envoyait la valeur 10, cela pourrait signifier "Je n'ai plus beaucoup de batterie".
Comme d'habitude vous trouverez cette bibliothèque sur notre GitHub.
Afin de tester le bon fonctionnement de notre librairie, nous avons écrit un code Arduino. Pour le tester il faut, bien entendu, deux montages.
#include <SPI.h>
#include <RH_NRF24.h>
#include <communication.h>
uint8_t msg[] = {1, 2, 3, 4};
uint8_t len = sizeof(msg);
bool ok;
Communication com(8, 10);
void setup() {
Serial.begin(9600);
ok = com.initRadio();
if(!ok)
Serial.println("Init error");
}
void loop() {
ok = com.sendMsg(msg, len, 1);
if(!ok)
Serial.println("Sending error");
ok = com.receiveMsg(msg, len, 1);
if(!ok)
Serial.println("Receiving error");
else
Serial.println(msg[0]);
}
Ce code se contente d'instancier un objet de la classe Communication et de l'initialiser. Dans la boucle principale il envoie un message à l'autre montage et réceptionne un message de la part de ce dernier.
La bonne manipulation de ces composants nous a pris un peu de temps, car (de par le nombre important de bibliothèques déjà disponibles) nous avons fait un certain nombre de tests. Aussi, nous avons rencontré un problème : lorsque qu'un composant réceptionnait un message, nous n'arrivions pas à envoyer de réponse ou du moins pas de manière déterministe. Nous avons pu régler ce souci en mettant un condensateur de 10uF entre l'alimentation du composant et la masse. De ce que nous avons pu lire sur Internet cela serait dû à la faible puissance délivrée par la carte Arduino.
Le prochain article sera consacré à la présentation de la bibliothèque pour la manipulation du gyroscope.