Ceci est une ancienne révision du document !
Table des matières
Le transceiver (émetteur/récepteur) LoRa E45-TTL-100
- Basé sur le SX1276 de semtech.
- “E32-868T20D”
- Pilotable avec un UART.
- Mono canal.
- 100 mW
- Pas de support pour le RSSI (Radio Signal Strength Indicator)
- Consommation un peu trop élever pour être alimenté par le 3.3V de l'ESP32.
Fabrication d'un kit de mesure du signal LoRa
2 Modules :
- 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
Algorithme de négociation du spread factor :
- Si pas de méssage valide depuis linkDeadTimeout, on écoute sur le plus gros SF.
- Si validMessageCountSpeedIncreaseThreshold messages séquentielle valides reçu alors on tente d'augmenter le SF
- 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 pas l'augmentation de SF avant un temps waitBeforeSpeedIncreaseInterval
- 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 / SFdebit
- waitBeforeSpeedIncreaseInterval > 10 * messageTransmissionTime ?
Contenu des messages :
- indicateur de session
- indicateur de sequence
- SF demandé
Code :
Gateway
SPEED_INC_VALID_MSG_COUNT = SPEED_INC_REQ_COUNT = WAIT_ACK_TIMEOUT = TOO_FAST_TIMEOUT = LINK_DEAD_TIMEOUT = MIN_AIR_RATE = 0; MAX_AIR_RATE = 5;
String sessionId = null; int seqId = -1; 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 + "_" + seqId + "_"; 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 - 1, MIN_AIR_RATE); }
}
Emetteur
SPEED_INC_VALID_MSG_COUNT = SPEED_INC_REQ_COUNT = WAIT_ACK_TIMEOUT = TOO_FAST_TIMEOUT = LINK_DEAD_TIMEOUT = MIN_AIR_RATE = 0; MAX_AIR_RATE = 5;
String sessionId = random; int seqId = 0; byte airRate = 0; int sequentialValidMessages = 0; int speedIncreaseReqCount = 0;
long lastValidMessageReceivedTimestamp = now();
while(lastValidMessageReceivedTimestamp + LINK_DEAD_TIMEOUT > now()) {
message = sessionId + "_" + seqId + "_"; if (sequentialValidMessages > SPEED_INC_VALID_MSG_COUNT) { message = message + (airRate + 1); }
boolean notAckedMessage = true; while (notAckedMessage && lastMessageSentTimestamp + TOO_FAST_TIMEOUT > now()) { // Try to send a message and get an ACK for TOO_FAST_TIMEOUT sendMessage(message); long lastMessageSentTimestamp = now(); while (notAckedMessage && lastMessageSentTimestamp + WAIT_ACK_TIMEOUT > now()) { // Try to get an ACK for WAIT_ACK_TIMEOUT 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); }
}
Ressources
- Quelques billets de blog : https://quadmeup.com/tag/e45-ttl-100/