Showing Time of Movement With IMU Sensor
by alhuang in Circuits > Wearables
472 Views, 2 Favorites, 0 Comments
Showing Time of Movement With IMU Sensor
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
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
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);
}