Инструменты пользователя

Перевод этой страницы:

Инструменты сайта


Боковая панель

Для чего нужен ОрбиКрафт

Как с этим работать

Подсистемы конструктора

Полезная нагрузка на базе Arduino

Уроки

Лабораторная оснастка

Обратная связь

Новости

lesson5

05 Урок. Получение сырых данных с магнитометра.

Знакомство с магнитометром смартфона

Почти в каждом современном смартфоне установлен магнитометр, давайте познакомимся с ним. Установите в смартфон приложение для визуализации данных, полученных со встроенного магнитометра, например, MagnetMeter.

Откройте приложение – вы увидите синюю стрелку, которая показывает направление силовых линий магнитного поля.

Вращайте смартфон и убедитесь, что магнитные линии направлены всегда в одну сторону – почти на север. На показания магнитометра кроме поля Земли влияют и другие магнитные поля. Убедитесь в этом приблизив магнит к смартфону. Перемещая магнит около смартфона определите точное место установки магнитометра в корпусе смартфона.

Обратите внимание на величину напряженности магнитного поля Земли и поля вблизи магнита.

Проверка работоспособности магнитометра Орбикрафт

Соедините БКУ с СЭП и магнитометром.

Не прикрепляйте магнитометр к пластине, чтобы его было удобно вращать. Загрузите программу в БКУ и запустите ее.

Код на Python.

mag_test_2.py
def control(): # Основная функция программы, в которой нужно вызывать остальные функции
	mgn_result = [0,0,0,0] # Инициализируем mgn_result
	num = 1
	print "Enable magnetometer №", num
	magnetometer_turn_on(num)
	sleep(1)
	print "Get RAW data from magnetometer"
	for i in range(1000):
		mgn_result = magnetometer_request_raw(num)
		if not mgn_result[0]: # если сообщение об ошибке,
			print mgn_result[1], mgn_result[2], mgn_result[3]
		elif mgn_result[0] == 1:
			print "Fail because of access error, check the connection"
		elif mgn_result[0] == 2:
			print "Fail because of interface error, check your code"
		sleep(0.1)
 	print "Disable magnetometer №", num
	magnetometer_turn_off(num)

Код на С.

mag_test_2.c
#include <stdio.h>
#include <stdint.h>
#include "libschsat.h"
#define LSS_OK 0 
#define LSS_ERROR 1 
#define LSS_BREAK 2
 
void control(void) // Основная функция программы, в которой вызываем остальные функции
{
	int16_t mgn_result[] = {0, 0, 0, 0}; //Инициализируем mgn_result
	uint16_t num = 1; //номер магнитометра
	printf("Enable magnetometer № %d", num);
	magnetometer_turn_on(num); //Включение  магнитометр
	Sleep(1);
	printf("Get RAW data from magnetometer");
	int i;
	for (i = 0; i < 10; i++)
	{
		mgn_result[0] = magnetometer_request_raw(num, &mgn_result[1], &mgn_result[2], &mgn_result[3]);
		if (!mgn_result[0]) //если датчик вернул сообщение об ошибке,
		{
			printf("state: %d\n", i);
			printf(" x_raw = %d\n", mgn_result[1]);
			printf(" y_raw = %d\n", mgn_result[2]);
			printf(" z_raw = %d\n", mgn_result[3]);
		}
		else if (mgn_result[0] == 1)
		{
			printf("Fail because of access error, check the connection");
		}
		else if (mgn_result[0] == 2)
		{
			printf("Fail because of interface error, check your code");
		}
		Sleep(1);
	}
	printf("Disable magnetometer №%d", num);
	magnetometer_turn_off(num);//Выключение магнитометра
 
}

Запустите программу и посмотрите на значения, которые она выдает. Если магнитометр не вращать, то значения не изменяются. Если его вращать, то значения будут изменяться. Если вращать магнитометр вокруг одной из осей, то преимущественно будет изменяться одно из трех числовых значений, другие два будут изменяться в меньшей степени. Поднесите к магнитометру магнит и посмотрите, как изменяются значения при движении магнита у неподвижного магнитометра.

Получение азимута с магнитометра

Распечатайте транспортир (шаблон в файле Transportir.pdf), приклейте его к столу с помощью клеящих подушечек, не оставляющих следов (аналог UHU patafix), приклейте магнитометр на линейку аналогичным способом.

