Электронный уровень на 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); // Оптимизированная задержка
}
Удачи в сборке проекта! При появлении вопросов — пишите на форум, будем разбираться =)