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+
113#include < Wire.h>
214#include < Adafruit_NeoPixel.h>
315#include < Adafruit_Sensor.h>
719/* Assign a unique ID to this sensor at the same time */
820Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345 );
921
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 };
1224
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 };
1628
1729
1830// Support both classic and express
@@ -27,6 +39,7 @@ float corrections[3] = {0.0, 0.0, 0.0};
2739// example for more information on possible values.
2840Adafruit_NeoPixel strip = Adafruit_NeoPixel(10 , NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
2941
42+ // Map direction pie slices (of 30 deg each) to a neopixel, or two for the missing ones at USB & power.
3043int 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 }};
3144
3245#define BUTTON_A 4
@@ -39,6 +52,9 @@ void fill(int red, int green, int blue) {
3952}
4053
4154
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.
4258void warm_up (void )
4359{
4460 sensors_event_t event;
@@ -50,10 +66,14 @@ void warm_up(void)
5066}
5167
5268
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.
5373void calibrate (void )
5474{
5575 sensors_event_t event;
56- float values[3 ];
76+ float values[2 ];
5777
5878 fill (0 , 128 , 0 );
5979
@@ -103,10 +123,12 @@ void setup(void)
103123}
104124
105125
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 ;
110132 return min_clipped;
111133}
112134
@@ -123,20 +145,22 @@ void loop(void)
123145
124146 float x = event.magnetic .x ;
125147 float y = event.magnetic .y * -1 ;
126- float z = event.magnetic .z * -1 ;
127148
128149 if (x == 0.0 && y == 0.0 ) {
129150 return ;
130151 }
131152
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 ]);
134155
135156 int compass_heading = (int )(atan2 (normalized_y, normalized_x) * 180.0 / 3.14159 );
136157 // compass_heading is between -180 and +180 since atan2 returns -pi to +pi
137158 // this translates it to be between 0 and 360
138159 compass_heading += 180 ;
139160
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
140164 int direction_index = ((compass_heading + 15 ) % 360 ) / 30 ;
141165
142166 // light the pixel(s) for the direction the compass is pointing
0 commit comments