Supachai Vorapojpisut
Created July 29, 2024

Wheelchair tracking using Kria KR260 board

Building a wheelchair activity tracking project using Kria KR260 board with BLE and webcam.

25
Wheelchair tracking using Kria KR260 board

Things used in this project

Hardware components

Kria™ KR260 Robotics Starter Kit
AMD Kria™ KR260 Robotics Starter Kit
×1
Webcam, Logitech® HD Pro
Webcam, Logitech® HD Pro
×1
M5StickC ESP32-PICO Mini IoT Development Board
M5Stack M5StickC ESP32-PICO Mini IoT Development Board
×1
M5Stack Capsule
×1
USB WiFi dongle
×1
USB Bluetooth dongle
×1

Software apps and online services

Edge Impulse Studio
Edge Impulse Studio
PlatformIO IDE
PlatformIO IDE
RealVNC Viewer

Story

Read more

Code

Code for M5StickC Beacon

Arduino
#include <Arduino.h>
#include <M5Unified.h>
#include <esp_log.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <BLEBeacon.h>

#define TAG "main"

#define DEVICE_NAME         "LivingRoom"
#define SERVICE_UUID        "7A0247E7-8E88-409B-A959-AB5092DDB03E"
#define BEACON_UUID         "2D7A9F0C-E0E8-4CC9-A71B-A21DB2D034A1"
#define BEACON_UUID_REV     "A134D0B2-1DA2-1BA7-C94C-E8E00C9F7A2D"
#define CHARACTERISTIC_UUID "82258BAA-DF72-47E8-99BC-B73D7ECD08A5"

BLEServer *pServer;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

void setup() {
  M5.begin();
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);
  Serial.begin(115200);

  // BLE device
  BLEDevice::init(DEVICE_NAME);

  // Add service
  BLEAdvertising *pAdvertising;
  pAdvertising = pServer->getAdvertising();
  pAdvertising->stop();

  // iBeacon
  BLEBeacon roomBeacon;
  roomBeacon.setManufacturerId(0x4c00);
  roomBeacon.setMajor(5);
  roomBeacon.setMinor(88);
  roomBeacon.setSignalPower(0xc5);
  roomBeacon.setProximityUUID(BLEUUID(BEACON_UUID_REV));

  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x1A);
  advertisementData.setManufacturerData(roomBeacon.getData());
  pAdvertising->setAdvertisementData(advertisementData);

  pAdvertising->start();
}

void loop() {
  static uint32_t lastTick = millis();
  M5.update();

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.printf("Living Room: %d", millis() - lastTick);
  ESP_LOGI(TAG, "Living Room: %d", millis() - lastTick);
  lastTick = millis();

  delay(1000);
}

Code for M5Stack Capsule Wheel Detection

Arduino
#include <Arduino.h>
#include <M5Unified.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include <SparkFun_BMI270_Arduino_Library.h>
#include <esp_log.h>

#define TAG   "main"

// WiFi/MQTT settings
#define WIFI_SSID       "SSID"
#define WIFI_PASS       "WIFI_PASS"
#define MQTT_BROKER     "broker.hivemq.com"
#define MQTT_PORT       1883
#define MQTT_DATA_TOPIC "hackster/amd/wheelchair/data"
#define MQTT_CMD_TOPIC  "hackster/amd/wheelchair/cmd"

#define DURATION        10
#define WHEEL_RADIUS    0.3

// persistent variables
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

JsonDocument doc;

BMI270 M5_IMU;
uint8_t i2cAddress = BMI2_I2C_SEC_ADDR; // 0x69

float prev_angle = 0;
float accum_distance = 0;

// MQTT callback function
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  char buf[256];
  ESP_LOGI(TAG, "Topic: %s", topic);
  for (int i = 0; i < length; i++) {
    buf[i] = (char)payload[i];
  }
  buf[length] = '\0';
  ESP_LOGI(TAG, "Payload: %s", buf);
}

// reconnect MQTT
void reconnectMQTT() {
  // reconnect WiFi
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    ESP_LOGI(TAG, "Connecting to WiFi...");
  }
  ESP_LOGI(TAG, "WiFi IP: %s", WiFi.localIP().toString().c_str());

  // reconnect MQTT
  while (!mqttClient.connected()) {
    ESP_LOGI(TAG, "Connecting to MQTT...");
    if (mqttClient.connect("AMD wheelchair")) {
      mqttClient.subscribe(MQTT_CMD_TOPIC);
    } else {
      ESP_LOGI(TAG, "Failed to connect to MQTT");
      delay(1000);
    }
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);

  // sensor
  pinMode(46, OUTPUT);
  digitalWrite(46, HIGH);
  Wire.begin(8, 10, 400000);
  uint8_t ans;
  do {
    delay(1000);
    ans = M5_IMU.beginI2C(i2cAddress);
    Serial.println(ans);
  } while(ans != BMI2_OK);
  
  // connect WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    ESP_LOGI(TAG, "Connecting to WiFi...");
  }
  ESP_LOGI(TAG, "WiFi IP: %s", WiFi.localIP().toString().c_str());

  // connect MQTT
  mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
  mqttClient.setCallback(mqttCallback);

  // initialize angle
  M5_IMU.getSensorData();
  float accX = M5_IMU.data.accelX;
  float accY = M5_IMU.data.accelY;
  prev_angle = atan2(accY, accX);
}

void loop() {
  static int idx = 0;

  reconnectMQTT();

  // read sensor data
  M5_IMU.getSensorData();
  float accX = M5_IMU.data.accelX;
  float accY = M5_IMU.data.accelY;
  float angle = atan2(accY, accX);
  float angle_diff = abs(prev_angle - angle);
  prev_angle = angle;
  float distance = angle_diff * WHEEL_RADIUS;
  accum_distance += distance;
  ESP_LOGI(TAG, "Angle diff: %f, distance: %f", angle_diff, accum_distance);

  idx++;
  if (idx >= DURATION) {
    // publish data
    doc["distance"] = accum_distance;
    mqttClient.publish(MQTT_DATA_TOPIC, doc.as<String>().c_str());
    ESP_LOGI(TAG, "Published data");
    accum_distance = 0;
    idx = 0;
  }
  M5.update();
  delay(1000);
}

Credits

Supachai Vorapojpisut
4 projects • 2 followers
Background in Electrical Engineering with past experience in firmware development for several processor platforms.

Comments