Clémence LeleuNicolas DAILLYGaetanSuch
Published

TP Monitoring

A custom Arduino MKR 1310 IoT shield designed to digitize classroom interaction through a secure LoRaWAN architecture and low-power hardware

IntermediateFull instructions provided24 hours27
TP Monitoring

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
Precisions : Arduino MKR 1310
×1
5 mm LED: Red
5 mm LED: Red
×1
5 mm LED: Yellow
5 mm LED: Yellow
×1
5 mm LED: Green
5 mm LED: Green
×1
Resistor 1k ohm
Resistor 1k ohm
×3
RedMicro Push button Switch
×1

Software apps and online services

The Things Stack
The Things Industries The Things Stack

Story

Read more

Custom parts and enclosures

CAO

All custom-designed components, including 3D modeling assets are available in the attached ZIP archive.

Schematics

Kicad - PCB Source

All custom-designed components, including PCB are available in the attached ZIP archive.

Code

V4.Connectivité_LoRaWAN.ino

Arduino
The program serves as the system's intelligence, bridging the gap between the user and the LoRaWAN network. It monitors the physical buttons using a software debouncing filter to prevent false triggers, then securely transmits each action to The Things Network (TTN) via the OTAA protocol. To ensure operational reliability, the code includes a visual error-handling routine: the LEDs provide immediate confirmation of a successful uplink or alert the user in case of connection failure, all while strictly adhering to European transmission standards (Duty Cycle) through an integrated safety delay.
#include <MKRWAN.h>


bool MODE_SIMULATION = false; 

// Broches (Pins)
const int PINS_BP[] = {3, 4, 5};   
const int PINS_LED[] = {8, 7, 6};  

LoRaModem modem;

String appEui = "0000000000000000"; 
String appKey = "YOUR_SECRET_KEY"; 

int modeActuel = 0;
unsigned long dernierEnvoi = 0;
const unsigned long DELAI_ANTI_SPAM = 10000; //Duty cycle de 10s - respect de la norme

void setup() {
  Serial.begin(9600);
  
  unsigned long startWait = millis();
  while (!Serial && millis() - startWait < 3000);

  Serial.println("DEMARRAGE DU SYSTEME");

  for (int i = 0; i < 3; i++) {
    pinMode(PINS_BP[i], INPUT_PULLUP);
    pinMode(PINS_LED[i], OUTPUT);
    digitalWrite(PINS_LED[i], LOW);
  }

  testLeds();

  if (MODE_SIMULATION) {
    Serial.println("MODE : SIMULATION ACTIVE");
  } else {
    Serial.println("MODE : REEL (Initialisation LoRa...)");
    
    // Initialisation du module sur la frquence Europe
    if (!modem.begin(EU868)) {
      Serial.println("ERREUR : Module LoRa introuvable.");
      while (1) clignoterErreur(); 
    }
    
    // Tentative de connexion OTAA
    Serial.println("Connexion  TTN via OTAA...");
    if (!modem.joinOTAA(appEui, appKey)) {
      Serial.println("ERREUR : Echec de connexion (Vrifiez couverture/identifiants).");
      // On ne bloque pas forcment ici, on pourra ressayer plus tard
    } else {
      Serial.println("Connect  TTN avec succs !");
      modem.minPollInterval(60); // Optimisation de la batterie/rception
    }
  }
}

void loop() {
  for (int i = 0; i < 3; i++) {
    // Lecture avec un petit anti-rebond 
    if (digitalRead(PINS_BP[i]) == LOW) {
      delay(50); // Anti-rebond
      if (digitalRead(PINS_BP[i]) == LOW) {
        gererAppui(i + 1, PINS_LED[i]);
      }
    }
  }
}

void gererAppui(int numMode, int pinLED) {
  if (numMode == modeActuel) return;

  if (millis() - dernierEnvoi < DELAI_ANTI_SPAM) {
    Serial.println("Trop rapide ! Patientez...");
    return;
  }

  Serial.print("Envoi Mode: "); Serial.println(numMode);

  bool succesEnvoi = false;

  if (MODE_SIMULATION) {
    delay(500);
    succesEnvoi = true; 
    Serial.println("[SIMU] Envoy.");
  } else {
    // Vrifier si nous sommes bien connects avant d'envoyer
    modem.beginPacket();
    modem.write((uint8_t)numMode); // On caste en uint8_t pour envoyer 1 seul octet
    int err = modem.endPacket(true);
    
    if (err > 0) {
      succesEnvoi = true;
    } else {
      Serial.print("Erreur code: "); Serial.println(err);
    }
  }

  if (succesEnvoi) {
    Serial.println("Succs !");
    modeActuel = numMode;
    dernierEnvoi = millis();
    majAffichageLed(pinLED);
  } else {
    Serial.println("ECHEC de l'envoi.");
    clignoterErreur();
    // On rallume la LED du mode prcdent
    if (modeActuel > 0) {
       majAffichageLed(PINS_LED[modeActuel - 1]);
    }
  }
}

void majAffichageLed(int pinAAllumer) {
  for (int i = 0; i < 3; i++) {
    digitalWrite(PINS_LED[i], LOW);
  }
  digitalWrite(pinAAllumer, HIGH);
}

void clignoterErreur() {
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) digitalWrite(PINS_LED[j], HIGH);
    delay(150);
    for (int j = 0; j < 3; j++) digitalWrite(PINS_LED[j], LOW);
    delay(150);
  }
}

void testLeds() {
  for (int i = 0; i < 3; i++) {
    digitalWrite(PINS_LED[i], HIGH);
    delay(100);
    digitalWrite(PINS_LED[i], LOW);
  }
}

Credits

Clémence Leleu
1 project • 0 followers
Nicolas DAILLY
42 projects • 32 followers
Associated Professor at UniLaSalle - Amiens / Head of the Computer Network Department / Teach Computer and Telecommunication Networks
GaetanSuch
1 project • 0 followers

Comments