Conveyor with PWM Speed and Item Counting

Published Jul 01, 2026
 168 hours to build
 Beginner

The system consists of two microcontroller boards, an Arduino Pro Mini and an STM8S103F3P6, each operating independently while complementing one another. The Arduino Pro Mini is responsible for controlling the conveyor motor, including its speed and rotation direction. Meanwhile, the STM8S103F3P6 functions as an automatic item-counting module, displaying the counting results locally on an I2C LCD.

display image

Components Used

STM8S103F3P6
Development Board
1
ST-Link/V2
Programmer Tools
1
FTDI USB
Serial Communication Tools
1
LDR Sensor Module (Light Intensity)
Sensor
1
KY-008: Laser Transmitter Module 5V
Sensor
1
LCD I2C
Display
1
Mini USB cable - USB type A
USB Cable for FTDI
1
Push button 12 x 12 mm
Switch
3
PCB Dot Matrix Single Layer 10cm x 22cm
Circuit Board
1
Arduino Pro Mini
Development Board
1
PL2303 USB
Programmer Tools
1
Gear Motor / Motor DC
Actuators
1
L298N
Motor Driver
1
Potentiometer
Variable Resistor
1
PVC Sheets 3 mm 10 x 50 cm
Chassis
5
Stainless Steel Concrete 30 cm
Shaft
1
EELIC PBB-KFL06P (6 mm)
Bearing Pillow Block
3
1/2 Inch Pipe 25 cm
Roller component
1
Oscar fabric 50 x 137 cm
Conveyor Belt
1
Wood stickers
Accessory
2
PVC Electrical insulation
Accessory
3
Sandpaper G-180 1 m
Roller Covering Material
1
Smart Car Rims
Drive Wheel
1
L Bracket
Conveyor Bracket
24
Hexagonal Spacer Female to Female M3 x 12
Mounting hardware
4
Hexagonal Spacer Female to Male M3 x 20
Mounting hardware
4
Bolts M3 x 8
Mounting hardware
8
Bolts M3 x 20
Mounting hardware
12
Bolts M3 x 30
Mounting hardware
2
Bolts M5 x 25
Mounting hardware
8
Bolts M5 x 20
Mounting hardware
32
Nuts M3
Mounting hardware
14
Nuts M5
Mounting hardware
40
Adaptor DC 5V with Micro USB
Power Supply
1
Adaptor DC 12V 2A
Power Supply
1
Jumper Wires Set
Cable
1
Description

Conveyor with PWM Speed and Item Counting

Helping Small Businesses Improve Production Efficiency

 

Many micro, small, and medium-sized enterprises (MSMEs) still rely on manual methods to transport and count products during production and packaging. As production volume increases, these repetitive tasks become more time-consuming, labor-intensive, and susceptible to human error, reducing operational efficiency and inventory accuracy.

Although industrial conveyor systems with automated counting capabilities are widely available, their cost and implementation complexity often make them inaccessible to small businesses and educational institutions.

As a solution, this project implements a low-cost automated conveyor system that helps improve production efficiency by automating the item counting process while remaining simple, affordable, and easy to build. The prototype demonstrates how practical automation can improve counting accuracy, reduce human error, and support small-scale manufacturing as well as educational applications.

 

What Makes This Conveyor Project Different?

Rather than functioning as a simple miniature conveyor, this prototype incorporates several automation features commonly found in industrial conveyor systems. Operators can manually adjust the conveyor speed using PWM control, change its direction, and rely on an integrated laser–LDR sensing system to count every passing item automatically.

The counting result is displayed instantly on a 16×2 LCD, eliminating repetitive manual counting and helping reduce human error. When a counting session is complete, the counter can be cleared to zero with a dedicated reset button, allowing the system to be reused immediately.

By integrating motor control, object detection, and real-time counting into a single prototype, this project demonstrates that practical industrial automation does not always require expensive equipment. It provides an affordable, easy-to-replicate platform for students, makers, and MSMEs to explore production automation and embedded control systems.

 

Why It Matters

  • Improves Productivity – Automates repetitive item counting during production.
  • Reduces Human Error – Minimizes mistakes caused by manual counting.
  • Affordable Automation – Demonstrates industrial automation using low-cost and widely available components.
  • Educational Platform – Helps students and makers understand motor control, sensors, and embedded systems through hands-on implementation.
  • Scalable Concept – The prototype can be expanded with IoT monitoring, quality inspection, barcode scanning, or sorting mechanisms for more advanced industrial applications.

 

