From 29736a4f926b1b64300885e4854d753c5f7432a9 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 25 May 2023 19:56:47 +0100 Subject: [PATCH] Update examples: replace "normalized" with "scaled"; add extra comments --- .../Example1-I2C_Simple_measurement.ino | 34 ++++++++------- .../Example2-I2C_Digital_compass.ino | 28 +++++++------ .../Example3-I2C_Continuous_measurement.ino | 28 +++++++------ .../Example4-SPI_Simple_measurement.ino | 34 ++++++++------- .../Example5-SPI_Digital_compass.ino | 28 +++++++------ ...ample6-SPI_Fast_Continuous_measurement.ino | 28 +++++++------ .../Example7-I2C_Sensor_Offset.ino | 41 ++++++++++++------- library.properties | 2 +- 8 files changed, 129 insertions(+), 94 deletions(-) diff --git a/examples/Example1-I2C_Simple_measurement/Example1-I2C_Simple_measurement.ino b/examples/Example1-I2C_Simple_measurement/Example1-I2C_Simple_measurement.ino index c2b7b06..19d51b0 100644 --- a/examples/Example1-I2C_Simple_measurement/Example1-I2C_Simple_measurement.ino +++ b/examples/Example1-I2C_Simple_measurement/Example1-I2C_Simple_measurement.ino @@ -55,9 +55,9 @@ void loop() uint32_t currentX = 0; uint32_t currentY = 0; uint32_t currentZ = 0; - double normalizedX = 0; - double normalizedY = 0; - double normalizedZ = 0; + double scaledX = 0; + double scaledY = 0; + double scaledZ = 0; // This reads the X, Y and Z channels consecutively // (Useful if you have one or more channels disabled) @@ -75,25 +75,29 @@ void loop() Serial.print("\tZ axis raw value: "); Serial.println(currentZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)currentX - 131072.0; - normalizedX /= 131072.0; - normalizedY = (double)currentY - 131072.0; - normalizedY /= 131072.0; - normalizedZ = (double)currentZ - 131072.0; - normalizedZ /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to convert to Gauss. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)currentX - 131072.0; + scaledX /= 131072.0; + scaledY = (double)currentY - 131072.0; + scaledY /= 131072.0; + scaledZ = (double)currentZ - 131072.0; + scaledZ /= 131072.0; // The magnetometer full scale is +/- 8 Gauss - // Multiply the normalized values by 8 to convert to Gauss + // Multiply the scaled values by 8 to convert to Gauss Serial.print("X axis field (Gauss): "); - Serial.print(normalizedX * 8, 5); // Print with 5 decimal places + Serial.print(scaledX * 8, 5); // Print with 5 decimal places Serial.print("\tY axis field (Gauss): "); - Serial.print(normalizedY * 8, 5); + Serial.print(scaledY * 8, 5); Serial.print("\tZ axis field (Gauss): "); - Serial.println(normalizedZ * 8, 5); + Serial.println(scaledZ * 8, 5); Serial.println(); delay(100); diff --git a/examples/Example2-I2C_Digital_compass/Example2-I2C_Digital_compass.ino b/examples/Example2-I2C_Digital_compass/Example2-I2C_Digital_compass.ino index b30d1e3..63ec0c0 100644 --- a/examples/Example2-I2C_Digital_compass/Example2-I2C_Digital_compass.ino +++ b/examples/Example2-I2C_Digital_compass/Example2-I2C_Digital_compass.ino @@ -46,28 +46,32 @@ void loop() uint32_t rawValueX = 0; uint32_t rawValueY = 0; uint32_t rawValueZ = 0; - double normalizedX = 0; - double normalizedY = 0; - double normalizedZ = 0; + double scaledX = 0; + double scaledY = 0; + double scaledZ = 0; double heading = 0; // Read all three channels simultaneously myMag.getMeasurementXYZ(&rawValueX, &rawValueY, &rawValueZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)rawValueX - 131072.0; - normalizedX /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to calculate an approximate heading. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)rawValueX - 131072.0; + scaledX /= 131072.0; - normalizedY = (double)rawValueY - 131072.0; - normalizedY /= 131072.0; + scaledY = (double)rawValueY - 131072.0; + scaledY /= 131072.0; - normalizedZ = (double)rawValueZ - 131072.0; - normalizedZ /= 131072.0; + scaledZ = (double)rawValueZ - 131072.0; + scaledZ /= 131072.0; // Magnetic north is oriented with the Y axis // Convert the X and Y fields into heading using atan2 (Arc Tangent 2) - heading = atan2(normalizedX, 0 - normalizedY); + heading = atan2(scaledX, 0 - scaledY); // atan2 returns a value between +PI and -PI // Convert to degrees diff --git a/examples/Example3-I2C_Continuous_measurement/Example3-I2C_Continuous_measurement.ino b/examples/Example3-I2C_Continuous_measurement/Example3-I2C_Continuous_measurement.ino index bd60868..ae44e81 100644 --- a/examples/Example3-I2C_Continuous_measurement/Example3-I2C_Continuous_measurement.ino +++ b/examples/Example3-I2C_Continuous_measurement/Example3-I2C_Continuous_measurement.ino @@ -29,9 +29,9 @@ volatile bool newDataAvailable = true; uint32_t rawValueX = 0; uint32_t rawValueY = 0; uint32_t rawValueZ = 0; -double normalizedX = 0; -double normalizedY = 0; -double normalizedZ = 0; +double scaledX = 0; +double scaledY = 0; +double scaledZ = 0; double heading = 0; void setup() @@ -97,20 +97,24 @@ void loop() // The measurement is already complete, we do not need to start a new one myMag.readFieldsXYZ(&rawValueX, &rawValueY, &rawValueZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)rawValueX - 131072.0; - normalizedX /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to calculate an approximate heading. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)rawValueX - 131072.0; + scaledX /= 131072.0; - normalizedY = (double)rawValueY - 131072.0; - normalizedY /= 131072.0; + scaledY = (double)rawValueY - 131072.0; + scaledY /= 131072.0; - normalizedZ = (double)rawValueZ - 131072.0; - normalizedZ /= 131072.0; + scaledZ = (double)rawValueZ - 131072.0; + scaledZ /= 131072.0; // Magnetic north is oriented with the Y axis // Convert the X and Y fields into heading using atan2 (Arc Tangent 2) - heading = atan2(normalizedX, 0 - normalizedY); + heading = atan2(scaledX, 0 - scaledY); // atan2 returns a value between +PI and -PI // Convert to degrees diff --git a/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino b/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino index 2983fe5..06794bb 100644 --- a/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino +++ b/examples/Example4-SPI_Simple_measurement/Example4-SPI_Simple_measurement.ino @@ -57,9 +57,9 @@ void loop() uint32_t currentX = 0; uint32_t currentY = 0; uint32_t currentZ = 0; - double normalizedX = 0; - double normalizedY = 0; - double normalizedZ = 0; + double scaledX = 0; + double scaledY = 0; + double scaledZ = 0; // This reads the X, Y and Z channels consecutively // (Useful if you have one or more channels disabled) @@ -77,25 +77,29 @@ void loop() Serial.print("\tZ axis raw value: "); Serial.println(currentZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)currentX - 131072.0; - normalizedX /= 131072.0; - normalizedY = (double)currentY - 131072.0; - normalizedY /= 131072.0; - normalizedZ = (double)currentZ - 131072.0; - normalizedZ /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to convert to Gauss. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)currentX - 131072.0; + scaledX /= 131072.0; + scaledY = (double)currentY - 131072.0; + scaledY /= 131072.0; + scaledZ = (double)currentZ - 131072.0; + scaledZ /= 131072.0; // The magnetometer full scale is +/- 8 Gauss - // Multiply the normalized values by 8 to convert to Gauss + // Multiply the scaled values by 8 to convert to Gauss Serial.print("X axis field (Gauss): "); - Serial.print(normalizedX * 8, 5); // Print with 5 decimal places + Serial.print(scaledX * 8, 5); // Print with 5 decimal places Serial.print("\tY axis field (Gauss): "); - Serial.print(normalizedY * 8, 5); + Serial.print(scaledY * 8, 5); Serial.print("\tZ axis field (Gauss): "); - Serial.println(normalizedZ * 8, 5); + Serial.println(scaledZ * 8, 5); Serial.println(); delay(100); diff --git a/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino b/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino index 205210c..5ecb189 100644 --- a/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino +++ b/examples/Example5-SPI_Digital_compass/Example5-SPI_Digital_compass.ino @@ -48,28 +48,32 @@ void loop() uint32_t rawValueX = 0; uint32_t rawValueY = 0; uint32_t rawValueZ = 0; - double normalizedX = 0; - double normalizedY = 0; - double normalizedZ = 0; + double scaledX = 0; + double scaledY = 0; + double scaledZ = 0; double heading = 0; // Read all three channels simultaneously myMag.getMeasurementXYZ(&rawValueX, &rawValueY, &rawValueZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)rawValueX - 131072.0; - normalizedX /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to calculate an approximate heading. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)rawValueX - 131072.0; + scaledX /= 131072.0; - normalizedY = (double)rawValueY - 131072.0; - normalizedY /= 131072.0; + scaledY = (double)rawValueY - 131072.0; + scaledY /= 131072.0; - normalizedZ = (double)rawValueZ - 131072.0; - normalizedZ /= 131072.0; + scaledZ = (double)rawValueZ - 131072.0; + scaledZ /= 131072.0; // Magnetic north is oriented with the Y axis // Convert the X and Y fields into heading using atan2 (Arc Tangent 2) - heading = atan2(normalizedX, 0 - normalizedY); + heading = atan2(scaledX, 0 - scaledY); // atan2 returns a value between +PI and -PI // Convert to degrees diff --git a/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino b/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino index 2d8f068..ab76b5d 100644 --- a/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino +++ b/examples/Example6-SPI_Fast_Continuous_measurement/Example6-SPI_Fast_Continuous_measurement.ino @@ -29,9 +29,9 @@ volatile bool newDataAvailable = true; uint32_t rawValueX = 0; uint32_t rawValueY = 0; uint32_t rawValueZ = 0; -double normalizedX = 0; -double normalizedY = 0; -double normalizedZ = 0; +double scaledX = 0; +double scaledY = 0; +double scaledZ = 0; double heading = 0; void setup() @@ -98,20 +98,24 @@ void loop() // The measurement is already complete, we do not need to start a new one myMag.readFieldsXYZ(&rawValueX, &rawValueY, &rawValueZ); - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). - // Normalize each field to +/- 1.0 - normalizedX = (double)rawValueX - 131072.0; - normalizedX /= 131072.0; + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). + // Here we scale each field to +/- 1.0 to make it easier to calculate an approximate heading. + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + scaledX = (double)rawValueX - 131072.0; + scaledX /= 131072.0; - normalizedY = (double)rawValueY - 131072.0; - normalizedY /= 131072.0; + scaledY = (double)rawValueY - 131072.0; + scaledY /= 131072.0; - normalizedZ = (double)rawValueZ - 131072.0; - normalizedZ /= 131072.0; + scaledZ = (double)rawValueZ - 131072.0; + scaledZ /= 131072.0; // Magnetic north is oriented with the Y axis // Convert the X and Y fields into heading using atan2 (Arc Tangent 2) - heading = atan2(normalizedX, 0 - normalizedY); + heading = atan2(scaledX, 0 - scaledY); // atan2 returns a value between +PI and -PI // Convert to degrees diff --git a/examples/Example7-I2C_Sensor_Offset/Example7-I2C_Sensor_Offset.ino b/examples/Example7-I2C_Sensor_Offset/Example7-I2C_Sensor_Offset.ino index 0881e01..30d4944 100644 --- a/examples/Example7-I2C_Sensor_Offset/Example7-I2C_Sensor_Offset.ino +++ b/examples/Example7-I2C_Sensor_Offset/Example7-I2C_Sensor_Offset.ino @@ -81,7 +81,7 @@ void setup() void loop() { - // The magnetic field values are 18-bit unsigned. The zero (mid) point is 2^17 (131072). + // The magnetic field values are 18-bit unsigned. The _approximate_ zero (mid) point is 2^17 (131072). // Use static variables to hold the offset. Set to 131072 initially. static uint32_t offsetX = 131072; static uint32_t offsetY = 131072; @@ -104,25 +104,29 @@ void loop() myMag.getMeasurementXYZ(¤tX, ¤tY, ¤tZ); // The magnetic field values are 18-bit unsigned. - // The zero (mid) point should be 2^17 (131072). - // Here we subtract the offset, then normalize each field to +/- 1.0, + // The _approximate_ zero (mid) point should be 2^17 (131072). + // Here we subtract the offset, then scale each field to +/- 1.0, // then multiply by 8 to convert to Gauss - double normalizedX = (double)currentX - (double)offsetX; // Convert to double _before_ subtracting - normalizedX /= 131072.0; - normalizedX *= 8.0; - double normalizedY = (double)currentY - (double)offsetY; // Convert to double _before_ subtracting - normalizedY /= 131072.0; - normalizedY *= 8.0; - double normalizedZ = (double)currentZ - (double)offsetZ; // Convert to double _before_ subtracting - normalizedZ /= 131072.0; - normalizedZ *= 8.0; + // + // Please note: to properly correct and calibrate the X, Y and Z channels, you need to determine true + // offsets (zero points) and scale factors (gains) for all three channels. Futher details can be found at: + // https://thecavepearlproject.org/2015/05/22/calibrating-any-compass-or-accelerometer-for-arduino/ + double scaledX = (double)currentX - (double)offsetX; // Convert to double _before_ subtracting + scaledX /= 131072.0; + scaledX *= 8.0; + double scaledY = (double)currentY - (double)offsetY; // Convert to double _before_ subtracting + scaledY /= 131072.0; + scaledY *= 8.0; + double scaledZ = (double)currentZ - (double)offsetZ; // Convert to double _before_ subtracting + scaledZ /= 131072.0; + scaledZ *= 8.0; // Print the three channels with commas in between so the Serial Plotter can plot them - Serial.print(normalizedX, 5); // Print with 5 decimal places + Serial.print(scaledX, 5); // Print with 5 decimal places Serial.print(","); - Serial.print(normalizedY, 5); + Serial.print(scaledY, 5); Serial.print(","); - Serial.println(normalizedZ, 5); + Serial.println(scaledZ, 5); } bool updateOffset(uint32_t *offsetX, uint32_t *offsetY, uint32_t *offsetZ) // Update the offsets @@ -154,6 +158,13 @@ bool updateOffset(uint32_t *offsetX, uint32_t *offsetY, uint32_t *offsetZ) // Up *offsetX = (setX + resetX) / 2; *offsetY = (setY + resetY) / 2; *offsetZ = (setZ + resetZ) / 2; + //Serial.print("Offsets: ") + //Serial.print(*offsetX); + //Serial.print(", "); + //Serial.print(*offsetY); + //Serial.print(", "); + //Serial.print(*offsetZ); + //Serial.println(); } return success; diff --git a/library.properties b/library.properties index 203116b..fddec3f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun MMC5983MA Magnetometer Arduino Library -version=1.1.1 +version=1.1.2 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=A I2C/SPI library for the MMC5983MA magnetic compass sensor.