Датчик mpu 9250 это

Датчик mpu 9250 это Квадрокоптеры

2описание оптопары на микросхеме tlp281-4

Рассмотрим работу оптопары на примере микросхемы TLP281, а точнее её разновидности TLP281-4. Микросхема TLP281-4 имеет 4 канала. То есть у неё есть 4 управляющих ножки и 4 выходных ножки, к которым подключается полезная нагрузка.

Будем использовать для работы модуль HW-399. Выглядит он так, как показано на иллюстрации ниже. Рядом приведена его схема.

Внешний вид модуля HW-399 с микросхемой TLP281-4 и её схема
Внешний вид модуля HW-399 с микросхемой TLP281-4 и её схема

Здесь выводы IN1…IN4 – это управляющие входные сигналы от микроконтроллера, например, Arduino, или другого управляющего элемента. На них можно подавать напряжение от 3,3 до 5 вольт. Выводы OUT1…OUT4 – выходы. Ножки HVCC и HGND – питание и земля управляемой части электрической схемы. На ножку питания HVCC можно подавать напряжение до 24 вольт.

Выводы IN1…IN4 соответствуют анодам светодиодов модуля, которые и являются источниками светового сигнала для фотокатодов модуля, которые являются электронными ключами OUT1…OUT4.

Для демонстрации работы оптопары давайте соберём схему, показанную на следующем рисунке. Здесь управлять будем одним каналом IN1 модуля HW-399 с помощью Arduino. К выходу OUT1 модуля подключим светодиод, питание на который будем подавать с отдельного источника питания (хотя можно и с самого Arduino, в данном случае это не принципиально). Подключать светодиод необходимо через токоограничивающий резистор, разумеется.

Схема подключения модуля HW-399 с микросхемой TLP284-1 к Arduino
Схема подключения модуля HW-399 с микросхемой TLP284-1 к Arduino

Как только мы соберём схему и подадим питание на внешнюю цепь (ножка HVCC), светодиод загорится. Это из-за того, что на управляющий пин IN1 ещё не подан управляющий сигнал. При отсутствии напряжения логической единицы на входе IN1 (допустим, он просто «висит» в воздухе или подключён к земле)

Смотрите про коптеры:  ТОП-6 лучших дронов с камерой для аэросъемки
Подключение оптопары TLP284-1 к Arduino
Подключение оптопары TLP284-1 к Arduino

Давайте загрузим в Arduino стандартный скетч из примеров – Blink. Этот скетч каждую секунду меняет логический уровень на 13-ой ножке Arduino. Таким образом, мы наглядно увидим, как работает управление оптопарой.

Подключение оптопары TLP284-1 к Arduino
Подключение оптопары TLP284-1 к Arduino

Когда на 13-ом выводе Arduino высокий логический уровень – загорается встроенный светодиод платы Arduino, и отправляется управляющий сигнал на вход IN1 модуля. На выходе OUT1 появляется высокий уровень, и светодиод, подключённый к модулю, гаснет, т.к. нулевая разность потенциалов, и ток не может протекать через светодиод.

Когда на 13-ой ножке Arduino низкий уровень, то встроенный светодиод гаснет, и управляющий сигнал переключается также в низкий уровень. Из-за этого между выходом OUT1 и питанием HVCC модуля возникает разность потенциалов, и подключённый к микросхеме TLP281 светодиод загорается. Таким образом эти два светодиода будут загораться как бы в противофазе.

Осциллограмма при работе оптопары в скетче Blink
Осциллограмма при работе оптопары в скетче Blink

На приведённой осциллограмме голубой график – управляющий сигнал с пина 13 платы Arduino. А фиолетовый график – напряжение на светодиоде на 1-ом выходе модуля HW-399.

2подключение 7-сегментного индикатора непосредственно к arduino

Мы можем подключить индикатор прямо к выводам Arduino. Для этого придётся задействовать сразу 7 ножек (или 8, если нужна десятичная точка). Обратим внимание, что индикатор 3361AS не имеет токоограничивающих резисторов. Необходимо обеспечить наличие сопротивления номиналом около 180…220 Ом на каждый вывод индикатора (т.к. питание подаём 5 В от Arduino).

Электрическая схема 7-сегментного индикатора 3361AS
Электрическая схема 7-сегментного индикатора 3361AS

Расположение выводов индикатора показано на иллюстрации:

Размеры корпуса и расположение выводов 7-сегментного индикатора 3361AS
Размеры корпуса и расположение выводов 7-сегментного индикатора 3361AS

Подключать индикатор будем в соответствии с таблицей. Будет выбран первый разряд, остальные два пока не будем трогать.

Вывод индикатора 3361ASНазначениеВывод Arduino
1Сегмент ED6
2Сегмент DD5
3DPD9
4Сегмент CD4
5Сегмент GD8
7Сегмент BD3
8Выбор 3-го разряда5V
9Выбор 2-го разряда5V
10Сегмент FD7
11Сегмент AD2
12Выбор 1-го разрядаGND

Напишем скетч, который последовательно выводит числа от 0 до 9 на первом разряде индикатора.

Скетч управления индикатором 3361AS (разворачивается)
const int A = 2;
const int B = 3;
const int C = 4;
const int D = 5;
const int E = 6;
const int F = 7;
const int G = 8;
const int DP = 9;

void setup() {
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(DP, OUTPUT);
}

void loop() {
  for (int i=0; i<=9; i  ){
    printNumber(i);
    delay(1000);
  }
}

