Grin BeanJAmes Lam
Created February 2, 2020 © GPL3+

Auto Recyclables Sorting Machine based on A.I.

Make recycling FUN and the recycling industry GREAT again by accurately sorting recyclables and filtering out inbound contamination.

IntermediateFull instructions provided106
Auto Recyclables Sorting Machine based on A.I.

Things used in this project

Hardware components

NVIDIA Jetson Nano Developer Kit
NVIDIA Jetson Nano Developer Kit
×1
Camera Module V2
Raspberry Pi Camera Module V2
×1
7'' HDMI Display with Capacitive Touchscreen
DFRobot 7'' HDMI Display with Capacitive Touchscreen
×1
Jetson Nano Metal Case
×1
NEMA17 Stepper Motor 0.89N-m
The torque of the motor is proportionate with the size of the turning mechanism that is used. That is, the larger the board or the longer the shaft, the higher the torque. The number of motor sets(stepper motor, stepper motor driver, stepper motor mount, coupler, shaft, shaft mounting bracket, 5 x boards, 2 x 3D-printed board-to-shaft connector) depends on the number of categories you would like to sort. The sorting is binary, so if there are 3 types of recyclables to sort, two sets of motor sets are required.
×1
Stepper Motor Driver DM320
×1
5mm-8mm Coupler
×1
8mm Diameter Shaft 500mm
×1
Stepper Motor Mount for NEMA17
×1
Shaft Mounting Bracket for 8mm Shaft
×1
4mm Acrylic Board
Drawings attached: one circular board, four identical rectangular boards. Other materials, such as wood or metal are also possible depending on the use.
×5
5mm Acrylic Board
Drawings attached. For the casing of AI processing modules (Jetson Nano and camera)
×1
3D-Printed Parts
.stl file attached. Board-to-Shaft Connector, 4040-to-MotorMount Adaptor, 4040-to-ShaftMount Adaptor
×2
Metal frame
Any frame will do. Here we use 4040 Aluminium extrusion for flexibility: 1400mm x 4pcs 1350mm x 5pcs 520mm x 6pcs Connectors with T-nuts and M6x16mm bolts x 30sets CAD model is attached.
×1
Bolts and Nuts
For each motor set: M3x5mm 2pcs for each 4040-MotorMount Adaptor M4x8mm 2pcs for each 4040-ShafyMount Adaptor M4x12mm + M4 nuts 4 sets for each stepper motor mount M6x15mm + M6 nuts 8 sets for every two board-to-shaft connectors
×1
Arduino Mega 2560
Arduino Mega 2560
Other Arduino board is also applicable depending on the number of motors and sensors used.
×1
12V 30A power supply
Can use lower current ones depending on the number of stepper motors you plan to use
×1
USB-A to B Cable
USB-A to B Cable
To connect Jetson Nano to Arduino
×1
Audio / Video Cable Assembly, Ultra Slim RedMere HDMI to HDMI
Audio / Video Cable Assembly, Ultra Slim RedMere HDMI to HDMI
For 7" touch screen
×1
Jumper wires (generic)
Jumper wires (generic)
To connect stepper motor driver to Arduino
×10
2-pin MTE Power Cable
Digilent 2-pin MTE Power Cable
To power Arduino (connect to 12V power supply)
×1
Electric Cable
For power supply, connect to stepper motor driver
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1

Software apps and online services

LabelImg
AWS EC2
Amazon Web Services AWS EC2
YOLO

Hand tools and fabrication machines

Allen keys
M3, M4 and M6 socket head
3D Printer (generic)
3D Printer (generic)
For 3D printing customised parts
Laser cutter (generic)
Laser cutter (generic)
For laser cutting acrylic boards
Breadboard, 270 Pin
Breadboard, 270 Pin
For easy plug and insert during testing
Multitool, Screwdriver
Multitool, Screwdriver
Leveling Ruler

Story

Read more

Custom parts and enclosures

Rectangular 4mm Acrylic Board

Use the file for laser cutting 4mm board
To be attached to shaft for the turning mechanism

Circular 4mm Acrylic Board

Use the file for laser cutting 4mm board
To be attached to the rear part of the turning mechanism, so that the recyclables are isolated from the motor set and other electronics

5mm Acrylic Board

For the casing of AI processing module on top of the metal frame

3D Printed Board-to-Shaft Connector

Design based on 4mm board, 8mm diameter shaft, M6 screws and nuts

3D Printed 4040-to-MotorMount Adaptor

3D Printed 4040-to-ShaftMount Adaptor

