Skip to content

Commit bbd8b5f

Browse files
author
Eric Stockenstrom
committed
v0.32 QMC 2018-09-03 QMC5883L version for testing
1 parent 41d4dd2 commit bbd8b5f

File tree

8 files changed

+1084
-0
lines changed

8 files changed

+1084
-0
lines changed

AntTrackMavlinkv0.32_QMC/AntTrackMavlinkv0.32_QMC.ino

+656
Large diffs are not rendered by default.
Binary file not shown.

AntTrackMavlinkv0.32_QMC/AzEl.ino

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
void GetAzEl(const struct Location &hom, const struct Location &cur){
2+
/*
3+
*
4+
* Aviation Formulary V1.33, by Ed Williams
5+
* http://williams.best.vwh.net/avform.htm
6+
*
7+
* The algorithm it gives for hc_vector.az bearing between two points is
8+
* this:
9+
*
10+
* tc1=mod(atan2(sin(lon2-lon1)*cos(lat2),
11+
* cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1)),
12+
* 2*pi)
13+
*/
14+
15+
float a, c, d, dLat, dLon;
16+
17+
#if defined Debug_All || defined Debug_AzEl
18+
Debug.print("hom.lat = "); Debug.print(hom.lat,7);
19+
Debug.print(" hom.lon = "); Debug.print(hom.lon,7);
20+
Debug.print(" hom.alt = "); Debug.print(hom.alt,0);
21+
Debug.print(" cur.lat = "); Debug.print(cur.lat,7);
22+
Debug.print(" cur.lon = "); Debug.print(cur.lon,7);
23+
Debug.print(" cur.alt = "); Debug.println(cur.alt,0);
24+
#endif
25+
26+
float lon1 = hom.lon / 180 * PI; // Degrees to radians
27+
float lat1 = hom.lat / 180 * PI;
28+
float lon2 = cur.lon / 180 * PI;
29+
float lat2 = cur.lat / 180 * PI;
30+
31+
//Calculate azimuth
32+
a=atan2(sin(lon2-lon1)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1));
33+
hc_vector.az=a*180/PI;
34+
if (hc_vector.az<0) hc_vector.az=360+hc_vector.az;
35+
36+
// Calculate the distance from home to craft
37+
dLat = (lat2-lat1);
38+
dLon = (lon2-lon1);
39+
a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2);
40+
c = 2* asin(sqrt(a));
41+
d = 6371000 * c; // Radius of the Earth is 6371km
42+
hc_vector.dist = d;
43+
44+
// Calculate elevation
45+
int16_t altR = cur.alt - hom.alt; // Relative alt
46+
47+
altR = altR * LimitCloseToHomeError(d, altR);
48+
49+
hc_vector.el=atan(altR/d);
50+
hc_vector.el=hc_vector.el*360/(2*PI); // Radians to degrees
51+
52+
#if defined Debug_All || defined Debug_AzEl
53+
if (hc_vector.dist >= minDist) { // Otherwise calculations are unreliable
54+
float elapsed = millis() - startup_millis;
55+
elapsed /=1000;
56+
Debug.print(" hc_vector.az= "); Debug.print(hc_vector.az);
57+
Debug.print(" hc_vector.el= "); Debug.print(hc_vector.el);
58+
Debug.print(" hc_vector.dist= "); Debug.print(hc_vector.dist);
59+
Debug.print(" Elapsed= "); Debug.println(elapsed, 3);
60+
}
61+
else {
62+
Debug.print(" hc_vector.dist = "); Debug.print(hc_vector.dist);
63+
Debug.print(" < minDist = "); Debug.println(minDist);
64+
}
65+
#endif
66+
67+
return;
68+
}
69+
//********************************************************
70+
// Limit close-to-home elevation error due to poor vertical GPS accuracy
71+
float LimitCloseToHomeError(float dist, int16_t alt) {
72+
73+
float h_norm = 10.0; // Normal at 10m dist
74+
float v_norm = 5.0; // Normal at 5m alt
75+
float h_ratio, v_ratio, t_ratio;
76+
77+
h_ratio = pow((dist / h_norm), 2);
78+
v_ratio = pow((float)(alt / v_norm), 2);
79+
t_ratio = h_ratio * v_ratio;
80+
if (t_ratio > 1.0)
81+
t_ratio = 1;
82+
return t_ratio;
83+
}
84+

