05 Lesson. Getting raw data from a magnetometer
Getting to know the magnetometer of a smartphone
Almost every modern smartphone has a magnetometer installed, let's get to know it. Install an indoor data visualization application obtained using an external magnet, sensor, or magnetometer.
Open the application and you will see a blue arrow that shows the direction of the magnetic field lines.

Rotate your smartphone and make sure that the magnetic lines are always directed in one direction – almost to the north. In addition to the Earth's field, other magnetic fields affect the readings of the magnetometer. Make sure of this by bringing the magnet closer to your smartphone. By moving the magnet near the smartphone, determine the exact location of the magnetometer in the smartphone case.

Pay attention to the magnitude of the intensity of the Earth's magnetic field and the field near the magnet.
Checking the performance of the Orbicraft magnetometer
Combine the BKU with a PSS and a magnetometer. Do not attach the magnetometer to the plate so that it is convenient to rotate it. Download the program to the BKU and run it.
Python code:
def control(): # The main programs for which it is important to create remote applications
mgn_result = [0,0,0,0] # Analyzing mgn_result
num = 1
output "Turn on magnetometer No.", num
magnetometer_turn_on(number)
standby mode(1)
print "Get raw data from the magnetometer"
for the value i in the range(1000):
mgn_result = magnetometer_request_raw(number)
if there is no mgn_result[0]: # to get the result,
output mgn_result[1], mgn_result[2], mgn_result[3]
elif mgn_result[0] == 1:
the message "Failed due to an access error, check the connection"
is displayed elif mgn_result[0] == 2:
the message "Failed due to an interface error, check your code"
standby mode(0.1)
output "Turn off magnetometer No.", the number
of magnetometer_turn_off(number)
Code in C:
#enable <standard file.h>
#enable <stdint.h>
#enable "libschsat.h"
#define LSS_OK 0
#define LSS_ERROR 1
#define LSS_BREAK 2
invalid control(void) // The main program for which remote applications are created
{
int16_t mgn_result[] = {0, 0, 0, 0}; // Analyzing mgn_result
uint16_t num = 1; //registrar number
printf("Enable (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) magnetometer No. %d", number);
magnetometer_turn_on(number); //Turning on the magnetometer
Sleep(1);
printf("Get (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) RAW data from the magnetometer");
int i;
for (i = 0; i < 10; i++)
{
mgn_result[0] = magnetometer_request_raw(number, &mgn_result[1], &mgn_result[2], &mgn_result[3]);
if (!mgn_result[0]) //if the sensor returned an error message,
{
printf("status: (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) %d\n", i);
printf(" (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) x_raw = %d\n", mgn_result[1]);
printf(" (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) y_raw = %d\n", mgn_result[2]);
printf(" (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) z_raw = %d\n", mgn_result[3]);
}
otherwise, if (mgn_result[0] == 1)
{
printf("Failed (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) due to an access error, check the connection");
}
else if (mgn_result[0] == 2)
{
printf("Failed(http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) due to an interface error, check your code");
}
Sleep(1);
}
printf("Disable (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html ) magnetometer no. %d", number);
magnetometer_turn_off(number);//Turning on the magnetometer
}
Run the program and look at the values it outputs. If the magnetometer is not rotated, the values do not change. If you rotate it, the values will change. If you rotate the magnetometer around one of the axes, one of the three numerical values will mainly change, the other two will change to a lesser extent. Hold a magnet up to the magnetometer and see how the values change when the magnet moves at a stationary magnetometer.
Getting the azimuth from the magnetometer
Print out the protractor (template in the file [protractor.PDF file] (/files/orbicraft/protractor.PDF file)), glue it to the table using adhesive pads that do not leave traces (analogous to the Uhu patafix hotel), glue the magnetometer to the ruler in a similar way.
Upload the following program to the BKU, which will make 60 measurements in 1 second increments.
Python code:
import math
time_step = 1 # Time step of the change, sec
mag_num = 1 # Number
of the def control module(): # main programs
print "Turn on the magnetometer", the value of the parameter
magnetometer_turn_on(mag_num)
standby mode(10)
mag_state = 0 # Analyzing the user status
alpha_goal = 0 # Left corner
omega_goal = 0 # The main target
for me in the range(12):
mag_state, magx_raw, magy_raw, magz_raw = magnetometer_request_raw(mag_num) # magnetometer request
if not, then mag_state: # if the digits are 0, then the digits are not
mag_alpha = math.atan2(magy_raw, magx_raw)/math.pi*180
print "mag_alpha atan2= ", mag_alpha
elif mag_state == 1:
output "Failure due to access error, check the connection"
elif mag_state == 2:
output "Failure due to an interface error, check your code"
standby mode(time_step)
output "Turn off the magnetometer", the value of the parameter
magnetometer_turn_off(mag_num)
Code in C:
#include <stdio.h>
#include <stdint.h>
#include "libschsat.h"
#define LSS_OK 0
#define LSS_ERROR 1
#define LSS_BREAK 2
#include <math.h>
void control(void){
int time_step = 10;
uint16_t mag_num = 1;
printf("Enable (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) magnetometer %d\n", mag_num);
magnetometer_turn_on(mag_num);
Sleep(1);
int mag_state = 0;
int16_t p_dataX;
int16_t p_dataY;
int16_t p_dataZ;
int16_t *pRAW_dataX = &p_dataX;
int16_t *pRAW_dataY = &p_dataY;
int16_t *pRAW_dataZ = &p_dataZ;
int i;
for (i = 0; i < 12; i++){
mag_state = magnetometer_request_raw(mag_num, pRAW_dataX, pRAW_dataY, pRAW_dataZ);
float mag_alpha;
if (!mag_state){
mag_alpha = atan2(p_dataY, (http://www.opengroup.org/onlinepubs/009695399/functions/atan2.html) p_dataX)/M_PI*180;
printf("mag_alpha (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) atan2 = %f\n", mag_alpha);
}
else if (mag_state == 1){
printf("Fail (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) because of access error, check the connection\n");
}
else if (mag_state == 2){
printf("Fail (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) because of interface error, check your code\n");
}
Sleep(time_step);
}
printf("Disable (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) magnetometer %d\n", mag_num);
magnetometer_turn_off(mag_num);
}
Rotate the magnetometer in 30 degree increments and record the output angle value in an EXCEL spreadsheet. You should get something like this table with data.
Data analysis in Excel
Please note that when rotating by 30 degrees, the angle value output by the magnetometer does not change exactly by 30 degrees. Let's calculate these values using EXCEL tools.
Creating a table
Create a new column that will contain the difference of adjacent numbers. Enter an equal sign in an empty cell C2, and then click on cell B1, enter the "-" sign, and then click on cell B2 and press Enter.

The difference B1-B2 will be calculated in cell C2. Pull down the corner — the formula will be automatically copied to all the lower cells.

The differences will be calculated automatically.
Please note that the value -326 is clearly erroneous. When passing through the value of 180 degrees, the sign of the measured angle changed, therefore, instead of -326, you need to enter the value (180-155) combined with the value (180-171). It will turn out to be 25 + 9 = 34. Enter the value 34 instead of -326.
Charting
Now you need to build a graph to visually see the distortions introduced into the angle measurement by an uncalibrated magnetometer. Highlight the calculated values of the differences.

Click Insert and select the pie chart.


Right-click on the colored circle and select the white fill color and the black outline color.


Now it can be seen with the naked eye that the magnetometer is far from ideal — the sectors of the circle are not exactly 30 degrees. Some are narrower and some are wider.

Let's build another graph that clearly illustrates the imperfection of the magnetometer. Highlight the calculated values of the differences. Click Insert and select the petal chart.
Now it is very clearly seen that the values are far from the ideal 12 of a square with a radius of 30.

Data analysis using functions
And now let's calculate the average value of the difference between the measured angles using the EXCEL CP VALUE function. Select any cell, enter the equal sign, the function name, and open the bracket.
Then select with the mouse the range of calculated values of the differences on the basis of which we built the diagrams and close the bracket. The function will look like this =CP VALUE(C2:C13). Press Enter and the function will calculate the average value of the specified numbers. And now let's calculate the standard deviation of the calculated differences from the average value, which will show the magnitude of the spread of values relative to the average. To do this, we use the STANDARD SLOPE function. Select any cell, enter the equal sign, the function name, and open the bracket.
Then select with the mouse the range of calculated values of the differences on the basis of which we built the diagrams and close the bracket. The function will look like this =STANDARD SLOPE(C2:C13). Press Enter and the function will calculate the standard deviation of the calculated differences from the average value. Now calculate the percentage of the mean value and the standard deviation.


As you can see, the spread is very large and is 17% of the average value. The magnetometer must be calibrated.
Getting raw data for magnetometer calibration
By default, the magnetometer is not calibrated, i.e. it gives inaccurate values. Refined values can be obtained from raw data by calibration, which consists in finding the transformation matrix and the displacement vector. The raw data from the magnetometer can be obtained by executing the Python code shown below. During data collection, the magnetometer must be randomly rotated, trying to turn it in all possible directions.
Python code:
``cpp raw_data.py (http://orbicraft.sputnix.ru/doku.php?do=export_code&id=lesson5&codeblock=4 ) def control(): #The main program in which we call the rest of the functions mgn_result = [0,0,0,0] #Initialize mgn_result num = 1 magnetometer_turn_on(num) #Turn on the sleep magnetometer(1) for i in range(500): #Perform 500 measurements mgn_result = magnetometer_request_raw(num) if not mgn_result[0]: #If the sensor did not return an error message print mgn_result[1], mgn_result[2], mgn_result[3] sleep(0.05) #Delay of five hundredths of a second magnetometer_turn_off(num) #Turning off the magnetometer
### Code in C:
```cpp raw_data.c (http://orbicraft.sputnix.ru/doku.php?do=export_code&id=lesson5&codeblock=5)
#include <stdio.h>
#include <stdint.h>
#include "libschsat.h"
#define LSS_OK 0
#define LSS_ERROR 1
#define LSS_BREAK 2
void control(void){ //The main program in which we call the rest of the functions
/*There is no need to declare an array for data output*/
int16_t mgn_result[] = {0, 0, 0, 0}; // Initialize mgn_result
uint16_t num = 1;
magnetometer_turn_on(num); //Turn on the magnetometer
Sleep(1);
int i;
for (i = 0; i < 500; i++) //Let's take 500 measurements
{
mgn_result[0] = magnetometer_request_raw(num, &mgn_result[1],&mgn_result[2],&mgn_result[3]);
if(!mgn_result[0]){ //If the sensor did not return an error message
printf("%d, (http://www.opengroup.org/onlinepubs/009695399/functions/printf.html) %d, %d\n", mgn_result[1], mgn_result[2], mgn_result[3]);
}
Sleep(0.5); //Delay of five hundredths of a second
}
magnetometer_turn_off(num);
}
Connect the BCU to the PSS and the magnetometer. Do not attach the magnetometer to the plate so that it is convenient to rotate it. Download the program to Orbicraft and run it. Randomly rotate the magnetometer to collect raw data from all possible orientations. Save the received data to a file with the txt extension. To do this, select all the results using Ctrl+A and copy using Ctrl+C and save.
Program operation analysis
The program uses the following functions for working with a magnetometer.
magnetometer_turn_on(num)
– the function of turning on the magnetometer, where num is the number of the magnetometer.
magnetometer_request_raw(num)
is a function that returns raw data measured by a magnetometer with the number num, which is a list of 4 numeric values. Therefore, we put the read data in the mgn_result list, consisting of 4 values. mgn_result = [0,0,0,0]
mgn_result = magnetometer_request_raw(num)
The first value of the list returns information about the error. If the value 0 is returned, then there is no error, if 1, then the sensor is not connected, if 2, then there is an error in the program. The program uses the loop operator
for (i = 0; i < 500; i++)
which will be executed 500 times, 500 values will be output accordingly. These values will be needed in the next lesson when calibrating the magnetometer.