Assembly File (SolidWorks 2018)

Schematics

Electronics Connections Schematic Diagram

The diagram shows the connection between Arduino, ultrasonic sensors, stepper motor driver and stepper motor

Code

Arduino code

Arduino
For controlling stepper motors and communicating with Jetson Nano
The code is for sorting 4 types of recyclables, which means, 3 sets of motors and 4 ultrasonic sensors.

When Arduino receives Serial input from Jetson Nano (P for Paper, B for Bottle, C for Can, R for Rubbish), it will control respective motors to turn and use gravity to transfer the item to the correct bin. Once the ultrasonic sensor which is installed at the rim of the bin, detects a distance of less than 5 cm, it will print out warning message.
//defines pins
//Master turnstile motor
const int stepPin = 10;  //PUL -Pulse
const int dirPin = 11; //DIR -Direction
const int enPin = 12;  //ENA -Enable
//Secondary left motor
const int LstepPin = 2;  //PUL -Pulse
const int LdirPin = 3; //DIR -Direction
const int LenPin = 4;  //ENA -Enable
//Secondary right motor
const int RstepPin = 6;  //PUL -Pulse
const int RdirPin = 7; //DIR -Direction
const int RenPin = 8;  //ENA -Enable

//Ultrasonic sensors
const int PtrigPin = 15;  //trigger pin for paper bin
const int PechoPin = 16;  //echo pin for paper bin
const int CtrigPin = 18;  //trigger pin for paper bin
const int CechoPin = 19;  //echo pin for paper bin
const int BtrigPin = 22;  //trigger pin for paper bin
const int BechoPin = 23;  //echo pin for paper bin
const int RtrigPin = 26;  //trigger pin for paper bin
const int RechoPin = 27;  //echo pin for paper bin

int motorpulse = 1200;


//IR sensor
#define IRpin A0            //IR singal pin

//classification of recyclables
char item;

// defines variables
long USduration;
int USdistance;
unsigned long US_int;
unsigned long US_frac;



