Originally responded to Jinky’s post because the formulae did not look correct and I had no idea what it was doing. Also the problem was the formulae returned a positive value all the time. Jinky needed to know when it was one way or the other.
I found “Analog Devices application note AN-1057 - Using an Accelerometer for Inclination Sensing” and the formulae’s in that document made sense to me. I purchased a MPU6050 (faily cheap) and experimented. The rest of my posts related to what I found that would do what Jinky was after and my experience programming an Arduino device like the UNO.
The devices are being used if a very basic way. Calibration has not been considered and all the other features available. Quartenions in 3D space sounds interesting if you were doing something more complex. For what Jinky needs I think it would only complicate the code.
when first opens the serial monitor/ sensor positioned randomly:
x = 6.91 y = 7.23, z = 1.91 m/y_tilt = 60
x = 3.24 y = 0.57, z = -10.40 m/s^2
x_tilt = 17
y_tilt = 3
x = 8.12 y = -4.32, z = 3.22 m/s^2
BEEP !!!!
===================
x_tilt = 56
y_tilt = -52
x = 9.36 y = -2.23, z = 2.47 m/s^2
BEEP !!!!
===================
so mine does not start at 0. The value is already detected first and gets displayed. I think it is the raw angle value that the sensor detects, becuase whenever i lay the imu sensor flat the x value is close to 0 and when i tilt it upright it becomes 85~ so 90 ish. So it is not setting the inital value as 0.
Also i am using an imu9250 so to read the sensor i give this command:
// read the sensor
IMU.readSensor();
x = IMU.getAccelX_mss();
y = IMU.getAccelY_mss();
z = IMU.getAccelZ_mss();
which is different to mpu6050. Is this the reason why i cannot get 0 value as an initial value? or is there another reason?
The sensor functions are different due to the different Arduino libraries being used. What you are using is correct for the imu-9250, based on information from the README file for the Bolder Flight Systems Library. (which, I think, is the one you are using)
// read the sensor
IMU.readSensor();
x = IMU.getAccelX_mss();
y = IMU.getAccelY_mss();
z = IMU.getAccelZ_mss();
But I just noticed in your original code the IMU.readSensor(); function is missing from the setup() routine. The README file says you must run this before reading the x,y,x values to ensure they are up to date.
This could explain the problem you are experiencing.
If this does not work I am at a loss as the why it is not working and in that case could you post your current code and I will try to figure why.
We’ve found a full tutorial on this one this acts as a 3D compass rose, but if you chop out the code related to the compass direction and grab the section that determines pitch (which will include direction) you should be good to go!
// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250 IMU(Wire,0x68);
int status;
float x = 0 ;
float y = 0 ;
float z = 0 ;
int x_start = 0;
int y_start = 0;
int x_now = 0;
int y_now = 0;;
void setup() {
// serial to display data
Serial.begin(115200);
while(!Serial) {}
// start communication with IMU
status = IMU.begin();
if (status < 0) {
Serial.println(“IMU initialization unsuccessful”);
Serial.println(“Check IMU wiring or try cycling power”);
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
x = atan(x/(sqrt(yy + zz)));
y = atan(y/(sqrt(xx + zz)));
x_start = (int)(x * 180/M_PI);
y_start = (int)(y * 180/M_PI);
}
void loop() {
// read the sensor
IMU.readSensor();
x = IMU.getAccelX_mss();
y = IMU.getAccelY_mss();
z = IMU.getAccelZ_mss();
// Print raw values
Serial.print(“x = “);
Serial.print(x);
Serial.print(” y = “);
Serial.print(y);
Serial.print(”, z = “);
Serial.print(z);
Serial.println(” m/s^2”);
// Convert acceleration to angular movement in radians
x = atan(x/(sqrt(yy + zz)));
y = atan(y/(sqrt(xx + zz)));
// Convert radians to degrees and ignore the decimal point
x_now = (int)(x * 180/M_PI);
y_now = (int)(y * 180/M_PI);
// Calculate tilt angle with respect to original at rest position
int x_tilt = x_now - x_start;
int y_tilt = y_now - y_start ;
// Beep
if ((x_tilt < -20) || (x_tilt > 40) || (y_tilt < -30) || (y_tilt > 30)) {
// beep function to make noise
Serial.println("===================");
Serial.println(" BEEP !!! “);
Serial.println(”===================");
When I used this formula at the very start of the project: float inclination = 180.0 acos( (ax0 ax + ay0 ay + az0 az)/sqrt( (ax ax + ay ay + az az) (ax0 ax0 + ay0 ay0 + az0*az0)))/M_PI;
there wasn’t any problem defining the initial value as 0. but it didn’t give the directions and didn’t indicate if itw as positive or nagative angles (front/back). Will there be a way to incorporate this forumla and the code that you came up with? becuase your code meauses + and - and indicates which (x,y,z,) side of the angle is and the previous formula lets the angles to float and makes the intial value to 0…? (I might be completly wrong, I just thought of it spontaneously)
Yeah, agree with Graham.
Copying from a web page often changes those characters, which the IDE does not like.
It did when I first started looking at your code.
Google stray /342 in program. It got me the first time it happened.
Its a known problem and related to Unicode characters.
Cheers
Jim
PS I copied the code you posted, clicked reply to your post, pasted it to the web page edit window, added the 4 lines I think it needed to work, then applied the </> menu option. At the time I did not check the code in the Arduino IDE.
I have just now and the errors appear in the code you originally posted. Some of the " characters are incorrect.
Hi thanks James, I tried this code, it works but the X-tilt never shows a positive numer. It only displays - value no matter which side it is inclined to. how can i fix this? Y-axis works fine, one side is positive and another side is negative. Just the x that is only showing the negative angle tilt values.
Hard to say with out more information.
If leave my device flat or at an angle (any angle); generally it will show tilt of both x and y as 0 sometimes -1 or +1. If I hold it in my hand it usually never shows 0.
You could change the code to print x_start, y_start, x_now, y_now where it shows x_tilt, y_tilt. It might give you a clue as to what is happening.
The raw values, usually, will never be zero, the device is just to sensitive and detects very small changes in position. (fractions of a degree)
Thanks, I tried changing the code to what you said above, I can see + and - values with this for ‘x_now’.
However, the starting value was at -86 (raw value?).
So I am not sure what can be wrong with x-tilt, just showing the negative values, with the previous code?
Spoiler alert - this post doesn’t contain a direct answer
You’ll need to do some DIY detective work and break down the formulas into simpler chunks. If you’re not sure about why something happened, that’s “the” moment to breakdown each variable/step with much finer detail (from a debugging perspective). At the end of the day, it’s just math and these types of issues will be perfectly repeatable until solved.
Perhaps don’t introduce complexity at any level unless you know (and trust) the layer below. Otherwise, you may enter a cycle of “why doesn’t this work”.
I often use visual tools such as Excel for projects like this, to create raw data tables and use charts/formulas that better-visualise the outcome. It makes for faster iteration and leads to better observations of how things should work in an ideal environment. From there, translating Excel formulas into another programming language is always easy-enough.
When/if you do find the issue, please report back with an update!
It works now, both y and x define positive and negative values. I think it is because the sensor wasn’t still in the beginning. After pinning into the breadboard it worked! thanks for the help so far James! I really appreciate it ! and Bryce & Graham as well thank you!!