Showing Time of Movement With IMU Sensor

by alhuang in Circuits > Wearables

350 Views, 2 Favorites, 0 Comments

Showing Time of Movement With IMU Sensor

Screenshot (432).png

For a design project, I wanted to help understand repetitive strain of laborers and workers. With the help of my professor and friends, I was able to write an develop an IMU sensor to record time whenever there is small range of motion.

Get Your Tools

lsm6dso32.png
1_elegoo_uno.jpg

Wire 'em Up!

Code for Processing

app UI.png
Screenshot (435).png

I mocked a UI that shows IMU data being transferred from Arduino to Processing. Below is the code that made it actually happen:

// accelerometer & gyro readings from Adafruit
// Modified by Bayan, Silas & Al to repetitive small ROM
// LSM6DSO32 sensor

#include <Adafruit_LSM6DSO32.h>

float d = 0;
float dold = 0;
float t = 0;
float a = 0;
float x;
float xold;
float y;
float yold;
float z;
float zold;
float motionscale = 0.2;
//motion counter
int n = 0;

int LED = 1;
long starttime = 0;
long endtime = 0;
Adafruit_LSM6DSO32 dso32;


void setup(void) {
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

//  Serial.println("Adafruit LSM6DSO32 test!");

  if (!dso32.begin_I2C()) {
    while (1) {
      delay(10);
    }
  }

  Serial.println("LSM6DSO32 Found!");

  dso32.setAccelRange(LSM6DSO32_ACCEL_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (dso32.getAccelRange()) {
    case LSM6DSO32_ACCEL_RANGE_4_G:
      Serial.println("+-4G");
      break;
    case LSM6DSO32_ACCEL_RANGE_8_G:
      Serial.println("+-8G");
      break;
    case LSM6DSO32_ACCEL_RANGE_16_G:
      Serial.println("+-16G");
      break;
    case LSM6DSO32_ACCEL_RANGE_32_G:
      Serial.println("+-32G");
      break;
  }

  // dso32.setGyroRange(LSM6DS_GYRO_RANGE_250_DPS );
  Serial.print("Gyro range set to: ");
  switch (dso32.getGyroRange()) {
    case LSM6DS_GYRO_RANGE_125_DPS:
      Serial.println("125 degrees/s");
      break;
    case LSM6DS_GYRO_RANGE_250_DPS:
      Serial.println("250 degrees/s");
      break;
    case LSM6DS_GYRO_RANGE_500_DPS:
      Serial.println("500 degrees/s");
      break;
    case LSM6DS_GYRO_RANGE_1000_DPS:
      Serial.println("1000 degrees/s");
      break;
    case LSM6DS_GYRO_RANGE_2000_DPS:
      Serial.println("2000 degrees/s");
      break;
    case ISM330DHCX_GYRO_RANGE_4000_DPS:
      break; // unsupported range for the DSO32
  }

  // dso32.setAccelDataRate(LSM6DS_RATE_12_5_HZ);
  Serial.print("Accelerometer data rate set to: ");
  switch (dso32.getAccelDataRate()) {
    case LSM6DS_RATE_SHUTDOWN:
      Serial.println("0 Hz");
      break;
    case LSM6DS_RATE_12_5_HZ:
      Serial.println("12.5 Hz");
      break;
    case LSM6DS_RATE_26_HZ:
      Serial.println("26 Hz");
      break;
    case LSM6DS_RATE_52_HZ:
      Serial.println("52 Hz");
      break;
    case LSM6DS_RATE_104_HZ:
      Serial.println("104 Hz");
      break;
    case LSM6DS_RATE_208_HZ:
      Serial.println("208 Hz");
      break;
    case LSM6DS_RATE_416_HZ:
      Serial.println("416 Hz");
      break;
    case LSM6DS_RATE_833_HZ:
      Serial.println("833 Hz");
      break;
    case LSM6DS_RATE_1_66K_HZ:
      Serial.println("1.66 KHz");
      break;
    case LSM6DS_RATE_3_33K_HZ:
      Serial.println("3.33 KHz");
      break;
    case LSM6DS_RATE_6_66K_HZ:
      Serial.println("6.66 KHz");
      break;
  }

  // dso32.setGyroDataRate(LSM6DS_RATE_12_5_HZ);
  Serial.print("Gyro data rate set to: ");
  switch (dso32.getGyroDataRate()) {
    case LSM6DS_RATE_SHUTDOWN:
      Serial.println("0 Hz");
      break;
    case LSM6DS_RATE_12_5_HZ:
      Serial.println("12.5 Hz");
      break;
    case LSM6DS_RATE_26_HZ:
      Serial.println("26 Hz");
      break;
    case LSM6DS_RATE_52_HZ:
      Serial.println("52 Hz");
      break;
    case LSM6DS_RATE_104_HZ:
      Serial.println("104 Hz");
      break;
    case LSM6DS_RATE_208_HZ:
      Serial.println("208 Hz");
      break;
    case LSM6DS_RATE_416_HZ:
      Serial.println("416 Hz");
      break;
    case LSM6DS_RATE_833_HZ:
      Serial.println("833 Hz");
      break;
    case LSM6DS_RATE_1_66K_HZ:
      Serial.println("1.66 KHz");
      break;
    case LSM6DS_RATE_3_33K_HZ:
      Serial.println("3.33 KHz");
      break;
    case LSM6DS_RATE_6_66K_HZ:
      Serial.println("6.66 KHz");
      break;
  }
}

void loop() {

  //  /* Get a new normalized sensor event */
  sensors_event_t accel;
  sensors_event_t gyro;
  sensors_event_t temp;
  dso32.getEvent(&accel, &gyro, &temp);



  /* Display the results (acceleration is measured in m/s^2) */



  xold = x;
  yold = y;
  zold = z;

  //define time between recordings
  delay(200);

  x = accel.acceleration.x;
  y = accel.acceleration.y;
  z = accel.acceleration.z;
  float diffx = xold - x;
  float diffy = yold - y;
  float diffz = zold - z;
  float ax = abs(diffx);
  float ay = abs(diffy);
  float az = abs(diffz);

  /* Distance measured */
  d =  sqrt(sq(ax) + sq(ay) + sq(az));

  /* range of motion */
  if (d > .5 && d < 20) {
//    Serial.print("small ROM");
//    Serial.print("  ");
//    Serial.print(d);
    /* number of movement */
    n = n + 1;
//    Serial.print("  ");
    //Serial.println(n);

    /*alarm for overcounted ROM*/
    //    if (n == 5) {
    //      Serial.println("alarm");
    //      n = 0;
    //    }
  }
  //  /* counttime if sensor moves */
  if (ax > motionscale || ay > motionscale || az > motionscale)
  {
    digitalWrite(LED, LOW);
    starttime = millis();

      //  Serial.print("movetime");
        Serial.print("  ");
        Serial.println(starttime);
  }
  else
  {
    digitalWrite(LED, HIGH);
    endtime = millis();
    int totaltime = (endtime - starttime) / 1000;
    //    Serial.println(totaltime);
  }


  //  // serial plotter friendly format

  //  Serial.print(temp.temperature);
  //  Serial.print(",");

  //  Serial.print(accel.acceleration.x);
  //  Serial.print(","); Serial.print(accel.acceleration.y);
  //  Serial.print(","); Serial.print(accel.acceleration.z);
  //  Serial.print(",");

  // Serial.print(gyro.gyro.x);
  // Serial.print(","); Serial.print(gyro.gyro.y);
  // Serial.print(","); Serial.print(gyro.gyro.z);
  // Serial.println();
  //  delayMicroseconds(10000);
}

Code for LED

Screenshot (433).png

This simple proof of concept to show how aggregated time of movement can be visualized on a interface without a screen. Below is the code:

// accelerometer & gyro readings from Adafruit
// Modified by Bayan, Silas & Al to repetitive small ROM
// LSM6DSO32 sensor
// Don't serial print anything, attiny85 doesn't have a serial port

#include <Adafruit_LSM6DSO32.h>
#include <FastLED.h>
#define LED_PIN     5
// Information about the LED strip
#define NUM_LEDS    8
#define CHIPSET     WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define BRIGHTNESS  100
#define BRIGHTALARM  200
#define UPDATES_PER_SECOND 100
CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;


float d = 0;
float dold = 0;
float t = 0;
float a = 0;
float x;
float xold;
float y;
float yold;
float z;
float zold;
float motionscale = 0.2;
//motion counter
int n = 0;

int LED = 1;
long starttime = 0;
long endtime = 0;
Adafruit_LSM6DSO32 dso32;


void setup(void) {

  FastLED.addLeds<WS2812B, LED_PIN, RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );  // GRB ordering is typical
  FastLED.setBrightness(  BRIGHTNESS );

  currentPalette = RainbowColors_p;
  currentBlending = LINEARBLEND;

  pinMode(LED, OUTPUT);
  Serial.begin(9600);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  //  Serial.println("Adafruit LSM6DSO32 test!");

  if (!dso32.begin_I2C()) {
    while (1) {
      delay(10);
    }
  }

  //Serial.println("LSM6DSO32 Found!");

  dso32.setAccelRange(LSM6DSO32_ACCEL_RANGE_8_G);
  //  Serial.print("Accelerometer range set to: ");
  //  switch (dso32.getAccelRange()) {
  //    case LSM6DSO32_ACCEL_RANGE_4_G:
  //      Serial.println("+-4G");
  //      break;
  //    case LSM6DSO32_ACCEL_RANGE_8_G:
  //      Serial.println("+-8G");
  //      break;
  //    case LSM6DSO32_ACCEL_RANGE_16_G:
  //      Serial.println("+-16G");
  //      break;
  //    case LSM6DSO32_ACCEL_RANGE_32_G:
  //      Serial.println("+-32G");
  //      break;
}

