1
+ /* Circuit Playground Express compass. */
2
+
3
+ /* Adafruit invests time and resources providing this open source code. */
4
+ /* Please support Adafruit and open source hardware by purchasing */
5
+ /* products from Adafruit! */
6
+
7
+ /* Written by Dave Astels for Adafruit Industries */
8
+ /* Copyright (c) 2018 Adafruit Industries */
9
+ /* Licensed under the MIT license. */
10
+
11
+ /* All text above must be included in any redistribution. */
12
+
1
13
#include < Wire.h>
2
14
#include < Adafruit_NeoPixel.h>
3
15
#include < Adafruit_Sensor.h>
7
19
/* Assign a unique ID to this sensor at the same time */
8
20
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345 );
9
21
10
- float raw_mins[3 ] = {1000.0 , 1000.0 , 1000.0 };
11
- float raw_maxes[3 ] = {- 1000.0 , -1000.0 , -1000.0 };
22
+ float raw_mins[2 ] = {1000.0 , 1000.0 };
23
+ float raw_maxes[2 ] = {-1000.0 , -1000.0 };
12
24
13
- float mins[3 ];
14
- float maxes[3 ];
15
- float corrections[3 ] = {0.0 , 0.0 , 0.0 };
25
+ float mins[2 ];
26
+ float maxes[2 ];
27
+ float corrections[2 ] = {0.0 , 0.0 };
16
28
17
29
18
30
// Support both classic and express
@@ -27,6 +39,7 @@ float corrections[3] = {0.0, 0.0, 0.0};
27
39
// example for more information on possible values.
28
40
Adafruit_NeoPixel strip = Adafruit_NeoPixel(10 , NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
29
41
42
+ // Map direction pie slices (of 30 deg each) to a neopixel, or two for the missing ones at USB & power.
30
43
int led_patterns[12 ][2 ] = {{4 , 5 }, {5 , -1 }, {6 , -1 }, {7 , -1 }, {8 , -1 }, {9 , -1 }, {9 , 0 }, {0 -1 }, {1 , -1 }, {2 , -1 }, {3 , -1 }, {4 , -1 }};
31
44
32
45
#define BUTTON_A 4
@@ -39,6 +52,9 @@ void fill(int red, int green, int blue) {
39
52
}
40
53
41
54
55
+ // Do some initial reading to let the magnetometer settle in.
56
+ // This was found by experience to be required.
57
+ // Indicated to the user by blue LEDs.
42
58
void warm_up (void )
43
59
{
44
60
sensors_event_t event;
@@ -50,10 +66,14 @@ void warm_up(void)
50
66
}
51
67
52
68
69
+ // Find the range of X and Y values.
70
+ // User needs to rotate the CPX a bunch during this.
71
+ // Can be refined by doing more of the saem by pressing the A button.
72
+ // Indicated to the user by green LEDs.
53
73
void calibrate (void )
54
74
{
55
75
sensors_event_t event;
56
- float values[3 ];
76
+ float values[2 ];
57
77
58
78
fill (0 , 128 , 0 );
59
79
@@ -103,10 +123,12 @@ void setup(void)
103
123
}
104
124
105
125
106
- float normalize (float value, float in_min, float in_max, float out_min, float out_max) {
107
- float mapped = (value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
108
- float max_clipped = mapped < out_max ? mapped : out_max;
109
- float min_clipped = max_clipped > out_min ? max_clipped : out_min;
126
+ // Map a value from the input range to the output range
127
+ // Used to map MAG values from the calibrated (min/max) range to (-100, 100)
128
+ float normalize (float value, float in_min, float in_max) {
129
+ float mapped = (value - in_min) * 200 / (in_max - in_min) + -100 ;
130
+ float max_clipped = mapped < 100 ? mapped : 100 ;
131
+ float min_clipped = max_clipped > -100 ? max_clipped : -100 ;
110
132
return min_clipped;
111
133
}
112
134
@@ -123,20 +145,22 @@ void loop(void)
123
145
124
146
float x = event.magnetic .x ;
125
147
float y = event.magnetic .y * -1 ;
126
- float z = event.magnetic .z * -1 ;
127
148
128
149
if (x == 0.0 && y == 0.0 ) {
129
150
return ;
130
151
}
131
152
132
- float normalized_x = normalize (x - corrections[0 ], mins[0 ], maxes[0 ], - 100.0 , 100.0 );
133
- float normalized_y = normalize (y - corrections[1 ], mins[1 ], maxes[1 ], - 100.0 , 100.0 );
153
+ float normalized_x = normalize (x - corrections[0 ], mins[0 ], maxes[0 ]);
154
+ float normalized_y = normalize (y - corrections[1 ], mins[1 ], maxes[1 ]);
134
155
135
156
int compass_heading = (int )(atan2 (normalized_y, normalized_x) * 180.0 / 3.14159 );
136
157
// compass_heading is between -180 and +180 since atan2 returns -pi to +pi
137
158
// this translates it to be between 0 and 360
138
159
compass_heading += 180 ;
139
160
161
+ // We add 15 to account to the zero position being 0 +/- 15 degrees.
162
+ // mod by 360 to keep it within a circle
163
+ // divide by 30 to find which pixel corresponding pie slice it's in
140
164
int direction_index = ((compass_heading + 15 ) % 360 ) / 30 ;
141
165
142
166
// light the pixel(s) for the direction the compass is pointing
0 commit comments