#ifndef LORARADIO_H #define LORARADIO_H #include #include #include #include /*! \mainpage Guide de démarrage rapide * * \section intro_sec Introduction * * Cette bibliothèque inclue deux classes : PinMap et LoRaRadio.@n * Attention, il faut préalablement installer la LMIC dans le dossier Documents\\Arduino\\libraries téléchargeable ici.@n * * Voici un code d'exemple de l'utilisation de l'objet LoRaRadio : * * \code{.cpp} * #include * #include * //Testé sur ESP8266 et ESP32. * * //Les pins dépendent des cartes * u1_t dio[3] = {26,33,32}; * * void os_getArtEui (u1_t* buf) { } * void os_getDevEui (u1_t* buf) { } * void os_getDevKey (u1_t* buf) { } * * static u1_t NWKSKEY[16] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11 }; //Disponible sur TTN * static u1_t APPSKEY[16] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11 }; //Disponible sur TTN * static u4_t DEVADDR = 0x11223344; //Adresse du noeud disponible sous TTN. * * unsigned long ts(millis()); * * //Les pins dépendent des cartes * PinMap pinMap(18, LMIC_UNUSED_PIN, 14, dio); * LoRaRadio radio(pinMap); * * uint8_t trame[] = "Hello World !"; * * void downlinkHandler(u1_t length, u1_t dataBeg, u1_t *data) * { * Serial.println("Réception d'un downlink :"); * for(uint8_t i(0); i < length; i++) * { * Serial.printf("%u -> %d\n",i,data[dataBeg + i]); * } * Serial.println(); * } * * void sendCompleteHandler() * { * Serial.println("Envoi de la trame terminée"); * } * * void setup() * { * Serial.begin(115200); * Serial.println("Starting setup"); * radio.init(); * radio.setTTNSession(0x1, DEVADDR, NWKSKEY, APPSKEY); * radio.setRadioEUChannels(); * radio.setMCUClockError(); * //Enregistrement des callbacks d'événements * radio.setDownlinkHandler(&(downlinkHandler)); * radio.setSendCompleteHandler(&(sendCompleteHandler)); * Serial.println("Ending setup"); * } * * void loop() * { * radio.run(); * //On envoie une trame toute les 30 secondes * if(millis() - ts > 30000) * { * Serial.printf("Envoie de la trame.\n"); * radio.send(1, trame, strlen((char *)trame)); * ts = millis(); * } * } * * \endcode * * \author Anatole SCHRAMM-HENRY * \date 29 Jan 2020 * \copyright All Right Reserved */ /*! @brief La classe PinMap permet de mapper les différentes connections faites entre le module SX127X physique et le microcontrôleur. * * Cet objet est ensuite utilisé par la classe LoRaRadio lors de son initialisation. */ class PinMap { friend class LoRaRadio; public: /*! * Le constructeur de la classe prend en paramètres : * @param nss : la broche du microcontrôleur qui est reliée au chip select du SX127X * @param rxtx : la broche du microcontrôleur qui est reliée à la broche rxtx du SX127X. Si cette broche n'éxiste pas, mettre la valeur : LMIC_UNUSED_PIN. * @param rst : la broche du microcontrôleur qui est reliée à la broche reset du SX127X. * @param dio : un tableau de type u1_t de 3 éléments contenant les broches du microcontrôleur qui sont respectivement reliée aux broches DIO0, DIO1 et DIO2 du SX127X. * Les broches DIOX transmettent des informations à la LMIC. Par exemple dans le mode LoRa, DIO0 correspond à TxDone et RxDone et DIO1 à RxTimeout. * DIO2 peut quand à lui prendre la valeur LMIC_UNUSED_PIN. */ PinMap(u1_t nss, u1_t rxtx, u1_t rst, const u1_t dio[3]) : _nss(nss), _rxtx(rxtx), _rst(rst) { _dio[0] = dio[0]; _dio[1] = dio[1]; _dio[2] = dio[2]; } protected: private: u1_t _nss, _rxtx, _rst, _dio[3]; }; /*! @brief La classe LoRaRadio permet de manipuler le module radio. * */ class LoRaRadio { public: /*! * Le constructeur de la classe prend en paramètres : * @param pinMap : un objet de type PinMap créé préalablement. * @param dataRate : de type dr_t indiquant quel spreading factor utiliser lors des envoies de données. Les valeurs possibles : DR_SF7B, DR_SF7, DR_SF8, DR_SF9, DR_SF10, DR_SF11, DR_SF12, DR_FSK et DR_NONE. * Plus le SF choisi est faible, plus le débit est élevé mais plus l'imunité face au bruit est mauvaise. * @param txPower : puissance d'émission comprise entre 7 et 27 inclu (à vérifier). */ LoRaRadio(PinMap pinMap, dr_t dataRate = DR_SF7, s1_t txPower = 23); /*! * Initialise le SX127X. Cette méthode doit obligatoirement être appelée en premier. */ void init(); /*! * Permet de renseigner les informations de la session TTN à utiliser. * @param channelId : l'id du canal * @param deviceAddress : l'adresse unique du noeud LoRa. Information disponible dans la console TTN. * @param networkSystemKey : la clef de chiffrement réseau. Information disponible dans la console TTN. * @param applicationSystemKey : la clef de chiffrement application. Information disponible dans la console TTN. * @param linkCheckMode : Active ou désactive la vérification périodique du lien. */ void setTTNSession(u4_t channelId, devaddr_t deviceAddress, xref2u1_t networkSystemKey, xref2u1_t applicationSystemKey, bit_t linkCheckMode = 0); /*! * Paramètre la radio pour utiliser les fréquences européennes comprises entre 867.1Mhz et 868.1Mhz. */ void setRadioEUChannels(); /*! * Directive permettant de compenser les imprécisions dû au cristal en alongeant la fenêtre de réception. Cette méthode est à utiliser si le downlink n'est pas reçu par le noeud. * @param percent : l'erreur de précision en % à corriger. */ void setMCUClockError(u2_t percent = 30); /*! * Envoi une trame à la gateway LoRa. * @param port : port de réception de la trame dans la console TTN. Peut prendre la valeur 1,2,3,4,5... * @param *data : pointeur sur un tableau d'uint8_t contenant les données à envoyer. La longueur maximale des données et de 51 octets/trame quelque soit le spreading factor selectionné. * @param length : le nombre d'octets de données. * @param confirmed : demander un accusé de réception lors de l'envoi. */ void send(u1_t port, uint8_t *data, uint8_t length, u1_t confirmed = false); /*! * Méthode à appeler dans la boucle principale afin que le module opère correctement. * */ void run(); /*! * Méthode qui enregistre un callback (pointeur de fonction) qui sera appelé lors de la réception d'un downlink. * @param *funcP : un pointeur sur fonction qui prend 3 paramètres. la longueur de la données reçu, l'indice de la première donnée dans le buffer et un pointeur sur le buffer. */ void setDownlinkHandler(void (*funcP)(u1_t, u1_t, u1_t*)); /*! * Méthode qui enregistre un callback (pointeur de fonction) qui sera appelé lorsque les donnée auront fini d'être envoyées suite à un appel à send(). * @param *funcP : un pointeur sur fonction qui ne prend pas de paramètre. */ void setSendCompleteHandler(void (*funcP)(void)); /*! * Permet de désactiver un canal et donc une fréquence d'envoie. * @param channel : le canal en question. */ void disableEUChannel(u1_t channel); /*! * Permet de désactiver tous les canaux sauf un. * @param channel : le canal à laisser actif. */ void disableAllEUChannelsBut(u1_t channel); /*! * Définition du prototype de la fonction nécessaire au bon fonctionnement de la LMIC. */ friend void onEvent(ev_t ev); protected: private: //Function pointers used to interact with events //Parameters : dataLen, dataBeg, dataBuffer static void (*downlinkHandler)(u1_t, u1_t, u1_t*); static void (*sendCompleteHandler)(void); dr_t _dataRate; s1_t _txPower; PinMap _pinMap; }; #endif //LORARADIO_H