// зажигает на 7-сегментном индикаторе заданную цифру
void printNumber(int num){
  int numbers[10][8] = { // многомерный массив, в котором описаны состояния сегментов A…G и DP для цифр от 0 до 9
    {1,1,1,1,1,1,0,0}, // 0 
    {0,1,1,0,0,0,0,0}, // 1 
    {1,1,0,1,1,0,1,0}, // 2 
    {1,1,1,1,0,0,1,0}, // 3 
    {0,1,1,0,0,1,1,0}, // 4 
    {1,0,1,1,0,1,1,0}, // 5 
    {1,0,1,1,1,1,1,0}, // 6 
    {1,1,1,0,0,0,0,0}, // 7 
    {1,1,1,1,1,1,1,0}, // 8 
    {1,1,1,1,0,1,1,0}  // 9 
  };
  lightSegments(numbers[num]);
}

// зажигает заданные сегменты
void lightSegments(int segments[]){
  digitalWrite(A, segments[0]);
  digitalWrite(B, segments[1]);
  digitalWrite(C, segments[2]);
  digitalWrite(D, segments[3]);
  digitalWrite(E, segments[4]);
  digitalWrite(F, segments[5]);
  digitalWrite(G, segments[6]);
  digitalWrite(DP, segments[7]);
}

Небольшое пояснение по поводу массива numbers[] в функции printNumber(). Отображение нуля на семисегментном индикаторе Этот массив состоит из 10-ти подмассивов, каждый из которых определяет одну цифру от 0 до 9. В свою очередь подмассивы состоят из 8-ми элементов, которые задают состояния сегментов от A до G и DP. Например, первый подмассив описан как {1,1,1,1,1,1,0,0} и он отвечает за вывод на индикатор нуля. Это означает, что сегменты A,B,C,D,E,F должны гореть, а сегменты G и DP – нет.

[1|1|1|1|1|1|0|0 ]
[A|B|C|D|E|F|G|DP]

В результате получаем примерно следующее:

Управление 7-сегментным индикатором с помощью Arduino Nano
Управление 7-сегментным индикатором с помощью Arduino Nano

И вот так в динамике:

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

2подключение 7-сегментного светодиодногоиндикатора к arduino

В качестве индикатора для вывода показаний компаса будем использовать семисегментный индикатор 3361AS-1. Он построен по принципу индикатора с общим катодом.

Светодиодный индикатор с общим катодом – это тип индикатора, состоящий из нескольких светодиодов в одном корпусе, у которых общая земля, а питание на каждый светодиод подаётся отдельно.

Напомню, что 7-сегментным индикатор называется из-за того, что он состоит из 7-ми светодиодов, которые расположены в форме цифры “8”. Зажигая определённые сегменты, можно изображать разные цифры. Это похоже на цифры индекса на почтовом конверте: закрашивая определённые участки, мы пишем разные индексы.

Обозначение сегментов индикатора латинскими буквами
Обозначение сегментов индикатора латинскими буквами

Воспользуемся популярным способом управления 7-сегментным индикатором с помощью драйвера CD4511. Это микросхема двоично-десятичного преобразователя, который переводит двоичный код числа в напряжение на соответствующих цифре сегментах индикатора. Такой преобразователь использует всего 4 ножки Arduino.

Выводы двоично-десятичного преобразователя CD4511
Выводы двоично-десятичного преобразователя CD4511

Отечественными аналогами данного преобразователя являются микросхемы серий ИД1…ИД7.

При подключении двоичного декодера будем руководствоваться следующей таблицей:

Вывод CD4511НазначениеПримечание
A0…A3Входы двоичного преобразователяСоответствуют разрядам двоичного числа.
a…gВыходы на сегменты индикатораПодключаются через токоограничительные резисторы к соответствующим сегментам светодиодного индикатора.
Lamp Test#Тест индикатора (включает все сегменты)Подключим к питанию, не использовать его.
Blanking#Очистка индикатора (отключает все сегменты)Подключим к питанию, чтобы не использовать его.
Latch Enabled#Выход активенБудет подключен к земле, чтобы выход был всегда активен.
VDDПитание микросхемы и индикатораОт 3 до 15 В.
GNDЗемляОбщая у CD4511, Arduino, 7-сегментного индикатора.

Индикатор 3361AS не имеет токоограничительных резисторов, поэтому необходимо озаботиться этим самому, подключая индикатор. При напряжении питания 5 В сопротивление на каждый сегмент должно быть около 200 Ом.

Желательно также подключить керамический конденсатор ёмкостью примерно 1 мкФ между землёй и питанием микросхемы CD4511.

Нам нужно одновременно управлять тремя разрядами десятичного числа, используя только один преобразователь CD4511. Но чисто физически это невозможно. Однако можно добиться иллюзии постоянного свечения всех разрядов светодиодного индикатора. Для этого придётся быстро переключаться между разрядами, постоянно обновляя показание каждого разряда.

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

Скетч для управления трёхразрядным 7-сегментным индикатором (разворачивается)
// Выводы Arduino для управления двоичным конвертером CD4511:
const byte bit0 = 11;
const byte bit1 = 10;
const byte bit2 = 9;
const byte bit3 = 8;

// Выводы Arduino для выбора десятичных разрядов индикатора 3361AS:
const byte B_0 = 5;
const byte B_1 = 6;
const byte B_2 = 7;

#define seconds() (millis()/1000) // макрос определения секунд, прошедших с начала работы скетча

