Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:laboratoare:2025_code:lab6_4 [2025/10/28 15:24] (current)
dan.tudose created
Line 1: Line 1:
 +<code C main.cpp>​
 +#include <​Arduino.h>​
 +#include <​Adafruit_NeoPixel.h>​
 +#include <​math.h>​
  
 +#include "​LSM6DSL.h"​
 +#include "​model.h" ​ // generated by train_model.py
 +
 +LSM6DSL imu;
 +
 +// LED setup (NeoPixel on GPIO3, 1 pixel)
 +#define NEOPIXEL_PIN ​  3
 +#define NEOPIXEL_COUNT 1
 +Adafruit_NeoPixel pixel(NEOPIXEL_COUNT,​ NEOPIXEL_PIN,​ NEO_GRB + NEO_KHZ800);​
 +
 +// sampling
 +const uint32_t SAMPLE_PERIOD_MS = 10; // ~100 Hz
 +uint32_t lastSampleMs = 0;
 +
 +// ring buffer for accel magnitude
 +static float magBuf[WINDOW_SIZE];​
 +static uint16_t magIndex = 0;
 +static uint16_t sampleCountSinceLastEval = 0;
 +
 +float logistic(float x) {
 +    // sigmoid
 +    return 1.0f / (1.0f + expf(-x));
 +}
 +
 +void setLED(bool shaking) {
 +    if (shaking) {
 +        // green
 +        pixel.setPixelColor(0,​ pixel.Color(0,​ 255, 0));
 +    } else {
 +        // off
 +        pixel.setPixelColor(0,​ pixel.Color(0,​ 0, 0));
 +    }
 +    pixel.show();​
 +}
 +
 +void computeFeatures(float &​mean_mag,​ float &​std_mag,​ float &​p2p_mag) {
 +    // Use the WINDOW_SIZE most recent samples in magBuf,
 +    // assuming magIndex is the "next write" index.
 +    float tmp[WINDOW_SIZE];​
 +    for (int i = 0; i < WINDOW_SIZE;​ i++) {
 +        // oldest -> newest reconstruction
 +        int idx = (magIndex + i) % WINDOW_SIZE;​
 +        tmp[i] = magBuf[idx];​
 +    }
 +
 +    // mean
 +    float sum = 0.0f;
 +    float minv = tmp[0];
 +    float maxv = tmp[0];
 +    for (int i = 0; i < WINDOW_SIZE;​ i++) {
 +        float v = tmp[i];
 +        sum += v;
 +        if (v < minv) minv = v;
 +        if (v > maxv) maxv = v;
 +    }
 +    mean_mag = sum / WINDOW_SIZE;​
 +
 +    // stddev
 +    float varSum = 0.0f;
 +    for (int i = 0; i < WINDOW_SIZE;​ i++) {
 +        float d = tmp[i] - mean_mag;
 +        varSum += d * d;
 +    }
 +    std_mag = sqrtf(varSum / WINDOW_SIZE);​
 +
 +    // peak-to-peak
 +    p2p_mag = maxv - minv;
 +}
 +
 +void setup() {
 +    Serial.begin(115200);​
 +    delay(2000);​
 +
 +    if (!imu.begin()) {
 +        Serial.println("#​ ERROR: IMU init failed"​);​
 +        while (true) { delay(1000);​ }
 +    }
 +
 +    pixel.begin();​
 +    pixel.show();​ // init off
 +
 +    // init magBuf
 +    for (int i = 0; i < WINDOW_SIZE;​ i++) {
 +        magBuf[i] = 1.0f; // ~1g stationary baseline
 +    }
 +
 +    Serial.println("#​ Sparrow shake detector running."​);​
 +}
 +
 +void loop() {
 +    uint32_t now = millis();
 +    if (now - lastSampleMs >= SAMPLE_PERIOD_MS) {
 +        lastSampleMs = now;
 +
 +        // 1. read imu
 +        float ax, ay, az;
 +        if (imu.readAccelG(ax,​ ay, az)) {
 +            // magnitude
 +            float mag = sqrtf(ax*ax + ay*ay + az*az);
 +
 +            // ring buffer write
 +            magBuf[magIndex] = mag;
 +            magIndex = (magIndex + 1) % WINDOW_SIZE;​
 +
 +            sampleCountSinceLastEval++;​
 +
 +            // 2. every STEP_SIZE samples, evaluate model
 +            if (sampleCountSinceLastEval >= STEP_SIZE) {
 +                sampleCountSinceLastEval = 0;
 +
 +                float mean_mag, std_mag, p2p_mag;
 +                computeFeatures(mean_mag,​ std_mag, p2p_mag);
 +
 +                // 3. logistic regression
 +                float decision =
 +                    ShakeModel::​W0 +
 +                    ShakeModel::​W1 * mean_mag +
 +                    ShakeModel::​W2 * std_mag +
 +                    ShakeModel::​W3 * p2p_mag;
 +
 +                float prob_shake = logistic(decision);​
 +
 +                bool shaking = (prob_shake > 0.5f);
 +
 +                // 4. act
 +                setLED(shaking);​
 +
 +                // debug
 +                Serial.print("​mean="​);​
 +                Serial.print(mean_mag,​ 4);
 +                Serial.print("​ std="​);​
 +                Serial.print(std_mag,​ 4);
 +                Serial.print("​ p2p="​);​
 +                Serial.print(p2p_mag,​ 4);
 +                Serial.print("​ prob="​);​
 +                Serial.print(prob_shake,​ 3);
 +                Serial.print("​ -> ");
 +                Serial.println(shaking ? "​SHAKE"​ : "​IDLE"​);​
 +            }
 +        }
 +    }
 +}
 +
 +</​code>​
iothings/laboratoare/2025_code/lab6_4.txt · Last modified: 2025/10/28 15:24 by dan.tudose
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0