/ LSM303 / servo_compass / servo_compass.ino
servo_compass.ino
 1  // SPDX-FileCopyrightText: 2019 Bill Earl for Adafruit Industries
 2  //
 3  // SPDX-License-Identifier: MIT
 4  
 5  // **********************************************
 6  // Zax-O-Meter Sketch 
 7  // for the Adafruit LSM303 Magnetometer Breakout
 8  //
 9  // Written by Bill Earl for Adafruit Industries
10  //
11  // **********************************************
12  
13  #include <Wire.h>
14  #include <Adafruit_Sensor.h>
15  #include <Adafruit_LIS2MDL.h>
16  
17  //Uncomment this line and comment out the above for the LSM303DLH
18  //#include <Adafruit_LSM303DLH_Mag.h>
19  #include <Servo.h>
20  
21  /* Assign a unique ID to this sensor at the same time */
22  Adafruit_LIS2MDL mag = Adafruit_LIS2MDL(12345);
23  //Uncomment this line and comment out the above for the LSM303DLH
24  //Adafruit_LSM303DLH_Mag_Unified mag = Adafruit_LSM303AGR_Mag_Unified(12345);
25  
26  // This is our continuous rotation servo
27  Servo servo;
28  
29  // Pi for calculations - not the raspberry type
30  const float Pi = 3.14159;
31  
32  // This is the value that gives you minimal rotation on
33  // a continuous rotation servo.  It is usually about 90.
34  // adjust this value to give minimal rotation for your servo
35  const float ServoNeutral = 90;  
36  
37  // This is the desired direction of travel
38  // expressed as a 0-360 degree compass heading
39  // 0.0 = North
40  // 90.0 = East
41  // 180.0 = South
42  // 270 = West
43  const float targetHeading = 0.0;
44  
45  
46  void setup(void) 
47  {
48    Serial.begin(115200);
49    Serial.println("Magnetometer Test"); Serial.println("");
50    
51    /* Initialise the sensor */
52    if(!mag.begin())
53    {
54      /* There was a problem detecting the LSM303 ... check your connections */
55      Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
56      while(1);
57    }
58    
59    servo.attach(9);  // Attach servo to pin 9
60  
61  }
62  
63  void loop(void) 
64  {
65    /* Get a new sensor event */ 
66    sensors_event_t event; 
67    mag.getEvent(&event);
68       
69    // Calculate the angle of the vector y,x
70    float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;
71    // Normalize to 0-360
72    if (heading < 0)
73    {
74      heading = 360 + heading;
75    }
76    
77    // Calculate the error between tha measured heading and the target heading.
78    float error = heading - targetHeading;
79    if (error > 180)
80    {
81      error = error - 360;  // for angles > 180, correct in the opposite direction.
82    }
83    // A non-zero difference between the heading and the 
84    // targetHeading will bias the servoNeutral value and 
85    // cause the servo to rotate back toward the targetHeading.
86    // The divisor is to reduce the reaction speed and avoid oscillations
87    servo.write(ServoNeutral + error / 4 );
88  
89    delay(40);
90  }