#include #include #include //Déclaration des constantes #define RFM95_CS 5 //M5 LoRa #define RFM95_DIO0 36 //M5 LoRa RH_RF95 rf95(RFM95_CS, RFM95_DIO0); uint8_t txbuf[RH_RF95_MAX_MESSAGE_LEN]; //Buffer d'emission uint8_t rxbuf[RH_RF95_MAX_MESSAGE_LEN], rxbuflen=sizeof(rxbuf); //Buffer de reception uint8_t state, RxSeq, TxSeq, credit, backoff, NewFrame, EIT; uint32_t attente; //Constantes d'état #define E0 0 #define E1 1 #define E2 2 #define E3 3 #define E4 4 #define E5 5 //Constantes de type #define TYPE_DATA 1 #define TYPE_ACK 2 #define TIMEOUT_ACK 70 //Constante de crédit #define MAX_CREDIT 5 //Constante d'adresse #define LOCAL_ADDR 2 #define SINK_ADDR 0 //Constantes d'infos champ de trame #define F_S_ADDR 0 //Adresse source #define F_D_ADDR 1 //Adresse destination #define F_TYPE 2 //Type #define F_NUM_SEQ 3 //Numéro de séquence #define F_MIN_PAYLOAD 4 //Indice du debut de payload #define F_MAX_PAYLOAD 9 //Indice de fin de payload #define TAILLE_TRAME 10 //Taille de la trame void setup() { M5.begin(); M5.Power.begin(); Serial.println("====Emetteur CAP4===="); M5.Lcd.println("====Emetteur CAP4===="); delay(3000); if(!rf95.init()){ Serial.println("Echec de la mise en place"); M5.Lcd.println("Echec de la mise en place"); } else{ Serial.println("Mise en place reussie !!!"); M5.Lcd.println("Mise en place reussie !!!"); //Configuration de la radio rf95.setModemConfig(RH_RF95::Bw125Cr45Sf128); rf95.setFrequency(867.8); state=E0; TxSeq=0; credit=MAX_CREDIT; Serial.println("Boucle principale."); M5.Lcd.println("Boucle principale."); NewFrame=1; //Initialisation drapeau randomSeed(analogRead(30)); // Initialisation utilisant la broche GPIO39 (VN) delay(10000); } } void loop() { switch(state){ case E0: //Code source à l'état d'émission if(NewFrame==1){ EIT=random(80,120)*random(80,123); delay(EIT); //attente pour l'envoi de la nouvelle trame Serial.printf(" EIT : %d ", EIT); Serial.println(); M5.Lcd.printf(" EIT : %d ", EIT); M5.Lcd.println(); } //Formatage des champs de la trame txbuf[F_S_ADDR]=LOCAL_ADDR; txbuf[F_D_ADDR]=SINK_ADDR; txbuf[F_TYPE]=TYPE_DATA; txbuf[F_NUM_SEQ]=TxSeq; //Ajout de la payload for(int i=F_MIN_PAYLOAD; i<=F_MAX_PAYLOAD;i++){ txbuf[i]=random(0, 256); } Serial.printf("EMISSION %d", TxSeq); Serial.println(); M5.Lcd.printf("EMISSION %d \n", TxSeq); Serial.println(); rf95.send(txbuf,TAILLE_TRAME); //Envoi des données rf95.waitPacketSent(); credit -=1; state=E1; break; case E1: //CdG attente = millis()+TIMEOUT_ACK; //Armement du Chien de Garde state = E2; break; case E2: //Mode Réception rf95.setModeRx(); state=E3; break; case E3: if(millis() > attente){ //Test expiration CdG Serial.println("===CDG expire==="); M5.Lcd.println("===CDG expire==="); state=E5; //Délais expiré } else{ if(rf95.recv(rxbuf, &rxbuflen)){ if((rxbuf[F_TYPE]==TYPE_ACK) && (rxbuf[F_NUM_SEQ]==TxSeq) && (rxbuf[F_D_ADDR]==LOCAL_ADDR)){ //Reception d'un ACK avec le bon num de séquence et la bonne adresse de destination state=E4; } else{ state=E2; } } } break; case E4: Serial.printf("ACK_RECU [%d] \n", TxSeq); M5.Lcd.printf("ACK_RECU [%d] \n", TxSeq); state=E0, TxSeq+=1, credit=5; break; case E5: //Serial.printf("Probleme\n"); //M5.Lcd.printf("Probleme\n"); if (credit==0){ Serial.print("ECHEC\n"); M5.Lcd.print("ECHEC\n"); state=E0; credit=MAX_CREDIT; TxSeq+=1; NewFrame=1; } else{ Serial.printf("Collision ? Nouvelle tentative n %d\n", MAX_CREDIT-credit); M5.Lcd.printf("Collision ? Nouvelle tentative n %d\n", MAX_CREDIT-credit); state=E0; NewFrame=0; //Toujours la même trame backoff=random(80,120)*random(80,123); delay(backoff); //Attente aléatoire ALOHA Serial.printf(" backoff : [[%d]] ", backoff); M5.Lcd.printf(" backoff : [[%d]] ", backoff); Serial.println(); M5.Lcd.println(); } break; default: state=E0; break; } }