Detection of Illegal Traffic in Protected Natural Areas

A sound-based system to detect and report unauthorized vehicle access in protected natural environments.

IntermediateFull instructions provided190
Detection of Illegal Traffic in Protected Natural Areas

Things used in this project

Hardware components

Seeed Studio XIAO nRF52840 Sense (XIAO BLE Sense)
Seeed Studio XIAO nRF52840 Sense (XIAO BLE Sense)
×1
USB Cable, USB Type C Plug
USB Cable, USB Type C Plug
×1

Software apps and online services

Edge Impulse Studio
Edge Impulse Studio
Arduino IDE
Arduino IDE

Story

Read more

Code

Untitled file

Arduino
#include <Arduino.h>
#include <PDM.h>
#include <MIT_Project_inferencing.h>  // Your Edge Impulse inferencing header

#define LORA_POWER_PIN 5
#define LORA_SERIAL Serial1

#define VEHICLE_DETECTION_THRESHOLD 0.7f

typedef struct {
    signed short *buffers[2];
    unsigned char buf_select;
    unsigned char buf_ready;
    unsigned int buf_count;
    unsigned int n_samples;
} inference_t;

static inference_t inference;
static bool record_ready = false;
static signed short *sampleBuffer;

static int print_results = -(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);

void sendAlertMessage(const char *msg) {
  LORA_SERIAL.println("AT+MSG=\"" + String(msg) + "\"");
  Serial.print("Sent alert: ");
  Serial.println(msg);
  delay(1000); // wait a bit after sending
}

// PDM callback - from your code
static void pdm_data_ready_inference_callback(void) {
  int bytesAvailable = PDM.available();
  int bytesRead = PDM.read((char *)&sampleBuffer[0], bytesAvailable);

  if (record_ready) {
    for (int i = 0; i < bytesRead >> 1; i++) {
      inference.buffers[inference.buf_select][inference.buf_count++] = sampleBuffer[i];
      if (inference.buf_count >= inference.n_samples) {
        inference.buf_select ^= 1;
        inference.buf_count = 0;
        inference.buf_ready = 1;
      }
    }
  }
}

static bool microphone_inference_start(uint32_t n_samples) {
  inference.buffers[0] = (signed short *)malloc(n_samples * sizeof(signed short));
  if (!inference.buffers[0]) return false;

  inference.buffers[1] = (signed short *)malloc(n_samples * sizeof(signed short));
  if (!inference.buffers[1]) {
    free(inference.buffers[0]);
    return false;
  }

  sampleBuffer = (signed short *)malloc((n_samples >> 1) * sizeof(signed short));
  if (!sampleBuffer) {
    free(inference.buffers[0]);
    free(inference.buffers[1]);
    return false;
  }

  inference.buf_select = 0;
  inference.buf_count = 0;
  inference.n_samples = n_samples;
  inference.buf_ready = 0;

  PDM.onReceive(&pdm_data_ready_inference_callback);
  PDM.setBufferSize((n_samples >> 1) * sizeof(int16_t));

  if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) {
    Serial.println("Failed to start PDM!");
    return false;
  }
  PDM.setGain(127);

  record_ready = true;
  return true;
}

static bool microphone_inference_record(void) {
  if (inference.buf_ready == 1) {
    Serial.println("Error: sample buffer overrun, decrease EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW");
    return false;
  }
  while (inference.buf_ready == 0) delay(1);
  inference.buf_ready = 0;
  return true;
}

static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr) {
  numpy::int16_to_float(&inference.buffers[inference.buf_select ^ 1][offset], out_ptr, length);
  return 0;
}

void setupCommunication() {
  pinMode(LORA_POWER_PIN, OUTPUT);
  digitalWrite(LORA_POWER_PIN, HIGH);
  delay(100);

  LORA_SERIAL.begin(9600);
  while (!LORA_SERIAL);

  LORA_SERIAL.println("AT+ID=AppEui,\"0807022103180204\"");
  delay(1000);
  LORA_SERIAL.println("AT+ID=DevEui,\"70B3D57ED007083C\"");
  delay(1000);
  LORA_SERIAL.println("AT+KEY=AppKey,\"AAFF6BE2A06CB4FE1FDEF2A0B3B2A7E0\"");
  delay(1000);
  LORA_SERIAL.println("AT+MODE=LWOTAA");
  delay(1000);
  LORA_SERIAL.println("AT+JOIN");
  delay(5000);
}

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println("Starting Edge Impulse vehicle detection with LoRa alert");

  setupCommunication();

  run_classifier_init();

  if (!microphone_inference_start(EI_CLASSIFIER_SLICE_SIZE)) {
    Serial.println("Failed to start microphone inference");
    while (1);
  }
}

void loop() {
  if (!microphone_inference_record()) {
    Serial.println("Failed to record audio");
    return;
  }

  signal_t signal;
  signal.total_length = EI_CLASSIFIER_SLICE_SIZE;
  signal.get_data = &microphone_audio_signal_get_data;
  ei_impulse_result_t result = {0};

  EI_IMPULSE_ERROR err = run_classifier_continuous(&signal, &result, false);
  if (err != EI_IMPULSE_OK) {
    Serial.print("Classifier error ");
    Serial.println((int)err);
    return;
  }

  if (++print_results >= EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW) {
    print_results = 0;
    Serial.println("Predictions:");
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
      Serial.print("    ");
      Serial.print(result.classification[ix].label);
      Serial.print(": ");
      Serial.println(result.classification[ix].value, 5);

      if (strcmp(result.classification[ix].label, "vehicle") == 0 &&
          result.classification[ix].value >= VEHICLE_DETECTION_THRESHOLD) {
        sendAlertMessage("Illegal movement detected");
      }
    }
  }
}

Credits

Claudia Álvarez
1 project • 1 follower
Nuria Cuenca caracuel
1 project • 2 followers
José António Vigário Novo
1 project • 2 followers
ainhoa cid
1 project • 2 followers
Luka Mali
20 projects • 24 followers
Maker Pro, prototyping enthusiast, head of MakerLab, a lecturer at the University of Ljubljana, founder.

Comments