Bluetooth-Controlled Mini Lift Using Stepper Motor with Android Mobile App

 

Bluetooth-Controlled Mini Lift Using Stepper Motor with Android Mobile App

01 Overview

This Mini Lift project is achieved with the use of a stepper motor. The motor will rotate either clockwise or counterclockwise depending on whether you want it to go up or down, controlled by a mobile app over Bluetooth. Additionally, a TFT LCD display shows the user which floor the lift is currently on, as well as when it is moving.

Project Use Case

This project is a good introduction to combining precise stepper-motor control, wireless (Bluetooth) input from a custom mobile app, and a visual status display — concepts that extend to small-scale automation, hoists, and other position-controlled mechanisms.

02 Hardware and Software Components

Gather everything below before you start.

Hardware Components

Component Description
Arduino Due Main microcontroller. Runs at 3.3V logic, which the TFT display requires.
Stepper Motor NEMA 17 (17HS4401) Drives the lift mechanism up and down.
5mm x 8mm Motor Shaft Coupling Connects the stepper motor shaft to the lift's drive mechanism.
Stepper Motor Driver DRV8825 Drives the NEMA 17 stepper motor with adjustable current limiting and microstepping.
HC-05 Bluetooth Module Receives floor commands wirelessly from the Android app.
2.2" TFT LCD Display ILI9341 (240x320) Shows the current floor and lift movement status.
47Ω Resistor Placed in series with the TFT display's LED backlight pin.
100μF Capacitor Placed in series on the stepper driver's motor supply line.
Breadboard Platform for building and testing the circuit.
9V Power Supply Powers the stepper motor driver.
Jumper Wires Connects all modules to the Arduino and breadboard.
Rubber Belt / String Transfers the stepper motor's rotation into vertical lift movement.
Container / Platform The lift platform/car itself.

Software Tools

Software Description
Arduino IDE Used to write, compile, and upload the sketch to the Arduino Due.
MIT App Inventor Cloud-based, block-coding tool used to build the Android control app.
App Inventor Companion App Lets you preview the app live on your Android device while building it.

Libraries Used

Library Purpose
SPI (Serial Peripheral Interface) Required by the Adafruit_ILI9341 library to communicate with the TFT display.
Adafruit_ILI9341 Driver library for the ILI9341-based TFT LCD display.

03 Application Discussion

Stepper Motor NEMA 17

A stepper motor, also known as a step motor or stepping motor, is a type of brushless DC electric motor. Very precise positioning and speed control can be achieved with computer-controlled stepping, which is why stepper motors are the motor of choice for many precision motion control applications.

How Does It Work?

Stepper motors divide a full rotation into a number of equal steps. They have multiple coils organized into groups called phases. By using electromagnets to energize each phase in sequence, the motor rotates one step at a time.

Specifications

Spec Value
Phase 2
Step Angle 1.8°
Step Angle Accuracy ± 5% (full step, no load)
Rated Current 1.3 A
Phase Resistance 2.4 Ω
Resistance Accuracy ± 10%
Phase Inductance 2.8 mH
Inductance Accuracy ± 20%
Holding Torque 28 N·cm
Detent Torque 1.6 N·cm
Rotor Inertia 34 g·cm²

Stepper Motor Driver DRV8825

The DRV8825 stepper motor driver features adjustable current limiting, over-current protection, over-temperature protection, and six microstep resolutions (down to 1/32-step). It operates from 8.2V to 45V and can deliver up to approximately 1.5A per phase without a heat sink or forced air flow (rated for up to 2.2A per coil with sufficient additional cooling).

How Does It Work?

The stepper motor driver is the circuit that controls how the stepper motor operates. It works by sending current through the motor's various phases in pulses. The DRV8825, a microstepping driver, allows higher resolutions by enabling intermediate step locations, achieved by energizing the coils with intermediate current levels.

Specifications

Spec Value
Operating Voltage 8.2–45 V
Continuous Current per Phase 1.5 A
Maximum Current per Phase 2.2 A
Logic Voltage 2.5–5.25 V
Microstep Resolutions Full, 1/2, 1/4, 1/8, 1/16, 1/32

HC-05 Bluetooth Module

The HC-05 Bluetooth Module is an easy-to-use Bluetooth SPP (Serial Port Protocol) module, designed for transparent wireless serial connection setup. It's one of the most widely used wireless communication protocols in embedded projects due to its low cost and wide range of applications.

How Does It Work?

The serial port Bluetooth module is a fully qualified Bluetooth V2.0+EDR (Enhanced Data Rate) 3Mbps modulation module with a complete 2.4GHz radio transceiver and baseband. It uses a CSR BlueCore 04-External single-chip Bluetooth system with CMOS technology and Adaptive Frequency Hopping. In simple terms, the Bluetooth module manages the wireless communication channel — it can transmit and receive data wirelessly, communicating via serial communication, which makes it easy to interface with a microcontroller.

