sunnyiut
Published

Wireless Digital Stethoscope

nRF5340 based portable, energy-efficient, BLE-enabled heart sound capture & streaming for accurate diagnosis & telemedicine.

AdvancedWork in progress640

Things used in this project

Hardware components

nRF5340 Development Kit
Nordic Semiconductor nRF5340 Development Kit
×2
Microphone, Omnidirectional
Microphone, Omnidirectional
×1
Texas Instruments OPA2333 op-amp mic pre-amplifier
×1
Texas Instruments OPA365
op-amp for anti aliasing low pass filter
×1
Microchip MCP73833
battery charger
×1
Polymer Lithium Ion Battery - 2200mAh 3.7V
Seeed Studio Polymer Lithium Ion Battery - 2200mAh 3.7V
×1
Flash Memory Card, MicroSD Card
Flash Memory Card, MicroSD Card
×1
LED (generic)
LED (generic)
×4
Nordic Semiconductor nPM1300
×1

Software apps and online services

nRF Connect SDK
Nordic Semiconductor nRF Connect SDK
PCBWay PCBA

Story

Read more

Code

main.c

C/C++
#include <zephyr/kernel.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/device.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include "audio_service.h"

#define ADC_RES 12
#define ADC_CHANNEL 0
#define SAMPLE_BUF_SIZE 128

static const struct device *adc_dev = DEVICE_DT_GET(DT_NODELABEL(adc));
static uint16_t sample_buffer[SAMPLE_BUF_SIZE];

static void bt_connected(struct bt_conn *conn, uint8_t err) {
    if (!err) {
        audio_service_set_conn(conn);
    }
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
    .connected = bt_connected,
};

void start_adc_streaming(void) {
    struct adc_channel_cfg ch_cfg = {
        .gain = ADC_GAIN_1_4,
        .reference = ADC_REF_INTERNAL,
        .acquisition_time = ADC_ACQ_TIME_DEFAULT,
        .channel_id = ADC_CHANNEL,
        .input_positive = NRF_SAADC_INPUT_AIN0,
    };
    adc_channel_setup(adc_dev, &ch_cfg);

    struct adc_sequence seq = {
        .channels = BIT(ADC_CHANNEL),
        .buffer = sample_buffer,
        .buffer_size = sizeof(sample_buffer),
        .resolution = ADC_RES,
    };

    while (1) {
        adc_read(adc_dev, &seq);
        audio_service_send((uint8_t *)sample_buffer, sizeof(sample_buffer));
        k_msleep(20); // ~50 Hz frame rate
    }
}

void main(void) {
    bt_enable(NULL);
    audio_service_init();
    bt_le_adv_start(BT_LE_ADV_CONN_NAME, NULL, 0, NULL, 0);
    start_adc_streaming();
}

audio_service.c

C/C++
#include "audio_service.h"
#include <zephyr/bluetooth/gatt.h>

static struct bt_conn *current_conn;

#define AUDIO_CHRC_UUID BT_UUID_DECLARE_128(0xF0,0x00,0xAA,0x01,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x01)

static uint8_t dummy_data;

BT_GATT_SERVICE_DEFINE(audio_svc,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_DECLARE_128(0xF0,0x00,0xAA,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x00)),
    BT_GATT_CHARACTERISTIC(AUDIO_CHRC_UUID, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, NULL, &dummy_data),
);

void audio_service_init(void) {}

void audio_service_send(const uint8_t *data, size_t len) {
    if (current_conn) {
        bt_gatt_notify(NULL, &audio_svc.attrs[1], data, len);
    }
}

void audio_service_set_conn(struct bt_conn *conn) {
    current_conn = conn;
}

audio_service.h

C Header File
#ifndef AUDIO_SERVICE_H
#define AUDIO_SERVICE_H

#include <zephyr/bluetooth/conn.h>

void audio_service_init(void);
void audio_service_send(const uint8_t *data, size_t len);
void audio_service_set_conn(struct bt_conn *conn);

#endif

prj.conf

C/C++
# Bluetooth
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="DigiStetho"
CONFIG_BT_MAX_CONN=1
CONFIG_BT_GATT_NOTIFY=y

# Audio
CONFIG_BT_AUDIO=y
CONFIG_BT_AUDIO_TX=y
CONFIG_BT_AUDIO_CODEC_LC3=y

# ADC Sampling
CONFIG_ADC=y
CONFIG_NRFX_SAADC=y

# Stack and memory
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=8192

Credits

sunnyiut
2 projects • 4 followers
Electronics enthusiast working as a researcher in Biomedical Engineering sector. Graduated in Electrical and Electronics Engineering.

Comments