Купить всё для Ардуино   Купить макетную плату с перемычками на AliExpress

Делаем простой инклинометр (угломер) с помощью Ардуино

Этот проект представляет собой создание простого инклинометра (угломера) на Ардуино с автоматическим измерением углов наклона в разных плоскостях.

Этот инклинометр можно поворачивать в любом положении, сохраняя читаемость цифр даже перевернув плату вверх ногами. Устройство контролируется Arduino 101 с помощью акселерометров для считывания угла наклона осей X-Y.

Кроме того, есть функция, показывающая температуру окружающей среды в градусах Цельсия или градусах Фаренгейта. Сборка очень проста, и надеемся, вам понравится.

Шаг 1: Список комплектующих

Arduino 101: эта версия Arduino больше не производится, несмотря на наличие интересных функций, таких как датчик температуры, 6-осевой акселерометр, гироскоп, датчик температуры и bluetooth на борту.

Для этого проекта очень полезно избегать внешнего MPU.

Многофункциональный щит (MFD): MFD может упростить и ускорить разработку прототипа. Основные возможности:

  • 4-значный 7-сегментный светодиодный дисплейный модуль, управляемый двумя серийными 74HC595
  • 4 светодиода для поверхностного монтажа в параллельной конфигурации
  • 10K регулируемый прецизионный потенциометр
  • 3 независимых кнопки
  • Пьезо-зуммер
  • Интерфейс датчика DS18B20
  • Интерфейс датчика температуры LM35
  • Интерфейс инфракрасного приемника
  • Контакты последовательного интерфейса для удобного подключения к последовательным модулям, таким как Bluetooth (беспроводной интерфейс), голосовый модуль, модуль распознавания голоса и т.д.

Шаг 2: Сборка

Сборка очень проста и нет необходимости в каких-либо схемах.

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

Примечание. Этот проект можно обновить до любой модели Arduino, используя внешний MPU-6050.

Шаг 3: Настройка

Для настройки инклинометра Ардуино есть 3 кнопки:

Левая кнопка: выберите рабочий режим.

a) Автоматическая ось. В этом режиме ось (X или Y) для измерения степени наклона автоматически выбирается внутренним гироскопом.
б) Х-ось. Показать только углы оси X.
c) Y-ось. Показать только углы оси Y.
d) Температура - показать температуру окружающей среды в градусах Цельсия или Фаренгейта.

Центральная кнопка: задайте нулевой градус по оси X и Y. Когда выбран температурный режим, эта кнопка устанавливает температурный масштаб (ºC или ºF).

Правая кнопка: Сбросьте оси до исходных углов.

Примечание! Ось X отображается на дисплее символом «=» и осью Y символом «||». Диапазон углов для показаний наклона составляет от -90 ° до + 90 °.

Шаг 4: Функция передачи

Основными функциями кода являются:

  • Чтение углов наклона акселерометров.
  • Расчет передаточной функции эффекта перевернутой стороны для 7-сегментного светодиодного дисплея.

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

  • Вид спереди - Инклинометр в первоначальном положении
  • Вид спереди - Инклинометр вверх дном

Функция передачи для отображения 7-сегмент (от А до F) работает следующим образом:

От A до D, от B до E, от C до F, от D до A, от E до B, от F до C, от G до G

Для завершения эффекта перевернутости необходимо инвертировать последовательность символов на дисплее:

От: 1, 2, 3, 4

До: 4, 3, 2, 1

Шаг 5: Код

Приложенный ниже код должен применяться только к Arduino 101.

Для другой версии Arduino требуется некоторое обновление кода, а также использование внешнего MPU-6050 для акселерометров.

#define SDA_PORT PORTD
#define SDA_PIN 5
#define SCL_PORT PORTD
#define SCL_PIN 6

#include <CurieTimerOne.h>
#include <CurieIMU.h>

