- PVSM.RU - https://www.pvsm.ru -

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test)

Изучая спецификацию (datasheet) на МЕМС-датчик (акселерометр, гироскоп и проч.) мы сталкиваемся с такой процедурой, как самопроверка (self-test) или самодиагностика. Обычно в спецификациях есть описание, как это делать. Кому интересно: что это и как это правильно делать? — добро пожаловать под кат.

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 1

Введение

Самопроверка позволяет определить, что данные с датчика показывают то, что должны показывать. Датчики не всегда имели режим самодиагностики. Чтобы определить соответствие измеряемых данных тому, что указано в спецификации, разработчик должен был проверять это специальными экспериментами. В случае акселерометра — совершать наклоны на определённые углы и снимать изменение показаний. Анализируя результаты, можно было оценить погрешность, выдаваемую датчиком. Если показатели не соответствовали спецификации, датчик признавался бракованным.

Это усложняло массовое производство и во все датчики стали включать процедуру самодиагностики. Замысел процедуры достаточно прост — создать условия, при которых мы будем знать, что должен показывать датчик, и сравнить с тем, что он показывает. Отклонения выше заданных забраковывают датчик. Для компасов делают элемент, создающий магнитное поле (прямо в корпусе датчика). Включение режима самодиагностики включает этот элемент — эталонный источник. Для акселерометра и гироскопа элемент генерирует электростатическое поле, которое отклоняет грузик (см. фото ниже) и имитирует физическое движение или вращение. Величина смещения известна, соответственно известна величина, которую должен показать датчик. Если погрешность снятых показаний в заявленных пределах — значит с датчиком всё в порядке и он работает в соответствии со спецификацией.

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 2
(статья из интернет-журнала, откуда я позаимствовал картинку содержит ещё много красивых увеличенных фоток, ссылки см. внизу)

1. Влияние на самопроверку внешних сил

Рассмотрим акселерометр. Как указано ранее, в режиме самодиагностики на микромеханический грузик воздействует электростатическая сила, отклоняющая его на определённое расстояние, и имитирующая тем самым ускорение. Однако ожидаемую величину на выходе датчика мы не увидим. Дело в том, что в спокойном состоянии на грузик действуют другие силы (напр. сила тяжести). Они дополнительно отклоняют грузик.

Для того, чтобы учесть внешние силы, в процедуре самопроверки снимаются показания датчика в обычном режиме. Затем включается источник отклонения (переход в режим «самопроверка») и снова снимаются показания датчика.

aнорм = aвнешние
aST = aвнешние + aвнутр. ист.

Разница показаний этих двух режимов должна показывать величину с эталонного источника. Если величина находится в допустимом спецификацией диапазоне, то это значит, что датчик работает должным образом.

aвнутр. ист. = aST — aнорм
MIN < aвнутр. ист. < MAX

Отсюда важный вывод — внешние силы в обоих режимах должны быть равны. Т. е. датчик должен быть неподвижен. Когда устройство в руках — оно подвижно. Когда вы что-то нажимаете (или заканчиваете нажимать) на устройстве — оно тоже подвижно. Если на устройство действует вибрация — оно подвижно. И так далее.

2. Что ещё нужно учитывать при проведении самопроверки?

При проведении самопроверки датчика также необходимо учитывать:

  • При переключении датчика в режим измерений, может потребоваться некоторое количество времени для того, чтобы акселерометр стал готов для сбора данных. Время уточнять в спецификации.
  • Проведение самодиагностики желательно проводить в различных измеряемых диапазонах датчика (2G, 4G, и т. п.).
  • Иногда возможно инверсионное включение эталонного источника (может тянуть в одну или в другую сторону). В спецификации тогда будет указано два режима самопроверки (например «Self-test P(ositive)» и «Self-test N(egative)»).

3. Как найти величину отклонения грузика эталонным источником?

Величины отклонения грузика эталонным источником по осям:

  • Могут быть указаны явно в спецификации.
  • Может быть указан широкий диапазон возможных значений. Принцип тот же — если полученная разница aвнутр. ист. попадает в этот диапазон, то датчик в порядке. Нужно только понимать, что такой подход практикуется не для самых точных датчиков.
  • Значения могут храниться в специальных регистрах (что-нибудь вроде «SELF_TEST_X_ACCEL»). Это значит производитель уточнил величины отклонения для каждого конкретного датчика и положил в его память. Производитель может сэкономить память и записать не значение, а коэффициент формулы, с помощью которой можно рассчитать значение. Сам метод расчёта тогда будет в спецификации или в одном из её приложений.

