|

Электронный уровень на Arduino с TFT 1.8″/2.8″ и MPU6050

Всем привет 🙂

В этой статье мы рассмотрим как сделать интересный проект на Arduino — электронный уровень с цветным TFT дисплеем и датчиком-гироскопом-акселерометром MPU6050.

На дисплее отображается линия, которая всегда держится вдоль линии горизонта.

Датчик MPU6050 подключаем стандартно — SDA и SCL на соответствующие пины Arduino, МСС это плюс питания 5v, GND это земля, подключается на соответствующий пин Arduino.

Для работы со скетчем вам понадобятся следующие библиотеки — MPU6050, Adafruit_GFX, Adafruit_ST7735(или Adafruit_ILI9341). Библиотеку Wire устанавливать не нужно, она уже предустановлена в Arduino IDE. Все неустановленные библиотеки можно установить через менеджер библиотек Arduino IDE.

Этот скетч предназначен для дисплея TFT 1.8″ с контроллером ST7735. После этого кода есть версия для дисплея TFT 2.8″ с контроллером ILI9341.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <Wire.h>
#include <MPU6050.h>

// Определение пинов для TFT дисплея
#define TFT_CS   10
#define TFT_RST  8
#define TFT_DC   9

Adafruit_ST7735 tft(TFT_CS, TFT_DC, TFT_RST);
MPU6050 mpu;

// Калибровочные смещения акселерометра (настраивайте при необходимости)
float accelOffsetX = 0;
float accelOffsetY = 0;
float accelOffsetZ = 0;

void setup() {
  tft.initR(INITR_BLACKTAB); // Инициализация дисплея
  tft.fillScreen(ST7735_WHITE); // Заливка белым фоном

  Wire.begin(); // Инициализация I2C
  mpu.initialize(); // Инициализация MPU6050

  // Проверка подключения MPU6050
  if (!mpu.testConnection()) {
    while (1); // Остановка при отсутствии подключения
  }
}

void loop() {
  // Чтение данных акселерометра
  int16_t ax, ay, az;
  mpu.getAcceleration(&ax, &ay, &az);
  
  // Применение калибровочных смещений
  float accelX = (ax / 16384.0) - accelOffsetX;
  float accelY = (ay / 16384.0) - accelOffsetY;
  float accelZ = (az / 16384.0) - accelOffsetZ;

  // Вычисление углов наклона
  float roll = atan2(accelY, accelZ) * RAD_TO_DEG;
  float pitch = atan2(-accelX, sqrt(accelY * accelY + accelZ * accelZ)) * RAD_TO_DEG;

  // Корректировка коэффициентов под ваш датчик
  int deltaY = pitch * 1.2; // Чувствительность по вертикали
  int deltaRoll = roll * 2;  // Чувствительность по горизонтали

  // Расчет положения границы
  int leftY = 80 + deltaY - deltaRoll;
  int rightY = 80 + deltaY + deltaRoll;

  // Ограничение значений в пределах экрана
  leftY = constrain(leftY, 0, 160);
  rightY = constrain(rightY, 0, 160);

  // Отрисовка
  tft.fillScreen(ST7735_WHITE); // Очистка экрана
  
  // Заливка синей области
  for (int x = 0; x < tft.width(); x++) {
    int y = map(x, 0, tft.width()-1, leftY, rightY);
    y = constrain(y, 0, tft.height());
    tft.drawFastVLine(x, y, tft.height() - y, ST7735_BLUE);
  }

  delay(50); // Задержка для стабильности
}

Вот код для дисплея покрупнее, с контроллером ILI9341:

#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Wire.h>
#include <MPU6050.h>

// Пин-конфигурация для ILI9341
#define TFT_CS   10
#define TFT_DC    9
#define TFT_RST   8

Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
MPU6050 mpu;

// Калибровочные параметры (настраивайте под ваш датчик)
float accelOffsetX = 0;
float accelOffsetY = 0;
float accelOffsetZ = 0;

void setup() {
  tft.begin(); // Инициализация дисплея
  tft.setRotation(3); // Портретный режим (настройте под ваше крепление)
  tft.fillScreen(ILI9341_WHITE);

  Wire.begin();
  mpu.initialize();
  
  if (!mpu.testConnection()) {
    tft.setTextColor(ILI9341_RED);
    tft.setTextSize(2);
    tft.println("MPU6050 Error!");
    while(1);
  }
}

void loop() {
  // Чтение сырых данных
  int16_t ax, ay, az;
  mpu.getAcceleration(&ax, &ay, &az);

  // Нормализация данных
  float accelX = (ax / 16384.0) - accelOffsetX;
  float accelY = (ay / 16384.0) - accelOffsetY;
  float accelZ = (az / 16384.0) - accelOffsetZ;

  // Вычисление углов
  float roll = atan2(accelY, accelZ) * RAD_TO_DEG;
  float pitch = atan2(-accelX, sqrt(accelY*accelY + accelZ*accelZ)) * RAD_TO_DEG;

  // Коэффициенты чувствительности
  int deltaY = pitch * 2.0;    // Вертикальная чувствительность
  int deltaRoll = roll * 3.5;  // Горизонтальная чувствительность

  // Расчет границы жидкости
  int startY = 120 + deltaY - deltaRoll; // Центр экрана 240/2=120
  int endY = 120 + deltaY + deltaRoll;

  // Ограничение значений
  startY = constrain(startY, 0, 240);
  endY = constrain(endY, 0, 240);

  // Отрисовка
  tft.fillScreen(ILI9341_WHITE);
  
  for(int x = 0; x < tft.width(); x++) {
    int y = map(x, 0, tft.width()-1, startY, endY);
    y = constrain(y, 0, tft.height());
    tft.drawFastVLine(x, y, tft.height() - y, ILI9341_BLUE);
  }

  delay(20); // Оптимизированная задержка
}

Удачи в сборке проекта! При появлении вопросов — пишите на форум, будем разбираться =)

5/5 - (1 голос)


Поделись!