AntTrackMavlinkv0.32_QMC/Compass.ino

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#if (Heading_Source == 3) // Tracker_Compass // else don't compile this module
2+
#include <Wire.h>
3+
#include <QMC5883L.h>
4+
5+
QMC5883L compass;
6+
7+
#ifndef Debug
8+
#define Debug Serial // USB
9+
#endif
10+
11+
// Get the mag declination of your location here http://www.magnetic-declination.com/ and insert in # defined in next line
12+
#define DECLINATION -18.9 // In degrees
13+
14+
15+
//******************************************************************************
16+
uint8_t Initialise_Compass() {
17+
18+
// There is no check for missing magnetometer in this library. Possibly scan for known address
19+
20+
Wire.begin();
21+
Serial.begin(9600);
22+
compass.init();
23+
24+
return 1;
25+
}
26+
27+
//******************************************************************************
28+
float GetMagHeading() {
29+
int x,y,z;
30+
compass.read(&x,&y,&z);
31+
32+
float fHeading = RadToDeg(atan2(y, x)); //All in degrees now
33+
34+
fHeading += DECLINATION; // Add magnetic declination
35+
36+
fHeading = Normalise_360(fHeading);
37+
38+
#if defined Debug_All || defined Debug_Compass
39+
/* Display the results (magnetic vector values are in micro-Tesla (uT)) */
40+
// Debug.print("X: "); Debug.print(x); Debug.print(" ");
41+
// Debug.print("Y: "); Debug.print(y); Debug.print(" ");
42+
// Debug.print("Z: "); Debug.print(z); Debug.println(" ");
43+
Debug.print("Heading = "); Debug.println(fHeading,0);
44+
#endif
45+
46+
return fHeading;
47+
}
48+
49+
//******************************************************************************
50+
51+
int16_t Normalise_360(int16_t arg) {
52+
if (arg < 0) arg += 360;
53+
if (arg > 359) arg -= 360;
54+
return arg;
55+
}
56+
//***************************************************
57+
float RadToDeg (float _Rad) {
58+
return _Rad * 180 / PI;
59+
}
60+
//***************************************************
61+
#endif

