Проект 32: Серво с управлением движением

Описание

В этом проекте мы совместим 6-осевой датчик движения MPU6050 с сервомотором SG90, чтобы создать систему с управлением движением. Наклоняя модуль MPU6050 вдоль оси X, Arduino будет считывать данные ускорения, преобразовывать их в угол и командовать сервомотору вращаться соответствующим образом. Это основной принцип работы стабилизации подвеса и роботизированных рук с управлением движением.

Аппаратное обеспечение

  1. Плата разработки UNO R3 (ch340) x1

  2. Модуль MPU6050 x1

  3. Серво мотор SG90 x1

  4. Макетная плата x1

  5. Соединительные провода

Принцип работы

MPU6050 измеряет ускорение силы тяжести. Когда модуль расположен идеально горизонтально, оси X и Y показывают 0g, а ось Z — 1g. При наклоне модуля вектор гравитации распределяется по осям. Считывая необработанное значение ускорения по оси X, можно определить угол наклона.

Arduino считывает это необработанное значение по оси X (которое обычно варьируется от -17000 до +17000 в зависимости от наклона) и с помощью функции map() преобразует этот диапазон в значение угла от 0 до 180 градусов. Это значение затем передается сервомотору с помощью библиотеки Servo, заставляя рычаг мотора повторять наклон датчика.

Схема подключения

MPU6050:

  • VCC -> 5V

  • GND -> GND

  • SCL -> A5

  • SDA -> A4

Серво SG90:

  • Коричневый/черный провод -> GND

  • Красный провод -> 5V

  • Оранжевый/желтый провод (сигнал) -> Цифровой пин 9
    Img

Пример кода

/*

Electronics Learning Starter Kit for Arduino

Project 32

Motion Controlled Servo

Edit By Keyes

*/

#include <Wire.h>
#include <Servo.h>

const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ;

Servo myServo;  // create servo object to control a servo

void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  
  myServo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
}

void loop() {
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 6, true);  // request a total of 6 registers
  
  AcX = Wire.read()<<8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
  AcY = Wire.read()<<8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read()<<8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  
  // Map the X-axis acceleration (-17000 to 17000) to Servo angle (0 to 180)
  // Note: You may need to adjust the -17000 and 17000 values based on your specific sensor's calibration
  int servoAngle = map(AcX, -17000, 17000, 0, 180);
  
  // Constrain the angle to prevent servo damage
  servoAngle = constrain(servoAngle, 0, 180);
  
  myServo.write(servoAngle);  // tell servo to go to position in variable 'servoAngle'
  
  Serial.print("AcX: ");
  Serial.print(AcX);
  Serial.print(" => Angle: ");
  Serial.println(servoAngle);
  
  delay(50);  // small delay for stability
}

Объяснение кода

Преобразование значений:

int servoAngle = map(AcX, -17000, 17000, 0, 180);

Функция map() принимает необработанное значение ускорения по оси X (AcX) и масштабирует его из исходного диапазона (-17000 до 17000) в целевой диапазон для сервомотора (0 до 180 градусов).

Ограничение угла:

servoAngle = constrain(servoAngle, 0, 180);

Функция constrain() гарантирует, что даже если датчик выдаст значение немного за пределами ожидаемого диапазона, значение servoAngle никогда не опустится ниже 0 или не превысит 180. Это защищает механические шестерни сервомотора от повреждений.

Результат проекта

После загрузки кода возьмите модуль MPU6050 в руку. При наклоне модуля влево и вправо вдоль оси X сервомотор SG90 будет вращаться синхронно, повторяя движение вашей руки. Вы можете открыть монитор порта, чтобы видеть необработанные значения ускорения и соответствующие им вычисленные углы.

P32