Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions senseBox-bike-atrai-v2/src/display/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <Adafruit_SSD1306.h>
#include <QRCodeGenerator.h>
#include <Adafruit_MAX1704X.h>
#include "bicycle_loading_bitmap.h"
#include "bitmaps.h"

Adafruit_SSD1306 SBDisplay::display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
QRCode SBDisplay::qrcode;
Expand All @@ -30,6 +30,10 @@ void SBDisplay::bicycleAnimationTask(void *pvParameter)
{
for (int i = 0; i < 36; i++)
{
if (!isBicycleAnimationShowing)
{
vTaskDelete(xBicycleAnimationTaskHandle);
}
display.clearDisplay();
display.drawBitmap(32, -10, bicycle_loading_bitmap[i], 64, 64, 1); // this displays each frame hex value
drawProgressbar(4, (dsplH - 12) - prgsH - 8, prgsW, prgsH, loadingProgress * 100);
Expand All @@ -39,12 +43,11 @@ void SBDisplay::bicycleAnimationTask(void *pvParameter)
display.println(loadingMessage);
// drawBattery(0, 0, 16, 4);
display.display();
vTaskDelay(pdMS_TO_TICKS(100));

if (!isBicycleAnimationShowing)
{
vTaskDelete(xBicycleAnimationTaskHandle);
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
}
Expand Down Expand Up @@ -199,4 +202,40 @@ void SBDisplay::drawQrCode(const char *qrStr, const char *lines[])
void SBDisplay::readBleId()
{
bleId = SenseBoxBLE::getMCUId();
}

void SBDisplay::showError(String msg)
{
// Stop animation task and wait for it to complete
if (isBicycleAnimationShowing)
{
isBicycleAnimationShowing = false;
delay(150); // Wait for animation task to finish its cycle and delete itself
}

// Clear display buffer completely
display.clearDisplay();
display.display();
delay(10); // Brief delay to ensure display is cleared

display.clearDisplay();

// Draw warning symbol centered at the top
int symbolX = (SCREEN_WIDTH - 32) / 2; // Center horizontally (32 is symbol width)
int symbolY = 8; // Position from top
display.drawBitmap(symbolX, symbolY, warning_symbol, 32, 32, WHITE);

// Draw text lines at the bottom
display.setTextSize(1);
display.setTextColor(WHITE, BLACK);

// First text line
display.setCursor(0, SCREEN_HEIGHT - 20);
display.print("ERROR:");

// Second text line
display.setCursor(0, SCREEN_HEIGHT - 10);
display.print(msg);

display.display();
}
1 change: 1 addition & 0 deletions senseBox-bike-atrai-v2/src/display/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SBDisplay
static void drawBattery(int x, int y, int width, int height);
static void bicycleAnimationTask(void *pvParams);
static void readBleId();
static void showError(String msg);

private:
static Adafruit_SSD1306 display;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1224,4 +1224,16 @@ const unsigned char bicycle_loading_bitmap[36][512] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};

// Warning symbol (triangle with exclamation mark) - 32x32 pixels
const unsigned char warning_symbol[] PROGMEM = {
0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00,
0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00,
0x00, 0x1e, 0x78, 0x00, 0x00, 0x1e, 0x78, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x3c, 0x3c, 0x00,
0x00, 0x79, 0x9e, 0x00, 0x00, 0x79, 0x9e, 0x00, 0x00, 0xf1, 0x8f, 0x00, 0x00, 0xf1, 0x8f, 0x00,
0x01, 0xe1, 0x87, 0x80, 0x01, 0xe1, 0x87, 0x80, 0x03, 0xc1, 0x83, 0xc0, 0x03, 0xc1, 0x83, 0xc0,
0x07, 0x81, 0x81, 0xe0, 0x07, 0x81, 0x81, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0,
0x1e, 0x00, 0x00, 0x78, 0x1e, 0x01, 0x80, 0x78, 0x3c, 0x01, 0x80, 0x3c, 0x3f, 0xff, 0xff, 0xfc,
0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
14 changes: 11 additions & 3 deletions senseBox-bike-atrai-v2/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ void setup()
for (BaseSensor *sensor : sensors)
{
sensor->begin();
if (!sensor->isInitialized()) {
SBDisplay::showError(sensor->name);
delay(1500);
}
}

SBDisplay::showLoading("Ventilation...", 0.6);
Expand All @@ -65,15 +69,19 @@ void setup()
// Start sensor measurements
for (BaseSensor *sensor : sensors)
{
sensor->startSubscription();
if (sensor->isInitialized()) {
sensor->startSubscription();
}
}

SBDisplay::showLoading("Enable BLE...", 1);

// Start BLE advertising
for (BaseSensor *sensor : sensors)
{
sensor->startBLE();
if (sensor->isInitialized()) {
sensor->startBLE();
}
}

display.readBleId();
Expand All @@ -87,7 +95,7 @@ void loop()
{
// Read acceleration and distance sensor data as fast as possible
distanceSensor.readSensorData();
bool classified = accelerationSensor.readSensorData();
bool classified = !accelerationSensor.isInitialized() || accelerationSensor.readSensorData();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is may be problematic, because the accelerationsensor is responsible for the measurement intervall of the other sensors. If classified is always true (when acceleration sensor doesnt work) then dust and temp/humid will be measured at a much smaller intervall than before.
But maybe this is also fine?


// Read temperature and fine dust sensor data after a surface classification
if (classified)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "AccelerationSensor.h"
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"

AccelerationSensor::AccelerationSensor() : BaseSensor("accelerationSensorTask", 2048, 0) {}
AccelerationSensor::AccelerationSensor() : BaseSensor("accelerationSensorTask", 2048, 0) {
name = "Acceleration Sensor";
}

String surfaceClassificationUUID = "B944AF10F4954560968F2F0D18CAB521";
String anomalyUUID = "B944AF10F4954560968F2F0D18CAB523";
Expand All @@ -10,25 +12,27 @@ int anomalyCharacteristic = 0;

void AccelerationSensor::initSensor()
{
// Try initializing MPU6050 first
if (mpu.begin(0x68, &Wire1))
{
Serial.println("MPU6050 Found!");
initialized = true;
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
activeSensor = MPU6050;
}
else if (icm.begin() == 0)
{
// If MPU6050 fails, try ICM42670P
Serial.println("ICM42670P Found!");
initialized = true;
icm.startAccel(21, 8); // Accel ODR = 100 Hz, Full Scale Range = 16G
icm.startGyro(21, 500); // Gyro ODR = 100 Hz, Full Scale Range = 2000 dps
activeSensor = ICM42670X;
}
else if (icm2.begin_I2C(0x68, &Wire1))
{
Serial.println("ICM20948 Found!");
initialized = true;
icm2.setAccelRange(ICM20948_ACCEL_RANGE_8_G);
icm2.setAccelRateDivisor(10.25); // 100 Hz sample rate
activeSensor = ICM20948;
Expand All @@ -52,12 +56,17 @@ float probSett = 0.0;
float probStanding = 0.0;
float anomaly = 0.0;

// float prevAccTime = millis();
float prevAccTime = millis();

bool AccelerationSensor::readSensorData()
{
if (!initialized)
{
Serial.println("No acceleration sensor initialized");
return false;
}

bool classified = false;


if (activeSensor == MPU6050)
{
Expand Down
5 changes: 5 additions & 0 deletions senseBox-bike-atrai-v2/src/sensors/BaseSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ void BaseSensor::sensorTask(void *pvParameters)
}
vTaskDelay(pdMS_TO_TICKS(sensor->taskDelay));
}
}

bool BaseSensor::isInitialized()
{
return initialized;
}
5 changes: 5 additions & 0 deletions senseBox-bike-atrai-v2/src/sensors/BaseSensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ class BaseSensor
public:
BaseSensor(const char *taskName, uint32_t taskStackSize = 8192, uint32_t taskDelay = 1000);

String name;

void begin();
void subscribe(std::function<void(std::vector<float>)> callback);
void startSubscription();
void stopSubscription();
void startBLE();
void stopBLE();
bool isInitialized();

protected:
bool initialized = false;
const int maxInitAttempts = 5;
virtual void initSensor() = 0;
virtual bool readSensorData() = 0;
static void sensorTask(void *pvParameters);
Expand Down
24 changes: 15 additions & 9 deletions senseBox-bike-atrai-v2/src/sensors/BatterySensor/BatterySensor.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include "BatterySensor.h"
#include <display/Display.h>

BatterySensor::BatterySensor() : BaseSensor("batterySensorTask", 2048, 10000) {}
BatterySensor::BatterySensor() : BaseSensor("batterySensorTask", 2048, 10000) {
name = "Battery Sensor";
}

// 5b262dea-4565-4ea0-912f-1e453bda0ca7
// String batteryUUID = "5B262DEA45654EA0912F1E453BDA0CA7";
Expand All @@ -14,21 +15,26 @@ Adafruit_MAX17048 maxlipo;

void BatterySensor::initSensor()
{
while (!maxlipo.begin())
{
SBDisplay::showLoading("MAX17048 Error", 0);
for (int i = 0; i < maxInitAttempts && !initialized; i++) {
Serial.print("MAX17048 initialization failed\n");
initialized = maxlipo.begin();
delay(500);
}
if (!initialized) {
Serial.println(F("Couldnt find Adafruit MAX17048?\nMake sure a battery is plugged in!"));
delay(2000);
return;
}

BLEModule::createService("180F");
batteryCharacteristic = BLEModule::createCharacteristic(batteryUUID.c_str());
// add more if needed
}

bool BatterySensor::readSensorData()
{
// read sensor data
if(!initialized)
{
Serial.println("MAX17048 not initialized");
return false;
}
float batteryCharge = maxlipo.cellPercent();

if (measurementCallback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "edge-impulse-sdk/tensorflow/lite/schema/schema_generated.h"
#include <edge-impulse-sdk/tensorflow/lite/micro/micro_error_reporter.h>

DistanceSensor::DistanceSensor() : BaseSensor("distanceTask", 8192, 0) {}
DistanceSensor::DistanceSensor() : BaseSensor("distanceTask", 8192, 0) {
name = "Distance Sensor";
}

String distanceUUID = "B3491B60C0F34306A30D49C91F37A62B";
int distanceCharacteristic = 0;
Expand Down Expand Up @@ -51,7 +53,12 @@ void DistanceSensor::initSensor()
Wire.begin();
Wire.setClock(1000000); // Sensor has max I2C freq of 1MHz
sensor_vl53l8cx_top.begin();
sensor_vl53l8cx_top.init_sensor();
initialized = sensor_vl53l8cx_top.init_sensor() == 0;
if (!initialized)
{
Serial.println("VL53L8CX initialization failed");
return;
}
sensor_vl53l8cx_top.vl53l8cx_set_ranging_frequency_hz(30);
sensor_vl53l8cx_top.vl53l8cx_set_resolution(VL53L8CX_RESOLUTION_8X8);
sensor_vl53l8cx_top.vl53l8cx_start_ranging();
Expand All @@ -63,6 +70,7 @@ void DistanceSensor::initSensor()
Serial.printf("Model provided is schema version %d not equal "
"to supported version %d.",
model->version(), TFLITE_SCHEMA_VERSION);
initialized = false;
return;
}
// This imports all operations, which is more intensive, than just importing the ones we need.
Expand All @@ -87,10 +95,12 @@ void DistanceSensor::initSensor()
Serial.println(model_input->dims->data[2]);
Serial.println(model_input->type);
Serial.println("Bad input tensor parameters in model");
initialized = false;
return;
}
input_length = model_input->bytes / sizeof(float);
// ----------------------------- setup complete -----------------------------
initialized = true;
Serial.println("setup complete");

distanceCharacteristic = BLEModule::createCharacteristic(distanceUUID.c_str());
Expand All @@ -100,6 +110,11 @@ void DistanceSensor::initSensor()

bool DistanceSensor::readSensorData()
{
if (!initialized)
{
Serial.println("Distance sensor not initialized");
return false;
}
Wire.setClock(1000000); // Sensor has max I2C freq of 1MHz
VL53L8CX_ResultsData Results;
uint8_t NewDataReady = 0;
Expand Down
22 changes: 16 additions & 6 deletions senseBox-bike-atrai-v2/src/sensors/DustSensor/DustSensor.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "DustSensor.h"

DustSensor::DustSensor() : BaseSensor("DustSensorTask", 2048, 1000) {}
DustSensor::DustSensor() : BaseSensor("DustSensorTask", 2048, 1000) {
name = "Dust Sensor";
}

String dustUUID = "7E14E07084EA489FB45AE1317364B979";
int dustCharacteristic = 0;
Expand All @@ -15,12 +17,14 @@ void DustSensor::initSensor()

sensirion_i2c_init();

while (sps30_probe() != 0)
{
for (int i = 0; i < maxInitAttempts && !initialized; i++) {
Serial.print("SPS sensor probing failed\n");
delay(500);
initialized = (sps30_probe() == 0);
delay(100);
}
if (!initialized) {
return;
}

Serial.print("SPS sensor probing successful\n");

ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days);
Expand All @@ -34,15 +38,21 @@ void DustSensor::initSensor()
if (ret < 0)
{
Serial.print("error starting measurement\n");
initialized = false;
return;
}

Serial.print("measurements started\n");

dustCharacteristic = BLEModule::createCharacteristic(dustUUID.c_str());
}

bool DustSensor::readSensorData()
{
if (!initialized)
{
Serial.println("SPS30 not initialized");
return false;
}
Wire.setClock(100000); // Sensor has max I2C freq of 1MHz
struct sps30_measurement m;
char serial[SPS30_MAX_SERIAL_LEN];
Expand Down
Loading