void setup()
{
  pinMode(bit0, OUTPUT);
  pinMode(bit1, OUTPUT);
  pinMode(bit2, OUTPUT);
  pinMode(bit3, OUTPUT);
  
  pinMode(B_0, OUTPUT);
  pinMode(B_1, OUTPUT);
  pinMode(B_2, OUTPUT);

  digitalWrite(B_0, HIGH);
  digitalWrite(B_1, HIGH);
  digitalWrite(B_2, HIGH);
}

void loop()
{
  // Каждую секунду увеличиваем показания индикатора на 1:
  int sec = seconds();
  for (int i=0; i<1000; i  ) {
    while (sec == seconds()) {
      printNumber(i);
    }
    sec = seconds();
  }
}

// Выводит 3-разрядное число на 7-сегментный индикатор.
void printNumber(int n) {
  setDigit(B_0, n/100); // выводим сотни десятичного числа
  setDigit(B_1, n/10 ); // выводим десятки
  setDigit(B_2, n/1  ); // выводим единицы
}

// Выводит заданное число на заданный разряд индикатора.
void setDigit(byte digit, int value) {
  digitalWrite(digit, LOW); // выбираем разряд индикатора 3361AS-1
  setNumber(value); // выводим на этот разряд число
  delay(4);
  digitalWrite(digit, HIGH); // снимаем выбор разряда индикатора
}

// Выставляет двоичный код на входе преобразователя CD4511
void setNumber(int n) {
  static const struct number {
    byte b3;
    byte b2;
    byte b1;
    byte b0;
  }
  
  numbers[] = {
    {0, 0, 0, 0}, // 0 
    {0, 0, 0, 1}, // 1 
    {0, 0, 1, 0}, // 2 
    {0, 0, 1, 1}, // 3 
    {0, 1, 0, 0}, // 4 
    {0, 1, 0, 1}, // 5 
    {0, 1, 1, 0}, // 6 
    {0, 1, 1, 1}, // 7 
    {1, 0, 0, 0}, // 8 
    {1, 0, 0, 1}, // 9 
  };

  digitalWrite(bit0, numbers[n].b0);
  digitalWrite(bit1, numbers[n].b1);
  digitalWrite(bit2, numbers[n].b2);
  digitalWrite(bit3, numbers[n].b3);
}
Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino
Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino

Итак, теперь мы умеем выводить трёхзначные числа на 7-сегментный индикатор, что нам понадобится для отображения азимута.

4управление 7-сегментным индикатором с помощью драйвера cd4511 и arduino

При подключении двоичного декодера будем руководствоваться следующей таблицей:

Вывод CD4511НазначениеПримечание
A0…A3Входы двоичного преобразователяСоответствуют разрядам двоичного числа.
a…gВыходы на сегменты индикатораПодключаются через токоограничивающие резисторы к соответствующим сегментам светодиодного индикатора.
Lamp Test#Тест индикатора (включает все сегменты)Подключим к питанию, не использовать его.
Blanking#Очистка индикатора (отключает все сегменты)Подключим к питанию, чтобы не использовать его.
Latch Enabled#Выход активенБудет подключен к земле, чтобы выход был всегда активен.
VDDПитание микросхемы и индикатораОт 3 до 15 В.
GNDЗемляОбщая у CD4511, Arduino, 7-сегментного индикатора.

Желательно также подключить керамический конденсатор ёмкостью примерно 1 мкФ между землёй и питанием микросхемы CD4511.

Подключение 7-сегментного индикатора к Arduino с двоичным декодером CD4511B
Подключение 7-сегментного индикатора к Arduino с двоичным декодером CD4511B

Теперь напишем простой скетч, чтобы проверить работоспособность 7-сегментного индикатора 3361AS-1 в связке с двоично-десятичным декодером, а также получить опыт работы с ними. Данный скетч будет поочерёдно перебирать числа от 0 до 9, перемещаясь по циклу от одного разряда индикатора к следующему.

Скетч для управления 7-сегментным индикатором (светится 1 разряд) (разворачивается)
// выводы Arduino для управления двоичным кодом на входе декодера CD4511:
const byte D_0 = 11;
const byte D_1 = 10;
const byte D_2 = 9;
const byte D_3 = 8;

// выводы Arduino для выбора десятичного разряда индикатора:
const byte B_0 = 7;
const byte B_1 = 6;
const byte B_2 = 5;

void setup() {
  pinMode(D_0, OUTPUT);
  pinMode(D_1, OUTPUT);
  pinMode(D_2, OUTPUT);
  pinMode(D_3, OUTPUT);
  pinMode(B_0, OUTPUT);
  pinMode(B_1, OUTPUT);
  pinMode(B_2, OUTPUT);
}

void loop() {
  for (int i=0; i<3; i  ){ // перебираем разряды с 0 по 2-ой
    setDigit(i);
    for (int n=0; n<10; n  ){ // перебираем числа от 0 до 9
      printNumber(n);
      delay(200);
    }    
  }
}

// выбирает разряд десятичного числа на счётчике:
void setDigit(byte b){
  switch (b) {
    case 0:
      digitalWrite(B_0, LOW);
      digitalWrite(B_1, HIGH);
      digitalWrite(B_2, HIGH);
      break;
    case 1:
      digitalWrite(B_0, HIGH);
      digitalWrite(B_1, LOW);
      digitalWrite(B_2, HIGH);
      break;
    case 2:
      digitalWrite(B_0, HIGH);
      digitalWrite(B_1, HIGH);
      digitalWrite(B_2, LOW);
      break;
  }
}