Величина отклонения обычно указывается в условных единицах датчика — LSB. Это то, что в выходном регистре лежит. Рассмотрим значения, которые даёт внутренний источник датчика LIS302DL (датчик 8-мибитный):

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 3

Он интересен тем, что как раз содержит два режима работы внутреннего источника. Глядя в таблицу можно подумать, что значения приведены для обоих направлений внутреннего источника. Однако на самом деле это расширенный диапазон для одного направления — «Self test P». Обычно направление одно и значения указывают так:

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 4

Либо могут указать в измеряемых единицах:

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 5

Чтобы из значений датчика получить измеряемую величину, нужно воспользоваться формулой:
Величина_в_единицах_измерения = Значение_в_LSB * Чувствительность.

Чтобы перевести измеряемую величину обратно в единицы датчика, нужно воспользоваться формулой:
Значение_в_LSB = Величина_в_единицах_измерения / Чувствительность.

Чувствительность в спецификациях пишут так:

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 6

или так

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 7

Можно чувствительность посчитать самостоятельно:
Чувствительность = Измеряемый_диапазон / разрешение

Пример: Величина_LSB = Величина_измеряемая * Разрешение / Измеряемый_диапазон = 8 * 0,001 * g * 65536 / 4 * g = 131,072, т. е. ±131.

4. Как понять, что величина находится в допустимом диапазоне?

Допустимый диапазон может быть указан несколькими способами:

  • Может быть явно указан минимум и максимум.
  • Может быть указан в виде допустимого процента отклонения (например где-нибудь в сноске).
  • По идее должен быть не больше уровня шума.

Уровень шума обычно указывают через среднеквадратичное отклонение (RMS). Диапазон погрешности будет тогда равен удвоенному среднеквадратичному отклонению (±). Примеры:

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 8

Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 9

В первом примере применена неизвестная мне единица измерения, кто знает как это перевести в mg, пишите в комментарии (то что в числителе микро-ж, это понятно, а что в знаменателе?). В последнем примере максимальный уровень шума = 8 * 0,001 * g = 0,0784 м/с2. Значит возможный разбег величины самопроверки = ±0,0784 м/с2. Здесь тоже нужно быть внимательным, т. к. иногда уровень шума указывают с включенным фильтром. Это значит, что замеры нужно делать с теми же настройками фильтра.

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

Пример кода самопроверки LSM303D

	uint8_t sign = lsm303d_read(LSM303D_ADDR_WHO_AM_I);
	if (sign != LSM303D_WHO_I_AM)
	{
		//on_fatal_error("Нет сигнала с LSM303D");
	}

	lsm303d_write(LSM303D_ADDR_CTRL_REG1,
			LSM303D_REG1_RATE_100HZ_A |
			LSM303D_REG1_X_ENABLE_A  |
			LSM303D_REG1_Y_ENABLE_A  |
			LSM303D_REG1_Z_ENABLE_A
			);

	delay_ms(100);

	uint8_t i;
	int32_t avg_x__norm = 0,
                avg_y__norm = 0,
		avg_z__norm = 0;
	vector v;

	// делаем 100 замеров в обычном режиме
	for (i = 0; i < 100; i++)
	{
		lsm303d_get_acc(&v);

		avg_x__norm += v.x;
		avg_y__norm += v.y;
		avg_z__norm += v.z;
	}

	avg_x__norm /= 100;
	avg_y__norm /= 100;
	avg_z__norm /= 100;

	// Включаем внутренний источник (режим "self-test")
	lsm303d_write(LSM303D_ADDR_CTRL_REG2,
			LSM303D_REG2_FULL_SCALE_2G_A |
			2
				);
	delay_ms(100);

	int32_t avg_x__st = 0,
		avg_y__st = 0,
		avg_z__st = 0;

	// делаем ещё 100 замеров
	for (i = 0; i < 100; i++)
	{
		lsm303d_get_acc(&v);

		avg_x__st += v.x;
		avg_y__st += v.y;
		avg_z__st += v.z;
	}

	avg_x__st /= 100;
	avg_y__st /= 100;
	avg_z__st /= 100;
        
        // Выключаем внутренний источник
	lsm303d_write(LSM303D_ADDR_CTRL_REG2, 0);
	delay_ms(100);

	float internal_source_x, internal_source_y, internal_source_z; // mg

	internal_source_x = (avg_x__st - avg_x__norm)*0.061;
	internal_source_y = (avg_y__st - avg_y__norm)*0.061;
	internal_source_z = (avg_z__st - avg_z__norm)*0.061;
        
        if ((internal_source_x < 70.0) ||
            (internal_source_x >1700.0) ||
            (internal_source_y < 70.0) ||
            (internal_source_y >1700.0) ||
            (internal_source_z < 70.0) ||
            (internal_source_z >1700.0))
        {
            // detect problem
            draw_EraseScreen();
            draw_TextOut(0,0,"problem..");
            draw_Show();
        }
        else
        {
            draw_EraseScreen();
            draw_TextOut(0,0,"ok");
            draw_Show();
        }

        while(1);

