Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 

Repository files navigation

Raspberry Pi BLE Sensor Node

A small embedded sensing pipeline built on Raspberry Pi 5 using C for sensor acquisition and processing, and Python for Bluetooth Low Energy advertising through BlueZ.

The project reads temperature from a physical BME280 sensor over Linux I²C, combines it with simulated environmental sources, filters and buffers measurements, computes summary statistics, packs them into a fixed-size BLE payload, and exposes the result through BLE manufacturer data.

C · Python · Linux I²C · BME280 · BLE · BlueZ · POSIX Threads


Overview

The main data path is:

BME280 temperature
simulated humidity / CO₂
          │
          ▼
      acquisition
          │
          ▼
     median filter
          │
          ▼
   circular buffers
          │
          ▼
      statistics
          │
          ▼
   27-byte payload
          │
          ▼
      payload.bin
          │
          ▼
 Python / BlueZ D-Bus
          │
          ▼
   BLE advertisement

The C application handles measurement, filtering, buffering, statistics, and binary payload generation. A separate Python process reads the generated payload and registers a BLE advertisement through the BlueZ D-Bus API.

Data Sources

The current implementation uses one physical sensor path and two simulated sources.

Temperature

Temperature is read from a physical BME280 connected through /dev/i2c-1.

The implementation:

  • verifies the BME280 chip ID
  • configures the sensor registers
  • reads temperature calibration coefficients
  • reads the raw 20-bit temperature value
  • applies the BME280 compensation calculation

Humidity

Humidity values are simulated in software and passed through the same buffering, statistics, and BLE pipeline.

CO₂

CO₂ values are also simulated in software. The current implementation generates test values rather than reading a physical CO₂ sensor.

Measurement Pipeline

The main application samples the environmental sources at a fixed interval.

sensor read
    │
    ▼
filter
    │
    ▼
circular buffer
    │
    ▼
statistics
    │
    ▼
BLE payload

Median Filtering

Temperature measurements are processed with a moving median filter using a five-sample window.

This reduces the effect of short-lived outliers before samples enter the main circular buffer.

Circular Buffers

Temperature, humidity, and CO₂ values are stored independently in fixed-size circular buffers.

Once a buffer reaches capacity, new samples overwrite the oldest entries.

The buffer implementation preserves chronological order when values are copied out for statistical processing.

Statistics

The buffered measurements are reduced into summary statistics.

The system calculates:

  • mean
  • standard deviation
  • minimum
  • maximum
  • median

The BLE payload carries four statistics for each data source:

standard deviation
maximum
minimum
median

The mean is calculated by the C process but is not included in the current 27-byte advertising payload.

BLE Payload

Environmental statistics are encoded into a fixed 27-byte binary payload.

Byte 0       packet counter
Bytes 1-2    truncated timestamp

Bytes 3-10   temperature statistics
Bytes 11-18  humidity statistics
Bytes 19-26  CO₂ statistics

Each source contributes four 16-bit values:

standard deviation
maximum
minimum
median

Temperature and humidity values are multiplied by 100 before integer encoding to preserve two decimal places.

CO₂ values are encoded without that scaling factor.

All 16-bit fields are stored in little-endian order.

BLE Advertising

The C process writes the encoded packet to:

payload.bin

ble_advertise.py reads the file and registers a BLE advertisement through the system BlueZ service.

The payload is exposed through ManufacturerData.

The current advertisement uses:

LocalName: RPi
Manufacturer ID: 0xFFFF
Type: peripheral

The Python process periodically reloads payload.bin, allowing the advertised data to reflect newer measurements without coupling the BLE transport directly to the sensor process.

BME280 Interface

The project accesses the BME280 through the Linux I²C device interface rather than a high-level sensor library.

The I²C layer provides operations for:

open device
set slave address
read register
read multiple registers
write register
close device

The sensor path is:

/dev/i2c-1
    │
    ▼
I2C_SLAVE 0x76
    │
    ▼
chip ID
    │
    ▼
configuration registers
    │
    ▼