// зажигает заданную цифру 7-сегментного индикатора
void printNumber(byte n){
  switch(n){
    case 0:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 1:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 2:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 3:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, LOW);
      break;
    case 4:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 5:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 6:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 7:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, HIGH);
      digitalWrite(D_2, HIGH);
      digitalWrite(D_3, LOW);
      break;
    case 8:
      digitalWrite(D_0, LOW);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, HIGH);
      break;
    case 9:
      digitalWrite(D_0, HIGH);
      digitalWrite(D_1, LOW);
      digitalWrite(D_2, LOW);
      digitalWrite(D_3, HIGH);
      break;
  }
}

Загрузим скетч в Arduino и посмотрим результат.

В один момент времени светится только один разряд индикатора. Как же задействовать одновременно сразу три разряда индикатора? Это будет немного сложнее. Сложность заключается в том, что нам одновременно нужно управлять тремя разрядами десятичного число, используя только один преобразователь CD4511.

Но чисто физически это невозможно. Однако можно добиться иллюзии постоянного свечения всех разрядов светодиодного индикатора. Для этого придётся быстро переключаться между разрядами, постоянно обновляя показание каждого разряда. Мы будем поочерёдно активировать каждый из разрядов индикатора 3361AS, выставлять на нём с помощью двоичного преобразователя CD4511 нужную цифру, а затем переключаться на следующий разряд.

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

Также перепишем функцию setNumber() отправки двоичного кода на вход микросхемы преобразователя CD4511. Вместо использования оператора switch, используем массив массивов.

Скетч для управления трёхразрядным 7-сегментным индикатором (разворачивается)
// Выводы Arduino для управления двоичным конвертером CD4511:
const byte bit0 = 11;
const byte bit1 = 10;
const byte bit2 = 9;
const byte bit3 = 8;

// Выводы Arduino для выбора десятичных разрядов индикатора 3361AS:
const byte B_0 = 5;
const byte B_1 = 6;
const byte B_2 = 7;

#define seconds() (millis()/1000) // макрос определения секунд, прошедших с начала работы скетча

void setup()
{
  pinMode(bit0, OUTPUT);
  pinMode(bit1, OUTPUT);
  pinMode(bit2, OUTPUT);
  pinMode(bit3, OUTPUT);
  
  pinMode(B_0, OUTPUT);
  pinMode(B_1, OUTPUT);
  pinMode(B_2, OUTPUT);

  digitalWrite(B_0, HIGH);
  digitalWrite(B_1, HIGH);
  digitalWrite(B_2, HIGH);
}

void loop()
{
  // Каждую секунду увеличиваем показания индикатора на 1:
  int sec = seconds();
  for (int i=0; i<1000; i  ) {
    while (sec == seconds()) {
      printNumber(i);
    }
    sec = seconds();
  }
}

// Выводит 3-разрядное число на 7-сегментный индикатор.
void printNumber(int n) {
  setDigit(B_0, n/100); // выводим сотни десятичного числа
  setDigit(B_1, n/10 ); // выводим десятки
  setDigit(B_2, n/1  ); // выводим единицы
}

// Выводит заданное число на заданный разряд индикатора.
void setDigit(byte digit, int value) {
  digitalWrite(digit, LOW); // выбираем разряд индикатора 3361AS-1
  setNumber(value); // выводим на этот разряд число
  delay(4);
  digitalWrite(digit, HIGH); // снимаем выбор разряда индикатора
}

// Выставляет двоичный код на входе преобразователя CD4511
void setNumber(int n) {
  static const struct number {
    byte b3;
    byte b2;
    byte b1;
    byte b0;
  }
  
  numbers[] = {
    {0, 0, 0, 0}, // 0 
    {0, 0, 0, 1}, // 1 
    {0, 0, 1, 0}, // 2 
    {0, 0, 1, 1}, // 3 
    {0, 1, 0, 0}, // 4 
    {0, 1, 0, 1}, // 5 
    {0, 1, 1, 0}, // 6 
    {0, 1, 1, 1}, // 7 
    {1, 0, 0, 0}, // 8 
    {1, 0, 0, 1}, // 9 
  };

  digitalWrite(bit0, numbers[n].b0);
  digitalWrite(bit1, numbers[n].b1);
  digitalWrite(bit2, numbers[n].b2);
  digitalWrite(bit3, numbers[n].b3);
}

Получится вот такая картина.

Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino
Управление трёхразрядным семисегментным индикатором с помощью преобразователя CD4511 и Arduino

В динамике это выглядит так. Тут как раз временами видны мерцания сегментов светодиодного индикатора.

Можно попробовать поиграть значением задержек в функции setDigit(). Если сделать задержки меньше, то мерцание станет меньше заметно. Но начнут сильнее засвечиваться соседние сегменты на выбранном разряде индикатора. Тут необходимо выбрать какое-то компромиссное решение.

6как читать данные сдатчика тока и напряжения ina219

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

Осциллограмма чтения регистров датчика INA219
Осциллограмма чтения регистров датчика INA219

Чтобы понять, что здесь происходит, необходимо познакомиться с картой регистров датчика INA219. Датчик содержит всего 6 регистров. Все регистры 16-разрядные.

