Skip to content

Commit f37f9fb

Browse files
committed
Initial checkin
1 parent 26b42cd commit f37f9fb

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

CPX_Compass/CPX_Compass.ino

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#include <Wire.h>
2+
#include <Adafruit_NeoPixel.h>
3+
#include <Adafruit_Sensor.h>
4+
#include <Adafruit_LSM303_U.h>
5+
#include <math.h>
6+
7+
/* Assign a unique ID to this sensor at the same time */
8+
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
9+
10+
float raw_mins[3] = {1000.0, 1000.0, 1000.0};
11+
float raw_maxes[3] = {-1000.0, -1000.0, -1000.0};
12+
13+
float mins[3];
14+
float maxes[3];
15+
float corrections[3] = {0.0, 0.0, 0.0};
16+
17+
18+
// Support both classic and express
19+
#ifdef __AVR__
20+
#define NEOPIXEL_PIN 17
21+
#else
22+
#define NEOPIXEL_PIN 8
23+
#endif
24+
25+
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
26+
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
27+
// example for more information on possible values.
28+
Adafruit_NeoPixel strip = Adafruit_NeoPixel(10, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
29+
30+
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+
32+
#define BUTTON_A 4
33+
34+
void fill(int red, int green, int blue) {
35+
for (int i = 0; i < 10; i++) {
36+
strip.setPixelColor(i, red, green, blue);
37+
}
38+
strip.show();
39+
}
40+
41+
42+
void warm_up(void)
43+
{
44+
sensors_event_t event;
45+
fill(0, 0, 128);
46+
for (int ignore = 0; ignore < 100; ignore++) {
47+
mag.getEvent(&event);
48+
delay(10);
49+
}
50+
}
51+
52+
53+
void calibrate(void)
54+
{
55+
sensors_event_t event;
56+
float values[3];
57+
58+
fill(0, 128, 0);
59+
60+
unsigned long start_time = millis();
61+
while (millis() - start_time < 5000) {
62+
63+
mag.getEvent(&event);
64+
values[0] = event.magnetic.x;
65+
values[1] = event.magnetic.y * -1;
66+
if (values[0] != 0.0 && values[1] != 0.0) { /* ignore the random zero readings... it's bogus */
67+
for (int i = 0; i < 2; i++) {
68+
raw_mins[i] = values[i] < raw_mins[i] ? values[i] : raw_mins[i];
69+
raw_maxes[i] = values[i] > raw_maxes[i] ? values[i] : raw_maxes[i];
70+
}
71+
}
72+
delay(5);
73+
}
74+
for (int i = 0; i < 2; i++) {
75+
corrections[i] = (raw_maxes[i] + raw_mins[i]) / 2;
76+
mins[i] = raw_mins[i] - corrections[i];
77+
maxes[i] = raw_maxes[i] - corrections[i];
78+
}
79+
fill(0, 0, 0);
80+
}
81+
82+
83+
void setup(void)
84+
{
85+
strip.begin();
86+
strip.show();
87+
88+
pinMode(BUTTON_A, INPUT_PULLDOWN);
89+
90+
/* Enable auto-gain */
91+
mag.enableAutoRange(true);
92+
93+
/* Initialise the sensor */
94+
if(!mag.begin())
95+
{
96+
/* There was a problem detecting the LSM303 ... check your connections */
97+
fill(255, 0, 0);
98+
while(1);
99+
}
100+
101+
warm_up();
102+
calibrate();
103+
}
104+
105+
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;
110+
return min_clipped;
111+
}
112+
113+
114+
void loop(void)
115+
{
116+
// Pressing button A does another round of calibration.
117+
if (digitalRead(BUTTON_A)) {
118+
calibrate();
119+
}
120+
121+
sensors_event_t event;
122+
mag.getEvent(&event);
123+
124+
float x = event.magnetic.x;
125+
float y = event.magnetic.y * -1;
126+
float z = event.magnetic.z * -1;
127+
128+
if (x == 0.0 && y == 0.0) {
129+
return;
130+
}
131+
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);
134+
135+
int compass_heading = (int)(atan2(normalized_y, normalized_x) * 180.0 / 3.14159);
136+
// compass_heading is between -180 and +180 since atan2 returns -pi to +pi
137+
// this translates it to be between 0 and 360
138+
compass_heading += 180;
139+
140+
int direction_index = ((compass_heading + 15) % 360) / 30;
141+
142+
// light the pixel(s) for the direction the compass is pointing
143+
// the empty spots where the USB and power connects are use the two leds to either side.
144+
int *leds;
145+
leds = led_patterns[direction_index];
146+
for (int pixel = 0; pixel < 10; pixel++) {
147+
if (pixel == leds[0] || pixel == leds[1]) {
148+
strip.setPixelColor(pixel, 255, 255, 255);
149+
} else {
150+
strip.setPixelColor(pixel, 0, 0, 0);
151+
}
152+
}
153+
strip.show();
154+
delay(50);
155+
}

0 commit comments

Comments
 (0)