e45-ttl-100
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 | ||
e45-ttl-100 [2019/01/17 04:35] – bigMax | e45-ttl-100 [2020/10/29 13:58] (Version actuelle) – ↷ Liens modifiés en raison d'un déplacement. serge | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== Le transceiver (émetteur/ | + | ====== Le modem LoRa E45-TTL-100 ====== |
+ | <WRAP center round important 60%> | ||
+ | Ce device n'est pas compatible avec LoRaWAN. | ||
+ | </ | ||
+ | |||
+ | * " | ||
* Basé sur le SX1276 de semtech. | * Basé sur le SX1276 de semtech. | ||
* " | * " | ||
Ligne 8: | Ligne 13: | ||
* Consommation un peu trop élever pour être alimenté par le 3.3V de l' | * Consommation un peu trop élever pour être alimenté par le 3.3V de l' | ||
- | ===== Fabrication d'un kit de mesure du signal LoRa ===== | + | ===== Fabrication d'un kit de mesure du signal |
- | 2 Modules : | + | [[ max_lora_signal_test_kit | Une page est dédié ]] |
- | * Une module mobile qui emet des messages et mesure la qualité du signal et le débit (ou meilleut spread factor) utilisable. | + | |
- | * Une simili gateway fixe qui répond au message LoRa | + | |
+ | ===== Incompatible avec LoRaWAN ===== | ||
+ | Le e45-ttl-100 n'est pas compatible avec LoRaWAN. | ||
- | Algorithme de négociation du spread factor : | + | Tous les device LoRa ne semble |
- | * Si pas de méssage valide depuis linkDeadTimeout, | + | La bibliothèque [[ https://github.com/sandeepmistry/arduino-LoRa ]] est codé pour dialoguer avec le protocole sérié SPI. Or le e45-ttl-100 communique avec le protocole série UART. |
- | * Si validMessageCountSpeedIncreaseThreshold messages séquentielle valides reçu alors on tente d' | + | |
- | * Si on a reçu speedIncreaseRequestCount demandes séquentielles valides de changement de SF on change de SF. | + | |
- | * Si on a pas reçu de message depuis tooFastTimeout on décrémente le SF. | + | |
- | * Après un retour à la normal suite à un tooFastTimeout on ne retente | + | |
- | * La gateway acquitte les méssages en retournant le message avec le numéro de sequence incrémenté. | + | |
- | * Tant qu'un message n'est pas acquitté il est retransmis. | + | |
- | * linkDeadTimeout > 2 x tooFastTimeout | + | |
- | * tooFastTimeout dépend du SF tel que tooFastTimeout > 2 x messageTransmissionTime | + | |
- | * messageTransmissionTime = messageSize | + | |
- | * waitBeforeSpeedIncreaseInterval > 10 * messageTransmissionTime ? | + | |
- | + | ||
- | Contenu des messages : | + | |
- | * indicateur de session | + | |
- | * indicateur de sequence | + | |
- | * SF demandé | + | |
- | + | ||
- | + | ||
- | ==== Gateway | + | |
- | <code c> | + | |
- | SPEED_INC_VALID_MSG_COUNT = 5; | + | |
- | SPEED_INC_REQ_COUNT = 2; | + | |
- | WAIT_ACK_TIMEOUT = 10000; | + | |
- | TOO_FAST_TIMEOUT = WAIT_ACK_TIMEOUT * 2 + 1000; | + | |
- | LINK_DEAD_TIMEOUT = TOO_FAST_TIMEOUT * 2 + 1000; | + | |
- | MIN_AIR_RATE = 0; | + | |
- | MAX_AIR_RATE = 5; | + | |
- | + | ||
- | String sessionId = null; | + | |
- | int seqId = 0; | + | |
- | byte airRate = 0; | + | |
- | int sequentialValidMessages = 0; | + | |
- | int speedIncreaseReqCount = 0; | + | |
- | + | ||
- | long lastValidMessageReceivedTimestamp = now(); | + | |
- | + | ||
- | while(lastValidMessageReceivedTimestamp + LINK_DEAD_TIMEOUT > now()) { | + | |
- | + | ||
- | boolean notValidMessage = true; | + | |
- | while (notValidMessage && lastMessageSentTimestamp + TOO_FAST_TIMEOUT > now()) { | + | |
- | String receivedMsg = receiveMessage(); | + | |
- | int msgSessionId = receivedMsg.substring(); | + | |
- | int msgSeqId = receivedMsg.substring(); | + | |
- | + | ||
- | if (sessionId == null && msgSeqId == 0 || sessionId == msgSessionId && msgSeqId == seqId + 1) { | + | |
- | int msgRequestedAirRate = receivedMsg.substring(); | + | |
- | seqId = msgSeqId + 1; | + | |
- | String ack = msgSessionId + " | + | |
- | + | ||
- | if (msgRequestedAirRate == airRate + 1) { | + | |
- | speedIncreaseReqCount ++; | + | |
- | ack = ack + (airRate + 1); | + | |
- | } | + | |
- | + | ||
- | sendMessage(ack); | + | |
- | + | ||
- | if (speedIncreaseReqCount > SPEED_INC_REQ_COUNT) { | + | |
- | speedIncreaseReqCount = 0; | + | |
- | requestedAirRate = min(requestedAirRate + 1, MAX_AIR_RATE); | + | |
- | configLora(requestedAirRate); | + | |
- | } | + | |
- | + | ||
- | } | + | |
- | } | + | |
- | + | ||
- | if (notValidMessage) { | + | |
- | sequentialValidMessages = 0; | + | |
- | requestedAirRate = max(requestedAirRate | + | |
- | } | + | |
- | + | ||
- | } | + | |
- | </code> | + | |
- | + | ||
- | ==== Emetteur ==== | + | |
- | <code c> | + | |
- | SPEED_INC_VALID_MSG_COUNT = 5; | + | |
- | SPEED_INC_REQ_COUNT = 2; | + | |
- | WAIT_ACK_TIMEOUT = 10000; | + | |
- | TOO_FAST_TIMEOUT = WAIT_ACK_TIMEOUT * 2 + 1000; | + | |
- | LINK_DEAD_TIMEOUT = TOO_FAST_TIMEOUT * 2 + 1000; | + | |
- | WAIT_BEFORE_SPEED_INC_INTERVAL = 10 * WAIT_ACK_TIMEOUT; | + | |
- | MIN_AIR_RATE = 0; | + | |
- | MAX_AIR_RATE = 5; | + | |
- | + | ||
- | String sessionId = random; | + | |
- | int seqId = 1; | + | |
- | byte airRate = 0; | + | |
- | int sequentialValidMessages = 0; | + | |
- | int speedIncreaseReqCount = 0; | + | |
- | + | ||
- | long lastValidMessageReceivedTimestamp = now(); | + | |
- | long lastTooFastTimeout = 0; | + | |
- | + | ||
- | while(lastValidMessageReceivedTimestamp + LINK_DEAD_TIMEOUT > now()) { | + | |
- | message = sessionId + " | + | |
- | if (lastTooFastTimeout + WAIT_BEFORE_SPEED_INC_INTERVAL < now() && sequentialValidMessages > SPEED_INC_VALID_MSG_COUNT) { | + | |
- | message = message + (airRate + 1); | + | |
- | } | + | |
- | + | ||
- | boolean notAckedMessage = true; | + | |
- | while (notAckedMessage && lastMessageSentTimestamp + TOO_FAST_TIMEOUT > now()) { | + | |
- | | + | |
- | + | ||
- | sendMessage(message); | + | |
- | long lastMessageSentTimestamp = now(); | + | |
- | while (notAckedMessage && lastMessageSentTimestamp + WAIT_ACK_TIMEOUT > now()) { | + | |
- | | + | |
- | + | ||
- | String receivedMsg = receiveMessage(); | + | |
- | int msgSessionId = receivedMsg.substring(); | + | |
- | int msgSeqId = receivedMsg.substring(); | + | |
- | + | ||
- | if (msgSessionId == sessionId && msgSeqId == seqId + 1) { | + | |
- | sequentialValidMessages ++; | + | |
- | int msgRequestedAirRate = receivedMsg.substring(); | + | |
- | if (msgRequestedAirRate == airRate + 1) { | + | |
- | speedIncreaseReqCount ++; | + | |
- | + | ||
- | if (speedIncreaseReqCount > SPEED_INC_REQ_COUNT) { | + | |
- | speedIncreaseReqCount = 0; | + | |
- | airRate = min(airRate + 1, MAX_AIR_RATE); | + | |
- | configLora(requestedAirRate); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | notAckedMessage = false; | + | |
- | seqId = msgSeqId + 1; | + | |
- | lastValidMessageReceivedTimestamp = now(); | + | |
- | + | ||
- | } else { | + | |
- | sequentialValidMessages = 0; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | if (notAckedMessage) { | + | |
- | sequentialValidMessages = 0; | + | |
- | airRate = max(airRate - 1, MIN_AIR_RATE); | + | |
- | lastTooFastTimeout = now(); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | </ | + | |
===== Ressources ===== | ===== Ressources ===== | ||
- | * {{ :: | + | * {{ media_03: |
- | * {{ :: | + | * {{ media_08: |
* [[ http:// | * [[ http:// | ||
* Quelques billets de blog : [[ https:// | * Quelques billets de blog : [[ https:// | ||
+ | |||
+ | |||
+ | {{tag> |
e45-ttl-100.txt · Dernière modification : 2020/10/29 13:58 de serge