Device Wiring

● Arduino Pro Mini (Motor Speed Control) :

 

● STM8S103F3P6 (Items Counting) :

 

Step 1 : Download & Install Arduino IDE

  1. Please click the following link to download the Arduino IDE : 

    https://bit.ly/ArduinoIDE_Installer

     

  2. Select Legacy IDE (1.8.19).

     

  3. Please select the OS (Operating System) ➜ Click Download.

     

  4. Open the Downloads folder ➜ Select arduino-1.8.19-windows ➜ Right-click ➜ Select Run as administrator.

     

  5. Arduino Setup: License Agreement ➜ Click I Agree.

     

  6. Arduino Setup: Installation Options ➜ Click Next.

     

  7. Arduino Setup: Installation Folder ➜ Click Install.

     

  8. Please wait for the installation to complete.

     

  9. Once the installation is complete ➜ Click Close.

 

Step 2 : Arduino IDE Configuration

  1. Open the Application (.EXE) :

    Arduino IDE

     

  2. Select FilePreferences.

     

  3. In addition to the Arduino board, you must manually fill in the Additional Board Manager URLs field in the Arduino IDE, as shown in the example below :

    https://raw.githubusercontent.com/tenbaht/sduino/master/package_sduino_stm8_index.json

     

     

  4. Select ToolsBoard ➜ Click Boards Manager.

     

  5. Make sure the Arduino AVR board is already installed. If not, you must install it.

     

  6. Then type stm8 ➜ Select Sduino STM8 plain C core (non-C++) by Michael Mayer ➜ Click Install.

     

  7. Wait until the installation is complete ➜ Click Close.

 

Step 3 : Download & Install PL2303 USB Driver

  1. Please click the following link to download the PL2303 USB Driver : 

    https://bit.ly/PL2303P_USBdriver

     

  2. Select PL2303 Prolific DriverInstaller.zip ➜ Click Download.

     

  3. Open the Downloads folder ➜ Right-click ➜ Select Extract Here.

     

  4. Open the folder containing the extracted files ➜ Select PL2303-Prolific_DriverInstaller_v1200 ➜ Right-click ➜ Select Run as administrator.

     

  5. To begin the installation ➜ click Next.

     

  6. Wait until the installation is complete ➜ Click Finish.

 

Step 4 : Download & Install ST-Link USB Driver

  1. Please click the following link to download the ST-Link USB Driver :

    https://bit.ly/STLink_USBdriver

     

  2. Select en.stsw-link009.zip ➜ Click Download.

     

  3. Open the Downloads folder ➜ Right-click ➜ Select Extract Here.

     

  4. Open the folder containing the extracted files ➜ Select dpinst_amd64 ➜ Right-click ➜ Select Run as administrator.

     

  5. To begin the installation ➜ click Next.

     

  6. Wait until the installation is complete ➜ Click Finish.

     

Step 5 : Download & Install FTDI USB Driver

  1. Please click the following link to download the FTDI USB Driver :

    https://bit.ly/CDM_FTDI_USBdriver

     

  2. Select CDM212364_Setup.zip ➜ Click Download.

     

  3. Open the Downloads folder ➜ Right-click ➜ Select Extract Here.

     

  4. Open the folder containing the extracted files ➜ Select CDM212364_Setup ➜ Right-click ➜ Select Run as administrator.

     

  5. To begin the installation ➜ click ExtractNext.

     

  6. License Agreement ➜ Make sure you have selected the option: I accept this agreement. Then click Next.

     

  7. Wait until the installation is complete ➜ Click Finish.

     

Step 6 : Download & Install CH340 USB Driver

  1. Please click the following link to download the CH340 USB Driver :

    https://bit.ly/CH341SER_USB_Driver

     

  2. Select CH341SER.zip ➜ Click Download.

     

  3. Open the Downloads folder ➜ Right-click ➜ Select Extract Here.

     

  4. Open the folder containing the extracted files ➜ Select SETUP ➜ Right-click ➜ Select Run as administrator.

     

  5. To begin the installation ➜ click INSTALL.

     

  6. Wait until the installation is complete ➜ Click OKX.

 

