Motor Controll

Note

🌟 Welcome to the SunFounder Facebook Community! Whether you’re into Raspberry Pi, Arduino, or ESP32, you’ll find inspiration, help ideas here.

  • ✅ Be the first to get free learning resources.

  • ✅ Stay updated on new products & exclusive giveaways.

  • ✅ Share your creations and get real feedback.

  • 👉 Need faster updates or support? Click [here] join our Facebook community

  • 👉 Or join our WhatsApp group: Click [here]

Kit purchase

Looking for parts? Check out our all-in-one kits below — packed with components, beginner-friendly guides, and tons of fun.

../_images/umsk_kit.png

Name

Includes Arduino board

PURCHASE LINK

Ultimate Sensor Kit

Arduino Uno R4 Minima

BUY

Universal Maker Sensor Kit

×

BUY

Course Introduction

In this lesson, you’ll learn how to build a simple tilt-controlled motor system using the Arduino UNO R4, an MPU6050 sensor, and an L9110 motor driver.

Tilting the MPU6050 forward makes the motor spin forward, and tilting it backward makes the motor spin in reverse. The greater the tilt, the faster the motor rotates, and when the board is level, the motor stops.

Note

If this is your first time working with an Arduino project, we recommend downloading and reviewing the basic materials first.

Required Components

In this project, we need the following components:

SN

COMPONENT INTRODUCTION

QUANTITY

PURCHASE LINK

1

Arduino UNO R4 Minima/Arduino UNO R4 WIFI

1

BUY

2

USB Cable

1

3

Breadboard

1

BUY

4

Wires

Several

BUY

5

L9110 Motor Driver Module

1

6

MPU6050 Module

1

BUY

7

TT Motor

1

Wiring

../_images/motor_controll_bb.png

Common Connections:

  • MPU6050

    • SDA: Connect to SDA on the Arduino.

    • SCL: Connect to SCL on the Arduino.

    • GND: Connect to breadboard’s negative power bus.

    • VCC: Connect to breadboard’s red power bus.

  • TT Motor

    • Connect to MOTOR A on the L9110 Motor Driver Module.

  • L9110 Motor Driver Module

    • GND: Connect to breadboard’s negative power bus.

    • VCC: Connect to breadboard’s red power bus.

    • A-1B: Connect to 6 on the Arduino.

    • A-1A: Connect to 5 on the Arduino.

Writing the Code

Note

  • You can copy this code into Arduino IDE.

  • Don’t forget to select the board(Arduino UNO R4) and the correct port before clicking the Upload button.

#include <Wire.h>

// ====== MPU6050 ======
#define MPU_ADDR       0x68
#define REG_PWR_MGMT_1 0x6B
#define REG_ACCEL_XOUT_H 0x3B

// ====== L9110 motor pins (choose PWM-capable pins) ======
const int PIN_INA = 5;   // L9110 INA  -> Arduino D5 (PWM)
const int PIN_INB = 6;   // L9110 INB  -> Arduino D6 (PWM)

// ====== Mapping / filter ======
const float DEAD_ZONE_DEG = 3.0f;     // deadband around level
const float MAX_TILT_DEG  = 25.0f;    // tilt that maps to full speed
const float EMA_ALPHA     = 0.15f;    // low-pass filter for pitch

// Calibration
const unsigned long CALIB_MS = 2000;  // time to average zero level (ms)
float pitchZero = 0.0f;               // baseline (level) pitch
float pitchFilt = 0.0f;               // filtered pitch

// -------- helpers --------
int16_t read16(int reg) {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 2, true);
  int16_t hi = Wire.read();
  int16_t lo = Wire.read();
  return (hi << 8) | lo;
}

void mpuInit() {
  Wire.begin();
  // wake up MPU6050
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(REG_PWR_MGMT_1);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(100);
}

float readPitchDeg() {
  // read accelerometer raw
  int16_t ax = read16(REG_ACCEL_XOUT_H);
  int16_t ay = read16(REG_ACCEL_XOUT_H + 2);
  int16_t az = read16(REG_ACCEL_XOUT_H + 4);

  // Convert to g (±2g default -> 16384 LSB/g)
  float Ax = ax / 16384.0f;
  float Ay = ay / 16384.0f;
  float Az = az / 16384.0f;

  // Pitch (front/back tilt). Depending on sensor mounting, you may swap Ax/Ay.
  // Here we use atan2(Ax, Az) : positive when tilting "forward" if X-axis points forward.
  float pitch = atan2f(Ax, Az) * 180.0f / PI;
  return pitch;
}

void motorStop() {
  analogWrite(PIN_INA, 0);
  analogWrite(PIN_INB, 0);
}

void motorForward(uint8_t pwm) {
  analogWrite(PIN_INA, pwm);
  analogWrite(PIN_INB, 0);
}

void motorBackward(uint8_t pwm) {
  analogWrite(PIN_INA, 0);
  analogWrite(PIN_INB, pwm);
}

void setup() {
  pinMode(PIN_INA, OUTPUT);
  pinMode(PIN_INB, OUTPUT);
  motorStop();

  Wire.begin();
  mpuInit();
  Serial.begin(115200);
  Serial.println("MPU6050 + L9110 TT motor control (UNO R4)");

  // ---- calibration: average pitch while held level ----
  unsigned long t0 = millis();
  double sum = 0.0;
  uint32_t n = 0;
  while (millis() - t0 < CALIB_MS) {
    float p = readPitchDeg();
    sum += p;
    n++;
    delay(10);
  }
  pitchZero = (n > 0) ? (sum / n) : 0.0f;
  pitchFilt = 0.0f; // start filter at zeroed reference

  Serial.print("Calibrated pitchZero = ");
  Serial.println(pitchZero, 2);
}

void loop() {
  // 1) read & zero
  float pitch = readPitchDeg() - pitchZero;

  // 2) low-pass filter
  pitchFilt = (1.0f - EMA_ALPHA) * pitchFilt + EMA_ALPHA * pitch;

  // 3) dead zone & scaling
  float p = pitchFilt;
  if (fabs(p) < DEAD_ZONE_DEG) {
    motorStop();
  } else {
    // clamp and map abs(p) to PWM 0..255
    float mag = constrain(fabs(p), 0.0f, MAX_TILT_DEG);
    uint8_t pwm = (uint8_t) map((long)(mag * 1000), 0, (long)(MAX_TILT_DEG * 1000), 0, 255);

    if (p > 0) {
      motorForward(pwm);   // forward when tilting forward
    } else {
      motorBackward(pwm);  // backward when tilting backward
    }
  }

  // debug (optional)
  static uint32_t last = 0;
  uint32_t now = millis();
  if (now - last > 200) {
    last = now;
    Serial.print("pitchRaw=");
    Serial.print(readPitchDeg() - pitchZero, 2);
    Serial.print("  pitchFilt=");
    Serial.print(pitchFilt, 2);
    Serial.print("  PWM=");
    // read back approximate PWM (not exact on UNO R4, just logic)
    Serial.println();
  }

  delay(10);
}