Maker Pro
Maker Pro

Problem with measuring vibrations (Arduino UNO + step motor + accelerometer)

Dear all,

I'm trying to measure vibrations of the motor's shaft that is oscillating due to an eccentric load. For that, I am using the MPU 6050 6 axis accelerometer. The motor is a NEMA 17 stepper, connected to Arduino UNO via the EasyDriver v4.4.
I first uploaded my code for the stepper, where I have 2 buttons to control the rotation direction (if you press the left, it goes clockwise and if you press the right button it goes counter clockwise). This code works fine.
Later I uploaded the code only for the accelerometer and it worked fine, however when I'm trying to combine both so that the vibrations could be measured while the motor is running, apparently, I'm losing steps of the motor. Here is the code:
Code:
#include<Wire.h>
const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

#define RPMS                300.0
#define STEP_PIN                9
#define DIRECTION_PIN           8
#define GO_PIN_L                3
#define GO_PIN_R                4

#define STEPS_PER_REV         200
#define MICROSTEPS_PER_STEP     8
#define MICROSECONDS_PER_MICROSTEP   (1000000/(STEPS_PER_REV * MICROSTEPS_PER_STEP)/(RPMS / 60))

uint32_t LastStepTime = 0;
uint32_t CurrentTime = 0;

int Distance = 0;

void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);

  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIRECTION_PIN, OUTPUT);
  digitalWrite(STEP_PIN, LOW);
  digitalWrite(DIRECTION_PIN, LOW);
  pinMode(GO_PIN_L, INPUT);
  pinMode(GO_PIN_R, INPUT);
}

void loop() {
  Distance = Distance + 1;   // record this step
  if (digitalRead(GO_PIN_L) == LOW)
  {
    CurrentTime = micros();
    digitalWrite(8, LOW);
    if ((CurrentTime - LastStepTime) > MICROSECONDS_PER_MICROSTEP)
    {
      LastStepTime = CurrentTime;
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds((MICROSECONDS_PER_MICROSTEP * 0.9) / 2);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds((MICROSECONDS_PER_MICROSTEP * 0.9) / 2);
    }
  }
  if (digitalRead(GO_PIN_R) == LOW)
  {
    CurrentTime = micros();
    digitalWrite(8, HIGH);
    if ((CurrentTime - LastStepTime) > MICROSECONDS_PER_MICROSTEP)
    {
      LastStepTime = CurrentTime;
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds((MICROSECONDS_PER_MICROSTEP * 0.9) / 2);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds((MICROSECONDS_PER_MICROSTEP * 0.9) / 2);
    }
  }
//  Wire.beginTransmission(MPU_addr);
//  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
//  Wire.endTransmission(false);
//  Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
//  float AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
//  float AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
//  float AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
//  Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
//  // GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
//  // GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
//  // GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
//  Serial.print("AcX = "); Serial.println(AcX / 16384);
//  Serial.print(" AcY = "); Serial.println(AcY / 16384);
//  Serial.print(" AcZ = "); Serial.println(AcZ / 16384);
//  Serial.print(" Tmp = "); Serial.print(Tmp / 340.00 + 36.53);
//  Serial.println("");
//  // Serial.print(" | GyX = "); Serial.print(GyX);
//  // Serial.print(" | GyY = "); Serial.print(GyY);
//  // Serial.print(" | GyZ = "); Serial.println(GyZ);
//  delay(333);
}

So the commented portion of the code is used to read and print accelerations. Since this is in the same loop as the code for the motor, I'm sure that the delay(333) has a negative effect, but also when I tried step-by-step to include lines of code for accelerometer, the motor slowly starter to losing speed and steps... The problem is, that the accelerometer code interferes with the motor's code, which requires a smooth code transition.

Does anyone of you have a clue how this could be done so that both devices (the motor with EasyDriver v 4.4 and the accelerometer) could run simultaneously?
Kind regards,

Luka
 
Last edited:
I'm guessing here:
1) 300 RPMs is pretty fast for any 1.8-degree stepper. For testing, slow that down to 10 RPMs just to see if you get any results.

2) your serial speed is set really low. Try speeding it up to 115200 ,,,,,,,, even the China clones will run that fast. And anyway, IIRC with the serial speed set to 115,200 that is fast enough for only about 800 serial transmissions per second. The Serial() call takes some time of its own.
 
in mechanics/machinist rpms are counter productive. There is really no way to "measure the oscillations" of a spinning shaft or eccentric, unless you understand this slight idea I had.
'mechanically its impossible. if a light was positioned parrallel to the shaft, and the eccentric was to obstruct the light as the shaft spun, you could read the rpms with a suitable sensor on the opposing side of the eccentric.' The caveat is that even the fastest computer in the world has problems keeping up with 10,000 rpm motors. For a digital output, it has to be a high power direct connection, and it also has to have enough input from other sensor arrays to calculate any variations in the speed of the shaft. If all you want is vibrations.>>>>

A flying arm, positioned within proximity of the eccentric, and counter balanced to adjust a potentiometer as the rpms push it away from the shaft... could give a fairly accurate reference of the shaft speed. this is similar to a centrifical clutch on a small go cart, where the revs engage the clutch the faster the engine spins. Except backwards.

I have always wanted to build one!
 
Top