Карта регистров датчика тока и напряжения INA219
Адрес регистраНазвание регистраНазначение регистраТип
0x00ConfigurationСброс всех регистров, настройка диапазона измерений, усиления PGA, разрешения АЦП и фильтрации.Чтение/Запись
0x01Shunt voltageХранит измеренное значение напряжения на шунтирующем резисторе 0,1 Ом.Чтение
0x02Bus voltageХранит измеренное значение напряжения шины.Чтение
0x03PowerХранит измеренное значение мощности.Чтение
0x04CurrentСодержит значение силы тока, протекающего через шунтирующий резистор.Чтение
0x05CalibrationКалибровочный регистр. Задаёт диапазон измерений и позволяет осуществлять калибровку системы.Чтение/Запись

Для обмена с модулем воспользуемся отладочной платой с микросхемой FT2232H и программой SPI via FTDI. Это будет проще, чем использовать Arduino, т.к. для внесения изменений в целях эксперимента не придётся каждый раз перепрограммировать ПЗУ, а можно будет вносить изменения в передаваемые команды «на лету».

Чтение регистров датчика тока INA219 с помощью FT2232H
Чтение регистров датчика тока INA219 с помощью FT2232H

Запустим программу SPI via FTDI, выберем в меню «Устройство» интерфейс I2C. Подключимся к порту A. Просканируем устройства на шине I2C. Программа найдёт устройство по адресу 64 (0x40), если конечно вы не меняли адрес перемычками A0 и A1.

Чтение регистров датчика тока INA219 с помощью FT2232H и программы "SPI via FTDI"
Чтение регистров датчика тока INA219 с помощью FT2232H и программы “SPI via FTDI”

Как вы уже наверное догадались, команда “0” означает адрес регистра, из которого мы хотим прочитать данные. А число 0x399F – это данные в нулевом регистре (регистр конфигурации). И это соответствует документации, т.к. после включения и загрузки микросхема INA219 имеет именно такую конфигурацию по умолчанию. Вот какую структуру имеет регистр конфигурации.

Структура конфигурационного регистра датчика тока INA219
Структура конфигурационного регистра датчика тока INA219

В регистре конфигурации датчика INA219 присутствуют следующие части:

  • RST (reset) – сброс;
  • BRNG (bus voltage range) – диапазон измерения шины;
  • BADC (bus ADC resolution/averaging) – разрешающая способность АЦП шины;
  • SADC (shunt ADC resolution/averaging) – разрешающая способность АЦП шунта;
  • MODE – режим;
  • PG – усиление и диапазон PGA.

0x399F в двоичном виде это “001_11_0011_0011_111”. Следовательно, значения по умолчанию после включения такие.

  • BRNG равен “1”, что означает диапазон измерений 32 вольта FSR;
  • PG равно “11”: задаёт диапазон ±320 мВ и коэффициент усиления 8;
  • BADC, SADC равны “0011”: максимальная разрешающая способность АЦП – 12 бит;
  • MODE, равное “111”, означает непрерывный режим работы, включены и шунт, и шина.

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

К сожалению, последовательного чтения всех регистров микросхемы INA219 «за один проход» не предусмотрено.

Вернёмся к нашей осциллограмме. Мы видим на ней 6 циклов чтения (каждый начинается с зелёной точки ● и заканчивается тёмно-красной ●). Сначала читаем регистр с напряжением шунта Vшунт. (адрес 0x01), который хранит значение 0x1957.

Далее читаем значение регистра напряжения шины Vшины (0x02), в котором значение 0x19BA. Далее читаем регистр калибровки Cal (0x05) со значением 0x1000. Потом регистр тока шунта Iшунт. (0x04), в котором значение 0x1959.

Вывод монитора порта в момент снятия осциллограммы с датчика INA219
Вывод монитора порта в момент снятия осциллограммы с датчика INA219

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

7подключение трёхканального датчика тока и напряжения ina3221 к arduino

Датчик тока INA3221 практически идентичен датчику INA219. Основное отличие состоит в том, что он имеет 3 измерительных канала вместо одного. Показания с них можно снимать независимо друг от друга. Будем использовать вот такую небольшую плату с датчиком:

Плата с датчиком INA3221
Плата с датчиком INA3221

Подключается данный модуль к Arduino всего 4-мя проводами: два для питания, и ещё два – шина I2C.

Вывод модуля INA3221Вывод ArduinoНазначение
SDAA4Данные шины I2C
SCLA5Импульсы синхронизации шины I2C
VS 3.3VПитание
GNDGNDОбщий
Подключение датчика INA3221 к Arduino Nano
Подключение датчика INA3221 к Arduino Nano

Назначение остальных выводов модуля показано на приведённом рисунке и в таблице ниже.

Вывод модуля INA3221Назначение
TCЦифровой выход оповещения о сбое таймингов (timing control alert).
WARЦифровой выход оповещения о сбоях измерений (warning).
CRIЦифровой выход оповещения о критических сбоях (critical).
PVЦифровой выход оповещения о валидности питающего напряжения (power valid).
VPUАналоговый вход подтягивающего напряжения для смещения выходных цепей определения валидности питания.
POWАналоговый вход питания измеряемой нагрузки.
CH1, CH2, CH3Порты для подключения измеряемых цепей.

Используем библиотеку для работы с датчиком INA3221. Поместим файлы с расширениями *.cpp и *.h в одну директорию, в ней же создадим файл с расширением *.ino и следующим содержимым:

Скетч для чтения показаний датчика INA3221
#include "Wire.h"
#include "SDL_Arduino_INA3221.h"

SDL_Arduino_INA3221 ina3221; // создаём экземпляр класса датчика

// Три канала измерения датчика INA3221
#define CHANNEL_1 1
#define CHANNEL_2 2
#define CHANNEL_3 3

