Thank you.
As for this I tried to use a modified code of the one you gave where I used the TinyGPSPlus.h instead of the TinyGPS++.h where the TinyGPSPlus.h is the one that is for ESP32. I ran the code for a bit and disconnected the ESP32 to stop the readings so I can copy what output got printed on the serial monitor. Here is what got printed to the serial monitor after using a modified version of your code:
14:51:08.524 -> .........>...............Calibrate MPU6050 done
14:51:15.875 -> "01:" Serial2.available()=0
14:51:15.875 -> positionXYZ = -0.84, 0.04, 0.00
14:51:15.875 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.875 -> positionXYZ = -0.56, 0.03, 0.00
14:51:15.875 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.875 -> positionXYZ = -0.97, 0.05, 0.00
14:51:15.875 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.875 -> positionXYZ = -1.11, 0.05, 0.00
14:51:15.875 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.875 -> positionXYZ = -1.33, 0.06, 0.00
14:51:15.875 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -1.54, 0.08, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -1.76, 0.09, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -1.97, 0.10, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -2.18, 0.11, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -2.40, 0.12, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -2.61, 0.14, 0.00
14:51:15.911 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.911 -> positionXYZ = -2.83, 0.14, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -3.04, 0.15, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -3.25, 0.17, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -3.47, 0.18, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -3.68, 0.18, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -3.90, 0.18, 0.00
14:51:15.945 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.945 -> positionXYZ = -4.12, 0.20, 0.00
14:51:15.976 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.976 -> positionXYZ = -4.33, 0.21, 0.00
14:51:15.976 -> trueXYZ = 0.00, 0.00, 0.00
14:51:15.976 -> positionXYZ = -4.55, 0.23, 0.00
14:51:15.976 -> trueXYZ = 0.00, 0.00, 0.00
I don't if this is too long or short to use for an example but here you can see the positionXYZ reading keeps on increasing non-stop meaning it is not tracking the position of the robot.
This is modified code mentioned I don't know if it affects anything or not but to me it is still the same where the trueXYZ value is still 0:
`// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
#include <Wire.h>
#include <MPU6050.h>
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
//#include <MPU6050_6Axis_MotionApps20.h>
//#include <MPU6050_tockn.h>
// MPU6050 object
MPU6050 mpu;
// GPS object
TinyGPSPlus gps;
static const int RXPin = 4, TXPin = 3;
static const uint32_t GPSBaud = 4800;
// Kalman filter variables
float dt = 0.02; // Time step (adjust as needed)
float accAngleX, accAngleY;
float gyroAngleX, gyroAngleY, gyroAngleZ;
float gyroX, gyroY, gyroZ;
float angleX, angleY, angleZ;
float gyroXangle, gyroYangle, gyroZangle;
float kalAngleX, kalAngleY;
// Variables for position tracking
float positionXYZ[3] = {0.0, 0.0, 0.0}; // Initial position
float trueXYZ[3] = {0.0, 0.0, 0.0}; // Initial true position
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
// Initialize MPU6050
Wire.begin();
Serial.println("Wire.begin() done");
mpu.initialize();
Serial.println("mpu.initialize() done");
// Calibrate MPU6050
mpu.CalibrateGyro();
mpu.CalibrateAccel();
Serial.println("Calibrate MPU6050 done");
}
void loop() {
// Read accelerometer and gyroscope data from MPU6050
//mpu.update();
// Get accelerometer angles
accAngleX = atan2(mpu.getAccelerationY(), mpu.getAccelerationZ()) * RAD_TO_DEG;
accAngleY = atan2(-mpu.getAccelerationX(), mpu.getAccelerationZ()) * RAD_TO_DEG;
// Get gyroscope angles
gyroX = mpu.getXGyroOffset() / 131.0;
gyroY = mpu.getYGyroOffset() / 131.0;
gyroZ = mpu.getZGyroOffset() / 131.0;
// Calculate gyro angle using integration
gyroXangle += gyroX * dt;
gyroYangle += gyroY * dt;
gyroZangle += gyroZ * dt;
// Complementary filter for angle calculation
angleX = 0.98 * (gyroXangle + gyroX * dt) + 0.02 * accAngleX;
angleY = 0.98 * (gyroYangle + gyroY * dt) + 0.02 * accAngleY;
angleZ = gyroZangle;
// Kalman filter
kalAngleX = kalmanFilterX(angleX, gyroX);
kalAngleY = kalmanFilterY(angleY, gyroY);
// once every 1005 milliseconds print
dbgi("01:",Serial2.available(),1005);
// Read GPS data and update true position
while (Serial2.available() > 0) {
if (gps.encode(Serial2.read())) {
trueXYZ[0] = gps.location.lat();
trueXYZ[1] = gps.location.lng();
trueXYZ[2] = gps.altitude.meters();
}
}
// Update position using sensor fusion (combining accelerometer, gyro, and GPS)
positionXYZ[0] = kalAngleX;
positionXYZ[1] = kalAngleY;
positionXYZ[2] = trueXYZ[2]; // Z-axis position from GPS
// Print positionXYZ and trueXYZ
Serial.print("positionXYZ = ");
Serial.print(positionXYZ[0]);
Serial.print(", ");
Serial.print(positionXYZ[1]);
Serial.print(", ");
Serial.println(positionXYZ[2]);
Serial.print("trueXYZ = ");
Serial.print(trueXYZ[0]);
Serial.print(", ");
Serial.print(trueXYZ[1]);
Serial.print(", ");
Serial.println(trueXYZ[2]);
}
// Kalman filter for X-axis angle
float kalmanFilterX(float angle, float gyroRate) {
static float P[2][2] = {{1, 0}, {0, 1}};
static float Pdot[4] = {0, 0, 0, 0};
static float Q_angle = 0.001, Q_gyro = 0.003, R_angle = 0.03;
float y, S;
static float K[2] = {0, 0};
float dt_c = 0.01;
Pdot[0] = Q_angle - P[0][1] - P[1][0];
Pdot[1] = -P[1][1];
Pdot[2] = -P[1][1];
Pdot[3] = Q_gyro;
P[0][0] += Pdot[0] * dt_c;
P[0][1] += Pdot[1] * dt_c;
P[1][0] += Pdot[2] * dt_c;
P[1][1] += Pdot[3] * dt_c;
y = angle - kalAngleX;
S = P[0][0] + R_angle;
K[0] = P[0][0] / S;
K[1] = P[1][0] / S;
angle += K[0] * y;
kalAngleX += K[1] * y;
P[0][0] -= K[0] * P[0][0];
P[0][1] -= K[0] * P[0][1];
P[1][0] -= K[1] * P[0][0];
P[1][1] -= K[1] * P[0][1];
return angle;
}
// Kalman filter for Y-axis angle
float kalmanFilterY(float angle, float gyroRate) {
// Similar to kalmanFilterX, implement the filter for Y-axis angle here
static float P[2][2] = {{1, 0}, {0, 1}};
static float Pdot[4] = {0, 0, 0, 0};
static float Q_angle = 0.001, Q_gyro = 0.003, R_angle = 0.03;
float y, S;
static float K[2] = {0, 0};
float dt_c = 0.01;
Pdot[0] = Q_angle - P[0][1] - P[1][0];
Pdot[1] = -P[1][1];
Pdot[2] = -P[1][1];
Pdot[3] = Q_gyro;
P[0][0] += Pdot[0] * dt_c;
P[0][1] += Pdot[1] * dt_c;
P[1][0] += Pdot[2] * dt_c;
P[1][1] += Pdot[3] * dt_c;
y = angle - kalAngleY;
S = P[0][0] + R_angle;
K[0] = P[0][0] / S;
K[1] = P[1][0] / S;
angle += K[0] * y;
kalAngleY += K[1] * y;
P[0][0] -= K[0] * P[0][0];
P[0][1] -= K[0] * P[0][1];
P[1][0] -= K[1] * P[0][0];
P[1][1] -= K[1] * P[0][1];
return angle;
}`
I see thank you so much for giving me advice on how to learn faster.
In truth, this is correct I push things that cannot be done within 2-3 hours back and do other things that can be settled quickly like other assignments but I am a slow learner too. I have two projects this semester which is a design project and this one. I really love designing and I always avoid coding whenever coding comes up in my previous semester, somehow during all my years studying there was no indivual coding assignments so I was able to avoid it and now all that avoiding has come to bite me back. Back to the projects, I tend to do designing one first because in my mind one component can be done in 2-3 hours so I end up finishing one thing and forgetting the other when it's supposed to be done in sync and progress equally among the project. I will try my best to finish this project in time I hope I can make it.
Thank you I will try to seperate everything out first so I can filter out everything that is working correctly and everything that is not working.
Sincerely, Nish