// dso32.setGyroRange(LSM6DS_GYRO_RANGE_250_DPS );
//  Serial.print("Gyro range set to: ");
//  switch (dso32.getGyroRange()) {
//    case LSM6DS_GYRO_RANGE_125_DPS:
//      Serial.println("125 degrees/s");
//      break;
//    case LSM6DS_GYRO_RANGE_250_DPS:
//      Serial.println("250 degrees/s");
//      break;
//    case LSM6DS_GYRO_RANGE_500_DPS:
//      Serial.println("500 degrees/s");
//      break;
//    case LSM6DS_GYRO_RANGE_1000_DPS:
//      Serial.println("1000 degrees/s");
//      break;
//    case LSM6DS_GYRO_RANGE_2000_DPS:
//      Serial.println("2000 degrees/s");
//      break;
//    case ISM330DHCX_GYRO_RANGE_4000_DPS:
//      break; // unsupported range for the DSO32
//  }

// dso32.setAccelDataRate(LSM6DS_RATE_12_5_HZ);
//  Serial.print("Accelerometer data rate set to: ");
//  switch (dso32.getAccelDataRate()) {
//    case LSM6DS_RATE_SHUTDOWN:
//      Serial.println("0 Hz");
//      break;
//    case LSM6DS_RATE_12_5_HZ:
//      Serial.println("12.5 Hz");
//      break;
//    case LSM6DS_RATE_26_HZ:
//      Serial.println("26 Hz");
//      break;
//    case LSM6DS_RATE_52_HZ:
//      Serial.println("52 Hz");
//      break;
//    case LSM6DS_RATE_104_HZ:
//      Serial.println("104 Hz");
//      break;
//    case LSM6DS_RATE_208_HZ:
//      Serial.println("208 Hz");
//      break;
//    case LSM6DS_RATE_416_HZ:
//      Serial.println("416 Hz");
//      break;
//    case LSM6DS_RATE_833_HZ:
//      Serial.println("833 Hz");
//      break;
//    case LSM6DS_RATE_1_66K_HZ:
//      Serial.println("1.66 KHz");
//      break;
//    case LSM6DS_RATE_3_33K_HZ:
//      Serial.println("3.33 KHz");
//      break;
//    case LSM6DS_RATE_6_66K_HZ:
//      Serial.println("6.66 KHz");
//      break;
//  }
//
//  // dso32.setGyroDataRate(LSM6DS_RATE_12_5_HZ);
//  Serial.print("Gyro data rate set to: ");
//  switch (dso32.getGyroDataRate()) {
//    case LSM6DS_RATE_SHUTDOWN:
//      Serial.println("0 Hz");
//      break;
//    case LSM6DS_RATE_12_5_HZ:
//      Serial.println("12.5 Hz");
//      break;
//    case LSM6DS_RATE_26_HZ:
//      Serial.println("26 Hz");
//      break;
//    case LSM6DS_RATE_52_HZ:
//      Serial.println("52 Hz");
//      break;
//    case LSM6DS_RATE_104_HZ:
//      Serial.println("104 Hz");
//      break;
//    case LSM6DS_RATE_208_HZ:
//      Serial.println("208 Hz");
//      break;
//    case LSM6DS_RATE_416_HZ:
//      Serial.println("416 Hz");
//      break;
//    case LSM6DS_RATE_833_HZ:
//      Serial.println("833 Hz");
//      break;
//    case LSM6DS_RATE_1_66K_HZ:
//      Serial.println("1.66 KHz");
//      break;
//    case LSM6DS_RATE_3_33K_HZ:
//      Serial.println("3.33 KHz");
//      break;
//    case LSM6DS_RATE_6_66K_HZ:
//      Serial.println("6.66 KHz");
//      break;
//  }
//}