Specifications

Spec Value
Input Voltage 5 V
Communication Method Serial
Frequency 2.4 GHz
Default PIN/Password 1234
Mode Master and slave mode can be switched

2.2" TFT LCD Display ILI9341 (240x320)

TFT LCD is short for thin-film-transistor liquid-crystal display. It's a variant of LCD that uses thin-film transistor technology to improve image qualities such as addressability and contrast. These are commonly used in appliances including computer monitors, mobile phones, handheld devices, video game systems, navigation systems, projectors, and televisions.

How Does It Work?

All the pixels on a TFT LCD screen are arranged in a row-and-column format, and each pixel is attached to a very tiny silicon transistor that rests directly on the glass panel. This setup allows each pixel to be given a charge, and for that charge to be maintained even when the screen refreshes to produce a new image.

04 Hardware Setup

2.2" TFT LCD Display Connections

Important: The 2.2" TFT LCD display used here can only work on 3.3V logic. Unlike most Arduino boards, the Arduino Due runs at 3.3V, making it a great fit. Other boards like the Arduino Uno can still be used, as long as proper logic-level shifting is applied using resistors.
Display Pin Connect To
SDO / MISO Arduino Due SPI MISO pin (SPI header pin 1)
LED Arduino Due 5V, with a 47Ω resistor in series
SCK Arduino Due SPI SCK pin
SDI / MOSI Arduino Due SPI MOSI pin (SPI header pin 4)
DC / RS Arduino Due pin 26
RESET Arduino Due pin 22
CS Arduino Due pin 24
Vcc / Gnd Arduino Due 5V / Ground respectively

HC-05 Bluetooth Module Connections

Module Pin Connect To
RXD Arduino Due pin TX2 (pin 16)
TXD Arduino Due pin D4
Vcc / Gnd Arduino Due 5V / Ground respectively

Stepper Motor Driver DRV8825 Connections

Driver Pin Connect To
DIR Arduino Due pin 2
STEP Arduino Due pin 3
RESET / SLEEP Arduino Due 5V
GND (logic side) Arduino Due Ground
VMT / GND (motor supply side) 9V power supply and its Ground respectively, with a 100μF capacitor in series

Stepper Motor NEMA 17 Connections

Important: Before connecting the stepper motor to the driver, you must first limit the driver's current output to the motor. This motor has a maximum current rating of 1.3A with a 2.4Ω phase resistance, which indicates a maximum motor supply of 3.12V. Using a higher voltage allows higher step rates, but current must actively be limited to under 1.3A to prevent damage to the motor.

One way to set the current limit is to adjust and measure the voltage on the driver's REF pin to calculate the resulting current limit. The REF pin is the small circle on the circuit board and can be adjusted with a small screwdriver. The current limit is twice the reference voltage, so to set a 1.3A current limit, set the reference voltage to 0.65V.
Motor Wire Connect To
1st wire (usually red) Stepper Motor Driver pin 1B
2nd wire (usually black) Stepper Motor Driver pin 2B
3rd wire (usually blue) Stepper Motor Driver pin 1A
4th wire (usually green) Stepper Motor Driver pin 2A

05 Android App Setup

For the Android mobile app, this project uses the cloud-based MIT App Inventor. In just a few steps, you can set it up and start building apps.

Step 1 — Install the Companion App