calibration coefficients
    │
    ▼
raw temperature
    │
    ▼
compensated °C

Concurrency Experiment

The repository also includes a separate producer-consumer experiment using POSIX threads.

This is independent from the main sensing runtime and explores asynchronous data production and consumption with a bounded circular buffer.

The implementation uses:

  • pthread
  • mutexes
  • condition variables
  • bounded buffers
producer
   │
   ▼
bounded buffer
   │
   ▼
consumer

The producer waits when the buffer is full.

The consumer waits when the buffer is empty.

Synchronization is handled with pthread_mutex_t and pthread_cond_t.

Overflow Experiment

A second concurrency example intentionally slows the consumer until incoming data exceeds processing capacity.

This is used to observe bounded-buffer behavior under backpressure and overflow conditions.

Dropped values are recorded in:

buffer_overflow.log

Build

The main sensing project is located at:

borda_assignment/borda_project/env_sensing_project

Enter the directory:

cd borda_assignment/borda_project/env_sensing_project

Build the C application:

make

Run it:

./env_sensor

The program expects access to the Raspberry Pi I²C interface and a BME280 at address 0x76.

BLE Advertiser

Run the BLE process separately:

cd borda_assignment/borda_project/env_sensing_project
sudo python3 ble_advertise.py

The script requires:

  • BlueZ
  • Python D-Bus bindings
  • GLib bindings
  • an available Bluetooth adapter exposed as /org/bluez/hci0

The advertiser reads payload.bin from the current working directory.

Concurrency Examples

The pthread examples are located in:

borda_assignment/borda_project/bonus_part

Build them with:

cd borda_assignment/borda_project/bonus_part
make

Or compile the producer-consumer example directly:

gcc rtos_bonus.c circular_buffer.c -o rtos_bonus -lpthread

Run:

./rtos_bonus

The slow-consumer experiment can be compiled with:

gcc slow_consumer.c circular_buffer.c -o slow_consumer -lpthread

Run:

./slow_consumer

Repository Structure

.
├── LICENSE
├── README.md
│
└── borda_assignment/
    └── borda_project/
        │
        ├── env_sensing_project/
        │   ├── include/
        │   │   ├── ble_payload.h
        │   │   ├── bme280.h
        │   │   ├── circular_buffer.h
        │   │   ├── i2c_interface.h
        │   │   ├── median_filter.h
        │   │   └── stats.h
        │   │
        │   ├── src/
        │   │   ├── ble_payload.c
        │   │   ├── bme280.c
        │   │   ├── circular_buffer.c
        │   │   ├── i2c_interface.c
        │   │   ├── median_filter.c
        │   │   ├── stats.c
        │   │   └── main.c
        │   │
        │   ├── ble_advertise.py
        │   ├── Makefile
        │   └── report/
        │
        └── bonus_part/
            ├── circular_buffer.c
            ├── circular_buffer.h
            ├── rtos_bonus.c
            ├── slow_consumer.c
            └── Makefile

Design Notes

This repository is an experimental embedded-systems project rather than a production sensor platform.

A few implementation choices reflect that context:

  • only temperature comes from a physical sensor in the current pipeline
  • humidity and CO₂ are simulated
  • BLE transport and measurement processing communicate through a binary file
  • several configuration values are compiled into the source
  • the BlueZ adapter path is fixed to hci0
  • the main runtime is sequential
  • pthread experiments are kept as separate concurrency examples

The project covers the complete path from low-level sensing to filtering, buffering, binary encoding, concurrency, and wireless transport.

Project Context

Originally built for the Borda Academy 2025 Embedded Systems Developer Assignment.

The repository is preserved as a reference for low-level sensing, Linux hardware interfaces, BLE packetization, buffering, and concurrent data handling.

Author

Atakan Yaman

GitHub · LinkedIn

License

MIT

About

Embedded sensing on Raspberry Pi with Linux I²C, BME280 acquisition, filtering, fixed-size BLE payloads and BlueZ advertising.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages