I am going round in circles! I want to find the Max and Min values of repeated forced oscillations. I am using an MPU6050 with an Uno. The code does not work all the time and sometimes the Min value gets missed.
Also, It does not always record the maximum but the next reading (maybe the condition for separation of values : cmx-pmx && cmx - lmx is not met until further values tested). And I get some missed Min values or delayed recording in the serial monitor.
Why do I get missed Min values and why are some readings delayed in the serial printing?
Can I use 2 arrays: How to fill an array with x angle values then stop the array when back to neutral - 195 degrees - and find max value in first array and min value in second array?
The forced oscillation is slow : about 1 oscillation per second but does vary and may stop.
Do I even need an array? (just correct my faulty code!)
Thanks in advance. C
#include<Wire.h>
const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int minVal=265;
int maxVal=402;
int cmx = 1960; //initialise current max angle variable
int cmn = 1950; //initialise current min angle variable
int pmx = 1960; //initialise previous max angle variable
int pmn = 1950; //initialise previous min angle variable
int lmx = 1960; //initialise a variable to store the old previous max value
int lmn = 1950; //initialise a variable to store the old previous min value
int count_max; //initialise count for max angles
int count_min; //initialise count for min angles
double x;
double y;
double z;
void setup() {
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(115200);
}
void loop(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); //calculation of x angle (double)
if (x > 196){ //checking for angle over neutral angle (180 degrees)
cmx = x*10; //converting x angle (double) into current angle integer with one decimal place of accuracy
if (pmx - cmx > 20 && lmx - cmx > 40){ //checking current angle against previous angle and last previous angle
Serial.print ("Osc_max "); //printing maximum oscillation
Serial.println (lmx);
lmx = 1960; //reset these previous angles so as to try to avoid printing a second (but lesser) max value
pmx = 1960;
count_max++; //printing count for number of max values
Serial.print ("Count.Max ");
Serial.println (count_max);
}
//equivalent of small array to provide conditions to find max oscillation
lmx = pmx; //storing the old previous max value as last max value
pmx = cmx; //storing the old current max value as previous max value
}
else if (x<195){ //checking for angle under 180 degrees
cmn = x*10; //converting x angle (double) into current angle
if (cmn - pmn > 20 && cmn - lmn > 40 ){ //checking current angle against previous angle and last previous angle
Serial.print ("Osc_min "); //printing minimum oscillation
Serial.println (lmn);
lmn = 1950; //reseting these previous min angles so as to try to avoid printing other values
pmn = 1950;
count_min++; //printing count for number of min values
Serial.print ("Count.Min ");
Serial.println (count_min);
}
//equivalent of small array to provide conditions to find max oscillation
lmn = pmn; //storing the old previous min value as last prepvious value
pmn = cmn; //storing the old current min value as previous min value
}
Serial.print("AngleX= "); //printing actual angle to check validity of max and min printed values
Serial.println(x);
Serial.println("-----------------------------------------");
delay(250); //setting sampling rate for x angle
}
If you are measuring tilt angles, replace all of this (which is wrong)
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); //calculation of x angle (double)
Thanks I will replace and see what happens and I will look at your link for tilt sensing
I've jumped into coding and probably out of my depth .... willing to learn thou'
The delay was just to slow the sampling down so I could see what was going on
The Oscillation is forced and slow
And, I took the code from an example / tutorial so I will comment out this - actually remove it as see the outcome
Thanks
Thanks. Have just swapped out the code as you suggested and adjusted the remaining code.
It has changed the axis that responds to the calculated tilt; but will print out angles. Have scanned the content for the link you provided: Needs re-reading but interesting to see a Bosch sensor BMA220 to work with. Page not found for the 'tilt sensing using 3 axis accelerometer' so I guess I will contact Bosch for relevant software unless the arduino coding will work.
I am still worried about finding the max and min angles - if I remove the 'delay' the sampling will be increased and the 'if' statement will not work, I think. Would an 'array' work? or is there another handy way to find a max and min angle of a continuing oscillation?
Thanks for the last post .... I have been unwell and not able to do anything .... now I'm better I have re-done the code and I get max and min angles as suggested and I've used a condition to stop printing extra angles; but why do I often get a delayed printed max or min angle. I have included code to print the sampled angles so I can check all the angles. These keep printing fine but the defined max or min angles get printed out of sequence with these.....
Does anyone know why ?
here's the code :
#include<Wire.h>
const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int minVal=265;
int maxVal=402;
int cmx = 5; //initialise current max angle variable
int cmn = 3; //initialise current min angle variable
int pmx = 5; //initialise previous max angle variable
int pmn = 3; //initialise previous min angle variable
//int lmx = 5; //initialise a variable to store the old previous max value
//int lmn = 3; //initialise a variable to store the old previous min value
int count_max; //initialise count for max angles
int count_min; //initialise count for min angles
double x;
double y;
double z;
bool neutral; //condit. to check neurtal position
void setup() {
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(115200);
}
void loop(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
float AcX=Wire.read()<<8|Wire.read();
float AcY=Wire.read()<<8|Wire.read();
float AcZ=Wire.read()<<8|Wire.read();
float x_T = AcX;
float y_T = AcY;
float z_T = AcZ;
y = atan2(y_T , z_T) * 57.3;
x = atan2((- x_T) , sqrt(y_T * y_T + z_T * z_T)) * 57.3;
if (x > 3 && x < 6){ //checking neutral position
neutral = true;
}
if (x > 7){ //checking for angle greater than neutral position
cmx = x*10; //converting x angle (double) into current angle to one decimal place accuracy
if (cmx < pmx && neutral == true){ //checking current angle against previous angle
Serial.print ("Tilt_max "); //printing maximum tilt
Serial.println (pmx);
// lmx = 5; //reset these previous angles so as to try to avoid printing a second (but lesser) max value
pmx = 5;
cmx = 5;
count_max++; //printing count for number of max values
Serial.print ("Count.Max ");
Serial.println (count_max);
neutral = false; //stop printing any further angles
}
// lmx = pmx;
pmx = cmx; //storing the old current max value as previous value
}
else if (x < 2){ //checking for angle less than neutral position
cmn = x*10; //converting x angle (double) into current angle to one decimal place
if (cmn > pmn && neutral == true){ //checking current angle against previous angle
Serial.print ("Tilt_min "); //printing minimum tilt
Serial.println (pmn);
// lmn = 3; //reseting these previous min angles so as to try to avoid printing other values
pmn = 3;
cmn = 3;
count_min++; //printing count for number of min values
Serial.print ("Count.Min ");
Serial.println (count_min);
neutral = false; //stop printing further angles
}
// lmn = pmn; //storing the old previous min value as last prepvious value
pmn = cmn; //storing the old current min value as previous value
}
Serial.print("AngleX= "); //printing actual angle to check validity of max and min printed values
Serial.println(x);
//Serial.println("-----------------------------------------");
delay(50);
}