// Module connection pins (Digital Pins)
#define LATCH_PIN 4                             // Arduino 101 conection on Pin #4  = Latch of Display Module
#define CLK_PIN 7                               // Arduino 101 conection on Pin #7  = Clock of Display Module
#define DATA_PIN 8                              // Arduino 101 conection on Pin #8  = Data of Display Module

#define BTN_1_PIN A1
#define BTN_2_PIN A2
#define BTN_3_PIN A3

//    Front:       Upside Down:
//      A               D
//     ----            ----
//  F |    | B      C |    | E
//     -G -            -G -
//  E |    | C      B |    | F
//     ----            ----
//      D               A
//

// Chars Code {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, = , ||, º, C, F}

byte N[] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0x28, 0x12, 0xC6, 0x9C, 0x8E};

int delayRefresh;
byte view;
unsigned long ti;
float AcX, AcY, AcZ, gX, gY, gZ;
int uniAngle, dezAngle;
int axis, angle, angleX, angleRefX, angleY, angleRefY, temp;
boolean axisX, axisY, tempStatus, tCelsius;


void setup() {

  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);

  pinMode(BTN_1_PIN, INPUT);
  pinMode(BTN_2_PIN, INPUT);
  pinMode(BTN_3_PIN, INPUT);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  CurieTimerOne.start(180000, kbdRead);

  CurieIMU.begin();

  // Set the accelerometer range to 2G
  CurieIMU.setAccelerometerRange(2);

  // Set gyro range to 250º/second
  CurieIMU.setGyroRange(250);

  view = 0;              // Front View (regular view as default)
  axisX = true;
  axisY = false;
  angleRefX = 0;
  angleRefY = 0;
  axis = 0;
  tempStatus = false;
  tCelsius = true;

}


void loop() {

  delayRefresh = 70;

  CurieIMU.readAccelerometerScaled(AcX, AcY, AcZ);            // Read Accelerometers (G = m/s/s)
  CurieIMU.readGyroScaled(gX, gY, gZ);                        // Read Gyro (º/s)
  temp = (CurieIMU.readTemperature() / 512) + 13;             // Read the temperature in Celsius degrees (ºC)

  if (AcX < 0) {
    view = 0;                                                 // Front View (regular view)
  }

  if (AcX > 0) {
    view = 1;                                                 // Front View (Upside Down)
  }

  angleX = atan(AcX / AcZ) * 180 / PI - angleRefX;
  angleY = atan(AcY / AcZ) * 180 / PI - angleRefY;

  if ((abs(gY) > 5) && (abs(gX) < 2) && (axis == 0)) {
    axisX = true;
    axisY = false;
  }

  if ((abs(gX) > 5) && (abs(gY) < 2) && (axis == 0)) {
    axisX = false;
    axisY = true;
  }

  if (axisX) {
    angle = angleX;
  }

  if (axisY) {
    angle = angleY;
  }

  uniAngle = abs(int(angle)) % 10;
  dezAngle = abs(int(angle)) / 10;


  // Display the Angle (-XXº) or Temperature (ºC / ºF)

  if (tempStatus == false) {

    ti = millis();                                                            // Initial time for blinking dot

    while ((millis() - ti) < delayRefresh) {                                  // Timer in miliseconds to refresh the display


      if (view == 0) {                                                        // Front View mode (1)
        if (angle < 0) {
          displayChars(2, view, 0);                                           // Display Minus Signal "-" at Digi 0
        }
        displayChars(N[abs(dezAngle)], view, 1);                              // Display Digit 1
        displayChars(N[abs(uniAngle)], view, 2);                              // Display Digit 2
        if (axisY) {
          displayChars(N[10], view, 3);                                       // Display Degree Symbol "||" for Y-axis
        }
        if (axisX) {
          displayChars(N[11], view, 3);                                       // Display Degree Symbol "=" for X-axis
        }
      }

      if (view == 1) {                                                        // Front Upside Down mode (2)
        if (angle < 0) {
          displayChars(2, view, 3);                                           // Display Minus Signal "-" at Digit 3
        }
        displayChars(N[dezAngle], view, 2);                                   // Display Digit 2
        displayChars(N[uniAngle], view, 1);                                   // Display Digit 1
        if (axisY) {
          displayChars(N[10], view, 0);                                       // Display Symbol "||" for Y-axis
        }
        if (axisX) {
          displayChars(N[11], view, 0);                                       // Display Symbol "=" for X-axis
        }
      }
    }
  }

  if (tempStatus == true) {

    if (!tCelsius) {                                                          // Temperature conversion - Celsius to Fahrenheit
      temp = temp * 9 / 5 + 32;
    }

    ti = millis();                                                            // Initial time for blinking dot

    while ((millis() - ti) < delayRefresh) {                                  // Timer in miliseconds to refresh the display

      if (view == 0) {                                                        // Front View mode (1)
        displayChars(N[temp / 10], view, 0);                                  // Display Digit 0
        displayChars(N[temp % 10], view, 1);                                  // Display Digit 1
        displayChars(N[12], view, 2);                                         // Display Digit 2 - Symbol "º"
        if (tCelsius) {
          displayChars(N[13], view, 3);                                       // Display Degree Symbol "C"
        }
        else {
          displayChars(N[14], view, 3);                                       // Display Degree Symbol "F"
        }
      }

      if (view == 1) {                                                        // Front View mode (1)
        displayChars(N[temp / 10], view, 3);                                  // Display Digit 0
        displayChars(N[temp % 10], view, 2);                                  // Display Digit 1
        displayChars(N[12], view, 1);                                         // Display Digit 2 - Symbol "º"
        if (tCelsius) {
          displayChars(N[13], view, 0);                                       // Display Degree Symbol "C"
        }
        else {
          displayChars(N[14], view, 0);                                       // Display Degree Symbol "F"
        }
      }

    }

    displayChars(0, 1, 0);                                                    // Clear Digit 0
    displayChars(0, 1, 1);                                                    // Clear Digit 1
    displayChars(0, 1, 2);                                                    // Clear Digit 2
    displayChars(0, 1, 3);                                                    // Clear Digit 3

  }

}