void setup(void)
{
  Serial.begin(115200);
  Serial.println("Arduino INA3221 test");
  ina3221.begin();

  Serial.print("ID=0x");
  int id = ina3221.getManufID();
  Serial.println(id, HEX);

  Serial.println("Measuring voltage and current with ina3221 ...");
}

void loop(void)
{
  Serial.println("---------------------------------------------");
  Serial.println("Channel:tt(1)t(2)t(3)t"); // "t" - это символ табуляции

  // Вывод напряжений по трём каналам:
  Serial.print("Bus voltage, V: t");
  float busvoltage1 = ina3221.getBusVoltage_V(CHANNEL_1);
  float busvoltage2 = ina3221.getBusVoltage_V(CHANNEL_2);
  float busvoltage3 = ina3221.getBusVoltage_V(CHANNEL_3);
  Serial.print(busvoltage1); Serial.print("t");
  Serial.print(busvoltage2); Serial.print("t");
  Serial.print(busvoltage3); Serial.println("t");

  // Вывод напряжений на шунте по трём каналам:
  Serial.print("Shunt voltage, mV: t");
  float shuntvoltage1 = ina3221.getShuntVoltage_mV(CHANNEL_1);
  float shuntvoltage2 = ina3221.getShuntVoltage_mV(CHANNEL_2);
  float shuntvoltage3 = ina3221.getShuntVoltage_mV(CHANNEL_3);
  Serial.print(shuntvoltage1); Serial.print("t");
  Serial.print(shuntvoltage2); Serial.print("t");
  Serial.print(shuntvoltage3); Serial.println("t");

  // Вывод напряжений нагрузки по трём каналам:
  Serial.print("Load voltage, V: t");
  float loadvoltage1 = busvoltage1   (shuntvoltage1 / 1000);
  float loadvoltage2 = busvoltage2   (shuntvoltage2 / 1000);
  float loadvoltage3 = busvoltage3   (shuntvoltage3 / 1000);
  Serial.print(loadvoltage1); Serial.print("t");
  Serial.print(loadvoltage2); Serial.print("t");
  Serial.print(loadvoltage3); Serial.println("t");

  // Вывод тока по трём каналам:
  Serial.print("Current, mA: tt");
  float current_mA1 = ina3221.getCurrent_mA(CHANNEL_1);
  float current_mA2 = ina3221.getCurrent_mA(CHANNEL_2);
  float current_mA3 = ina3221.getCurrent_mA(CHANNEL_3);
  Serial.print(current_mA1); Serial.print("t");
  Serial.print(current_mA2); Serial.print("t");
  Serial.print(current_mA3); Serial.println("t");

  delay(2000);
}

Загрузим данный скетч в память Arduino. Перед тем как подключать нагрузку, необходимо подать с источника питания напряжение на контакты POW и GND, расположенные с одного из краёв модуля. Это напряжение будет подаваться на нагрузку и оно в данном модуле общее для всех трёх измерительных каналов. Допустимый диапазон напряжений от 0 до 26 вольт. Я сейчас подам 5 В.

Удобно в места подключения нагрузки и питания впаять клеммники для быстрого монтажа.

Теперь можно подключать нагрузку. Давайте нагрузим выходы модуля и посмотрим, что будет выводиться в монитор последовательного порта. Я подключу на канал 1 два параллельных резистора номиналом 4,3 кОм, что в сумме даст сопротивление 2,15 кОм. А на канал 3 – один резистор 4,3 кОм.

Датчик тока INA3221 с нагрузкой
Датчик тока INA3221 с нагрузкой

В мониторе последовательного порта видно, как меняются показания датчика INA3221 при изменении нагрузки. На иллюстрации для примера показаны три состояния: показания датчика без нагрузки, с нагрузкой на одном канале и с разной нагрузкой на двух каналах.

Показания датчика тока INA3221 в мониторе COM-порта
Показания датчика тока INA3221 в мониторе COM-порта

Если мы подключим в измеряемую цепь амперметр, то убедимся, что показания цифрового датчика INA3221 довольно точно совпадают с показаниями амперметра.

Показания датчика тока INA3221 в сравнении с амперметром
Показания датчика тока INA3221 в сравнении с амперметром

Движение без проблем: 9-осевой датчик mpu-9255

MPU9255 — уникальный продукт, включающий в себя 3-осевой гироскоп, 3-осевой акселерометр, 3-осевой компас и цифровой процессор Digital Motion Processor (DMP™). MPU9255 создан на базе платформы MotionApps (рис. 1). Большинство датчиков InvenSense — продукты этой платформы.

Движение без проблем: 9-осевой датчик MPU-9255 | Новости электротехники | Элек.ру

Рис. 1. Платформа для создания различных датчиков InvenSense

При построении MPU9255 компания InvenSense использует гибридную технологию. Это значит, что несколько кристаллов размещаются на одной подложке и соединяются с помощью микросварки (рис. 2). MPU9255 включает два кристалла. На одном из них реализованы 3-осевой гироскоп и 3-осевой акселерометр, на другом — 3-осевой магнитометр производства компании Asahi Kasei Microdevices Corporation. Для взаимодействия с внешним управляющим процессором используются стандартные интерфейсы: I²C и SPI.

Движение без проблем: 9-осевой датчик MPU-9255 | Новости электротехники | Элек.ру

Рис. 2. Технология создания MPU9255