Загрузите в БКУ следующую программу, которая произведет 60 измерений с шагом в 1 сек.

Код на Python.

azimuth.py
import math
time_step = 1		# Временной шаг измерений, сек
mag_num = 1		# Номер магнитометра
def control(): # основная функция программы
	print "Enable magnetometer", mag_num	
	magnetometer_turn_on(mag_num)
	sleep(1)
	mag_state = 0 		# Инициализируем статус магнитометра
	alpha_goal = 0		# Целевой угол
	omega_goal = 0 		# Целевая угловая скорость
		for i in range(60):
		mag_state, magx_raw, magy_raw, magz_raw = magnetometer_request_raw(mag_num) # опрос магнитометра
		if not mag_state: # если код ошибки 0, то ошибки нет
			mag_alpha = math.atan2(magy_raw, magx_raw)/math.pi*180
			print "mag_alpha atan2= ", mag_alpha
		elif mag_state == 1:
			print "Fail because of access error, check the connection"
		elif mag_state == 2:
			print "Fail because of interface error, check your code"
		sleep(time_step)
	print "Disable magnetometer", mag_num
	magnetometer_turn_off(mag_num)

Код на С.

azimuth.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 = 1;
	uint16_t mag_num = 1;
	printf("Enable 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 < 60; 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, p_dataX)/M_PI*180;
			printf("mag_alpha atan2 = %f\n", mag_alpha);
		}
		else if (mag_state == 1){
			printf("Fail because of access error, check the connection\n");
		}
		else if (mag_state == 2){
			printf("Fail because of interface error, check your code\n");
		}
		Sleep(time_step);
	}
	printf("Disable magnetometer %d\n", mag_num);
	magnetometer_turn_off(mag_num);
}

Поворачивайте магнитометр с шагом в 30 градусов и записывайте выдаваемое значение угла в таблицу EXCEL. Должна получится примерно вот такая таблица с данными.

Анализ данных в Excel

Обратите внимание, при повороте на 30 градусов значение угла, выдаваемое магнитометром изменяется не ровно на 30 градусов. Давайте вычислим эти значения средствами EXCEL.

Создание таблицы

Создайте новый столбец, который будет содержать разность соседних чисел. Введите в пустую ячейку С2 знак равенства, а затем кликните мышкой в ячейку В1, введите знак «-», а затем кликните в ячейку В2 и нажмите Enter.

В ячейке С2 будет вычислена разность В1-В2. Протяните вниз уголок — формула автоматически скопируется во все нижние ячейки.

Разности будут вычислены автоматически.

Обратите внимание, значение -326 явно ошибочное. При переходе через значение 180 градусов изменился знак измеренного угла, следовательно вместо -326 нужно внести значение (180-155) сложенное со значением (180-171). Получится 25+9=34. Введите вместо -326 значение 34.

Построение диаграмм

Теперь нужно построить график чтобы наглядно увидеть искажения, вносимые в измерение угла некалиброванным магнитометром. Выделите вычисленные значения разностей.

Нажмите Вставка и выберите круговую диаграмму.

Кликните правой кнопкой мышки в цветной круг и выберите белый цвет заливки и черный цвет контура.

Теперь невооруженным глазом видно, что магнитометр далек от идеала — сектора круга не ровно по 30 градусов. Некоторые уже, а некоторые шире.

Давайте построим еще один график, который наглядно проиллюстрирует неидеальность магнитометра. Выделите вычисленные значения разностей. Нажмите Вставка и выберите лепестковую диаграмму.

Теперь очень хорошо видно, что значения далеки от идеального 12 угольника радиусом 30.

Анализ данных с помощью функций

А теперь давайте вычислим среднее значение разности между измеренными углами с использованием функции EXCEL СРЗНАЧ. Выберите любую ячейку, введите знак равенства, имя функции и откройте скобку.

Затем выберите мышкой диапазон вычисленных значение разностей, на основе которого мы строили диаграммы и закройте скобку. Функция будет иметь такой вид =СРЗНАЧ(C2:C13). Нажмите Enter, и функция вычислит среднее значение указанных чисел. А теперь давайте вычислим стандартное отклонение вычисленных разностей от среднего значения, которое покажет величину разброса значений относительно среднего. Для этого используем функцию СТАНДОТКЛОНА. Выберите любую ячейку, введите знак равенства, имя функции и откройте скобку.

