🛠 Uplinks confirmés robustes et duty cycle
Objectifs
Fiabiliser les envois LoRaWAN de la MKR WAN 1310 : uplinks confirmés avec ACK, respect du plancher firmware d'une émission par 2 minutes (duty cycle EU, non modifiable), file d'attente en RAM, backoff en cas d'échec, et contournement du bug de compteur de trames qui bloque l'émission après ~255 envois (issue MKRWAN #141).
Matériel
- 1 carte MKR WAN 1310 + antenne 868 MHz, déjà jointe en OTAA (voir le tutoriel TTN)
- Compte TTN pour vérifier les ACK côté serveur
Code complet
// Uplink confirme robuste avec file d'attente — MKR WAN 1310
#include <MKRWAN.h>
LoRaModem modem;
String appEui = "0000000000000000";
String appKey = "00000000000000000000000000000000";
const int TAILLE_FILE = 8;
String file[TAILLE_FILE];
int tete = 0, queue = 0, nbFile = 0;
unsigned long dernierEnvoi = 0;
unsigned long totalEnvois = 0;
void setup {
Serial.begin(115200);
while (!Serial);
if (!modem.begin(EU868)) { Serial.println("Module KO"); while (1); }
// Le bug #141 (blocage après ~255 trames) se contourne en re-joignant
// periodiquement : rebegin + joinOTAA tous les 200 envois.
if (!modem.joinOTAA(appEui, appKey)) { Serial.println("Join KO"); while (1); }
modem.minPollInterval(60);
}
void loop {
// Production : ici un capteur ou un bouton empile des messages
if (millis % 60000 < 100 && nbFile < TAILLE_FILE) {
file[queue] = "T=" + String(analogRead(A0));
queue = (queue + 1) % TAILLE_FILE; nbFile++;
}
// Consommation : 1 message / 2 min maximum (plancher firmware EU)
if (nbFile > 0 && millis - dernierEnvoi >= 125000UL) {
modem.beginPacket;
modem.print(file[tete]);
int err = modem.endPacket(true); // true = uplink_confirme (attend ACK)
if (err > 0) {
tete = (tete + 1) % TAILLE_FILE; nbFile--;
totalEnvois++;
Serial.println("ACK recu");
} else {
Serial.println("Sans ACK : on garde en file, backoff 2 min");
}
dernierEnvoi = millis;
if (totalEnvois > 0 && totalEnvois % 200 == 0) {
modem.begin(EU868); // réinitialise le compteur de trames
modem.joinOTAA(appEui, appKey);
}
}
}
Vérification attendue
Chaque message confirmé disparaît de la file et apparaît « confirmé » dans le live data TTN ; un message sans ACK reste en file et repart au cycle suivant. Après plusieurs heures, l'émission ne se bloque plus grâce à la rejonction périodique.
Erreurs fréquentes
- Croire
endPacket(true)infaillible : sans ACK, la fonction renvoie une erreur mais ne réémet pas seule — c'est au sketch de reprendre la main. - Combler le trou avec
delay(1000)entre deux envois : le firmware refuse toute émission à moins de 2 minutes, quelle que soit la configuration logicielle. - Oublier le contournement du bug #141 et voir la carte « muette » après 255 trames sans message d'erreur.
- Ne pas tenir compte de la file pleine : au-delà de 8 messages, décider entre écraser, jeter ou stocker en flash 2 Mo (voir le tutoriel Eslov + flash).
- En classe A, les downlinks n'arrivent que dans les deux fenêtrès RX suivant un uplink : un ACK serveur invisible signifie souvent une fenêtre manquée, pas une clé erronée.
Autres tutoriels pour cette carte
Exemples de code pour cette carte
join-otaa.inoArduinouplink-confirme.inoArduinodownlink.inoArduinoactivation-abp.inoArduinosuivi-adr.inoArduinoclasse-c.inoArduino