Также в состав MPU9255 входят различные аналоговые и цифровые блоки (рис.3):

  • Цепи нормирования
  • 16-битные АЦП на каждом измерительном тракте
  • Система питания
  • Регистры
  • Коммуникационные интерфейсы
  • Буфер FIFO
  • 9 основных сенсоров
  • Датчик температуры

Движение без проблем: 9-осевой датчик MPU-9255 | Новости электротехники | Элек.ру

Рис. 3. Структурная схема MPU9255

Одним из достоинств MPU9255 является низкое потребление. Это достигается благодаря нескольким факторам: за счет низких питающих токов функциональных узлов микросхемы, за счет возможности настройки частоты опроса и за счет использования режимов пониженного потребления.

В качестве демонстрации низких токов потребления можно привести следующие характеристики:

  • потребление гироскопа в нормальном режиме составляет 3,2 мА, в спящем режиме — 8 мкА;
  • акселерометр в нормальном режиме потребляет всего 450 мкА, в режимах со сниженной частотой еще меньше — 8,4 мкА при 0,98 Гц, 19,8 мкА при 31,25 Гц, а в глубоком сне и вовсе 8 мкА;
  • магнитометр потребляет всего 280 мкА при частоте опроса 8 Гц.

Эффект от наличия режимов пониженного потребления усиливается за счет присутствия прерываний и встроенного буфера FIFO. MPU9255 поддерживает пять режимов прерываний: обнаружение движения, переполнение FIFO, окончание преобразования, ошибка шины I²C, сообщение по I²C. Самым интересным является прерывание при обнаружении движения. MPU9255 позволяет настраивать каждый канал как источник прерывания с программированным уровнем срабатывания. Кроме того, MPU9255 имеет аппаратную поддержку таких функций как ориентация Android-устройств, касания экрана, педометр, резкие движения.

Развитая система питания MPU9255 включает в себя основные цепи питания (в частности — LDO), цепи смещения и источники опорного напряжения, а также повышающий преобразователь.

Характеристики MPU9255:

3-хосевой гироскопИмеет четыре диапазона измерений ±250, ±500, ±1000, и ±2000 °/с, 16-битный АЦП, программируемый ФНЧ, встроенную систему калибровки
3-хосевой акселерометрИмеет четыре диапазона измерений ±2 g, ±4 g, ±8 g и ±16 g, 16-битный АЦП, встроенную систему калибровки, систему векторов прерывания
3-хосевой компас на базе датчиков ХоллаИмеет точность измерений 14 бит (0,6 мкТл/LSB) или 16 бит (15 мкТл/LSB), диапазон измерений ±4800 мкТл, 16-битный АЦП, встроенную систему калибровки
Цифровой процессорDigital Motion Processing™ (DMP™) с поддержкой режимов пониженного потребления, системы прерываний и буфера FIFO;
FIFO, байт512
Интерфейсы400 кГц I²C, 1 МГц SPI;
Напряжение питанияОсновное 2,4…3,6 В VDD, входов/выходов 1,7… VDD;
Диапазон рабочих температур, °C0…85

MPU9255 выпускается в 24-выводном QFN с габаритами 3×3×1 мм. Также одним из самых миниатюрных 9-осевых сенсоров в мире считается MPU9250 с корпусом QFN 3×3×1 мм производства компании InvenSense. Для применения MPU9250 идеально подойдет макетная плата EVB-MPU-9250, созданная специально для него, которая предназначена для быстрого создания коммерческих решений в области фитнеса, спорта и здоровья. Плата является сенсорной платформой с 10-ю степенями свободы, сочетая в себе 9-осевой MEMS-датчик, разъем для подключения внешнего датчика, микроконтроллер, Bluetooth-радиомодуль, последовательную Flash-память, аккумулятор и зарядный модуль для него.

Перспективные области применения датчика MPU9255:

  • портативные устройства (смартфоны, планшеты);
  • устройства управления (пульты ДУ, игровые геймпады, 3D-манипуляторы);
  • спортивная электроника (педометры, тренажеры).

Подключение bmp280 к плате arduino

Как упоминалось выше, модуль BMP280 может быть подключен к плате Arduino посредствам двух интерфейсов I2C или SPI. Какой выбрать – каждый решает сам исходя из возможностей используемого микроконтроллера и специфики проекта. На рисунке №2 показан вариант подключения датчика к плате Arduino Nano по I2C.

Рисунок №2 – подключение BMP280 по I2C-интерфейсу

Как известно, аппаратный интерфейс I2C у Arduino UNO, Nano, Mini и.т.п. расположен на пинах A4 (SDA) и A5 (SCL). Следовательно, в таком режиме обмена данными понадобиться всего 4 провода, два из которых используются для питания модуля, а два других – непосредственно как информационная шина.

Рисунок №3 – подключение BMP280 по SPI-интерфейсу

Вышеприведенная схема подключения составлена согласно расположению аппаратного интерфейса SPI на платах Arduino UNO, Nano, Mini и.т.п. Исключением является вывод CSB модуля BMP280. В данной схеме он подключен к 10-му пину Arduino, но может быть соединён с любым цифровым выводом, указанным при составлении программы.

Как правило, для BMP280 в Интернете можно найти с десяток библиотек, упрощающих работу с ним. Библиотека
Adafruit_BMP280.h позволяет максимально сократить время на освоение данного модуля, не урезая его функционал. Методы библиотеки дают возможность пользователю выбрать способ подключения, а также настроить периодичность и точность измерений в зависимости от режимов работы. Ниже будут рассмотрены некоторые приёмы работы с данной библиотекой.

