Оглавление |
---|
Информация | ||
---|---|---|
| ||
|
Основная информация
Предупреждение | ||
---|---|---|
| ||
Если на |
акселерометр на устройстве работает корректно, то его калибровать не требуется. |
Для настройки акселерометра требуется создать правило udev, определяющее привязку данных, получаемых от акселерометра, к осям координат устройства. Эта привязка может быть представлена в виде таблицы (матрицы) 3х3, содержащей коэффициенты коррекции для данных, получаемых от акселерометра.
За взаимодействие с датчиком поворота отвечает IIO подсистема ядра Linux, в частности утилита iio-sensor-proxy - https://gitlab.freedesktop.org/hadess/iio-sensor-proxy/#iio-sensor-proxy.
Ниже представлена таблица, содержащая в себе матрицу, используемую для калибровки экрана (Подробнее см.: https://gitlab.freedesktop.org/hadess/iio-sensor-proxy/#accelerometer-orientation).
Голубым отмечены заголовки строк и столбцов, относительно которых в дальнейшем будет производится калибровка.
Красным в таблице отмечены участки, которые не нужно редактировать (не участвуют в калибровке).
x | y | z | |
(1) | x1 | y1 | z1 |
(2) | x2 | y2 | z2 |
(3) | x3 | y3 | z3 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*", ENV{ACCEL_MOUNT_MATRIX}="x1,y1,z1;x2,y2,z2;x3,y3,z3" |
По умолчанию, iio-sensor-proxy принимает использует такую (единичную) матрицу:
x | y | z | |
(1) | 1 | 0 | 0 |
(2) | 0 | 1 | 0 |
(3) | 0 | 0 | 1 |
Значения интерпретируется в виде udev правила следующим образом:
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*", ENV{ACCEL_MOUNT_MATRIX}="1,0,0;0,1,0;0,0,1" |
Для калибровки экрана, необходимо изменять значения данной таблицы. Алгоритмы, по которым происходит калибровка, описаны далее в настоящей статье.
Настройка акселерометра: проверка наличия целевой матрицы
Целевая матрица используется для калибровки датчика поворота. По умолчанию, она должна находится в описании устройств из ACPI - Advanced Configuration and Power Interface (см.: https://ru.wikipedia.org/wiki/ACPI).
Для проверки наличия целевой матрицы устройства, необходимо получить DSL дамп (описание устройств из ACPI), путем вызова следующих команд:
Блок кода | ||||
---|---|---|---|---|
| ||||
cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
iasl -d dsdt.dat
iasl -tc dsdt.dsl |
iasl - Intel ACPI компилятор/декомпилятор, используется для работы с ACPI и не только, подробнее см.: https://linux.die.net/man/1/iasl.
вызов iasl -d dsdt.dat
дизассемблирует dsdt.dat в dsdt.dsl (формат ASL)ASL - ACPI Source Language, исходный язык для определения и написания методов ACPI, см.: https://wiki.osdev.org/AML.
В полученном файле (dsdt.dsl) необходимо найти матрицу по умолчанию:
- Если известны DEVDEVICE_ID/VENVENDOR_ID, необходимо найти данное устройство
- Затем у устройства необходимо найти метод ROTM (Rotation Matrix).
В случае, если целевая матрица не была обнаружена - необходимо перейти к другому способу калибровки, описанному в п.3.
Рассмотрим пример для планшета Lenovo IdeaPad 3IGL5-LTE:
Блок кода | ||||
---|---|---|---|---|
| ||||
Method (ROTM, 0, NotSerialized) { Name (RBUF, Package (0x03) { "0 -1 0", "1 0 0", "0 0 1" }) Return (RBUF) /* \_SB_.PCI0.I2C5.DEV_.ROTM.RBUF */ } |
Отсюда мы видим, что исходная целевая матрица для данной модели:
x | y | z | |
(1) | 0 | -1 | 0 |
(2) | 1 | 0 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*", ENV{ACCEL_MOUNT_MATRIX}="0,-1,0;1,0,0;0,0,1" |
В случае если полученная матрица некорректно откалибровала устройство, необходимо произвести калибровку по алгоритму, приведенному ниже (п.3).
Настройка акселерометра: калибровка при помощи udev правила
- Определить желаемое нормальное положение устройства (портретная либо альбомная ориентация). Нормальное положение зависит от нужд пользователя. За нормальное можно принять любое положение, и отталкиваясь от этого, проводить настройку. Можно также в качестве нормальной использовать ориентацию, в которой отображается экран при включении устройства (для планшетов iRU, например, это альбомный режим);
- Если режим отображения экрана не соответствует положению устройства, то определить, на сколько нужно осуществить поворот изображения для приведения его в правильное положение, и выполнить указанные далее изменения элементов матрицы для получения нужного режима отображения экрана.
Настройка акселерометра: применение единичной матрицы
Первым шагом необходимо задать начальную (единичную) матрицу в виде udev правила, помещенного в файл /etc/udev/rules.d/99-astra-orientation.rules (все дальнейшие действия по калибровке экрана будут сводится к его редактированию этого файла):
x | y | z | |
(1) | 1 | 0 | 0 |
(2) | 0 | 1 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||
---|---|---|
| ||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*", ENV{ACCEL_MOUNT_MATRIX}="1,0,0;0,1,0;0,0,1" |
Для применения правил необходимо перезагрузить устройство (можно упомянуть вариант с тригеррами и прочим, но у меня после этого не всегда нормально работает гироскоп, перезагрузить надежнее).
Настройка акселерометра: определение необходимого нормального положения устройства
После того, как была применена начальная матрица, необходимо выяснить, на сколько (градусов?) нужно сколько градусов нужно осуществить поворот изображения, для приведения его в правильное положение.
Все дальнейшие изменения по повороту применимы только к начальной (единичной) матрице (п. 3.1).
Настройка акселерометра: поворот
устройстваизображения на 90° по часовой стрелке
Исходная матрица:
x | y | z | |
(1) | 1 | 0 | 0 |
(2) | 0 | 1 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="1,0,0;0,1,0;0,0,1" |
Вычисления:
x | y | z | |
(1) | cos (90) | -1 * sin (90) | 0 |
(2) | sin (90) | cos (90) | 0 |
(3) | 0 | 0 | 1 |
Результирующая матрица:
x | y | z | |
(1) | 0 | -1 | 0 |
(2) | 1 | 0 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="0,-1,0;1,0,0;0,0,1" |
Настройка акселерометра: поворот
устройстваизображения на 180° по часовой стрелке
Исходная матрица:
x | y | z | |
(1) | 1 | 0 | 0 |
(2) | 0 | 1 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="1,0,0;0,1,0;0,0,1" |
Вычисления:
x | y | z | |
(1) | cos (180) | -1 * sin (180) | 0 |
(2) | sin (180) | cos (180) | 0 |
(3) | 0 | 0 | 1 |
Результирующая матрица:
x | y | z | |
(1) | -1 | 0 | 0 |
(2) | 0 | -1 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="-1,0,0;0,-1,0;0,0,1" |
Настройка акселерометра: поворот
устройстваизображения на 270° по часовой стрелке
Исходная матрица:
x | y | z | |
(1) | 1 | 0 | 0 |
(2) | 0 | 1 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="1,0,0;0,1,0;0,0,1" |
Вычисления:
x | y | z | |
(1) | cos (270) | -1 * sin (270) | 0 |
(2) | sin (270) | cos (270) | 0 |
(3) | 0 | 0 | 1 |
Результирующая матрица:
x | y | z | |
(1) | 0 | 1 | 0 |
(2) | -1 | 0 | 0 |
(3) | 0 | 0 | 1 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="0,1,0;-1,0,0;0,0,1" |
Настройка акселерометра: определение необходимости инвертирования
Если после выполнения п. 3.2 получилось инверсия какого либо из режимов просмотра (инвертированный альбомный/портретный режим), необходимо произвести инверсию относительно Y координат. (п. 3.3.1).
В случае, если после применение инверсии желаемый результат не был достигнут, необходимо вернуть матрицу, полученную из п. 3.2.х, и произвести инверсию относительно X координат (п. 3.3.2).
Настройка акселерометра: инвертирование Y координаты
Для инверсии
в качестве исходной матрицы необходимо брать матрицу, полученную после поворота (из п. 3.2.х).
x | y | z | |
(1) | x1 | y1 | z1 |
(2) | x2 | y2 | z2 |
(3) | x3 | y3 | z3 |
Для выполнения инверсии
необходимо каждую Y
координату (из тех, которые участвуют в калибровке) умножить на -1, т. е.:
- y1 * -1;
- y2 * -1.
Таким образом,
результирующей матрицей будет:
x | y | z | |
(1) | x1 | y1 = -1 * y1 | z1 |
(2) | x2 | y2 = -1 * y2 | z2 |
(3) | x3 | y3 | z3 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*", ENV{ACCEL_MOUNT_MATRIX}="x1,-y1,z1;x2,-y2,z2;x3,y3,z3" |
Настройка акселерометра: инвертирование X координаты
Для инверсии, в качестве исходной матрицы необходимо брать матрицу, полученную после поворота (из п. 3.2.х).
x | y | z | |
(1) | x1 | y1 | z1 |
(2) | x2 | y2 | z2 |
(3) | x3 | y3 | z3 |
Для выполнения инверсии
необходимо
каждую X координату (из тех, которые участвуют в калибровке) умножить на -1, т. е.:
- x1 * -1;
- x2 * -1.
Таким образом,
результирующей матрицей будет:
x | y | z | |
(1) | x1 = -1 * x1 | y1 | z1 |
(2) | x2 = -1 * x2 | y2 | z2 |
(3) | x3 | y3 | z3 |
Блок кода | ||||
---|---|---|---|---|
| ||||
ENV{IIO_SENSOR_PROXY_TYPE}=="*accel*",
ENV{ACCEL_MOUNT_MATRIX}="-x1,y1,z1;-x2,y2,z2;x3,y3,z3" |
Настройка акселерометра: настройка частоты опроса датчика
на примере (МИГ т8х)TODOповорота (МИГ Т8х)
Для снижения чувствительность (частоты опроса) датчика поворота, на планшете МИГ Т8х необходимо выполнить следующие действия:
- Получить минимально возможное значение из файла /sys/bus/iio/devices/iio:device0/in_accel_sampling_frequency_available
- Обновить значение на полученное минимальное путем редактирования файла /sys/bus/iio/devices/iio:device0/in_accel_sampling_frequency
У данного подхода есть недостаток, после перезагрузки датчик не запоминает измененное значение.
Ниже будет перечислен порядок действий, необходимый для того, чтобы система могла автоматически устанавливать минимальную частоту обновления датчика.
Блок кода | ||||
---|---|---|---|---|
| ||||
sudo mkdir /etc/mig
sudo touch /etc/mig/mig-t8x-accel-sampling-freq-fix.sh |
Далее, в файл /etc/mig/mig-t8x-accel-sampling-freq-fix.sh скопировать следующее:
Блок кода | ||||
---|---|---|---|---|
| ||||
SET_FREQ_FILE="/sys/bus/iio/devices/iio:device0/in_accel_sampling_frequency"
AV_FREQ_FILE="/sys/bus/iio/devices/iio:device0/in_accel_sampling_frequency_available"
freqLine=$(cat $AV_FREQ_FILE)
minFreq=0
for freq in $freqLine
do
minFreq=$freq
break
done
echo $minFreq > $SET_FREQ_FILE |
Теперь необходимо создать сервис:
Блок кода | ||||
---|---|---|---|---|
| ||||
sudo touch /etc/systemd/system/mig-t8x-accel-sampling-fix.service
sudo chmod 644 /etc/systemd/system/mig-t8x-accel-sampling-fix.service |
Далее, в созданный файл скопировать следующее:
Блок кода | ||||
---|---|---|---|---|
| ||||
[Unit]
Description=Fix accel sampling frequency for MIG T8x
[Service]
Type=simple
ExecStart=/bin/bash /etc/mig/mig-t8x-accel-sampling-freq-fix.sh
[Install]
WantedBy=multi-user.target |
После сохранения файла, необходимо активировать сервис:
Блок кода | ||||
---|---|---|---|---|
| ||||
sudo systemctl enable mig-t8x-accel-sampling-fix.service |
Теперь после перезагрузки системы датчик будет автоматически настраиваться на минимальную частоту обновления.
Ниже прикреплен сценарий автоматически выполняющий все предыдущие шаги: generate_mig-t8x-fix-accel-sampling-frequency.sh