Yanis MacAnas benalla
Published

Colibry Forest Sentinel

Ultra-low-power AI device that detects chainsaw sounds in forests to fight illegal logging.

IntermediateWork in progress213
Colibry Forest Sentinel

Things used in this project

Hardware components

ColibryNPU EvalboardXP
ASYGN ColibryNPU EvalboardXP
×1
MIKROE LR IoT Click
×1
SenseCAP M2 Multi-Platform LoRaWAN Indoor Gateway(SX1302) - EU868
Seeed Studio SenseCAP M2 Multi-Platform LoRaWAN Indoor Gateway(SX1302) - EU868
×1

Software apps and online services

Helium LoRa Network
Optional

Story

Read more

Code

main.c

C/C++
"driver_colibry.h" is provided by the board manufacturer
#include "lriot_chainsaw.h"
#include "driver_colibry.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define AUDIO_BLOCK_SIZE 128
#define FFT_SIZE         256
#define NPU_THRESHOLD    0.5f

// --- Circular buffer for DMA I2S ---
float audio_circ_buffer[FFT_SIZE];
volatile int dma_write_index = 0;  // Updated by DMA ISR
volatile bool fft_ready = false;    // Set by DMA ISR when buffer is full

float fft_output[FFT_SIZE];

// --- DMA callback stub ---
// This function should be called by the DMA interrupt
void i2s_dma_half_full_callback(const float *dma_buffer, int len)
{
    // Copy new samples into the circular buffer
    for (int i = 0; i < len; i++) {
        audio_circ_buffer[dma_write_index++] = dma_buffer[i];
        if (dma_write_index >= FFT_SIZE) {
            dma_write_index = 0;
            fft_ready = true;  // Full buffer ready for FFT
        }
    }
}

// --- Main ---
int main(void)
{
    // --- Initialize peripherals ---
    i2s_init_dma(audio_circ_buffer, FFT_SIZE); // DMA-based I2S, double-buffering
    fft_init(FFT_SIZE);
    npu_init();
    if (npu_load_model("chainsaw.nnpa") != 0) {
        printf("[NPU] Failed to load model\n");
        return -1;
    }

    if (lriot_chainsaw_init() != 0) {
        printf("[LoRaWAN] Init failed\n");
        return -1;
    }

    printf("[System] DMA-based pipeline initialized\n");

    // --- Main loop ---
    while (1)
    {
        // Check if FFT buffer is ready (set by DMA ISR)
        if (fft_ready)
        {
            fft_ready = false;

            // 1. Compute FFT on the full buffer
            fft_compute(audio_circ_buffer, fft_output, FFT_SIZE);

            // 2. Run NPU detection
            float detection_score = npu_process(fft_output, FFT_SIZE);

            // 3. Fire-and-forget LoRaWAN send if detected
            if (detection_score > NPU_THRESHOLD) {
                int ret = lriot_chainsaw_send_hex();
                if (ret == 0)
                    printf("[LoRaWAN] Event sent\n");
                else
                    printf("[LoRaWAN] Send failed\n");
            }
        }
        Delay_ms(1);
    }

    return 0;
}

lriot_chainsaw.h

C/C++
#ifndef LRIOT_CHAINSaw_H
#define LRIOT_CHAINSaw_H

#include "lriot.h"

// Initialize the LoRaWAN module
// Returns 0 on success, -1 on error
int lriot_chainsaw_init(void);

// Send "chainsaw" payload in HEX
// Returns 0 on success, -1 on error
int lriot_chainsaw_send_hex(void);

#endif // LRIOT_CHAINSaw_H

lriot_chainsaw.c

C/C++
#include "lriot_chainsaw.h"
#include <stdio.h>

static lriot_t lriot;
static lriot_cfg_t cfg;

int lriot_chainsaw_init(void)
{
    lriot_cfg_setup(&cfg);
    LRIOT_MAP_MIKROBUS(cfg, MIKROBUS_1);

    if (lriot_init(&lriot, &cfg) == LRIOT_ERROR) {
        return -1;
    }

    lriot_reset(&lriot);
    Delay_ms(2000);

    lriot_cmd(&lriot, "mac set deveui 0011223344556677");
    lriot_cmd(&lriot, "mac set appeui 0011223344556677");
    lriot_cmd(&lriot, "mac set appkey 00112233445566778899AABBCCDDEEFF");

    if (lriot_cmd(&lriot, "mac join otaa") != LRIOT_OK) {
        return -1;
    }

    return 0;
}

int lriot_chainsaw_send_hex(void)
{
    const char *payload_hex = "636861696e736177"; // "chainsaw" in hex
    char cmd_buf[64];
    snprintf(cmd_buf, sizeof(cmd_buf), "mac tx uncnf 1 %s", payload_hex);

    if (lriot_cmd(&lriot, cmd_buf) != LRIOT_OK) {
        return -1;
    }

    return 0;
}

Credits

Yanis Mac
1 project • 1 follower
Anas benalla
1 project • 1 follower

Comments