Festival IoT

Make your festival connected with Festival IoT.

IntermediateFull instructions provided165
Festival IoT

Things used in this project

Story

Read more

Custom parts and enclosures

Report project

This is the report about the project

Video of the project

Here you can watch the video who's explain the project.

Schematics

Schema about the communication

With this, you can see how the communication works

Code

Arduino Code

C/C++
Thats the Arduino's code
#include <Wire.h>
#include <math.h>
#include <MKRWAN.h>
#include <SPI.h>
#include <MFRC522.h>

// =====================
// Partie LoRa & SPL
// =====================
LoRaModem modem;

// Configuration du capteur sonore
const int sampleWindow = 50; // fenêtre d'échantillonnage en ms (50 ms = 20 Hz)
#define SENSOR_PIN A0       // broche du capteur analogique

// Variables pour le calcul du SPL
unsigned int sample;
unsigned long startMillis;
unsigned int signalMax;
unsigned int signalMin;
float peakToPeak;
float voltage;
float dbSPL;

// Clés LoRa OTAA
#include "arduino_secrets.h"
String appEui = "1510200413062001";
String appKey = "0DF8488934F5A2FA1404C319199B87F3";

// =====================
// Partie RFID RC522
// =====================
// Définition des broches du RC522
#define RST_PIN  5   // Broche de réinitialisation du RC522
#define SS_PIN   4   // Broche de sélection (SDA) du RC522

// Création de l'instance MFRC522
MFRC522 mfrc522(SS_PIN, RST_PIN);

// Flag pour indiquer qu'une carte a déjà été envoyée (tant qu'elle est dans le champ)
bool cardSent = false;

// Temps de référence pour l'envoi du SPL
unsigned long lastSPLTime = 0;
const unsigned long splInterval = 20000;  // 20 secondes

// ★ Taille max d'un UID RFID (ISO14443 : 4, 7 ou 10 octets)
#define MAX_UID_LENGTH 10

// ★ Ajouts pour le mode association
enum State { NORMAL, ASSOC };
State state = NORMAL;
unsigned long assocStart = 0;
const unsigned long ASSOC_TIMEOUT = 30000; // 30 secondes

// ★ UID du badge maître (à adapter à votre badge maître)
const byte masterUID[] = { 0x3B, 0x04, 0xA0, 0x00 };
const byte masterUIDLen = sizeof(masterUID);

// ★ ID unique de l’objet (1 octet, à définir)
const uint8_t objectID = 0x42;

// ★ Helper pour comparer deux UID
bool compareUID(const byte *a, const byte *b, byte len) {
  for (byte i = 0; i < len; i++)
    if (a[i] != b[i]) return false;
  return true;
}