Step 7 : Wiring ST-Link/V2 to the STM8S103F3P6

 

Notes :

  1. The single wire interface module or SWIM is basically used to communicate with the STM8 board.

     

  2. You can see the wiring between the ST-Link/V2 and the STM8S103F3P6 board in detail in the picture above.

     

  3. Based on personal experience, the STM8 can only be programmed with ST-Link.

 

Step 8 : Removing write protection on STM8S103F3P6

The write protection on the STM8S103F3P6 board can be removed through several steps, among others :

 

  1. Connect the STM8S103F3P6 board to the ST-Link/V2, then connect the ST-Link/V2 to a PC or laptop.

     

  2. Open CMD (Command Prompt).

     

  3. Enter into the directory :

    C:\Users\[Computer Name]\AppData\Local\Arduino15\packages\sduino\tools\STM8Tools\2019.02.05\win

     

  4. Input the command :

    stm8flash -cstlinkv2 -pstm8s103?3 -u

     

  5. Press Enter, then you can see the result as the picture below.

 

Step 9 : STM8 (Sduino) I2C Address Scanner

/*
  =====================================================
  I2C Scanner for STM8S103F3P6
  by: Devan Cakra Mudra Wijaya, S.Kom.
  =====================================================

  Functions:
  - Detects all connected I2C devices
  - Displays device addresses in HEX format
  - Displays the total number of detected devices


  =====================================================
  SDA and SCL Pins for STM8S103F3P6
  =====================================================
  SDA -> PB5
  SCL -> PB4
*/

// Include the I2C library for I2C communication
#include "I2C.h"

// Constant that defines the delay between scans (5000 ms = 5 seconds)
const uint16_t SCAN_INTERVAL = 5000;


// The setup() function runs once when the board is powered on or reset
// It is used to initialize hardware, serial communication, sensors, modules, and the program's initial configuration
void setup() {

  // Start Serial communication at 9600 baud rate
  Serial_begin(9600);

  // Wait for 5 seconds before starting the program
  delay(5000);

  // Display program header
  Serial_println_s("====================================");
  Serial_println_s("         I2C DEVICE SCANNER         ");
  Serial_println_s("by: Devan Cakra Mudra Wijaya, S.Kom.");
  Serial_println_s("====================================");

  // Print an empty line
  Serial_println_s("");

  // Initialize I2C communication
  I2C_begin();
}


// The loop() function runs continuously after setup() has finished
// The main program logic is typically placed inside this function
void loop() {

  // Variable to store the error code returned from I2C communication
  uint8_t error;

  // Variable to store the I2C address currently being checked
  uint8_t address;

  // Counter variable for the number of detected devices
  uint8_t deviceCount = 0;

  // Display information indicating that the scan process has started
  Serial_println_s("------------------------------------");
  Serial_println_s("Scanning I2C bus...");
  Serial_println_s("------------------------------------");

  // Loop through addresses from 1 to 126
  // Valid I2C addresses range from 0x01 to 0x7E
  for (address = 1; address < 127; address++) {

    // Perform I2C write transaction (STM8 I2C driver)
    // Used to test ACK response from device
    // Error code depends on I2C driver implementation
    error = I2C_write(address, 0x00);

    // If no error occurs:
    if (error == 0) {

      // Display information that a device was found
      Serial_print_s("[FOUND] Device at address 0x");

      // If the address is less than 16:
      // Add a leading zero to keep HEX formatting aligned
      if (address < 16) {
        Serial_print_s("0");
      }

      // Display the address in HEX format
      Serial_print_ub(address, HEX);
      Serial_println_s("");

      // Increment the detected device count
      deviceCount++;
    }

    // If an unknown error occurs:
    else if (error == 4) {

      // Display an error message
      Serial_print_s("[ERROR] Unknown error at address 0x");

      // If the address is less than 16:
      // Add a leading zero to keep HEX formatting aligned
      if (address < 16) {
        Serial_print_s("0");
      }

      // Display the problematic address in HEX format
      Serial_print_ub(address, HEX);
      Serial_println_s("");
    }

    // If the error is neither 0 nor 4:
    // Ignore it, as this usually means no device exists at that address
  }

  // Print an empty line
  Serial_println_s("");

  // If no devices were found:
  if (deviceCount == 0) {

    // Display a message indicating that no devices were found
    Serial_println_s("No I2C devices found.");
  }
  else { // If at least one device was found:

    // Display the total number of detected devices
    Serial_print_s("Total devices found: ");

    // Display the value of deviceCount
    Serial_print_ub(deviceCount, DEC);
    Serial_println_s("");
  }

  // Display information about the next scan
  Serial_print_s("Next scan in ");

  // Convert milliseconds to seconds
  Serial_print_ub(SCAN_INTERVAL / 1000, DEC);

  // Display the unit in seconds
  Serial_println_s(" seconds.");

  // Empty line
  Serial_println_s("\n");

  // Wait 5 seconds before performing the next scan
  delay(SCAN_INTERVAL);
}

 