void loop() {

  //  /* Get a new normalized sensor event */
  sensors_event_t accel;
  sensors_event_t gyro;
  sensors_event_t temp;
  dso32.getEvent(&accel, &gyro, &temp);



  static uint8_t startIndex = 0;
  startIndex = startIndex + 1; /* motion speed */


  FastLED.show();
  FastLED.delay(1000 / UPDATES_PER_SECOND);


  /* Display the results (acceleration is measured in m/s^2) */



  xold = x;
  yold = y;
  zold = z;

  //define time between recordings
  delay(200);

  x = accel.acceleration.x;
  y = accel.acceleration.y;
  z = accel.acceleration.z;
  float diffx = xold - x;
  float diffy = yold - y;
  float diffz = zold - z;
  float ax = abs(diffx);
  float ay = abs(diffy);
  float az = abs(diffz);

  /* Distance measured */
  d =  sqrt(sq(ax) + sq(ay) + sq(az));

  /* range of motion */
  if (d > .5 && d < 20) {
    //    Serial.print("small ROM");
    //    Serial.print("  ");
    //    Serial.print(d);
    /* number of movement */
    n = n + 1;
    //    Serial.print("  ");
    //Serial.println(n);

    /*alarm for overcounted ROM*/
    //    if (n == 5) {
    //      Serial.println("alarm");
    //      n = 0;
    //    }
  }
  //  /* counttime if sensor moves */
  if (ax > motionscale || ay > motionscale || az > motionscale)
  {
//    digitalWrite(LED, LOW);
    leds[7] = CRGB::Purple;
    FastLED.show();
    starttime = millis();

    //  Serial.print("movetime");
    //Serial.print("  ");
    Serial.println(starttime);
  }
  else
  {
//    digitalWrite(LED, HIGH);
    leds[7] = CRGB::Black;
    FastLED.show();
    endtime = millis();
    int totaltime = (endtime - starttime) / 1000;
    //    Serial.println(totaltime);
  }

  if (starttime > 1000 && starttime < 8000) {
    leds[0] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 2000 && starttime < 9000) {
    leds[1] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 3000 && starttime < 10000) {
    leds[2] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 4000 && starttime < 11000) {
    leds[3] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 5000 && starttime < 12000) {
    leds[4] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 6000 && starttime < 13000) {
    leds[5] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 7000 && starttime < 14000) {
    leds[6] = CRGB::Red;
    FastLED.show();
  }
  if (starttime > 8000 && starttime < 15000) {
    leds[0] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 9000 && starttime < 16000) {
    leds[1] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 10000 && starttime < 17000) {
    leds[2] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 11000 && starttime < 18000) {
    leds[3] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 12000 && starttime < 19000) {
    leds[4] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 13000 && starttime < 20000) {
    leds[5] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 14000 && starttime < 21000) {
    leds[6] = CRGB::Yellow;
    FastLED.show();
  }
  if (starttime > 15000 && starttime < 22000) {
    leds[0] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 16000 && starttime < 23000) {
    leds[1] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 17000 && starttime < 24000) {
    leds[2] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 18000 && starttime < 25000) {
    leds[3] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 19000 && starttime < 26000) {
    leds[4] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 20000 && starttime < 27000) {
    leds[5] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 21000 && starttime < 28000) {
    leds[6] = CRGB::Green;
    FastLED.show();
  }
  if (starttime > 22000) {
    FastLED.setBrightness(  BRIGHTALARM );
    leds[0, 1, 2, 3, 4, 5, 6] = CRGB::Green;
    FastLED.show();
    delay(500);
    // Now turn the LED off, then pause
    leds[0, 1, 2, 3, 4, 5, 6] = CRGB::Black;
    FastLED.show();
    delay(500);
  }
  //  // serial plotter friendly format

  //  Serial.print(temp.temperature);
  //  Serial.print(",");

  //  Serial.print(accel.acceleration.x);
  //  Serial.print(","); Serial.print(accel.acceleration.y);
  //  Serial.print(","); Serial.print(accel.acceleration.z);
  //  Serial.print(",");

  // Serial.print(gyro.gyro.x);
  // Serial.print(","); Serial.print(gyro.gyro.y);
  // Serial.print(","); Serial.print(gyro.gyro.z);
  // Serial.println();
  //  delayMicroseconds(10000);
}