Здесь показаны различия между двумя версиями данной страницы.
lesson5 [2020/02/27 15:58] golikov |
lesson5 [2020/03/25 16:28] |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
- | ====== 05 Урок. Получение сырых данных с магнитометра. ====== | ||
- | |||
- | ===== Знакомство с магнитометром смартфона ===== | ||
- | Почти в каждом современном смартфоне установлен магнитометр, давайте познакомимся с ним. Установите в смартфон приложение для визуализации данных, полученных со встроенного магнитометра, например, MagnetMeter. | ||
- | |||
- | {{::05image001.png?nolink&400|}} | ||
- | |||
- | Откройте приложение – вы увидите синюю стрелку, которая показывает направление силовых линий магнитного поля. | ||
- | |||
- | {{:05image003.png?nolink&200|}} | ||
- | |||
- | Вращайте смартфон и убедитесь, что магнитные линии направлены всегда в одну сторону – почти на север. | ||
- | На показания магнитометра кроме поля Земли влияют и другие магнитные поля. Убедитесь в этом приблизив магнит к смартфону. Перемещая магнит около смартфона определите точное место установки магнитометра в корпусе смартфона. | ||
- | |||
- | {{::05image004.png?nolink&200|}} | ||
- | |||
- | Обратите внимание на величину напряженности магнитного поля Земли и поля вблизи магнита. | ||
- | |||
- | ===== Проверка работоспособности магнитометра Орбикрафт===== | ||
- | |||
- | Соедините БКУ с СЭП и магнитометром. | ||
- | |||
- | Не прикрепляйте магнитометр к пластине, чтобы его было удобно вращать. Загрузите программу в БКУ и запустите ее. | ||
- | |||
- | Код на Python. | ||
- | <file 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) | ||
- | </file> | ||
- | |||
- | Код на С. | ||
- | <file c 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);//Выключение магнитометра | ||
- | |||
- | } | ||
- | </file> | ||
- | |||
- | |||
- | Запустите программу и посмотрите на значения, которые она выдает. Если магнитометр не вращать, то значения не изменяются. Если его вращать, то значения будут изменяться. | ||
- | Если вращать магнитометр вокруг одной из осей, то преимущественно будет изменяться одно из трех числовых значений, другие два будут изменяться в меньшей степени. | ||
- | Поднесите к магнитометру магнит и посмотрите, как изменяются значения при движении магнита у неподвижного магнитометра. | ||
- | |||
- | ===== Получение азимута с магнитометра ===== | ||
- | |||
- | Распечатайте транспортир (шаблон в файле Transportir.pdf), приклейте его к столу с помощью клеящих подушечек, не оставляющих следов (аналог UHU patafix), приклейте магнитометр на линейку аналогичным способом. | ||
- | |||
- | {{::05image005.png?nolink&200|}} | ||
- | |||
- | Загрузите в БКУ следующую программу, которая произведет 60 измерений с шагом в 1 сек. | ||
- | |||
- | |||
- | Код на Python. | ||
- | <file python azimuth.py> | ||
- | |||
- | import math | ||
- | time_step = 1 # Временной шаг измерений, сек | ||
- | mag_num = 1 # Номер магнитометра | ||
- | def control(): # основная функция программы | ||
- | print "Enable magnetometer", mag_num | ||
- | magnetometer_turn_on(mag_num) | ||
- | sleep(10) | ||
- | mag_state = 0 # Инициализируем статус магнитометра | ||
- | alpha_goal = 0 # Целевой угол | ||
- | omega_goal = 0 # Целевая угловая скорость | ||
- | for i in range(12): | ||
- | 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) | ||
- | |||
- | </file> | ||
- | |||
- | Код на С. | ||
- | <file c 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 = 10; | ||
- | 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 < 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, 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); | ||
- | } | ||
- | </file> | ||
- | |||
- | Поворачивайте магнитометр с шагом в 30 градусов и записывайте выдаваемое значение угла в таблицу EXCEL. Должна получится примерно вот такая таблица с данными. | ||
- | |||
- | {{:05_image_101.png?nolink&200|}} | ||
- | |||
- | ===== Анализ данных в Excel ===== | ||
- | |||
- | Обратите внимание, при повороте на 30 градусов значение угла, выдаваемое магнитометром изменяется не ровно на 30 градусов. Давайте вычислим эти значения средствами EXCEL. | ||
- | |||
- | ==== Создание таблицы ==== | ||
- | |||
- | Создайте новый столбец, который будет содержать разность соседних чисел. Введите в пустую ячейку С2 знак равенства, а затем кликните мышкой в ячейку В1, введите знак «-», а затем кликните в ячейку В2 и нажмите Enter. | ||
- | |||
- | {{::05_image007.png?nolink&200|}} | ||
- | |||
- | В ячейке С2 будет вычислена разность В1-В2. Протяните вниз уголок — формула автоматически скопируется во все нижние ячейки. | ||
- | |||
- | {{::05_image008.png?nolink&200|}} | ||
- | |||
- | Разности будут вычислены автоматически. | ||
- | |||
- | {{::05image009.png?nolink&200|}} | ||
- | |||
- | Обратите внимание, значение -326 явно ошибочное. При переходе через значение 180 градусов изменился знак измеренного угла, следовательно вместо -326 нужно внести значение (180-155) сложенное со значением (180-171). Получится 25+9=34. Введите вместо -326 значение 34. | ||
- | |||
- | ==== Построение диаграмм ==== | ||
- | |||
- | Теперь нужно построить график чтобы наглядно увидеть искажения, вносимые в измерение угла некалиброванным магнитометром. Выделите вычисленные значения разностей. | ||
- | |||
- | {{::05_image010.png?nolink&200|}} | ||
- | |||
- | Нажмите **Вставка** и выберите круговую диаграмму. | ||
- | |||
- | {{::05image011.png?nolink&200|}} | ||
- | |||
- | {{::05image012.png?nolink&200|}} | ||
- | |||
- | Кликните правой кнопкой мышки в цветной круг и выберите белый цвет заливки и черный цвет контура. | ||
- | |||
- | {{::05image014.png?nolink&200|}} | ||
- | |||
- | {{::05image015.png?nolink&200|}} | ||
- | |||
- | Теперь невооруженным глазом видно, что магнитометр далек от идеала — сектора круга не ровно по 30 градусов. Некоторые уже, а некоторые шире. | ||
- | |||
- | {{::05_image016.png?nolink&200|}} | ||
- | |||
- | Давайте построим еще один график, который наглядно проиллюстрирует неидеальность магнитометра. Выделите вычисленные значения разностей. | ||
- | Нажмите **Вставка** и выберите лепестковую диаграмму. | ||
- | |||
- | {{::05image017.png?nolink&200|}} | ||
- | |||
- | {{::05image018.png?nolink&200|}} | ||
- | |||
- | Теперь очень хорошо видно, что значения далеки от идеального 12 угольника радиусом 30. | ||
- | |||
- | |||
- | {{:2_1.gif?direct|}} | ||
- | |||
- | ==== Анализ данных с помощью функций ==== | ||
- | |||
- | А теперь давайте вычислим среднее значение разности между измеренными углами с использованием функции EXCEL СРЗНАЧ. | ||
- | Выберите любую ячейку, введите знак равенства, имя функции и откройте скобку. | ||
- | |||
- | {{::05image019.png?nolink&200|}} | ||
- | |||
- | Затем выберите мышкой диапазон вычисленных значение разностей, на основе которого мы строили диаграммы и закройте скобку. Функция будет иметь такой вид =СРЗНАЧ(C2:C13). | ||
- | Нажмите Enter, и функция вычислит среднее значение указанных чисел. | ||
- | А теперь давайте вычислим стандартное отклонение вычисленных разностей от среднего значения, которое покажет величину разброса значений относительно среднего. Для этого используем функцию СТАНДОТКЛОНА. | ||
- | Выберите любую ячейку, введите знак равенства, имя функции и откройте скобку. | ||
- | |||
- | |||
- | {{::05image020.png?nolink&200|}} | ||
- | |||
- | Затем выберите мышкой диапазон вычисленных значение разностей, на основе которого мы строили диаграммы и закройте скобку. | ||
- | Функция будет иметь такой вид =СТАНДОТКЛОНА(C2:C13). | ||
- | Нажмите Enter, и функция вычислит стандартное отклонение вычисленных разностей от среднего значения. | ||
- | Теперь вычислите процентное соотношение среднего значения и стандартного отклонения. | ||
- | |||
- | |||
- | {{::05image021.png?nolink&200|}} | ||
- | |||
- | {{::05image022.png?nolink&200|}} | ||
- | |||
- | Как видите, разброс очень велик и составляет 17% от среднего значения. | ||
- | Магнитометр необходимо откалибровать. | ||
- | |||
- | ===== Получение сырых данных для калибровки магнитометра ===== | ||
- | |||
- | По умолчанию магнитометр не откалиброван, т.е. выдает неточные значения. Уточненные значения можно получить из сырых данных путем калибровки, которая заключается в нахождении матрицы преобразования и вектора смещения. Сырые данные с магнитометра можно получить, выполнив код на языке Python, представленный ниже. Во время сбора данных магнитометр необходимо хаотично вращать, стараясь повернуть его во все возможные стороны. | ||
- | |||
- | Код на Python. | ||
- | <file 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) #Выключение магнитометра | ||
- | </file> | ||
- | |||
- | Код на С. | ||
- | <file c 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 < 500; 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); | ||
- | } | ||
- | </file> | ||
- | |||
- | Соедините БКУ с СЭП и магнитометром. Не прикрепляйте магнитометр к пластине, чтобы его было удобно вращать. Загрузите программу в Орбикрафт и запустите ее. Хаотично вращайте магнитометр, чтобы собрать сырые данные со всех возможных вариантов его ориентации. | ||
- | Сохраните полученные данный в файл с расширением txt. Для этого выделите все результаты с помощью Ctrl+A и скопируйте с помощью Ctrl+C и сохраните. | ||
- | |||
- | ==== Анализ работы программы ==== | ||
- | |||
- | В программе используются следующие функции работы с магнитометром. | ||
- | <code python> magnetometer_turn_on(num) </code> – функция включения магнитометра, где num – это номер магнитометра. | ||
- | |||
- | <code python> magnetometer_request_raw(num) </code> – функция возвращающая сырые данные измеренные магнитометром с номером num, представляющие собой список из 4 числовых значений. | ||
- | Поэтому считанные данные мы помещаем в список mgn_result, состоящий из 4 значений. | ||
- | mgn_result = [0,0,0,0] | ||
- | <code c>mgn_result = magnetometer_request_raw(num) </code> | ||
- | Первое значение списка возвращает информацию об ошибке. Если возвращено значение 0,то ошибки нет, если 1, то датчик не соединен, если 2, то ошибка в программе. | ||
- | В программе использован оператор цикла <code c>for (i = 0; i < 500; i++)</code> который будет выполнен 500 раз, соответственно будет выведено 500 значений. | ||
- | Эти значения понадобятся на следующем уроке при калибровке магнитометра. | ||
- | |||
- | |||