Step 10 : Items Counting (auto_counter.ino)

#include <LiquidCrystal_I2C.h>

#define ldrPin PD2
#define laserPin PD3
#define pbPin PD4
#define LCD_ADDR 0x27

int counter = 0;
int currentState = 0;
int previousState = 0;
int ldr = 0; 
bool pushbutton = false;

LiquidCrystal_I2C(lcd, 0x27, 16, 2);

void setup() {
  Serial_begin(9600);
  device_init();
}

void loop() {
  sensor();
  reset();
  display();
}

void device_init(){
  pinMode(pbPin,INPUT);
  pinMode(ldrPin,INPUT);
  pinMode(laserPin,OUTPUT);
  digitalWrite(laserPin,HIGH);
  lcd_begin();
  lcd_backlight();
}

void sensor(){
  ldr = digitalRead(ldrPin);
  if(ldr == LOW){ currentState = 0; }
  if(ldr == HIGH){ currentState = 1; } 
  Serial_print_s("\nTotal items\t: ");
  if(currentState == 1 && currentState != previousState){ counter = counter + 1; Serial_print_i(counter-1); }
  else{ Serial_print_i(counter-1); }
  delay(1000);
}

void reset(){
  pushbutton = digitalRead(pbPin);
  if(previousState != 0 && pushbutton == HIGH){
    counter = 1;
    pushbutton == true;
  }
}

void display(){
  lcd_setCursor(2, 0);
  lcd_print_s("Total items:");
  lcd_setCursor(7, 1);
  lcd_print_i(counter); 
}

 

Step 11 : Upload Firmware to the STM8S103F3P6

  1. Open the Arduino IDE first, then open this project by clicking File -> Open :

    auto_counter.ino

     

  2. Board Setup in Arduino IDE

    Click Tools -> Board -> STM8S Boards -> STM8S103F3 Breakout Board

     

  3. Change Programmer in Arduino IDE

    Click Tools -> Programmer -> ST-Link/V2

     

  4. Before uploading the program please click: Verify.

     

  5. If there is no error in the program code, the next step is to use the STM8 programming tool according to the procedure. Then click: Upload.

     

  6. If there is still a problem when uploading the program, then try checking the driver / port / programmer tool / others section.

 

Step 12 : Wiring FTDI to the STM8S103F3P6

 

Notes :

  1. Serial communication on this STM8S103F3P6 board is very possible, especially for Serial Monitor and Serial Plotter purposes. Tools that can be used for serial communication include: CP2102 USB, CH340 USB, FTDI USB, or with PL2303 USB.

     

  2. You can see the wiring between the FTDI USB and the STM8S103F3P6 board in detail in the picture above.

     

  3. Based on experience, I admit that using FTDI USB or CP2102 USB is much better than PL2303 USB or CH340 USB because they are known to be more stable in performance.

 

Step 13 : Motor Speed Control (pwm_conveyor.ino)

// global variable initialization
#define PB1_PIN PD2 // PD2 pin to push button 1
#define ENA_PIN PD3 // PD3 pin to enable motor A
#define PB2_PIN PD4 // PD4 pin to push button 2
#define IN1_PIN PD5 // PD5 pin to rotate the motor backward
#define IN2_PIN PD6 // PD6 pin to rotate the motor forward
#define PTM_PIN PC0 // PC0 pin to potentiometer