AntTrackMavlinkv0.32_QMC/Servos.ino

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
2+
3+
void PositionServos(float Az, float El, float hmHdg) {
4+
5+
// Note my 180 degree servos have a PWM range of 700 through 2300 microseconds
6+
// Your's may differ
7+
// Uncomment TestServos() in setup() code to observe how well your servos reach their limits
8+
9+
#ifdef Az_Servo_360 // Set the limits of the servos here
10+
int16_t llAz = 0; // Az lower limit in degrees
11+
int16_t ulAz = 360; // Az upper limit in degrees
12+
int16_t llEl = 0; // El lower limit in degrees
13+
int16_t ulEl = 90; // El upper limit in degrees
14+
int16_t MinAzPWM = 650; // Self explanatory
15+
int16_t MaxAzPWM = 2400;
16+
int16_t MinElPWM = 1125;
17+
int16_t MaxElPWM = 1875;
18+
#else
19+
int16_t llAz = 0;
20+
int16_t ulAz = 180;
21+
int16_t llEl = 0;
22+
int16_t ulEl = 180;
23+
int16_t MaxAzPWM = 2300;
24+
int16_t MinAzPWM = 700;
25+
int16_t MaxElPWM = 2300;
26+
int16_t MinElPWM = 700;
27+
#endif
28+
#if defined Debug_All || defined Debug_Servos
29+
Debug.print("Az = " );
30+
Debug.print(Az);
31+
Debug.print("\t El = ");
32+
Debug.print(El);
33+
Debug.print("\t hmHdg = " );
34+
Debug.println(hmHdg);
35+
#endif
36+
int16_t pntAz = pointAz(Az, hmHdg); // Remap Azimuth into a 180 degree window with home-heading centre, negative behind us
37+
38+
#ifndef Az_Servo_360 // Note if NOT. Do this for 180, not for 360 azimuth servo
39+
if (pntAz<0) { // Pointing direction is negative, so it needs to point behind us,
40+
pntAz = 0 - pntAz; // so flip the frame of reference over and mirror it (neg to pos)
41+
El = 180 - El; // and make the el servo reach over and behind
42+
}
43+
#endif
44+
45+
// If the craft moves out of this restricted field of reference, servos should wait at the most recent in-field position
46+
// This code is not neccessary with two 180 degree servos covering an entire hemisphere
47+
48+
if ((pntAz>=llAz) && (pntAz<=ulAz) && (El>=llEl) && (El<=ulEl)) { // Our restricted FOV
49+
LastGoodpntAz = pntAz;
50+
LastGoodEl = El;
51+
}
52+
53+
azPWM = map(LastGoodpntAz, ulAz, llAz, MinAzPWM, MaxAzPWM); // Map the az / el to the servo PWMs
54+
elPWM = map(LastGoodEl, ulEl, llEl, MinElPWM, MaxElPWM); // Servos happen to be mounted such that action is reversed
55+
56+
azServo.writeMicroseconds(azPWM);
57+
elServo.writeMicroseconds(elPWM);
58+
59+
#if defined Debug_All || defined Debug_Servos
60+
Debug.print("pntAz = " );
61+
Debug.print(pntAz);
62+
Debug.print(" El = ");
63+
Debug.print(El);
64+
Debug.print(" LastGoodpntAz = " );
65+
Debug.print(LastGoodpntAz);
66+
Debug.print(" LastGoodEl = ");
67+
Debug.print(LastGoodEl);
68+
Debug.print(" hmHdg = " );
69+
Debug.print(hmHdg);
70+
Debug.print(" azPWM = " );
71+
Debug.print(azPWM);
72+
Debug.print(" elPWM = ");
73+
Debug.println(elPWM);
74+
#endif
75+
76+
}
77+
//***************************************************
78+
int16_t pointAz(int16_t Azin, int16_t rhmHdg) {
79+
// Remap the craft's absolute Az from the home position to the 180 degree azimuth aperture facing us, and behind us
80+
// 0 degrees on the left and 180 on the right, same but mirrored and negative behind us 180 on the right 0 on the left.
81+
// Home (antenna) heading is at the centre (90 deg) of the 180 degree forward azimuth aperture
82+
// pointAz is the heading to the craft from the home position, and thus where to point the antenna,
83+
// RELATIVE to our frame of reference.
84+
85+
int16_t pntAz= Azin;
86+
87+
#if defined Debug_All || defined Debug_Servos
88+
// Debug.print("pointAz = ");
89+
// Debug.print(pntAz);
90+
// Debug.print(" rhmHdg = ");
91+
// Debug.println(rhmHdg);
92+
#endif
93+
94+
pntAz = pntAz - rhmHdg + 90; // Make heading relative to 90 degrees in front of us
95+
if (pntAz<0) pntAz = 90-pntAz; // Correct the 90 deg boundary if necessary
96+
97+
#ifndef Az_Servo_360 // Note if not. Do this for 180, not for 360 azimuth servo
98+
if ((pntAz>180) && (pntAz<=360)) pntAz=180-pntAz; // Mirror the hemisphere behind us, and make it negative
99+
#endif
100+
101+
if (pntAz>360) pntAz=pntAz-360; // All the way round to positive territory again
102+
103+
return pntAz;
104+
}
105+
//***************************************************
106+
107+

