Цифровой индикатор глубины сверления на Arduino Nano и гироскопе GY-521 (MPU-6050)
Компоненты и материалы
- Arduino Nano R3 — 1 шт.
- GY-521 (MPU-6050) — акселерометр/гироскоп — 1 шт.
- 7-сегментный дисплей 8 разрядов (MAX7219, SPI) — 1 шт.
- Тактильная кнопка — 1 шт. (фиксация стоп-позиции)
- Выключатель питания — 1 шт.
- Питание: 6×AA батареи (9В) или Power Bank 5V — 1 комплект
- Неодимовый магнит (для крепления к станку) — 1 шт.
- 3D-печатный держатель под гайку SW17 (STL в проекте) — 1 шт.
Инструменты
- 3D-принтер (Anycubic i3 Mega / любой FDM)
- Паяльник, клей (горячий/эпоксидный)
ПО
- Arduino IDE
- Библиотека LedControl (для MAX7219) — через менеджер библиотек.
- Библиотека Wire (встроена) — для I2C MPU-6050.
Идея и принцип
Станочный сверлильный станок имеет ручное колесо регулировки глубины (поворот ~270°). Вместо неудобной шкалы с риской — электронный индикатор. MPU-6050 крепится прямо на вал ручки (через 3D-держатель на гайке SW17) и измеряет угол наклона акселерометром. Arduino пересчитывает угол в глубину (мм) и показывает на 8-значном дисплее. Кнопка запоминает целевую глубину («Стоп»), при достижении — показывает «StOP».
Подключение
| Модуль | Arduino Nano |
|---|---|
| MPU-6050 VCC | 5V |
| MPU-6050 GND | GND |
| MPU-6050 SCL | A5 |
| MPU-6050 SDA | A4 |
| MAX7219 VCC | 3.3V (или 5V, если модуль 5V-толерантен) |
| MAX7219 GND | GND |
| MAX7219 DIN | D12 |
| MAX7219 CS | D10 |
| MAX7219 CLK | D11 |
| Кнопка | D9 (INPUT_PULLUP) |
Корпус и монтаж
- Корпус с магнитом клеится в корпус станка (металл).
- Держатель MPU-6050 надевается на гайку SW17 ручки глубины. Выровняйте его горизонтально (на дисплее 0.0).
- Провода проложите через крышку корпуса.
Алгоритм обработки данных MPU-6050
- Инициализация: пробуждение из сна (рег. 0x6B=0), настройка диапазона ±8g (рег. 0x1C=0x10). Критично: delay(1000) после пробуждения — без этого при автономном питании датчик не выдает данные.
- Калибровка смещения (offset): при старте 100 измерений, усреднение ошибки угла X.
- Чтение raw данных: регистры 0x3B–0x40 (6 байт: Ax, Ay, Az).
- Угол Roll (X) по акселерометру:
AccAngleX = atan2(AcY, sqrt(AcX² + AcZ²)) * RAD_TO_DEG - AccAngleErrorX; - Сглаживание (комплементарный фильтр 50/50):
TotalAngleX = 0.5 * TotalAngleX + 0.5 * AccAngleX; - Приведение к 0–360°: акселерометр дает -90..+90°. Используем знаки Ax, Ay, Az для определения квадранта:
delta = 0; if (AccZ < 0) delta = 180.0 - TotalAngleX * 2.0; if (AccZ > 0 && AccY < 0) delta = 360.0; DrillingMachineAngle = TotalAngleX + delta; if (DrillingMachineAngle > 350) DrillingMachineAngle = 0; - Перевод в глубину (мм): измерьте макс. угол ручки (у автора 316°) при макс. глубине (50 мм).
currentPos = 50.0 / 316.0 * DrillingMachineAngle;
Логика работы (loop)
- Отображает текущую глубину слева (4 разряда, 1 знак после запятой).
- Нажатие кнопки → сохраняет
stopPos = currentPos, показывает «8888» 1 сек. - Если стоп установлена:
currentPos >= stopPos→ справа «StOP» (маленькая 't' через setRow B00001111).- Иначе → справа остаток
stopPos - currentPos(мм).
- Если стоп не установлена — правые 4 разряда пусты.
- Обновление ~5 Гц (delay 200 мс).
Полный скетч (drilling-depth.ino)
/* drilling-depth.ino - Thomas Angielsky, 2021-03-20
* https://techpluscode.de/bohrtiefenanzeige-mit-gyro-sensor/ */
#include <Wire.h> #include <math.h> #include "LedControl.h"
#define MPU 0x68
char txt[8]; String s;
float currentPos, stopPos;
float rad_to_deg = 180.0/PI;
float AccX, AccY, AccZ;
float AccAngleX, AccAngleErrorX;
float TotalAngleX;
float DrillingMachineAngle, delta;
LedControl lc = LedControl(12, 11, 10, 1); // DIN, CLK, CS, 1 device
void setup() {
stopPos = 0.0; currentPos = 0.0;
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); Wire.write(0x00); Wire.endTransmission(true); // wake up
delay(1000); // КРИТИЧНО для автономной работы!
Wire.beginTransmission(MPU);
Wire.write(0x1C); Wire.write(0x10); Wire.endTransmission(true); // ±8g
// Калибровка offset
for(int a=0; a<100; a++) {
Wire.beginTransmission(MPU); Wire.write(0x3B); Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccY = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccZ = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccAngleErrorX += atan2(AccY, sqrt(AccX*AccX + AccZ*AccZ)) * rad_to_deg;
}
AccAngleErrorX /= 100.0;
pinMode(9, INPUT_PULLUP); // кнопка
lc.shutdown(0,false); lc.setIntensity(0,8); lc.clearDisplay(0);
}
void loop() {
// Чтение акселерометра
Wire.beginTransmission(MPU); Wire.write(0x3B); Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccY = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccZ = (Wire.read()<<8 | Wire.read()) / 4096.0;
AccAngleX = atan2(AccY, sqrt(AccX*AccX + AccZ*AccZ)) * rad_to_deg - AccAngleErrorX;
TotalAngleX = 0.5 * TotalAngleX + 0.5 * AccAngleX;
delta = 0;
if (AccZ < 0) delta = 180.0 - TotalAngleX * 2.0;
if (AccZ > 0 && AccY < 0) delta = 360.0;
DrillingMachineAngle = TotalAngleX + delta;
if (DrillingMachineAngle > 350) DrillingMachineAngle = 0;
currentPos = 50.0 / 316.0 * DrillingMachineAngle; // калибровка под СВОЙ станок!
// Кнопка - установка стопа
if (digitalRead(9) == LOW) {
stopPos = currentPos;
lc.setChar(0,3,'8',false); lc.setChar(0,2,'8',false);
lc.setChar(0,1,'8',false); lc.setChar(0,0,'8',false);
delay(1000);
}
// Правый дисплей (4 разряда): стоп или остаток
if (stopPos > 0) {
if (currentPos >= stopPos) {
lc.setChar(0,3,'5',false); // 'S' не встроен, используем '5' похоже
lc.setRow(0,2,B00001111); // маленькая 't'
lc.setChar(0,1,'0',false);
lc.setChar(0,0,'P',false);
} else {
dtostrf(stopPos - currentPos, 4, 1, txt);
s = " " + String(txt);
lc.setChar(0,0,s.charAt(s.length()-1),false);
lc.setChar(0,1,s.charAt(s.length()-3),true); // точка
lc.setChar(0,2,s.charAt(s.length()-4),false);
lc.setChar(0,3,s.charAt(s.length()-5),false);
}
} else {
lc.setChar(0,3,' ',false); lc.setChar(0,2,' ',false);
lc.setChar(0,1,' ',false); lc.setChar(0,0,' ',false);
}
// Левый дисплей (4 разряда): текущая глубина
dtostrf(currentPos, 4, 1, txt);
s = " " + String(txt);
lc.setChar(0,4,s.charAt(s.length()-1),false);
lc.setChar(0,5,s.charAt(s.length()-3),true); // точка
lc.setChar(0,6,s.charAt(s.length()-4),false);
lc.setChar(0,7,s.charAt(s.length()-5),false);
delay(200);
}
Тестирование и результат
- Подайте питание. Выровняйте держатель MPU до показа «0.0».
- Поверните ручку — цифры должны плавно меняться.
- Установите нужную глубину кнопкой. Сверлите — при достижении загорится «StOP».
- Точность ±0.1 мм, реакция мгновенная. Большие цифры — читать без очков до 85 лет!
Видео работы: techpluscode.de
Полезные ссылки
- Работа с MPU-6050: Medium, Arduino Playground, CircuitDigest
- Библиотека GY-521 (Rob Tilaart): GitHub
- Книга Paul Akers «2 Second Lean»: paulakers.net
- Немецкая версия статьи: techpluscode.de
Схема и 3D-модель
STL-файл держателя: drilling-depth-3d-model_Yn2q0MSNa4.zip (прикреплен к проекту).
Производственный процесс
- Интеграция данных сенсоров в Raspberry Pi: практическое руководство
- Датчик слежения за линией на Raspberry Pi — простой детектор двери/линии KY‑033
- Построение надёжного Temperature & Sensor API на Raspberry Pi с модулем GY‑91
- Создайте автоматизированную аэропоническую систему с Raspberry Pi и датчиком влажности
- Мастерство GPIO Raspberry Pi: подключение PIR-датчика движения на B+/Model 2
- Интеграция импульсного радара Acconeer A111 с Raspberry Pi: практическое руководство
- Подключение, калибровка и программирование PIR-датчика HC‑SR501 с Raspberry Pi
- Python/MicroPython логгер датчиков: бесшовное сохранение данных в Google Sheets
- Интеграция термопары с Arduino Portenta H7 через MAX6675
- Устройство точного измерения давления и расхода воздуха на аналоговом датчике