void displayChars(byte num, byte statusM, byte disp) {                        // Chars Display Routine

  if (statusM == 1) {                                                         // Front Upside Down
    num = ((num >> 2) << 5) | ((num >> 5 ) << 2) | (num & 2);
  }

  digitalWrite(LATCH_PIN, LOW);
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, ~num);                                // Display number
  shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, 128 >> disp);                         // Set Digit (0-1-2-3)
  digitalWrite(LATCH_PIN, HIGH);

}


void kbdRead() {                                                              // Push Buttons Reading

  if (!digitalRead(BTN_1_PIN)) {                                              // Set mode

    axis = (axis + 1) % 4;

    if (axis == 0) {                                                          // Set mode "auto view" (X & Y axis)
      tempStatus = false;
    }

    if (axis == 1) {                                                          // Set mode X-axis only
      axisX = true;
      axisY = false;
    }

    if (axis == 2) {                                                          // Set mode Y-axis only
      axisX = false;
      axisY = true;
    }

    if (axis == 3) {                                                          // Set Temperature mode
      tempStatus = true;
    }

  }

  if (!digitalRead(BTN_2_PIN) && !tempStatus) {                               // Set reference for X & Y axis
    angleRefX = angleX;
    angleRefY = angleY;
  }

  if (!digitalRead(BTN_2_PIN) && tempStatus) {                                // Set temperature scale (ºC or ºF) in temperature mode
    tCelsius = !tCelsius;
  }

  if (!digitalRead(BTN_3_PIN) && !tempStatus) {                               // Reset X & Y axis to original values/reference
    angleRefX = 0;
    angleRefY = 0;
  }

}

Как это работает можно посмотреть в итоговом видео.

На этом всё. Хороших вам проектов.

/ 11.09.2018

Ардуино+