В одном положении получились такие результаты:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 10

Затем плату с датчиком положил на бок и получил такие результаты:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 11

Разбег значений получился 11, 2 и 5 g * 10-3. Если провести ещё несколько испытаний, то можно уточнить диапазон для конкретно этого датчика:
380 < X < 410
370 < Y < 390
680 < Z < 700

Пример кода самопроверки LIS302DL

	uint8_t dev_id = lis302dl_read(0x0F);
	if (dev_id != 0x3b)
	{
		while(1); // ошибка
	}
        
        lis302dl_write(0x20,
            7 | // включить все оси
            // 100 Гц и диапазон 2G 
            (1 << 6) // включить
                      );

	delay_ms(100);

	uint8_t i;
	int32_t avg_x__norm = 0,
                avg_y__norm = 0,
		avg_z__norm = 0;

	// делаем 100 замеров в обычном режиме
	for (i = 0; i < 100; i++)
	{
		lis302dl_get_acc(&v);

		avg_x__norm += v.x;
		avg_y__norm += v.y;
		avg_z__norm += v.z;
	}

	avg_x__norm /= 100;
	avg_y__norm /= 100;
	avg_z__norm /= 100;

	// Включаем внутренний источник (режим "self-test P")
	lis302dl_write(0x20,
            7 | // включить все оси
            (1 << 4) | // self-test P
            // 100 Гц и диапазон 2G 
            (1 << 6) // включить
                      );
	delay_ms(100);

	int32_t avg_x__st = 0,
		avg_y__st = 0,
		avg_z__st = 0;

	// делаем ещё 100 замеров
	for (i = 0; i < 100; i++)
	{
		lis302dl_get_acc(&v);

		avg_x__st += v.x;
		avg_y__st += v.y;
		avg_z__st += v.z;
	}

	avg_x__st /= 100;
	avg_y__st /= 100;
	avg_z__st /= 100;
        
        // Выключаем внутренний источник
	lis302dl_write(0x20,
            7 | // включить все оси
            // 100 Гц и диапазон 2G  
            (1 << 6) // включить
                      );
	delay_ms(100);

	int32_t internal_source_x, internal_source_y, internal_source_z; // LSB

	internal_source_x = avg_x__st - avg_x__norm;
	internal_source_y = avg_y__st - avg_y__norm;
	internal_source_z = avg_z__st - avg_z__norm;
        
        if ((internal_source_x < -32) ||
            (internal_source_x > -3) ||
            (internal_source_y < 3) ||
            (internal_source_y > 32) ||
            (internal_source_z < 3) ||
            (internal_source_z > 32))
        {
            // detect problem
            draw_EraseScreen();
            draw_TextOut(0,0,"problem..");
            draw_Show();
        }
        else
        {
            draw_EraseScreen();
            draw_TextOut(0,0,"ok");
            draw_Show();
        }

        while(1);

В одном положении получились такие результаты:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 12

В другом положении такие результаты:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 13

Разбег значений получился в районе 1 единицы. А это второй режим работы внутреннего источника, когда он тянет в другую сторону (Self-test M):
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 14

Здесь мы видим показания другого датчика («Self-test P»):
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 15

И второй режим с поворотом платы («Self-test M»):
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 16

Согласно спецификации, он не проходит самопроверку — значения по оси Z выступают за заявленный предел: максимум 32, а мы имеем 35.