boolean state1 = false, state2 = false; // initialize the status of digital readings on push buttons 1 and 2 into boolean data type
int pot = 0; // initialize the analog reading on potentiometer into integer data type

// Method: setup
void setup() {
  pinMode(PB1_PIN, INPUT_PULLUP);     // PD2 pin is used as an input
  pinMode(ENA_PIN, OUTPUT);           // PD3 pin is used as an output
  pinMode(PB2_PIN, INPUT_PULLUP);     // PD4 pin is used as an input
  pinMode(IN1_PIN, OUTPUT);           // PD5 pin is used as an output
  pinMode(IN2_PIN, OUTPUT);           // PD6 pin is used as an output
  pinMode(PTM_PIN, INPUT_PULLUP);     // PD7 pin is used as an input
}

// Method: loop
void loop() {
  pot = map(analogRead(PTM_PIN), 0, 1023, 0, 255); analogWrite(ENA_PIN, pot); // motor speed control with PWM
  forward(); // calling the forward method
  reverse(); // calling the reverse method
  delay(1000); // delay -> 1 second
}

// Method: forward
void forward(){
  state1 = digitalRead(PB1_PIN); // digital readout of button 1
  if(digitalRead(IN2_PIN)==LOW && state1==LOW){ // if button 1 is pressed when the motor is off then:
    digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, HIGH); state1 = true; // motor rotation will be clockwise
  }
  else if(digitalRead(IN2_PIN)==HIGH && state1==LOW){ // if button 1 is pressed while the motor is running then :
    digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, LOW); state1 = true; // the motor will be shut down as soon as possible
  }
}

// Method: reverse
void reverse(){
  state2 = digitalRead(PB2_PIN); // digital readout of button 2
  if (digitalRead(IN1_PIN)==LOW && state2==LOW) { // if button 2 is pressed when the motor is off then:
    digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); state2 = true; // motor rotation will be counterclockwise
  }
  else if(digitalRead(IN1_PIN)==HIGH && state2==LOW){ // if button 2 is pressed while the motor is running then :
    digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, LOW); state2 = true; // the motor will be shut down as soon as possible
  }
}

 

Step 14 : Upload Firmware to the Arduino Pro Mini

  1. Open the Arduino IDE first, then open this project by clicking File -> Open :

    pwm_conveyor.ino

     

  2. Board Setup in Arduino IDE

    Click Tools -> Board -> Arduino AVR Boards -> Arduino Pro or Pro Mini

     

  3. Change Processor in Arduino IDE

    Click Tools -> Processor -> ATmega328P (5V, 16 MHz)

     

  4. Port Setup in Arduino IDE

    ➤  Click Port.

    ➤  Choose according to your device port (you can see in device manager).

     

  5. Before uploading the program please click : Verify.

     

  6. If there is no error in the program code, then please click : Upload.

     

  7. Some things you need to do when using the Arduino Pro Mini board with PL2303 USB :

    ➤  Arduino IDE information :

          Uploading... -> immediately press the RESET button and release it.

     

    ➤  Wait until the message appears :

          Done Uploading -> The program is directly operated.

     

  8. If there is still a problem when uploading the program, then try checking the driver / port / others section.

 

Step 15 : Wiring PL2303 to the Arduino Pro Mini

 

Notes :

  1. This Arduino Pro Mini is not equipped with a USB port, so you need an additional device in the form of a USB to TTL Serial to connect to a laptop or PC. USB to TTL Serial like the PL2303 USB is commonly used as an intermediate medium for uploading programs.

     

  2. You can see the wiring between the PL2303 USB and the Arduino Pro Mini board in the picture above.

     

  3. To upload a program, in addition to using the PL2303 USB, you can also use other programming tools such as: CP2102 USB, CH340 USB, or with FTDI USB. Based on experience, I admit that using FTDI USB or CP2102 USB is much better than PL2303 USB or CH340 USB because they are known to be more stable in performance.

 

Codes

Downloads

Pictorial Diagram - STM8S103F3P6 Download
Pictorial Diagram - Arduino Pro Mini Download
Block Diagram - STM8S103F3P6 Download
Block Diagram - Arduino Pro Mini Download

Institute / Organization

Universitas Pembangunan Nasional Veteran Jawa Timur
Comments
Ad