Skip to content

Commit 3b83af8

Browse files
Added calibration + needle point
doesn't work incredibly well however, but it will point towards an ordinary magnet if close enough
1 parent 32fd05b commit 3b83af8

File tree

1 file changed

+73
-31
lines changed

1 file changed

+73
-31
lines changed

src/compass.c

+73-31
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
#include <stdio.h>
22

33
#include "pico/stdlib.h"
4-
#include "lib/fonts.h"
54
#include "lib/st7735.h"
65
#include "lib/ICM20948.h"
76

7+
struct Vec {
8+
float x;
9+
float y;
10+
float z;
11+
};
12+
813
// Thanks plaaosert for the ST7735 and IMU guide :D
914

1015
void SetupIMU() {
@@ -36,41 +41,78 @@ int main() {
3641

3742
SetupIMU();
3843

39-
float x;
40-
float y;
41-
float z;
42-
43-
while (true) {
44-
icm20948MagRead(&x, &y, &z);
44+
struct Vec mag;
45+
// For calibration:
46+
struct Vec magmin;
47+
struct Vec magmax;
4548

46-
char arrayX[10];
47-
if (x > 0) {
48-
sprintf(arrayX, "%.2f", x);
49-
} else {
50-
sprintf(arrayX, "%.1f", x);
51-
}
49+
int centre_x = ST7735_WIDTH / 2;
50+
int centre_y = ST7735_HEIGHT / 2;
51+
int point_x;
52+
int point_y;
53+
bool negative;
54+
float magnitude;
55+
int current;
56+
float heading;
57+
char arrayH[10];
5258

53-
char arrayY[10];
54-
if (y > 0) {
55-
sprintf(arrayY, "%.2f", y);
56-
} else {
57-
sprintf(arrayY, "%.1f", y);
58-
}
59+
icm20948MagRead(&magmin.x, &magmin.y, &magmin.z);
60+
icm20948MagRead(&magmax.x, &magmax.y, &magmin.z);
5961

60-
char arrayZ[10];
61-
if (z > 0) {
62-
sprintf(arrayZ, "%.2f", z);
62+
while (true) {
63+
// Read magnetometer values
64+
icm20948MagRead(&mag.x, &mag.y, &mag.z);
65+
66+
// Calibrate values
67+
if (mag.x < magmin.x) magmin.x = mag.x;
68+
if (mag.x > magmax.x) magmax.x = mag.x;
69+
if (mag.y < magmin.y) magmin.y = mag.y;
70+
if (mag.y > magmax.y) magmax.y = mag.y;
71+
if (mag.z < magmin.z) magmin.z = mag.z;
72+
if (mag.z > magmax.z) magmax.z = mag.z;
73+
74+
// Calibrate by removing offset of smallest seen value
75+
mag.x -= magmin.x;
76+
mag.y -= magmin.y;
77+
mag.z -= magmin.z;
78+
79+
// Scale value based of highest values seen
80+
// Creates values between 0 and 1
81+
82+
// Avoid Zero Division
83+
if (magmax.x - magmin.x > 0.001) mag.x /= magmax.x - magmin.x;
84+
if (magmax.y - magmin.y > 0.001) mag.y /= magmax.y - magmin.y;
85+
if (magmax.z - magmin.z > 0.001) mag.z /= magmax.z - magmin.z;
86+
87+
// Shift values to -0.5 <= x <= 0.5
88+
mag.x -= 0.5;
89+
mag.y -= 0.5;
90+
mag.z -= 0.5;
91+
92+
// Convert Gauss values to Radian heading
93+
heading = atan2(mag.x, mag.y);
94+
// Convert to positive heading (add a full radian turn)
95+
if (heading < 0) heading += 2 * 3.14159;
96+
97+
// Worked out using counterclockwise rotation matrix
98+
point_x = centre_x + (20 * sin(heading));
99+
point_y = centre_y + ((-20) * cos(heading));
100+
101+
// Draw compass needle
102+
ST7735_FillScreen(ST7735_BLACK);
103+
104+
ST7735_DrawPixel(centre_x, centre_y, ST7735_RED);
105+
ST7735_DrawPixel(point_x, point_y, ST7735_RED);
106+
107+
// Convert heading to degrees
108+
heading *= 180 / 3.14159;
109+
110+
if (heading > 0) {
111+
sprintf(arrayH, "%.2f", heading);
63112
} else {
64-
sprintf(arrayZ, "%.1f", z);
113+
sprintf(arrayH, "%.1f", heading);
65114
}
66-
67-
ST7735_WriteString(5, 5, arrayX, Font_16x26, ST7735_RED, ST7735_BLACK);
68-
ST7735_WriteString(5, 31, arrayY, Font_16x26, ST7735_GREEN, ST7735_BLACK);
69-
ST7735_WriteString(5, 57, arrayZ, Font_16x26, ST7735_BLUE, ST7735_BLACK);
70-
71-
ST7735_WriteString(7, 120, "x", Font_16x26, ST7735_RED, ST7735_BLACK);
72-
ST7735_WriteString(27, 120, "y", Font_16x26, ST7735_GREEN, ST7735_BLACK);
73-
ST7735_WriteString(47, 120, "z", Font_16x26, ST7735_BLUE, ST7735_BLACK);
115+
ST7735_WriteString(80, 80, arrayH, Font_16x26, ST7735_RED, ST7735_BLACK);
74116

75117
sleep_ms(100);
76118
}

0 commit comments

Comments
 (0)