Пример кода самопроверки MPU9250

	delay_ms(100);

	uint8_t i;
	int32_t avg_x__norm = 0,
                avg_y__norm = 0,
		avg_z__norm = 0;

	// делаем 100 замеров в обычном режиме
	for (i = 0; i < 100; i++)
	{
		mpu9250_get_acc(&v);

		avg_x__norm += v.x;
		avg_y__norm += v.y;
		avg_z__norm += v.z;
	}

	avg_x__norm /= 100;
	avg_y__norm /= 100;
	avg_z__norm /= 100;

	// Включаем внутренний источник (режим "self-test")
	mpu9250_selftest(1);
	delay_ms(100);

	int32_t avg_x__st = 0,
		avg_y__st = 0,
		avg_z__st = 0;

	// делаем ещё 100 замеров
	for (i = 0; i < 100; i++)
	{
		mpu9250_get_acc(&v);

		avg_x__st += v.x;
		avg_y__st += v.y;
		avg_z__st += v.z;
	}

	avg_x__st /= 100;
	avg_y__st /= 100;
	avg_z__st /= 100;
        
        mpu9250_selftest(0); // отключаем внутренний источник смещения
        delay_ms(100);

        // считываю коэффициенты, по которым определим значения смещения, определённые заводом
        uint8_t factory_acc_kx = spi_read_byte(SELF_TEST_X_ACCEL) - 1;
        uint8_t factory_acc_ky = spi_read_byte(SELF_TEST_Y_ACCEL) - 1;
        uint8_t factory_acc_kz = spi_read_byte(SELF_TEST_Z_ACCEL) - 1;
        
        // считаю значения смещения, которые получились сейчас
        int32_t now_acc_dx = avg_x__st - avg_x__norm; // internal_source
        int32_t now_acc_dy = avg_y__st - avg_y__norm;
        int32_t now_acc_dz = avg_z__st - avg_z__norm;
        
        // определяем заводские значения смещения
        int32_t full_scale_acc_k = 0; // 2G
        int32_t factory_acc_dx = (int32_t)((2620.0 / (1 << full_scale_acc_k)) * pow(1.01, factory_acc_kx));
        int32_t factory_acc_dy = (int32_t)((2620.0 / (1 << full_scale_acc_k)) * pow(1.01, factory_acc_ky));
        int32_t factory_acc_dz = (int32_t)((2620.0 / (1 << full_scale_acc_k)) * pow(1.01, factory_acc_kz));
        
        // определяю процент разницы между заводскими значениями и полученными сейчас
        double acc_err_x = abs_double(100.0 - (100.0 * now_acc_dx) / factory_acc_dx);
        double acc_err_y = abs_double(100.0 - (100.0 * now_acc_dy) / factory_acc_dy);
        double acc_err_z = abs_double(100.0 - (100.0 * now_acc_dz) / factory_acc_dz);
        
        // спецификация допускает 3% отклонение
        if ((acc_err_x > 3.0) ||
            (acc_err_y > 3.0) ||
            (acc_err_z > 3.0))
        {
            // detect problem
            draw_EraseScreen();
            draw_TextOut(0,0,"problem..");
            draw_Show();
        }
        else
        {
            draw_EraseScreen();
            draw_TextOut(0,0,"ok");
            draw_Show();
        }
        
        while(1);

В одном положении получились такие результаты:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 17

В другом положении:
Самодиагностика МЕМС акселерометра, гироскопа и компаса (self test) - 18

В этом датчике успешность прохождения самопроверки определяется допустимым отклонением от эталонного значения. Допуск отклонения равен ±3% (стр. 9 первой части спецификации). Т. е. этот датчик в порядке.

Ссылки

  1. Интернет-журнал «EDN Network». Статья «The embedded self-test feature in MEMS inertial sensors. Jay Esfandyari, Gang Xu, Marco Capovilla, Paolo Bendiscioli, Marco Bianco -July 22, 2012». Ссылка [1].
  2. Интернет-журнал «3D News». Статья «MEMS: микроэлектромеханические системы, часть 1». Ссылка [2].
  3. Спецификация (datasheet) на датчик LIS3DH. Ссылка [3].
  4. Спецификация (datasheet) на датчик LIS302DL. Ссылка [4].
  5. Спецификация (datasheet) на датчик LSM303D. Ссылка [5].
  6. Спецификация (datasheet) на датчик MPU9250.

Автор: 1div0

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/diy-ili-sdelaj-sam/101262

Ссылки в тексте:

[1] Ссылка: http://www.edn.com/design/analog/4390843/1/The-embedded-self-test-feature-in-MEMS-inertial-sensors

[2] Ссылка: http://www.3dnews.ru/600098

[3] Ссылка: http://www.st.com/web/en/resource/technical/document/datasheet/CD00274221.pdf

[4] Ссылка: http://www.st.com/web/en/resource/technical/document/datasheet/CD00135460.pdf

[5] Ссылка: http://www.st.com/web/en/resource/technical/document/datasheet/DM00057547.pdf

[6] Источник: http://geektimes.ru/post/262780/