// ★ Fonction helper pour envoi RFID standard
void sendRFID(byte *uid, byte len, uint8_t flag) {
  Serial.print("UID de la carte RFID : ");
  uint8_t uidPayload[len + 1];
  uidPayload[0] = flag;
  for (byte i = 0; i < len; i++) {
    uidPayload[i + 1] = uid[i];
    if (uid[i] < 0x10) Serial.print("0");
    Serial.print(uid[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  Serial.println("Envoi de l'UID via LoRa...");
  modem.beginPacket();
  modem.write(uidPayload, len + 1);
  int err = modem.endPacket(true);
  if (err > 0) Serial.println("UID envoyé !");
  else Serial.println("Erreur envoi UID.");
}

void setup() {
  // Initialisation du port série pour le debug
  Serial.begin(115200);

  // --- Initialisation LoRa & mesure SPL ---
  pinMode(SENSOR_PIN, INPUT);
  if (!modem.begin(EU868)) {
    Serial.println("Erreur : Impossible de démarrer le module LoRa");
    while (1) {}
  }
  Serial.print("Version du module LoRa : ");
  Serial.println(modem.version());
  Serial.print("Device EUI : ");
  Serial.println(modem.deviceEUI());

  int connected = modem.joinOTAA(appEui, appKey);
  if (!connected) {
    Serial.println("Erreur lors du join OTAA LoRa. Vérifiez votre emplacement (proximité d'une fenêtre par ex.)");
    while (1) {}
  }
  modem.minPollInterval(20);  // Intervalle minimum entre envois
  Serial.println("Module LoRa initialisé et connecté.");

  // --- Initialisation RFID RC522 ---
  Serial.println("Initialisation du RC522 RFID...");
  SPI.begin();
  mfrc522.PCD_Init();
  Serial.println("RC522 initialisé. Approchez une carte RFID du lecteur.");
}

void loop() {
  unsigned long now = millis();

  // ★ Gestion du timeout d'association
  if (state == ASSOC && now - assocStart >= ASSOC_TIMEOUT) {
    Serial.println("Timeout assoc, retour en NORMAL");
    state = NORMAL;
    cardSent = false;  // on réactive l'envoi en mode normal
  }

  // ------------------------------
  // Partie RFID : Lecture et envoi UID
  // ------------------------------
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
    byte len = mfrc522.uid.size;
    byte *uid = mfrc522.uid.uidByte;

    if (!cardSent) {
      if (state == NORMAL) {
        // ★ Détection du badge maître
        if (len == masterUIDLen && compareUID(uid, masterUID, len)) {
          Serial.println("Badge maître détecté → PASSAGE EN MODE ASSOC");
          state = ASSOC;
          assocStart = now;
          cardSent = true;

          // Envoi du message "début association" : flag 0x02 + objectID
          uint8_t p[2] = { 0x02, objectID };
          modem.beginPacket();
          modem.write(p, sizeof(p));
          modem.endPacket(true);
          Serial.println("Message début association envoyé.");
        }
        else {
          // Mode NORMAL : envoi classique UID
          sendRFID(uid, len, 0x01);
          cardSent = true;
        }
      }
      else if (state == ASSOC) {
        // ★ En mode ASSOC : on associe ce badge à l'objet
        Serial.println("Badge à associer détecté → envoi payload assoc");
        // buffer suffisamment grand pour 2 octets + UID max
        uint8_t payload[2 + MAX_UID_LENGTH] = { 0 };
        payload[0] = 0x03;         // flag d'association
        payload[1] = objectID;     // ID de l'objet
        // copie de l'UID
        for (byte i = 0; i < len; i++) {
          payload[2 + i] = uid[i];
        }
        // envoi seulement 2+len octets
        modem.beginPacket();
        modem.write(payload, 2 + len);
        modem.endPacket(true);
        Serial.println("Association envoyée, retour en NORMAL");

        state = NORMAL;
        cardSent = true;
      }
    }
    mfrc522.PICC_HaltA();
  }
  else {
    // reset du flag lorsqu’il n’y a plus de carte
    cardSent = false;
  }

  // ------------------------------
  // Partie SPL : Mesure & envoi LoRa toutes les 20 secondes
  // ------------------------------
  if (now - lastSPLTime >= splInterval) {
    lastSPLTime = now;

    // Réinitialisation pour la mesure
    startMillis = millis();
    signalMax = 0;
    signalMin = 1024;

    // Collecte des données sur une fenêtre de 50 ms
    while (millis() - startMillis < sampleWindow) {
      sample = analogRead(SENSOR_PIN);
      if (sample < 1024) {
        if (sample > signalMax) signalMax = sample;
        if (sample < signalMin) signalMin = sample;
      }
    }

    // Calcul du SPL
    peakToPeak = signalMax - signalMin;
    voltage = (peakToPeak * 3.3) / 1024.0;
    float sensitivity = 0.005;   // V/Pa
    float refPressure = 20e-6;   // 20 µPa
    float pressure = voltage / sensitivity;
    dbSPL = 20 * log10(pressure / refPressure) - 50; // calibration

    // Affichage pour debug
    Serial.print("Voltage: "); Serial.print(voltage);
    Serial.print(" V, SPL: "); Serial.print(dbSPL); Serial.println(" dB");

    // Préparation du payload SPL
    uint8_t splPayload[4] = {0};
    int16_t splValue = (int16_t)dbSPL;
    splPayload[0] = (splValue >> 8) & 0xFF;
    splPayload[1] = splValue & 0xFF;

    // Envoi SPL via LoRa
    Serial.println("Envoi du payload SPL via LoRa...");
    modem.beginPacket();
    modem.write(splPayload, sizeof(splPayload));
    int errSPL = modem.endPacket(true);
    if (errSPL > 0) Serial.println("Payload SPL envoyé correctement !");
    else {
      Serial.println("Erreur lors de l'envoi du payload SPL :(");
      Serial.println("Attention : le module peut limiter le nombre d'envois par minute.");
    }

    // Vérification d'un éventuel downlink
    delay(1000);
    if (!modem.available()) {
      Serial.println("Aucun message downlink reçu.");
    } else {
      char rcv[64];
      int i = 0;
      while (modem.available()) {
        rcv[i++] = (char)modem.read();
      }
      Serial.print("Message downlink (hex) : ");
      for (unsigned int j = 0; j < i; j++) {
        if (rcv[j] < 16) Serial.print("0");
        Serial.print(rcv[j] >> 4, HEX);
        Serial.print(rcv[j] & 0xF, HEX);
        Serial.print(" ");
      }
      Serial.println();
    }
  }
}

Credits

Quentin POLLET
1 project • 1 follower
Nicolas DAILLY
41 projects • 26 followers
Associated Professor at UniLaSalle - Amiens / Head of the Computer Network Department / Teach Computer and Telecommunication Networks
Alexandre Létocart
11 projects • 7 followers
fcaron
22 projects • 7 followers
b-Kos
1 project • 0 followers

Comments