Skip to content

4.final project sorter

Sorter

Overview

This is the final version of the sorter within the FabAcademy period👍

Created a circuit design and programming part in week10

You can see it at 0:13 - 0:56 in the following video.

Design with Fusion360

Created shafts (φ8 mm x 800 mm)

Create linear bushing and thread it through the shaft

Linear bush and Timing belt can be attached to the back of the base.

Attached the base.

Attached the stepper motor and the rotary shaft screw

Created the case for the stepper motor and the rotary shaft screw

When the base passes directly over the part with the ultrasonic sensor, the sensor reacts and the lid of the box it passes through opens.

For this reason, I thought of adding a rack and pinion gear in the part where the trash is dropped into the box

Keep the sorter and the boxes a short distance apart, and after the base is in front of the target box, the rack brings the base forward and causes it to react to the ultrasonic sensor.

Create gears to be attached to a stepping motor to operate the rack and pinion.

Each gear has the following parameters.

The left side is the gear attached to the tip of the stepping motor, and the right side is the other larger gear.

The base of the sorter was created as follows

Attach the gears as follows

Next, create the rack and pinion

The pinion gear was created with the following parameters

Referred to How to make rack gear【歯車マスターの道】Fusion360でラックギアを作る方法

The rack gear was created with the following parameters

Duplicate the tooth using the rectangle pattern.

Sketch a rectangle under the teeth

Created a base on which to place the tilting mechanism of the sorter as shown below.

I have made the rack and pinion engage in parallel as they operate.

Create a mechanism to tilt the base on which the object is placed.

I use servo motor to tilt the gears.

The two gears use the same size and the parameters are as follows

Attach the case as follows

put it on the base as follows

Create a case for the servo motor as shown below.

Create a base to put things on.

The base is made of MDF 2.5mm.

A case that allows mounting of the electronic base is attached to the base of the sorter.

Also drilled a hole for the timing belt.

I have covered the top with acrylic to protect the board.

Attach to the guide as follows

Design electric circuit with Kicad

Designed the following

Wired as follows

The electronic parts are as follows

The board is as follows

The wiring is as follows

These are the control pins which are used to control the where EN, SLP and RST control the power states and DIR and STEP control the input.

SLP and RST are shorted because they are not used in this project.

M0, M1, and M2 are pins for use when using microstep, but are not used this time

VMOT, GND: This is the stepper motor power supply pins. Connect 8.2-45V external power supply with VMOT and common ground.

Programming

#include <WiFi.h>
#include <WebServer.h>
#include <ESP32Servo.h>
#include <AccelStepper.h>

#define SSID "ENV_WIFI"
#define PASS "ENV_PASS"

Servo myservo1;

int pos = 80;

#define motorInterfaceType 1

const int dirPin1 = 22;
const int stepPin1 = 23;
const int stepSpeed = 1700;
const int stepsPerRevolution = 200;

AccelStepper myStepper1(motorInterfaceType, stepPin1, dirPin1);

const int dirPin2 = 19;
const int stepPin2 = 21;

AccelStepper myStepper2(motorInterfaceType, stepPin2, dirPin2);

int minUs = 500;
int maxUs = 2400;

WebServer server(80);

void setup()
{
  Serial.begin(115200);
  myservo1.setPeriodHertz(50);
  myservo1.attach(5, minUs, maxUs);
  myservo1.write(80);

  pinMode(stepPin1, OUTPUT);
  pinMode(dirPin1, OUTPUT);

  pinMode(stepPin2, OUTPUT);
  pinMode(dirPin2, OUTPUT);

  connectWiFi();
  server.on("/", handleRoot);
  server.on("/nothing", nothing);
  server.on("/charcol", charcol);
  server.on("/notcharcol", notcharcol);
  server.on("/plastic", plastic);
  server.begin();
  Serial.println("HTTP server started");
}

void loop()
{
  server.handleClient();
}

void connectWiFi()
{
  WiFi.begin(SSID, PASS);
  Serial.println();
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());
}

void handleRoot()
{
  server.send(200, "text/plain", "Hello");
}

void nothing()
{
  server.send(200, "text/plain", "nothing");
}

