working streaming of raw accel/gyro data. must restart firmware after run of test_basic.py
This commit is contained in:
@ -146,3 +146,10 @@ make html
|
|||||||
|
|
||||||
The output will be stored in the ``_build_sphinx`` folder. You may check for
|
The output will be stored in the ``_build_sphinx`` folder. You may check for
|
||||||
other output formats other than HTML by running ``make help``.
|
other output formats other than HTML by running ``make help``.
|
||||||
|
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
This was a useful tutorial for getting a bunch of bluetooth stuff working:
|
||||||
|
- https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/lessons/lesson-4-bluetooth-le-data-exchange/topic/blefund-lesson-4-exercise-1/
|
||||||
|
- Source code: https://github.com/NordicDeveloperAcademy/bt-fund/blob/main/l4/l4_e1_sol/src/my_lbs.h
|
64
firmware/app/src/bt_services.c
Normal file
64
firmware/app/src/bt_services.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <zephyr/sys/printk.h>
|
||||||
|
#include <zephyr/sys/byteorder.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/hci.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
#include <zephyr/bluetooth/uuid.h>
|
||||||
|
#include <zephyr/bluetooth/gatt.h>
|
||||||
|
|
||||||
|
#include "bt_services.h"
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(main, CONFIG_APP_LOG_LEVEL);
|
||||||
|
|
||||||
|
static sensors_raw_t sensors;
|
||||||
|
|
||||||
|
void set_sensors(const sensors_raw_t *values)
|
||||||
|
{
|
||||||
|
sensors = *values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback definitions
|
||||||
|
static ssize_t read_sensors(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
|
||||||
|
uint16_t len, uint16_t offset)
|
||||||
|
{
|
||||||
|
const char *value = attr->user_data;
|
||||||
|
size_t size = sizeof(sensors_raw_t);
|
||||||
|
|
||||||
|
LOG_INF("Attribute read, handle: %u, conn: %p, bytes: %d", attr->handle, (void *)conn, size);
|
||||||
|
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service declaration
|
||||||
|
|
||||||
|
static ssize_t read_string(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset)
|
||||||
|
{
|
||||||
|
const char *value = attr->user_data;
|
||||||
|
LOG_INF("String read, handle: %u, conn: %p\t%s", attr->handle, (void *)conn, value);
|
||||||
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, attr->user_data, strlen((char *)attr->user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_GATT_SERVICE_DEFINE(my_lbs_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_IMU),
|
||||||
|
// Read raw sensor values
|
||||||
|
BT_GATT_CHARACTERISTIC(BT_UUID_IMU_SENSORS,
|
||||||
|
BT_GATT_CHRC_READ,
|
||||||
|
BT_GATT_PERM_READ,
|
||||||
|
read_sensors,
|
||||||
|
NULL,
|
||||||
|
&sensors),
|
||||||
|
BT_GATT_DESCRIPTOR(BT_UUID_GATT_CUD,
|
||||||
|
BT_GATT_PERM_READ,
|
||||||
|
read_string,
|
||||||
|
NULL,
|
||||||
|
"Read raw sensor values"),
|
||||||
|
// TODO: add characteristic to read state estimate
|
||||||
|
);
|
36
firmware/app/src/bt_services.h
Normal file
36
firmware/app/src/bt_services.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef BT_SERVICES_H_
|
||||||
|
#define BT_SERVICES_H_
|
||||||
|
|
||||||
|
// NOTE: these are randomly generated for development
|
||||||
|
// https://www.uuidgenerator.net/
|
||||||
|
#define BT_UUID_IMU_VAL BT_UUID_128_ENCODE(0xc77cb872, 0xa346, 0x40bf, 0x97a5, 0x3223f6f0a47c)
|
||||||
|
#define BT_UUID_IMU_SENSORS_VAL BT_UUID_128_ENCODE(0x99b59474, 0x5570, 0x464b, 0xbe37, 0x64465aa050fd)
|
||||||
|
// #define BT_UUID_IMU_EULER_VAL BT_UUID_128_ENCODE()
|
||||||
|
// #define BT_UUID_IMU_QUATERNION_VAL BT_UUID_128_ENCODE()
|
||||||
|
|
||||||
|
#define BT_UUID_IMU BT_UUID_DECLARE_128(BT_UUID_IMU_VAL)
|
||||||
|
#define BT_UUID_IMU_SENSORS BT_UUID_DECLARE_128(BT_UUID_IMU_SENSORS_VAL)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double accel_x; ///< [m/s]
|
||||||
|
double accel_y; ///< [m/s]
|
||||||
|
double accel_z; ///< [m/s]
|
||||||
|
double gyro_x;
|
||||||
|
double gyro_y;
|
||||||
|
double gyro_z;
|
||||||
|
double mag_x;
|
||||||
|
double mag_y;
|
||||||
|
double mag_z;
|
||||||
|
} sensors_raw_t;
|
||||||
|
|
||||||
|
typedef sensors_raw_t (*sensors_cb_t)(void);
|
||||||
|
|
||||||
|
struct my_imu_cb
|
||||||
|
{
|
||||||
|
sensors_cb_t sensors_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_sensors(const sensors_raw_t *values);
|
||||||
|
|
||||||
|
#endif // BT_SERVICES_H_
|
@ -7,6 +7,8 @@
|
|||||||
#include <app/drivers/blink.h>
|
#include <app/drivers/blink.h>
|
||||||
|
|
||||||
#include <app_version.h>
|
#include <app_version.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "bt_services.h"
|
||||||
|
|
||||||
// #include <zephyr/bluetooth/bluetooth.h>
|
// #include <zephyr/bluetooth/bluetooth.h>
|
||||||
// #include <zephyr/bluetooth/hci.h>
|
// #include <zephyr/bluetooth/hci.h>
|
||||||
@ -317,16 +319,28 @@ int thread_sensors(void)
|
|||||||
uint8_t pct_bat = 100.0 * (vbat - 3.3) / (4.2 - 3.3);
|
uint8_t pct_bat = 100.0 * (vbat - 3.3) / (4.2 - 3.3);
|
||||||
bt_bas_set_battery_level(pct_bat);
|
bt_bas_set_battery_level(pct_bat);
|
||||||
|
|
||||||
|
sensors_raw_t values;
|
||||||
|
values.accel_x = accel_x.val1 + accel_x.val2 * 1e-6;
|
||||||
|
values.accel_y = accel_y.val1 + accel_y.val2 * 1e-6;
|
||||||
|
values.accel_z = accel_z.val1 + accel_z.val2 * 1e-6;
|
||||||
|
values.gyro_x = gyro_x.val1 + gyro_x.val2 * 1e-6;
|
||||||
|
values.gyro_y = gyro_y.val1 + gyro_y.val2 * 1e-6;
|
||||||
|
values.gyro_z = gyro_z.val1 + gyro_z.val2 * 1e-6;
|
||||||
|
values.mag_x = NAN;
|
||||||
|
values.mag_y = NAN;
|
||||||
|
values.mag_z = NAN;
|
||||||
|
set_sensors(&values);
|
||||||
|
|
||||||
sprintf(str_v, "V :%7.5f", vbat);
|
sprintf(str_v, "V :%7.5f", vbat);
|
||||||
sprintf(str_i, "I :%7.5f", current.val1 + current.val2 * 1e-6);
|
sprintf(str_i, "I :%7.5f", current.val1 + current.val2 * 1e-6);
|
||||||
sprintf(str_p, "P :%7.4f", pressure.val1 + pressure.val2 * 1e-6);
|
sprintf(str_p, "P :%7.4f", pressure.val1 + pressure.val2 * 1e-6);
|
||||||
sprintf(str_t, "T :%7.4f", temperature.val1 + temperature.val2 * 1e-6);
|
sprintf(str_t, "T :%7.4f", temperature.val1 + temperature.val2 * 1e-6);
|
||||||
sprintf(str_ax, "AX:%+7.3f", accel_x.val1 + accel_x.val2 * 1e-6);
|
sprintf(str_ax, "AX:%+7.3f", values.accel_x);
|
||||||
sprintf(str_ay, "AY:%+7.3f", accel_y.val1 + accel_y.val2 * 1e-6);
|
sprintf(str_ay, "AY:%+7.3f", values.accel_y);
|
||||||
sprintf(str_az, "AZ:%+7.3f", accel_z.val1 + accel_z.val2 * 1e-6);
|
sprintf(str_az, "AZ:%+7.3f", values.accel_z);
|
||||||
sprintf(str_gx, "GX:%+7.3f", gyro_x.val1 + gyro_x.val2 * 1e-6);
|
sprintf(str_gx, "GX:%+7.3f", values.gyro_x);
|
||||||
sprintf(str_gy, "GY:%+7.3f", gyro_y.val1 + gyro_y.val2 * 1e-6);
|
sprintf(str_gy, "GY:%+7.3f", values.gyro_y);
|
||||||
sprintf(str_gz, "GZ:%+7.3f", gyro_z.val1 + gyro_z.val2 * 1e-6);
|
sprintf(str_gz, "GZ:%+7.3f", values.gyro_z);
|
||||||
sprintf(str_az_ref, "Zr:%+7.3f", accel_z_ref.val1 + accel_z_ref.val2 * 1e-6);
|
sprintf(str_az_ref, "Zr:%+7.3f", accel_z_ref.val1 + accel_z_ref.val2 * 1e-6);
|
||||||
sprintf(str_h, "H :%7.3f", humidity.val1 + humidity.val2 * 1e-6);
|
sprintf(str_h, "H :%7.3f", humidity.val1 + humidity.val2 * 1e-6);
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#include <zephyr/bluetooth/hci.h>
|
#include <zephyr/bluetooth/hci.h>
|
||||||
#include <zephyr/bluetooth/services/bas.h>
|
#include <zephyr/bluetooth/services/bas.h>
|
||||||
|
|
||||||
|
#include "bt_services.h"
|
||||||
|
|
||||||
extern int mtu_exchange(struct bt_conn *conn);
|
extern int mtu_exchange(struct bt_conn *conn);
|
||||||
extern int write_cmd(struct bt_conn *conn);
|
extern int write_cmd(struct bt_conn *conn);
|
||||||
extern struct bt_conn *conn_connected;
|
extern struct bt_conn *conn_connected;
|
||||||
@ -29,7 +31,8 @@ static const struct bt_data ad[] = {
|
|||||||
static unsigned char url_data[] = "\x17//brendanhaines.com";
|
static unsigned char url_data[] = "\x17//brendanhaines.com";
|
||||||
|
|
||||||
static const struct bt_data sd[] = {
|
static const struct bt_data sd[] = {
|
||||||
BT_DATA(BT_DATA_URI, url_data, sizeof(url_data) - 1), // -1 to strip \0
|
// BT_DATA(BT_DATA_URI, url_data, sizeof(url_data) - 1), // -1 to strip \0
|
||||||
|
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_IMU_VAL),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
|
static void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
|
||||||
|
39
python/test_basic.py
Normal file
39
python/test_basic.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# %% imports
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from bleak import BleakClient, BleakScanner
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
# %%
|
||||||
|
devices = await BleakScanner.discover()
|
||||||
|
for d in devices:
|
||||||
|
print(d)
|
||||||
|
|
||||||
|
|
||||||
|
# %%
|
||||||
|
address = "D7:FC:DA:4B:02:D7"
|
||||||
|
MODEL_NBR_UUID = "2A24"
|
||||||
|
SENSORS_UUID = "99b594745570464bbe3764465aa050fd"
|
||||||
|
|
||||||
|
|
||||||
|
timeseries = list()
|
||||||
|
async with BleakClient(address) as client:
|
||||||
|
# model_number = await client.read_gatt_char(MODEL_NBR_UUID)
|
||||||
|
# print("Model Number: {0}".format("".join(map(chr, model_number))))
|
||||||
|
start_time = time.time()
|
||||||
|
print("Starting capture...")
|
||||||
|
while time.time() < start_time + 20:
|
||||||
|
buffer = await client.read_gatt_char(SENSORS_UUID)
|
||||||
|
sensor_values = np.frombuffer(bytes(buffer), dtype=np.double)
|
||||||
|
timeseries.append(sensor_values)
|
||||||
|
print("DONE")
|
||||||
|
|
||||||
|
timeseries = np.array(timeseries)
|
||||||
|
|
||||||
|
# %%
|
||||||
|
plt.plot(timeseries)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
# %%
|
Reference in New Issue
Block a user