Итак, для того чтобы начать работу с BMP280 необходимо установить вышеуказанную библиотеку, подключить сам заголовочный файл Adafruit_BMP280.h, а также ещё два файла Wire.h и SPI.h, для доступа к необходимым интерфейсам.

#include <Wire.h> // Библиотека для работы с шиной I2C
#include <SPI.h>  // Библиотека для работы с шиной SPI
#include <Adafruit_BMP280.h> // Библиотека для работы с датчиком BMP280

// Для подключения по шине I2C
Adafruit_BMP280 bmp;

// Для подключения по аппаратному SPI (указываем только номер пина CS)
#define PIN_CS 10
Adafruit_BMP280 bmp(PIN_CS);

// Для подключения по программному SPI (указываем все пины интерфейса)
#define PIN_SCK  13
#define PIN_MISO 12
#define PIN_MOSI 11
#define PIN_CS   10
Adafruit_BMP280 bmp(PIN_CS, PIN_MOSI, PIN_MISO,  PIN_SCK);

Следует помнить, что при составлении программы должен быть указан только один из трёх возможных вариантов, иначе будет работать самый последний.


Теперь через объект bmp мы имеем возможность работать с функциями библиотеки, но изначально необходимо инициализировать модуль. Делать это целесообразно внутри функции setup() перед основным циклом:


void setup() {
  Serial.begin(9600); // Для вывода отладочной информации в терминал
    if(!bmp.begin()) { // Если датчик BMP280 не найден
    Serial.println(“BMP280 SENSOR ERROR”); // Выводим сообщение об ошибке
    while(1); // Переходим в бесконечный цикл
  }
}

Таким образом при выводе сообщения об ошибке следует проверить правильность подключения и соответствие его используемому интерфейсу. При успешной инициализации можно переходить к настройке самой микросхемы BMP280. Для этих целей в библиотеке предусмотрена функция setSampling(…), с помощью которой задаётся режим работы модуля, точность измерения атмосферного давления и температуры окружающей среды, степень фильтрации и период активности датчика. Ниже приведён пример настроек, заданных по умолчанию.

bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, // Режим работы
                Adafruit_BMP280::SAMPLING_X2, // Точность изм. температуры
                Adafruit_BMP280::SAMPLING_X16, // Точность изм. давления
                Adafruit_BMP280::FILTER_X16, // Уровень фильтрации
                Adafruit_BMP280::STANDBY_MS_500); // Период просыпания, мСек

Рассмотрим подробнее данную функцию. Её первый параметр отвечает за режим работы датчика. Всего доступно 4 варианта, а именно:

Второй и третий параметры отвечают за точность измерения температуры и атмосферного давления соответственно. Они могут принимать следующие значения:


Четвёртый параметр отвечает за уровень фильтрации измеренных данных. Значения этого параметра могут быть следующие:

Последний, пятый параметр функции setSampling(…) отвечает за период перехода модуля в активное состояние с целью выполнения измерений. Параметр может принимать следующие значения:

На этом стадию настройки параметров датчика BMP280 можно считать завершённой. Библиотека Adafruit_BMP280 предоставляет пользователю три функции, с помощью которых можно считать показания температуры, атмосферного давления и высоты над уровнем моря. Ниже приведён фрагмент программного кода, с помощью которого эти данные выводятся в окно терминала. Считывание происходит в основном цикле loop().

void loop() {
  // Выводим значение температуры
  Serial.print(F("Temperature = "));
  Serial.print(bmp.readTemperature()); // Функция измерения температуры
  Serial.println(" *C");

  // Выводим значение атмосферного давления
  Serial.print(F("Pressure = "));
  Serial.print(bmp.readPressure());  // Функция измерения атм. давления
  Serial.println(" Pa");

  // Выводим значение высоты
  Serial.print(F("Approx altitude = "));
  Serial.print(bmp.readAltitude(1013.25)); // Функция измерения высоты
  Serial.println(" m");
}

Следует пару слов сказать о функции bmp.readAltitude(1013.25) и откуда берётся число 1013.25. Это значение давления над уровнем моря конкретной локации, где находится в данный момент датчик. Параметр задаётся в сотнях Ра. Он уникален для каждой местности и по своей сути является отправной точкой или калибровочной константой для корректного измерения высоты.

Такой подход обусловлен специфическим алгоритмом вычисления, который построен на принципе фиксации уменьшения атмосферного давления с ростом высоты и наоборот. В любом случае данную константу можно подсмотреть в Интернете на одном из профильных сайтов. Результат вывода значений в терминал показан на рисунке №4.

Рисунок №4 – результат чтения данных с модуля BMP280 

Как видно из рисунка, давление выводится в Паскалях, что для восприятия не очень удобно. Гораздо привычнее получать значения в миллиметрах ртутного столба. Как известно 1Ра = 0,00750062 мм. рт. ст., следовательно необходимо полученное с помощью функции readPressure() значение умножить на 0,00750062.

ОБРАТИТЕ ВНИМАНИЕ!!! Может возникнуть такая ситуация, при которой модуль не будет определяться при подключении его по шине I2C. Дело в том, что каждое устройство на этой шине должно иметь свой уникальный адрес. Данная серия модулей в зависимости от модификации может иметь адреса 0x77 или 0x76.


#define BMP280_ADDRESS (0x77) /**< The default I2C address for the sensor. */

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

Сенсоры для Arduino до низким ценам можно купить в магазине 3DIY!

Оцените статью
Радиокоптер.ру
Добавить комментарий