void charcol()
{
  Serial.println("charcol");

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(2500);
  myStepper1.runToPosition();

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(-150);
  myStepper2.runToPosition();

  delay(500);

  for (pos = 80; pos < 140; pos += 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  for (pos = 140; pos >= 80; pos -= 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(10);
  myStepper2.runToPosition();

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(0);
  myStepper1.runToPosition();

  server.send(200, "text/plain", "charcol");
}

void notcharcol()
{
  Serial.println("notcharcol");

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(1700);
  myStepper1.runToPosition();

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(-150);
  myStepper2.runToPosition();

  for (pos = 80; pos < 140; pos += 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  for (pos = 140; pos >= 80; pos -= 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  delay(500);

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(10);
  myStepper2.runToPosition();

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(0);
  myStepper1.runToPosition();

  server.send(200, "text/plain", "notcharcol");
}

void plastic()
{
  Serial.println("plastic");

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(500);
  myStepper1.runToPosition();

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(-150);
  myStepper2.runToPosition();

  delay(500);

  for (pos = 80; pos < 140; pos += 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  for (pos = 140; pos >= 80; pos -= 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(10);
  myStepper2.runToPosition();

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(0);
  myStepper1.runToPosition();

  server.send(200, "text/plain", "plastic");
}

Explanation of Codes

Library for using wifi

#include <WiFi.h>

Library for use as a web server

#include <WebServer.h>

Library for using servo

#include <ESP32Servo.h>

Library for using stepper

#include <AccelStepper.h>

Define SSID and password

#define SSID "ENV_WIFI"
#define PASS "ENV_PASS"

Create an instance for servo motor

Servo myservo1;

Published values for SG90 servo

int minUs = 500;
int maxUs = 2400;

Define pins to which DRV8825’s STEP & DIR pins are connected.

const int dirPin = 22;
const int stepPin = 23;

const int dirPin2 = 16;
const int stepPin2 = 17;

Set motorInterfaceType to 1. (1 means an external stepper driver with Step and Direction pins)

#define motorInterfaceType 1

Create an instance for each stepper motor

AccelStepper myStepper(motorInterfaceType, stepPin, dirPin);

AccelStepper myStepper2(motorInterfaceType, stepPin2, dirPin2);

Create an instance of the web server to process the web server with the name server. The port number is set to the common port 80

WebServer server(80);

The data transfer rate for serial communication was specified at 115200 bps(baud)

Serial.begin(115200);

Use 50hz servo

servo.attach(pin, min, max)

  • pin: the number of the pin that the servo is attached to

  • min (optional): the pulse width, in microseconds, corresponding to the minimum (0-degree) angle on the servo (defaults to 544)

  • max (optional): the pulse width, in microseconds, corresponding to the maximum (180-degree) angle on the servo (defaults to 2400)

attach() documentation

  myservo1.setPeriodHertz(50);
  myservo.attach(4, minUs, maxUs);

Configures stepper pins to behave as an output

  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);

  pinMode(stepPin2, OUTPUT);
  pinMode(dirPin2, OUTPUT);

Connect WiFi

 connectWiFi();

When starting the web server, define a function for each address.

  server.on("/", handleRoot);
  server.on("/nothing", nothing);
  server.on("/charcol", charcol);
  server.on("/notcharcol", notcharcol);
  server.on("/plastic", plastic);
  server.begin();
  Serial.println("HTTP server started");

In void loop(), only “WebServer.handleClient()” is called, and the processing is described in the each function

void loop() {
  server.handleClient();
}

Configure Wifi Connect settings

void connectWiFi(){
  WiFi.begin(SSID, PASS);
  Serial.println();
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi connected");
  Serial.println(WiFi.localIP());
}

WiFi.begin() to connect to a network

WiFi.begin(SSID, PASS);

Connecting to a Wi-Fi network can take a while, so we usually add a while loop that keeps checking if the connection was already established by using WiFi.status(). When the connection is successfully established, it returns WL_CONNECTED

while(WiFi.status() != WL_CONNECTED){
  delay(500);
  Serial.print(".");
}
void handleRoot(){
  server.send(200, "text/plain", "OK");
}

Return value to client

HTTP 200 OK is the response code returned if the request is successful

server.send(200, "text/plain", "OK");

The main part is writen in the following three functions.

The contents of the following functions are almost the same, the only difference is that they control the moving position of the stepper motors and the different servo motors.

// Flow for trash that can be turned into charcoal

void charcoal(){}

// Flow for trash that cannot be turned into charcoal

void notcharcol(){}

// Flow for plastic
void plastic(){}

Here is an example of charcol() code

void charcol(){

Serial.println("charcol");

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(2500);
  myStepper1.runToPosition();

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(-150);
  myStepper2.runToPosition();

  delay(500);

  for (pos = 80; pos < 140; pos += 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  for (pos = 140; pos >= 80; pos -= 1)
  {
    myservo1.write(pos);
    delay(50);
  }

  myStepper2.setMaxSpeed(1000);
  myStepper2.setAcceleration(50);
  myStepper2.setSpeed(200);
  myStepper2.moveTo(10);
  myStepper2.runToPosition();

  myStepper1.setMaxSpeed(1000);
  myStepper1.setAcceleration(50);
  myStepper1.setSpeed(200);
  myStepper1.moveTo(0);
  myStepper1.runToPosition();

  server.send(200, "text/plain", "charcol");

}

Sets the maximum permitted speed. The run() function will accelerate up to the speed set by this function. Caution: the maximum speed achievable depends on your processor and clock speed. The default maxSpeed is 1.0 steps per second.

myStepper.setMaxSpeed(1000);

Sets the acceleration/deceleration rate.

Parameters [in] acceleration The desired acceleration in steps per second per second. Must be > 0.0. This is an expensive call since it requires a square root to be calculated. Dont call more ofthen than needed

myStepper.setAcceleration(50);

Sets the desired constant speed

myStepper.setSpeed(200);

Set the target position. The run() function will try to move the motor (at most one step per call) from the current position to the target position set by the most recent call to this function. Caution: moveTo() also recalculates the speed for the next step. If you are trying to use constant speed movements, you should call setSpeed() after calling moveTo().

myStepper.moveTo(2500);

Moves the motor (with acceleration/deceleration) to the target position and blocks until it is at position. Dont use this in event loops, since it blocks.

myStepper.runToPosition();

Rotate the servo motor from 80 to 140 degrees, and after that, Rotate it from 140 to 80 degrees, rotating 1 degree every 50 ms.

for (pos = 80; pos < 140; pos += 1)
{
  myservo1.write(pos);
  delay(50);
}

for (pos = 140; pos >= 80; pos -= 1)
{
  myservo1.write(pos);
  delay(50);
}

Packaging

A stepper motor moves the base to the left and right in the x-axis direction.





The timing belt at the base where the things are placed is passed through as follows.

Pull in the direction of the arrow to apply the belt tightly.

The wiring for the stepping motor is hidden by a black tube as shown below.

The servo motor wiring is also hidden with black tubing as shown below.

I installed a Drag Chain I use to hide the wiring of the stepper motor to hide the wiring for the stepper motor.

The drag chain was created by ModelStation

Drag chain is fixed to the acrylic cover of the electrical board

Drag chain is attached to the kerf bending columns as follows.


Last update: June 26, 2022