diy:projets:tl_partieemetteur
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
diy:projets:tl_partieemetteur [2018/05/26 13:56] – [Les changements d'états de la led] sdurand | diy:projets:tl_partieemetteur [2018/07/02 09:34] (Version actuelle) – [Le programme principal et la fonction qui gère la led] sdurand | ||
---|---|---|---|
Ligne 41: | Ligne 41: | ||
</ | </ | ||
avec **V** qui peut valoir **1 pour éteindre la led** ou **0 pour allumer la led** (**ceci dépend de la façon | avec **V** qui peut valoir **1 pour éteindre la led** ou **0 pour allumer la led** (**ceci dépend de la façon | ||
- | dont vous avez branché la led au raspberry**) et **X** qui est toujours le **numéro du pin de la led**. | + | dont vous avez branché la led au raspberry**, notre branchement est sans doute hasardeux) 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: | Quand vous aurez fini de jouer, vous devrez dé-exportez la led. Là aussi, c'est très simple: | ||
Ligne 52: | Ligne 53: | ||
**effectuer toutes les opérations** dont je viens de vous parler, c'est comme ça que je vous recommande de procéder. | **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 | J'ai personnellement choisi de **créer une classe** pour encapsuler ces opérations. Le code de cette classe est | ||
- | disponible | + | disponible |
tout réécrire vous même. | tout réécrire vous même. | ||
Ligne 121: | Ligne 122: | ||
Passons maintenant au coeur du programme, la **conversion de bits en signaux lumineux**. Nous allons commencer | Passons maintenant au coeur du programme, la **conversion de bits en signaux lumineux**. Nous allons commencer | ||
- | par créer la boucle nous permettant d' | + | par créer la boucle nous permettant d' |
**la norme C++14**, vous pouvez faire ça comme suit: | **la norme C++14**, vous pouvez faire ça comme suit: | ||
<code C++> | <code C++> | ||
Ligne 142: | Ligne 143: | ||
</ | </ | ||
+ | Au final, **votre code devrait ressembler a quelque chose comme ça**: | ||
+ | <code C++> | ||
+ | void transmit(LedController& | ||
+ | // On initialise la variable timer comme le temps référence de notre transmission | ||
+ | auto timer = std:: | ||
+ | // On allume la led pour signaler au récepteur le début de la transmission | ||
+ | | ||
+ | // On parcourt le message | ||
+ | | ||
+ | // On parcourt les bits de chaque caractère | ||
+ | for(unsigned int i = 0; i < 8; i++) { | ||
+ | // On incrémente le timer d'un pas pré-calculé (dépendant le la fréquence de transmission choisie) | ||
+ | timer += time_step; | ||
+ | // On regarde avant la pause si on doit allumer ou non la led | ||
+ | const bool lightUp = c & powers_of_two[i]; | ||
+ | // On attend | ||
+ | | ||
+ | |||
+ | // On positionne la led dans le bon état | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | // On attend suffisamment pour que le récepteur reçoive un octet de zéros pour marquer la fin de transmission | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | En ce qui concerne **les pauses**, je vous invite simplement à consulter le code ci-dessus, | ||
+ | vous avez sans doute remarquer que le " | ||
+ | détaillées. | ||
---- | ---- | ||
Ligne 148: | Ligne 183: | ||
===== Sources du projet ===== | ===== Sources du projet ===== | ||
- | La totalité des sources de cette partie du projet sont disponibles à [[https://github.com/SDurand7/LedTransmitter|cette addresse]]. | + | ==== La classe pour contrôler le gpio ==== |
- | Je vous invite à consulter le guide vers la partie émetteur pour récupérer les sources de la partie récepteur. | + | |
+ | <code C++> | ||
+ | #include " | ||
+ | |||
+ | |||
+ | // Private method that export the choosen gpio | ||
+ | void LedController:: | ||
+ | std:: | ||
+ | |||
+ | if(!exportFile.is_open()) { | ||
+ | std::cerr << " | ||
+ | throw ERR_EXPORT; | ||
+ | } | ||
+ | |||
+ | exportFile << this-> | ||
+ | exportFile.close(); | ||
+ | } | ||
+ | |||
+ | |||
+ | // Private method that unexport the previously opened gpio | ||
+ | void LedController:: | ||
+ | std:: | ||
+ | |||
+ | if(!unexportFile.is_open()) { | ||
+ | std::cerr << " | ||
+ | throw ERR_UNEXPORT; | ||
+ | } | ||
+ | |||
+ | unexportFile << this-> | ||
+ | unexportFile.close(); | ||
+ | } | ||
+ | |||
+ | |||
+ | // Constructor of our class: | ||
+ | // numero: numero of the gpio's pin we want to open | ||
+ | // dirOut: boolean indicating if the direction we want is out or not (as it is a LedController, | ||
+ | // litUp: boolean indicating if the led should be initially on or off | ||
+ | LedController:: | ||
+ | this-> | ||
+ | |||
+ | export_gpio(); | ||
+ | // Adding a little delay to make sure that the files created when exporting exists before we start working on them | ||
+ | std:: | ||
+ | |||
+ | std:: | ||
+ | |||
+ | if(!directionFile.is_open()) { | ||
+ | unexport_gpio(); | ||
+ | |||
+ | std::cerr << " | ||
+ | throw ERR_EXPORT; | ||
+ | } | ||
+ | |||
+ | // Setting the direction according to the boolean dirOut | ||
+ | directionFile << (dirOut ? " | ||
+ | directionFile.close(); | ||
+ | |||
+ | if(!litUp) { | ||
+ | turnOff(); | ||
+ | } | ||
+ | else { | ||
+ | turnOn(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | // Destructor that will unexport the gpio previously opened | ||
+ | LedController:: | ||
+ | unexport_gpio(); | ||
+ | } | ||
+ | |||
+ | |||
+ | // Public method lighting up the led | ||
+ | void LedController:: | ||
+ | std:: | ||
+ | |||
+ | value.open(std:: | ||
+ | |||
+ | if(!value.is_open()) { | ||
+ | unexport_gpio(); | ||
+ | |||
+ | std::cerr << " | ||
+ | throw ERR_VALUE; | ||
+ | } | ||
+ | |||
+ | value << " | ||
+ | |||
+ | value.close(); | ||
+ | } | ||
+ | |||
+ | |||
+ | // Public method turning off the led | ||
+ | void LedController:: | ||
+ | std:: | ||
+ | |||
+ | value.open(std:: | ||
+ | |||
+ | if(!value.is_open()) { | ||
+ | unexport_gpio(); | ||
+ | |||
+ | std::cerr << " | ||
+ | throw ERR_VALUE; | ||
+ | } | ||
+ | |||
+ | value << " | ||
+ | |||
+ | value.close(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Son header ==== | ||
+ | |||
+ | <code C++> | ||
+ | #ifndef LEDCONTROLLER_HPP | ||
+ | #define LEDCONTROLLER_HPP | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | // Refer to the constructor source code for more info on this define | ||
+ | #define EXPORT_DELAY 400 | ||
+ | |||
+ | // A few define to make errors handling clearer | ||
+ | #define ERR_EXPORT -2 | ||
+ | #define ERR_UNEXPORT -3 | ||
+ | #define ERR_VALUE -4 | ||
+ | #define ERR_DIRECTION -5 | ||
+ | |||
+ | |||
+ | |||
+ | class LedController { | ||
+ | public: | ||
+ | LedController(int numero, bool dirOut = true, bool litUp = false); | ||
+ | ~LedController(); | ||
+ | |||
+ | void turnOn(); | ||
+ | void turnOff(); | ||
+ | |||
+ | private: | ||
+ | void export_gpio(); | ||
+ | void unexport_gpio(); | ||
+ | int numero; | ||
+ | }; | ||
+ | |||
+ | #endif | ||
+ | </ | ||
+ | |||
+ | ==== Le programme principal et la fonction qui gère la led ==== | ||
+ | |||
+ | <code C++> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | #define GPIO_PIN 21 | ||
+ | #define BITRATE 20 | ||
+ | #define BITTIME static_cast< | ||
+ | |||
+ | #define ALL_GOOD 0 | ||
+ | |||
+ | |||
+ | const auto time_step = std:: | ||
+ | // We are asuming here that a char is always an octet, and we will assume in every part of the code | ||
+ | const unsigned char powers_of_two[8] = {128, 64, 32, 16, 8, 4, 2, 1}; | ||
+ | |||
+ | |||
+ | // Function that iterates over message and switch on and off the led of lc according to the bits | ||
+ | void transmit(LedController& | ||
+ | // Initializing timer as the reference time | ||
+ | auto timer = std:: | ||
+ | // Turning on the light to tell the receptor we're starting to emit | ||
+ | lc.turnOn(); | ||
+ | |||
+ | // Iterating over the message | ||
+ | for(const char& c: message) { | ||
+ | // Iterating over the bits of c (again, we're assuming that a char is an octet long) | ||
+ | for(unsigned int i = 0; i < 8; i++) { | ||
+ | // Incrementing the timer, computing wether we should lightUp the led or not, and sleeping until it's time to change the state of the led | ||
+ | timer += time_step; | ||
+ | const bool lightUp = c & powers_of_two[i]; | ||
+ | std:: | ||
+ | |||
+ | lightUp ? lc.turnOn() : lc.turnOff(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | std:: | ||
+ | lc.turnOff(); | ||
+ | |||
+ | // Sleeping long enough to make sure that the receptor received at least a full octet of zeros (it will mark the end of transmission for it) | ||
+ | std:: | ||
+ | } | ||
+ | |||
+ | // This main simply get the input from stdin and act in consequence | ||
+ | int main() { | ||
+ | LedController lc(GPIO_PIN); | ||
+ | std:: | ||
+ | |||
+ | // Getting the first string | ||
+ | std::cout << " | ||
+ | std:: | ||
+ | |||
+ | // Sending message if it is different of "/ | ||
+ | // "/ | ||
+ | while(message != "/ | ||
+ | // I feel like it's ok to not use a switch because I don't plan to add more commands, but if you plan to, you should definitely use one | ||
+ | if(message == "/ | ||
+ | // The test sequence is a sequence of upper case " | ||
+ | transmit(lc, | ||
+ | } | ||
+ | else { | ||
+ | transmit(lc, | ||
+ | } | ||
+ | |||
+ | std::cout << " | ||
+ | |||
+ | std::cout << " | ||
+ | std:: | ||
+ | } | ||
+ | |||
+ | return ALL_GOOD; | ||
+ | } | ||
+ | </ | ||
---- | ---- | ||
- | // | + | // |
diy/projets/tl_partieemetteur.1527342994.txt.gz · Dernière modification : 2018/05/26 13:56 de sdurand