Showing Time of Movement With IMU Sensor
by alhuang in Circuits > Wearables
400 Views, 2 Favorites, 0 Comments
Showing Time of Movement With IMU Sensor
.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 IMU sensor
https://www.adafruit.com/product/4692
https://www.adafruit.com/product/4692
https://www.adafruit.com/product/4692
Download these if you haven't already...
https://www.adafruit.com/product/4692
https://www.adafruit.com/product/4692 https://playground.arduino.cc/Interfacing/Process...
Processing https://www.adafruit.com/product/4692
Wire 'em Up!
Connect your IMU sensor and LED strip following these tutorials.
Code for Processing

.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
.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); }