Install the App Inventor Companion App on your Android device so you can preview your app live as you build it. If you don't have an Android device, you'll need to install software on your computer to use the on-screen Android emulator instead. Learn more about the initial setup on the official MIT App Inventor setup guide (https://appinventor.mit.edu/explore/ai2/setup-device-wifi.html).

Step 2 — Create a New Project

Click on the Project tab, start a new project, and give it a proper name. In the main interface, you'll see a component palette on the left, a viewer in the middle, and components/properties tabs on the right.

Step 3 — Add and Arrange Components

Drag and drop the required components from the palette onto the viewer screen in order. To make components easier to identify, rename them using the rename button below the components list. Grouping components into a consistent arrangement makes it easier to show or hide a group of components at a time later on.

Step 4 — Customize the Interface

Customize the labels and buttons to your liking — for example, custom button images plus a grayscale version to use when a button is disabled, and a background image on Screen1. Then uncheck the visibility of the arrangement containing the floor controls so the initial screen looks like a "not yet connected" state.

Step 5 — Test on Your Device

To see how the app looks on your phone, connect it to the App Inventor Companion by clicking the Connect button on the top menu and selecting "AI Companion".

Note: An importable .aia project file and a ready-to-install .apk for this app are provided alongside the Arduino code in the Code section.

06 Code

Read the Code Breakdown section to understand what each part does.

Mini_Lift.ino

Arduino / C++
#include "SPI.h"
#include "Adafruit_ILI9341.h"

#define dirPin 2
#define stepPin 3
#define stepsPerRevolution 200

#define TFT_DC 26
#define TFT_CS 24
#define TFT_RST 22
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

int input; //a string to hold incoming data
int lastInput;
int floorDiff;
int compensation;
bool stringComplete = false;

void setup() {
  Serial2.begin(9600);
  tft.begin();
  displayFloor();
  //Set pins as output
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  Serial.println("Mini Lift program has started.");
}

void moveUp() {
  digitalWrite(dirPin, HIGH);
  for (int i = 0; i < (1.8*stepsPerRevolution*floorDiff)+compensation ; i++) {
    digitalWrite(stepPin, HIGH); //These four lines result in 1 step
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
}

void moveDown() {
  digitalWrite(dirPin, LOW);
  for (int i = 0; i < (1.8*stepsPerRevolution*floorDiff)-compensation; i++) {
    digitalWrite(stepPin, HIGH); //These four lines result in 1 step
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
}

unsigned long displayFloor() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(1);
  tft.setCursor(0, 70);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
  tft.setTextColor(ILI9341_WHITE); tft.setTextSize(5);
  tft.println("Mini Lift");
  tft.setTextColor(ILI9341_MAGENTA);  tft.setTextSize(3);
  tft.print("Current Floor:");
  tft.setTextColor(ILI9341_MAGENTA);  tft.setTextSize(3);
  tft.println(input);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
}

unsigned long displayMoving() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(1);
  tft.setCursor(0, 80);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
  tft.setTextColor(ILI9341_CYAN); tft.setTextSize(3);
  tft.print("Lift is moving ");
  if (lastInput < input) {
    tft.println((char)24);
  }
  else if (lastInput > input) {
    tft.println((char)25);
  }
  tft.print("from floor ");
  tft.print(lastInput);
  tft.print(" - ");
  tft.println(input);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
}

void serialEvent() {
  while (Serial2.available()) {
    input = Serial2.read();
    displayMoving();
    stringComplete = true;
  }
}

void loop() {
  serialEvent();
  if (stringComplete) {
    Serial2.print(lastInput);
    if (lastInput < input) {
      floorDiff = input - lastInput;
      moveUp();
    }
    else if (lastInput > input) {
      floorDiff = lastInput - input;
      moveDown();
    }
    displayFloor();
  }
  delay(100);
  lastInput = input;
  stringComplete = false;
}
Note: The loop also includes calibration logic for the belt-rolling compensation value mentioned in the Hardware Setup section, which depends on your specific rubber belt setup and isn't included in the excerpt above.

MIT App Inventor Project

The Android app is built entirely with MIT App Inventor's block-based editor (no text code to copy) — see the Code Breakdown section below for how the connection and floor-button blocks work.

07 Code Breakdown

Arduino Code

Pre-Initialization

Arduino / C++
#include "SPI.h"
#include "Adafruit_ILI9341.h"

These are the libraries needed for the project. The Adafruit_ILI9341 library controls the TFT LCD display, and since it depends on the Serial Peripheral Interface, the SPI library is also included.

Arduino / C++
#define dirPin 2
#define stepPin 3
#define stepsPerRevolution 200

#define TFT_DC 26
#define TFT_CS 24
#define TFT_RST 22
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

This defines the direction and step pins for the stepper motor, as well as steps per revolution. Typical stepper motors move 1.8° per step, which works out to 200 steps per revolution. It also defines the DC, CS, and reset pins for the TFT LCD display and creates the TFT object with those pins assigned.

Arduino / C++
int input; //a string to hold incoming data
int lastInput;
int floorDiff;
int compensation;
bool stringComplete = false;

This initializes the variables used later. input stores the incoming data, and lastInput stores the previous input.

setup()

Arduino / C++
Serial2.begin(9600);
tft.begin();
displayFloor();
//Set pins as output
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);

This sets the Serial2 baud rate to 9600 bps, the default for serial communication. The Arduino Due has 4 serial ports, and Serial2 is on pins 16 and 17. It also initializes the TFT display and immediately calls displayFloor(), then sets the stepper motor pins as outputs.

Stepper Motor Control Functions

