В предыдущем посте мы обсуждали возможность добавления расширения для универсальных проектов и сделали краткий обзор по классам GPIO. Сегодня я собираюсь продолжить обзор расширения IoT и обсудить I2C и его классы.
МЫ будем работать с датчиком MPU6050, который предоставляет данные из гироскопа и акселерометра. Эти данные очень полезны для людей, которые хотели бы создать свои собственные беспилотные летательные аппараты (дроны) и вертолеты.
Этот датчик не требует какой-либо пайки и содержит преобразователь напряжения (с 5V до 3,3V) (чип 6050 использует питание 3,3V), что позволяет использовать питание от ESC или других плат с выводом в 5V.
Для общения MPU 6050 использует I2C концентратор. Таким образом, для того, чтобы подготовить датчик к работе, необходимо подключить 5V и GND контакты к VCC на Raspberry и GND на датчике. Кроме того, вы должны подключить SDA и SCL контакты. У этого датчика нет светодиодов, поэтому непросто понять все ли в порядке. Так что самый простой способ проверить работает он или нет — начать разработку.
Все необходимые классы вы можете найти в пространстве имен Windows.Devices.I2c и первый из них — это I2cDevice. Каждое устройство, к которому вы подключаетесь используя концентратор I2C, должно быть связано с объектом класса I2cDevice и только благодаря этому объекту разработчики могут общаться с устройством. Наиболее распространенные методы это Read и Write, которые работают с массивом байтов для получения или отправления данных. Но в большинстве случаев вам необходимо не просто так отправить данные на устройство, а отправить их с целью получения определенного ответа. Для того чтобы избежать вызова двух методов, в классе I2CDevice есть метод WriteRead. Он принимает два параметра в виде массива байтов. Первый массив содержит данные, которые вы собираетесь отправить на устройство, второй — буфер для данных из устройства.
Благодаря классу I2cDevice легко обмениваться данными с устройствами, но для того, чтобы получить ссылку на объект I2cDevice, вам нужно выполнить несколько задач.
Прежде всего, вам необходимо получить ссылку на I2C устройства. Microsoft использует тот же подход, что и для всех других устройств, таких как Bluetooth, WiFi и т.п. Вы должны использовать понятное имя для создания строки запроса для устройства и попытаться его найти. Метод GetdeviceSelector класса I2cDevice позволяет создать строку запроса. Для того, чтобы найти информацию о существующем устройстве вы должны использовать метод FindAllAsync класса DeviceInformation. Этот метод возвращает информацию о доступных I2C устройствах и вы можете использовать эту информацию для того, чтобы создать объект класса I2cDevice. На следующем шаге необходимо создать строку подключения к датчику. Это можно легко сделать с помощью класса I2cConnectionString. Если у вас есть информация об устройстве I2C и строка подключения внешнего устройства/датчика — можно создать объект, используя метод FromIdAsync класса I2cDevice.
Таким образом, для моего MPU 6050я создал следующий код:
class MPU6050 { //I2C address private const byte MPUAddress = 0xD2>>1; private I2cDevice mpu5060device; public async Task BeginAsync() { string advanced_query_syntax = I2cDevice.GetDeviceSelector("I2C1"); DeviceInformationCollection device_information_collection = await DeviceInformation.FindAllAsync(advanced_query_syntax); string deviceId = device_information_collection[0].Id; I2cConnectionSettings mpu_connection = new I2cConnectionSettings(MPUAddress); mpu_connection.BusSpeed = I2cBusSpeed.FastMode; mpu_connection.SharingMode = I2cSharingMode.Shared; mpu5060device = await I2cDevice.FromIdAsync(deviceId, mpu_connection); mpuInit(); } }
метод mpuInit отправляет начальные значения датчика (опишу его ниже). По документации MPUAddress должен быть 0xD2, но мы должны взять только 7 бит данного значения, поэтому я сместил значение на один бит вправо.
После того, как у нас появится объект класса I2cDevice, мы можем начать работать с устройством. Это не так то просто, так как у MPU 6050 есть множество регистров и вы должны понимать большинство из них. Кроме того, вы должны инициализировать датчик, чтобы получить значения. Давайте рассмотрим несколько регистров:
- 0x6B — управление питанием. Можно устанавливать различные настройки, относящиеся к режиму питания, но самый важный бит под номером семь. Благодаря ему вы можете установить датчик в исходное состояние;
- Данные акселерометра — 0x3B — 0x40. Есть 6 байт, которые содержат данные для осей х, у и z. Для каждой оси — 2 байта данных;
- 0x41 — 0x42 — два байта, которые представляют температуру;
- 0x43 — 0x48 — 6 байт для данных гироскопа (подобно акселерометру);
Таким образом, вы можете использовать метод mpuInit для настройки начального состояния датчика. Например, вы можете сбросить данные датчика с помощью следующей команды:
mpu5060device.Write(new byte[] { 0x6B, 0x80 });
Для того, чтобы измерить что-то — используйте метод WriteRead. Что бы не городить кучу кода, в качестве примера работы с датчиками, я покажу как измерить температуру. Для этого вы можете использовать следующий код:
byte mpuRegRead(byte regAddr)< { byte[] data=new byte[1]; mpu5060device.WriteRead(new byte[] { regAddr },data); return data[0]; } public double mpuGetTemperature() { double temperature; short calc = 0 byte []data = new byte[2]; data[0] = mpuRegRead(MPU_REG_TEMP_OUT_H);//0x41 data[1] = mpuRegRead(MPU_REG_TEMP_OUT_L);//0x42 calc = (short)((data[0] << 8) | data[1]); temperature = (calc / 340.0) + 36.53; return temperature; }
Позже я опубликую ссылку на дополнительные классы для работы с остальными сенсорами, написанные на C#.
Ссылка на источник: Windows 10: How to use IoT extension for Raspberry Pi 2 (part 2)
Добавить комментарий