Затем выберите мышкой диапазон вычисленных значение разностей, на основе которого мы строили диаграммы и закройте скобку. Функция будет иметь такой вид =СТАНДОТКЛОНА(C2:C13). Нажмите Enter, и функция вычислит стандартное отклонение вычисленных разностей от среднего значения. Теперь вычислите процентное соотношение среднего значения и стандартного отклонения.

Как видите, разброс очень велик и составляет 17% от среднего значения. Магнитометр необходимо откалибровать.

Получение сырых данных для калибровки магнитометра

По умолчанию магнитометр не откалиброван, т.е. выдает неточные значения. Уточненные значения можно получить из сырых данных путем калибровки, которая заключается в нахождении матрицы преобразования и вектора смещения. Сырые данные с магнитометра можно получить, выполнив код на языке Python, представленный ниже. Во время сбора данных магнитометр необходимо хаотично вращать, стараясь повернуть его во все возможные стороны.

Код на Python.

raw_data.py
def control(): #Основная программы, в которой вызываем остальные функции
	mgn_result = [0,0,0,0] 		#Инициализируем mgn_result
	num = 1
	magnetometer_turn_on(num) 	#Включаем магнитометр
	sleep(1)
	for i in range(500):		#Выполним 500 измерений
		mgn_result = magnetometer_request_raw(num)
		if not mgn_result[0]: #Если датчик не вернул сообщение об ошибке
			print mgn_result[1], mgn_result[2], mgn_result[3]
		sleep(0.05)			#Задержка пять сотых секунды
 	magnetometer_turn_off(num)	#Выключение магнитометра

Код на С.

raw_data.c
#include <stdio.h>
#include <stdint.h>
#include "libschsat.h"
#define LSS_OK 0 
#define LSS_ERROR 1 
#define LSS_BREAK 2
 
 
void control(void){ //Основная программа, в которой вызываем остальные функции
/*Для вывода данных необходимость в объявлении массива отпадает*/
	int16_t mgn_result[] = {0, 0, 0, 0}; //Инициализируем mgn_result
	uint16_t num = 1;
	magnetometer_turn_on(num); //Включаем магнитометр
	Sleep(1);
	int i;
	for (i = 0; i < 1000; i++) //Выполним 500 измерений
	{
		mgn_result[0] = magnetometer_request_raw(num, &mgn_result[1],&mgn_result[2],&mgn_result[3]);
		if(!mgn_result[0]){ //Если датчик не вернул сообщение об ошибке
			printf("%d, %d, %d\n", mgn_result[1], mgn_result[2], mgn_result[3]);
		}
		Sleep(0.5); //Задержка пять сотых секунды
	}
	magnetometer_turn_off(num); 
}

Соедините БКУ с СЭП и магнитометром. Не прикрепляйте магнитометр к пластине, чтобы его было удобно вращать. Загрузите программу в Орбикрафт и запустите ее. Хаотично вращайте магнитометр, чтобы собрать сырые данные со всех возможных вариантов его ориентации. Сохраните полученные данный в файл с расширением txt. Для этого выделите все результаты с помощью Ctrl+A и скопируйте с помощью Ctrl+C и сохраните.

Анализ работы программы

В программе используются следующие функции работы с магнитометром.

 magnetometer_turn_on(num) 

– функция включения магнитометра, где num – это номер магнитометра.

 magnetometer_request_raw(num) 

– функция возвращающая сырые данные измеренные магнитометром с номером num, представляющие собой список из 4 числовых значений. Поэтому считанные данные мы помещаем в список mgn_result, состоящий из 4 значений. mgn_result = [0,0,0,0]

 mgn_result = magnetometer_request_raw(num) 

Первое значение списка возвращает информацию об ошибке. Если возвращено значение 0,то ошибки нет, если 1, то датчик не соединен, если 2, то ошибка в программе. В программе использован оператор цикла for i in range(1000) который будет выполнен 1000 раз, соответственно будет выведено 1000 значений. Эти значения понадобятся на следующем уроке при калибровке магнитометра.

lesson5.txt · Последние изменения: 2019/05/14 11:15 — golikov

Инструменты страницы