Arduino / C++
void moveUp() {
  digitalWrite(dirPin, HIGH);
  for (int i = 0; i < (1.8*stepsPerRevolution*floorDiff)+compensation ; i++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
}

void moveDown() {
  digitalWrite(dirPin, LOW);
  for (int i = 0; i < (1.8*stepsPerRevolution*floorDiff)-compensation; i++) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
}

moveUp() and moveDown() are nearly identical, differing only in the direction pin — HIGH rotates the motor clockwise, LOW rotates it counter-clockwise. Each is a for-loop that steps the motor a set number of times, with delayMicroseconds() controlling speed. Steps per revolution is multiplied by floorDiff to determine how many rotations are needed, then adjusted by a compensation value. This compensation matters when using a one-sided rolling belt: as the belt rolls up, it accumulates radius and needs fewer rotations to reach the same height.

TFT Display Functions

Arduino / C++
unsigned long displayFloor() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(1);
  tft.setCursor(0, 70);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
  tft.setTextColor(ILI9341_WHITE); tft.setTextSize(5);
  tft.println("Mini Lift");
  tft.setTextColor(ILI9341_MAGENTA);  tft.setTextSize(3);
  tft.print("Current Floor:");
  tft.setTextColor(ILI9341_MAGENTA);  tft.setTextSize(3);
  tft.println(input);
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println("--===---===----===---===--");
}

displayFloor() prints text on the TFT display. First the screen is filled black and rotated 90° for landscape view (the 1 in setRotation() means 90°, and can be set from 0–3). The cursor is then positioned so the text prints roughly centered on the screen — cursor coordinates of 0,0 would print at the top instead. Printing works like printing to the Serial Monitor, with the added ability to set text color and size.

displayMoving() is called while the stepper motor is moving, and shows which floor the lift is moving from and to. (char)24 and (char)25 render as up and down arrows, respectively.

serialEvent()

Arduino / C++
void serialEvent() {
  while (Serial2.available()) {
    input = Serial2.read();
    displayMoving();
    stringComplete = true;
  }
}

This checks for incoming data on the Bluetooth serial connection. While data is available, it's stored in input, and the stringComplete flag is set to true to indicate the data was received successfully.

loop()

Arduino / C++
serialEvent();
if (stringComplete) {
  Serial2.print(lastInput);
  if (lastInput < input) {
    floorDiff = input - lastInput;
    moveUp();
  }
  else if (lastInput > input) {
    floorDiff = lastInput - input;
    moveDown();
  }
  displayFloor();
}
delay(100);
lastInput = input;
stringComplete = false;

The loop calls serialEvent() to check for new data. If data was received, it sends the last known floor back over Serial2, then compares lastInput and input to decide whether to call moveUp() or moveDown(), calculating floorDiff in the process. After moving, it calls displayFloor() to update the screen. The short delay gives communication time to process, and finally lastInput is updated and stringComplete is reset to false.

MIT App Inventor Code

Connection Buttons

Since MIT App Inventor uses code blocks, the logic is fairly readable directly from the blocks editor. When the Bluetooth list-picker button is clicked, its "BeforePicking" event populates the list with nearby Bluetooth devices the user can connect to. Its "AfterPicking" event runs after a device is chosen — if the connection to the HC-05 module succeeds, it hides the "not connected" arrangement and shows the arrangement containing the floor controls, then checks the lift's last known floor so the app resumes from where it left off (e.g., disabling the button for the floor the lift is already on).

The Disconnect button does the opposite — it disconnects from the Bluetooth device and restores the "not connected" arrangement.

Floor Buttons

Each floor button, when clicked, checks that the app is still connected to the Bluetooth device, then sends that floor's number over Bluetooth for the HC-05 module to receive. This value is stored in the input variable in the Arduino code, which — combined with the calculations described above — tells the stepper motor how far to rotate. The rest of the block logic disables the pressed button (switching its image to a grayscale version) and re-enables any previously disabled buttons.

08 Conclusion

Stepper motors are really strong. A motor's position can be moved and held at any of its steps as long as it's carefully sized to the application in terms of torque and speed. In this build, it was able to lift a small platform of office supplies, and can lift heavier loads still, according to experiments conducted by other sources. Stepper motors like this one are used in a wide variety of applications, including industrial machines, medical scanners, blood analysis machinery, 3D printing equipment, and more.

09 References

  • DRV8825 Stepper Motor Driver Carrier, High Current — Pololu
    (https://www.pololu.com/product/2133)
  • All About Stepper Motors: What is a Stepper Motor? — Adafruit Learning System
    (https://learn.adafruit.com/all-about-stepper-motors/what-is-a-stepper-motor)
  • Arduino TFT Display and Font Library — Instructables
    (https://www.instructables.com/id/Arduino-TFT-display-and-font-library/)

10 Project Authors

  • Eddyson Canoy
Quality Checked by
  • Lukie-Mar Lonzaga
  • Miles Darren Bagnol
  • Elijah Joseph Orias
Bluetooth-Controlled Mini Lift Using Stepper Motor with Android Mobile App – CreateLabz

 

17hs4401, Android, Arduino, Arduino due, Bluetooth, Driver, Drv8825, Hc-05, Hc05, Ili9341, Knowledgebase, Lcd, Lift, Mit app inventor, Nema, Nema 17, Qvga, Spi, Stepper, Stepper motor, Tft

Leave a comment

All comments are moderated before being published