Making a Robot Play Fetch

0 3648 Medium

Use the new Pixy2 and a DFRobot ESP32 FireBeetle to create a robot that can find and retrieve items!

 

 

 

Things used in this project

HARDWARE LIST
1 DFRobot ESP32 FireBeetle
1 DFRobot Servo Robot Gripper
1 DFRobot 2WD MiniQ Chassis
1 Pixy2 Camera
1 Texas Instruments Dual H-Bridge motor drivers L293D
1 1800mAh 11.1V LiPo Battery

SOFTWARE APPS AND ONLINE SERVICES

· PixyMon

· Arduino IDE

 

HAND TOOLS AND FABRICATION MACHINES

· Soldering iron (generic)

· 3D Printer (generic)

· Hot glue gun (generic)

 

Story

Pixy recently came out with their next version of their Pixy Camera, which can recognize objects and track them. DFRobot sent me one, so I decided to create a robot that can grab an item and then bring it back.

 

Robot Platform

I used a MiniQ robot chassis from DFRobot as the platform that the robot would be built upon. It comes with multiple mounting holes, so I designed a battery riser using Fusion 360 that attaches to a set of holes. Then I mounted the gripper to the front.

 

Pixy Camera Setup

The makers of the Pixy Camera provide a software called PixyMon, which shows what the camera "sees" and lets users adjust parameters, set interfaces, and create color codes. I downloaded and installed PixyMon from their website here. Then I connected the Pixy2 to my PC via USB and went to the File menu and selected Configure.

 

 

First, I set the interface to I2C, as I will be using a non-Arduino board.

 

 

Next, I tuned some miscellaneous settings in the expert menu, as seen in the image.

 

 

Finally, I got out the block I wanted to use and clicked "Set signature 1" under the Action menu. This sets what the Pixy looks for.

 

Wiring

Since I setup the Pixy to use the I2C mode, only 4 wires are needed to connect it to the ESP32 FireBeetle. Just connect SDA, SCL, 5V, and GND.

 

 

 

 

Then I wired up the L293D dual H-bridge DC motor driver to pins IO26, IO27, IO9, and IO10, along with power and output, as seen in this image.

 

Creating the Program

The program "flow" goes as follows:

· Find target block

· Get width and position

· Adjust robot position based on where the block is

· Move forward until it gets close enough

· Grab object

· Reverse backwards

· Release object

Using the Robot

I first put up a piece of white paper for the background to prevent other objects from being accidentally detected. Then, I reset the ESP32 and watched it drive towards the object, grab it, and then return it, as seen in the video.

Schematics

Board Schematic

 

 

ESP32 Code

CODE
#include <ESP32_Servo.h>
#include <Pixy2I2C.h>
#include "esp32-hal-ledc.h"
Pixy2I2C pixy;

#define CENTER 100
#define DEADZONE 10

int motor_pins[] = {26,27,9,10};

Servo gripper;
int servo_pin = 25;
int pos;
int state = 1;

const int freq = 490, resolution = 8;

void setup()
{
  Serial.begin(115200);
  Serial.print("Starting...\n");
  
  pixy.init();
  gripper.attach(servo_pin);
  for(int i=0;i<4;i++){
    ledcAttachPin(motor_pins[i],i+2);
    ledcSetup(i+2,freq,resolution);
    
  }
  set_gripper(0);
  delay(2000);
  set_gripper(1);
}

void loop()
{ 
  int i; 
  // grab blocks!
  pixy.ccc.getBlocks();
  
  // If there are detect blocks, print them!
  if (pixy.ccc.numBlocks)
  {
    //Serial.print("Detected ");
    //Serial.println(pixy.ccc.numBlocks);
    for (i=0; i<pixy.ccc.numBlocks; i++)
    {
      /*Serial.print(pixy.ccc.blocks[i].m_width);
      Serial.print(" ");
      Serial.println(pixy.ccc.blocks[i].m_height);
      /*Serial.print("  block ");*/
      //Serial.print(i);
      //Serial.print(": ");
      //pixy.ccc.blocks[i].print();
      if(pixy.ccc.blocks[i].m_width > 220){
        set_gripper(2);
        move(0);
        state = 0;
        move(4);
        delay(3000);
        move(0);
        set_gripper(1);
        while(1);
      }
    Serial.print(pixy.ccc.blocks[i].m_x);
    Serial.print(",");
    Serial.println(pixy.ccc.blocks[i].m_width);
    }
    if(state==1){
    if(pixy.ccc.blocks[i].m_x >= CENTER-DEADZONE || pixy.ccc.blocks[i].m_x <= CENTER+DEADZONE){
      move(3);
      delay(2);
      move(0);
    }
    else if(pixy.ccc.blocks[i].m_x > CENTER){
      //while(pixy.ccc.blocks[i].m_x > CENTER){
        move(1);
        delay(2);
        move(0);
      //}
    }
    
    else if(pixy.ccc.blocks[i].m_x < CENTER){
      //while(pixy.ccc.blocks[i].m_x < CENTER){
        move(2);
        delay(2);
        move(0);
      //}
    }
  }  
  }
  if(Serial.available()>0){
    pos = Serial.parseInt();
    Serial.println(pos);
    if(pos != 0){
      gripper.write(pos);
    }
  }
  
}

void move(int dir){
  switch(dir){
    case 0: //stop
      ledcWrite(2, 0);
      ledcWrite(3, 0);
      ledcWrite(4, 0);
      ledcWrite(5, 0);
      break;
    case 1: //left
      ledcWrite(2, 120);
      ledcWrite(3, 0);
      ledcWrite(4, 120);
      ledcWrite(5, 0);
      break;
    case 2: //right
      ledcWrite(2, 0);
      ledcWrite(3, 120);
      ledcWrite(4, 0);
      ledcWrite(5, 120);
      break;
    case 3: //forward
      ledcWrite(2, 0);
      ledcWrite(3, 120);
      ledcWrite(4, 120);
      ledcWrite(5, 0);
      break;
    case 4: //back
      ledcWrite(2, 120);
      ledcWrite(3, 0);
      ledcWrite(4, 0);
      ledcWrite(5, 120);
      break;
  }
}

void set_gripper(int state){
  switch(state){
    case 0: 
      gripper.write(180);//closed
      break;
    case 1:
      gripper.write(0);//open
      break;
    case 2:
      gripper.write(60);//grip
      break;
  }
}

The article was first published in Hackster, January 8, 2019

cr: https://www.hackster.io/gatoninja236/making-a-robot-play-fetch-657ebc

author: Arduino “having11” Guy

License
All Rights
Reserved
licensBg
0