void setup() {
  Serial.begin(9600);
  
  //Sets the pins as Outputs
  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(enPin,OUTPUT);
  digitalWrite(enPin,HIGH);
  
  pinMode(LstepPin,OUTPUT); 
  pinMode(LdirPin,OUTPUT);
  pinMode(LenPin,OUTPUT);
  digitalWrite(LenPin,LOW);
  
  pinMode(RstepPin,OUTPUT); 
  pinMode(RdirPin,OUTPUT);
  pinMode(RenPin,OUTPUT);
  digitalWrite(RenPin,LOW);

  pinMode(PtrigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(PechoPin, INPUT); // Sets the echoPin as an Input
  pinMode(BtrigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(BechoPin, INPUT); // Sets the echoPin as an Input
  pinMode(CtrigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(CechoPin, INPUT); // Sets the echoPin as an Input
  pinMode(RtrigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(RechoPin, INPUT); // Sets the echoPin as an Input

  pinMode(IRpin, INPUT); // Sets the IRPin as an Input
  
  Serial.println("Program start!");

}

void loop() {
  
  //detection of motion to trigger camera
  IRdetect();

  //detection of bin level
  USdetect();
  
  if (Serial.available())
  {
   
    //input from camera/user to tell which recyclables
    item = Serial.read();
    Serial.println(item);
    switch (item){
      case 'P':
         
         LCW();
         CCW();
         delay(1000);
         LCCW();
         
      break;
      
      case 'C':
         CCW();
         delay(1000);
      break;
      
      case 'B':
         
         RCW();
         CW();
         delay(1000);
         RCCW();
         
      break;
      
      case 'R':
         CW();
         delay(1000);
      break;
    }    
              
  }
  else
    Serial.println("Pending for input...");
    delay(100);

  Serial.println("----------End of loop----------\n\n");

}

//function for Master turnstile motor to go CLOCKWISE, pulse decide how much it turns
void CW()
{
  //Enables the motor direction to move
  digitalWrite(enPin, LOW);
  digitalWrite(dirPin,HIGH);
  Serial.println("Master Going clockwise");
  //400 Pulses for making one full cycle rotation
  for(int x = 0; x < motorpulse; x++){
    //Serial.println(x);
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(50); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(50); 
  }
  //digitalWrite(enPin, HIGH);
}

//function for Master turnstile motor to go ANTI-CLOCKWISE, pulse decide how much it turns
void CCW()
{
  //Enable and change the rotations direction
  digitalWrite(enPin, LOW);
  digitalWrite(dirPin,LOW);
  Serial.println("Master Going anti-clockwise");
  //400 pulses for making one full cycle rotation
  for(int x = 0; x < motorpulse; x++) {
    //Serial.println(x);
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(50);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(50);
  }
  //digitalWrite(enPin, HIGH);
}

//function for Left motor to go CLOCKWISE, pulse decide how much it turns
void LCW()
{
  //Enables the motor direction to move
  digitalWrite(LdirPin,HIGH);
  Serial.println("Left motor going clockwise");
  //400 Pulses for making one full cycle rotation
  for(int x = 0; x < motorpulse; x++){
    //Serial.println(x);
    digitalWrite(LstepPin,HIGH); 
    delayMicroseconds(500); 
    digitalWrite(LstepPin,LOW); 
    delayMicroseconds(500); 
  }
  //One second delay
  delay(1000);
}

//function for Left motor to go ANTI-CLOCKWISE, pulse decide how much it turns
void LCCW()
{
  //Changes the rotations direction
  digitalWrite(LdirPin,LOW);
  Serial.println("Left motor going anti-clockwise");
  //400 pulses for making one full cycle rotation
  for(int x = 0; x < motorpulse; x++) {
    //Serial.println(x);
    digitalWrite(LstepPin,HIGH);
    delayMicroseconds(500);
    digitalWrite(LstepPin,LOW);
    delayMicroseconds(500);

  }
  //One second delay
  delay(1000);
}


//function for Right motor to go CLOCKWISE, pulse decide how much it turns
void RCW()
{
  //Enables the motor direction to move
  digitalWrite(RdirPin,HIGH);
  Serial.println("Right motor going clockwise");
  //400 Pulses for making one full cycle rotation
  for(int x = 0; x < motorpulse; x++){
    digitalWrite(RstepPin,HIGH); 
    delayMicroseconds(500); 
    digitalWrite(RstepPin,LOW); 
    delayMicroseconds(500); 
  }
  //One second delay
  delay(1000);
}

//function for Right motor to go ANTI-CLOCKWISE, pulse decide how much it turns
void RCCW()
{
  //Changes the rotations direction
  digitalWrite(RdirPin,LOW);
  Serial.println("Right motor going anti-clockwise");
  //400 pulses for making one full cycle rotation
  for(int x = 0; x < motorstep; x++) {
    digitalWrite(RstepPin,HIGH);
    delayMicroseconds(500);
    digitalWrite(RstepPin,LOW);
    delayMicroseconds(500);

  }
  //One second delay
  delay(1000);
}


void USdetect() {  

  for (int n = 0; n < 4; n++)
  {
    int trigPin;
    int echoPin;
    switch(n)
    {
      case 0:
        trigPin = PtrigPin;
        echoPin = PechoPin;
      break;

      case 1:
        trigPin = CtrigPin;
        echoPin = CechoPin;
      break;
      
      case 2:
        trigPin = BtrigPin;
        echoPin = BechoPin;
      break;
      
      case 3:
        trigPin = RtrigPin;
        echoPin = RechoPin;
      break;
      
    }
    Serial.print(trigPin);
    // Clears the trigPin
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    
    // Sets the trigPin on HIGH state for 10 micro seconds
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    
    // Reads the echoPin, returns the sound wave travel time in microseconds
    USduration = pulseIn(echoPin, HIGH);
  
    if((USduration < 60000) && (USduration > 1))
    {
      // Calculating the distance
      USdistance= USduration*34/2;
      US_int=USduration/100;
      US_frac=USduration%100;
      
      // Prints the distance on the Serial Monitor
      Serial.print(" Ultrasonic Distance: ");
      Serial.print(US_int, DEC);
  
      if (US_frac<10)
      {
        Serial.print(".");
        Serial.print(US_frac, DEC);
      }
      else
      {
        Serial.print(".0");
      }
      Serial.println (" cm");
      delay (500);
    }
    if (US_int <= 5)
    {
        Serial.println("Warning!!");
        Serial.print(n);
        Serial.println("Bin is almost full!");
    }
    
    USduration = 0;
    Serial.println(n);
  }
  
}

Machine UI

Credits

Grin Bean

Grin Bean

1 project • 0 followers
JAmes Lam

JAmes Lam

1 project • 2 followers
Engineer during weekdays, maker during weekends
Thanks to Glenn Jocher, Tom Leung (member of GrinBean team), Archie Loong (member of GrinBean team), Ivan Lee (member of GrinBean team), and AlexeyAB.

Comments