libraries/QMC5883L/QMC5883L.cpp

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
QMC5883L.cpp - QMC5883L library
3+
Copyright (c) 2017 e-Gizmo Mechatronix Central
4+
Rewritten by Amoree. All right reserved.
5+
July 10,2017
6+
7+
SET continuous measurement mode
8+
OSR = 512
9+
Full Scale Range = 8G(Gauss)
10+
ODR = 200HZ
11+
12+
*/
13+
14+
#include "QMC5883L.h"
15+
16+
#include <Wire.h>
17+
18+
void QMC5883L::setAddress(uint8_t addr){
19+
address = addr;
20+
}
21+
22+
void QMC5883L::WriteReg(byte Reg,byte val){
23+
Wire.beginTransmission(address); //Start
24+
Wire.write(Reg); // To tell the QMC5883L to get measures continously
25+
Wire.write(val); //Set up the Register
26+
Wire.endTransmission();
27+
}
28+
29+
void QMC5883L::init(){
30+
WriteReg(0x0B,0x01);
31+
//Define Set/Reset period
32+
setMode(Mode_Continuous,ODR_200Hz,RNG_8G,OSR_512);
33+
}
34+
35+
void QMC5883L::setMode(uint16_t mode,uint16_t odr,uint16_t rng,uint16_t osr){
36+
WriteReg(0x09,mode|odr|rng|osr);
37+
Serial.println(mode|odr|rng|osr,HEX);
38+
}
39+
40+
41+
void QMC5883L::softReset(){
42+
WriteReg(0x0A,0x80);
43+
}
44+
45+
void QMC5883L::read(int* x,int* y,int* z){
46+
Wire.beginTransmission(address);
47+
Wire.write(0x00);
48+
Wire.endTransmission();
49+
Wire.requestFrom(address, 6);
50+
*x = Wire.read(); //LSB x
51+
*x |= Wire.read() << 8; //MSB x
52+
*y = Wire.read(); //LSB z
53+
*y |= Wire.read() << 8; //MSB z
54+
*z = Wire.read(); //LSB y
55+
*z |= Wire.read() << 8; //MSB y
56+
}

libraries/QMC5883L/QMC5883L.h

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
QMC5883L.h - QMC5883L library
3+
Copyright (c) 2017 e-Gizmo Mechatronix Central
4+
Rewritten by Amoree. All right reserved.
5+
July 10,2017
6+
*/
7+
8+
#ifndef QMC5883L_h
9+
#define QMC5883L_h
10+
11+
12+
#if ARDUINO >= 100
13+
#include "Arduino.h"
14+
#else
15+
#include "WProgram.h"
16+
#endif
17+
18+
#include "Wire.h"
19+
20+
#define QMC5883L_ADDR 0x0D//The default I2C address is 0D: 0001101
21+
22+
23+
//Registers Control //0x09
24+
25+
#define Mode_Standby 0b00000000
26+
#define Mode_Continuous 0b00000001
27+
28+
#define ODR_10Hz 0b00000000
29+
#define ODR_50Hz 0b00000100
30+
#define ODR_100Hz 0b00001000
31+
#define ODR_200Hz 0b00001100
32+
33+
#define RNG_2G 0b00000000
34+
#define RNG_8G 0b00010000
35+
36+
#define OSR_512 0b00000000
37+
#define OSR_256 0b01000000
38+
#define OSR_128 0b10000000
39+
#define OSR_64 0b11000000
40+
41+
42+
class QMC5883L{
43+
44+
public:
45+
void setAddress(uint8_t addr);
46+
void init();
47+
void setMode(uint16_t mode,uint16_t odr,uint16_t rng,uint16_t osr);
48+
void softReset();
49+
void read(uint16_t* x,uint16_t* y,uint16_t* z);
50+
void read(int* x,int* y,int* z);
51+
52+
private:
53+
void WriteReg(uint8_t Reg,uint8_t val);
54+
uint8_t address = QMC5883L_ADDR;
55+
56+
};
57+
58+
#endif

0 commit comments

Comments
 (0)