<< return to Pixycam.com

Object following Robot

Hello there all of you…I have built a robot using arduino uno, a pixy2 cam, a L298N motor controller and 2 DC motors in order to track objects of different colors in real time…The robot is working but not perfectly…I will appreciate if you have any recommendations for improvement of the code…and also if you can help me attach the pan tilt in the code if this will help the robot.

#include <PIDLoop.h> //###############################################
#include <Pixy2.h> //IMPORTING LIBRARIES
Pixy2 pixy; //###############################################

////////////////////////////////////////////////////////

// ENA IN1 IN2 IN3 IN4 ENB
int myPins[6] = {5, 6, 7, 8, 9, 10}; //VARIABLES DECLARATION. MOTOR CONTROLLER CONNECTED TO PINS 5,6,7,8,9,10. eACH OF THEM REPRESENT THER PARTICULAR ORDER WHOCH IS ENABLE INPUT 1,2,3,4 AND ENABLE

float deadZone = 0.15; //dead zone tha defines where the object will not move at all equals to 15%
int baseSpeed = 250; // base speed that the robot will run

////////////////////////////////////////////////////////

int cont = 0;
int signature, x, y, width, height;
float cx, cy, area;

void setup() {
Serial.begin(9600);
Serial.print(“Starting…\n”);
pixy.init();
for (int i = 0; i < 6; i++) {
pinMode(myPins[i], OUTPUT); //declaring all pins as output using a for loop
}
}

void loop() {
float turn = pixyCheck(); //checking the value of the turn. how much deviation we have from the center using the pixy check function
if (turn > -deadZone && turn < deadZone) { //applying deadzone
turn = 0;
}
if (turn < 0) {
moveRobot(170, -80); //deciding how much to move the robot
}
else if (turn > 0) { //looking if the turn is positive or negative and moving, otherwise keep going forward
moveRobot(-80, 170);
}
else {
moveRobot(70, 70); //takes the value of the left speed and the right speed
}
delay(1);
}

float pixyCheck() {
static int i = 0;
int j;
uint16_t blocks;
char buf[32];
// grab blocks!
blocks = pixy.ccc.getBlocks();

// If there are detect blocks, print them!
if (blocks)
{
signature = pixy.ccc.blocks[0].m_signature;
height = pixy.ccc.blocks[0].m_height; //height of the object
width = pixy.ccc.blocks[0].m_width; //width of the object
x = pixy.ccc.blocks[0].m_x;//x value of the object
y = pixy.ccc.blocks[0].m_y;//y value of the object
cx = (x + (width / 2)); //center x position
cy = (y + (height / 2)); //center y position
cx = mapfloat(cx, 0, 320, -1, 1); // aplying normalization. If value is from 0-320 change from -1 to 1. This helps in the computation
cy = mapfloat(cy, 0, 200, 1, -1);
area = width * height;

        //Serial.print("sig: ");
        //Serial.print(signature);
        //Serial.print(" x:");
        //Serial.print(x);
        //Serial.print(" y:");
        //Serial.print(y);
        //Serial.print(" width: ");
        //Serial.print(width);
        //Serial.print(" height: ");
        //Serial.print(height);
       //Serial.print(" cx: ");
        //Serial.print(cx);
        //Serial.print(" cy: ");
        //Serial.println(cy);

}
else {
cont += 1;
if (cont == 100) {
cont = 0;
cx = 0;
}
}
return cx; //sending back the x location to tell our robot to turn in a particular direction whether is positive or negative
}

float mapfloat(long x, long in_min, long in_max, long out_min, long out_max)
{
return (float)(x - in_min) * (out_max - out_min) / (float)(in_max - in_min) + out_min;
}

void moveRobot(int leftSpeed, int rightSpeed)
{
if (leftSpeed >= 0) {
digitalWrite(myPins[1], 0);
digitalWrite(myPins[2], 1);
}
else {
digitalWrite(myPins[1], 1);
digitalWrite(myPins[2], 0);
}

if (rightSpeed >= 0) {
digitalWrite(myPins[3], 0);
digitalWrite(myPins[4], 1);
}
else {
digitalWrite(myPins[3], 1);
digitalWrite(myPins[4], 0);
}

analogWrite(myPins[0], abs(leftSpeed));
analogWrite(myPins[5], abs(rightSpeed));
}

Hi, could you please indicate more specifically what’s not working?

Thanks,
Jesse

Hello, The problem basically is that the camera often loses the object and that the robot is quite slow comparing to other I have seen.

Hello,
Regarding Pixy losing the object, this page has some good information:

https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:pixy_is_detecting_the_wrong_objects

Use Pixy’s LED to help debug when it’s losing the object. (The LED will illuminate when it detects an object. The color will be the same color as the detected object.) Sometimes the robot’s movement can cause Pixy to lose the object.

Hope this helps :slight_smile:

Edward

Hi, I am doing a similar project. I can see that you have modified the code based off this video:
(https://www.youtube.com/watch?v=w_krOCBk1DE)
To make the robot move faster you can simply change the speed of the motors when they are moving forward. Currently you have the line moveRobot(70, 70); //takes the value of the left speed and the right speed but if you change it to moveRobot(190,190); for example, it will move much faster. You can go up to a speed of 255 I believe. I’m no expert, I myself am trying to figure out the pixy 2 with Arduino Uno and L298N. I have been troubleshooting for weeks and honestly the code you posted here helped me. I hope this helps.

Hello Sammy,
Nice video! Thank you for sharing :slight_smile:

Edward

hello,
i am planning to make a object following robot with pixy2 using this vid https://www.youtube.com/watch?v=w_krOCBk1DE
But the sensor he used is the original pixy.
What changes should i make in the code as the code isnt working for the robot with pixy2 cam.
Can you tell what changes to make in this code.
#include <SPI.h>
#include <Pixy.h>
Pixy pixy;

////////////////////////////////////////////////////////

// ENA IN1 IN2 IN3 IN4 ENB
int myPins[6] = {5, 6, 7, 8, 9, 10};
float deadZone = 0.15;
//int baseSpeed = 130;

////////////////////////////////////////////////////////

int cont = 0;
int signature, x, y, width, height;
float cx, cy, area;

void setup() {
Serial.begin(9600);
Serial.print(“Starting…\n”);
pixy.init();
for (int i = 0; i < 6; i++) {
pinMode(myPins[i], OUTPUT);
}
}

void loop() {
float turn = pixyCheck();
if (turn > -deadZone && turn < deadZone) {
turn = 0;
}
if (turn < 0) {
moveRobot(-80, 170);
}
else if (turn > 0) {
moveRobot(170, -80);
}
else {
moveRobot(70, 70);
}
delay(1);
}

float pixyCheck() {
static int i = 0;
int j;
uint16_t blocks;
char buf[32];
// grab blocks!
blocks = pixy.getBlocks();

// If there are detect blocks, print them!
if (blocks)
{
signature = pixy.blocks[0].signature;
height = pixy.blocks[0].height;
width = pixy.blocks[0].width;
x = pixy.blocks[0].x;
y = pixy.blocks[0].y;
cx = (x + (width / 2));
cy = (y + (height / 2));
cx = mapfloat(cx, 0, 320, -1, 1);
cy = mapfloat(cy, 0, 200, 1, -1);
area = width * height;

//        Serial.print("sig: ");
//        Serial.print(signature);
//        Serial.print(" x:");
//        Serial.print(x);
//        Serial.print(" y:");
//        Serial.print(y);
//        Serial.print(" width: ");
//        Serial.print(width);
//        Serial.print(" height: ");
//        Serial.print(height);
//        Serial.print(" cx: ");
//        Serial.print(cx);
//        Serial.print(" cy: ");
//        Serial.println(cy);

}
else {
cont += 1;
if (cont == 100) {
cont = 0;
cx = 0;
}
}
return cx;
}

float mapfloat(long x, long in_min, long in_max, long out_min, long out_max)
{
return (float)(x - in_min) * (out_max - out_min) / (float)(in_max - in_min) + out_min;
}

void moveRobot(int leftSpeed, int rightSpeed)
{
if (leftSpeed >= 0) {
digitalWrite(myPins[1], 0);
digitalWrite(myPins[2], 1);
}
else {
digitalWrite(myPins[1], 1);
digitalWrite(myPins[2], 0);
}

if (rightSpeed >= 0) {
digitalWrite(myPins[3], 0);
digitalWrite(myPins[4], 1);
}
else {
digitalWrite(myPins[3], 1);
digitalWrite(myPins[4], 0);
}

analogWrite(myPins[0], abs(leftSpeed));
analogWrite(myPins[5], abs(rightSpeed));
}

Hi, please see the email I sent!

For anyone else with this question, Pixy2 uses an updated library and syntax for Arduino. You can update your program to the new syntax, using our documentation as a reference: https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:hooking_up_pixy_to_a_microcontroller_-28like_an_arduino-29#arduino-api

Cheers,
Jesse

hello!!!
in this code include
<SPI.h>
#include <Pixy.h>
Pixy pixy;

////////////////////////////////////////////////////////

// ENA IN1 IN2 IN3 IN4 ENB
int myPins[6] = {5, 6, 7, 8, 9, 10};
float deadZone = 0.15;
//int baseSpeed = 130;

////////////////////////////////////////////////////////

int cont = 0;
int signature, x, y, width, height;
float cx, cy, area;

void setup() {
Serial.begin(9600);
Serial.print(“Starting…\n”);
pixy.init();
for (int i = 0; i < 6; i++) {
pinMode(myPins[i], OUTPUT);
}
}

void loop() {
float turn = pixyCheck();
if (turn > -deadZone && turn < deadZone) {
turn = 0;
}
if (turn < 0) {
moveRobot(-80, 170);
}
else if (turn > 0) {
moveRobot(170, -80);
}
else {
moveRobot(70, 70);
}
delay(1);
}

float pixyCheck() {
static int i = 0;
int j;
uint16_t blocks;
char buf[32];
// grab blocks!
blocks = pixy.getBlocks();

// If there are detect blocks, print them!
if (blocks)
{
signature = pixy.blocks[0].signature;
height = pixy.blocks[0].height;
width = pixy.blocks[0].width;
x = pixy.blocks[0].x;
y = pixy.blocks[0].y;
cx = (x + (width / 2));
cy = (y + (height / 2));
cx = mapfloat(cx, 0, 320, -1, 1);
cy = mapfloat(cy, 0, 200, 1, -1);
area = width * height;

//        Serial.print("sig: ");
//        Serial.print(signature);
//        Serial.print(" x:");
//        Serial.print(x);
//        Serial.print(" y:");
//        Serial.print(y);
//        Serial.print(" width: ");
//        Serial.print(width);
//        Serial.print(" height: ");
//        Serial.print(height);
//        Serial.print(" cx: ");
//        Serial.print(cx);
//        Serial.print(" cy: ");
//        Serial.println(cy);

}
else {
cont += 1;
if (cont == 100) {
cont = 0;
cx = 0;
}
}
return cx;
}

float mapfloat(long x, long in_min, long in_max, long out_min, long out_max)
{
return (float)(x - in_min) * (out_max - out_min) / (float)(in_max - in_min) + out_min;
}

void moveRobot(int leftSpeed, int rightSpeed)
{
if (leftSpeed >= 0) {
digitalWrite(myPins[1], 0);
digitalWrite(myPins[2], 1);
}
else {
digitalWrite(myPins[1], 1);
digitalWrite(myPins[2], 0);
}

if (rightSpeed >= 0) {
digitalWrite(myPins[3], 0);
digitalWrite(myPins[4], 1);
}
else {
digitalWrite(myPins[3], 1);
digitalWrite(myPins[4], 0);
}

analogWrite(myPins[0], abs(leftSpeed));
analogWrite(myPins[5], abs(rightSpeed));
}

i didnt understand this peice
void moveRobot(int leftSpeed, int rightSpeed)
{
if (leftSpeed >= 0) {
digitalWrite(myPins[1], 0);
digitalWrite(myPins[2], 1);
}
else {
digitalWrite(myPins[1], 1);
digitalWrite(myPins[2], 0);
}

if (rightSpeed >= 0) {
digitalWrite(myPins[3], 0);
digitalWrite(myPins[4], 1);
}
else {
digitalWrite(myPins[3], 1);
digitalWrite(myPins[4], 0);
}

analogWrite(myPins[0], abs(leftSpeed));
analogWrite(myPins[5], abs(rightSpeed));
}
could anyone please explain this
thank you

Hi, the part of the code you’re referring to was not written by us…you might want to refer to some Arduino forums.

Hope this helps!

Cheers,
Jesse

hello ,
thank you for replying
could you please tell me why this code is not working.
i put a else statement , to make the motors stop when they dont detect blocks but it doesnt work. 1 motor is always running for no reason , could someone please tell me why?

#include <SPI.h>
#include <Pixy2.h>
#include <PIDLoop.h>
Pixy2 pixy;

// Configure the motor driver.

#include “CytronMotorDriver.h”
// ENA IN1 IN2 IN3 IN4 ENB
int cont = 0;
int signature, x, y, width, height;
float cx, cy, area;

CytronMD motor1(PWM_DIR, 5, 6); // PWM 1 = Pin 3, DIR 1 = Pin 4.
CytronMD motor2(PWM_DIR, 9, 10); // PWM 2 = Pin 9, DIR 2 = Pin 10.
////////////////////////////////////////////////////////

void setup() {
Serial.begin(9600);
Serial.print(“Starting…\n”);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(10,OUTPUT);
pinMode(9,OUTPUT);
pixy.init();

}

void loop()

{
int i;
int x;

// 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(” block “);
Serial.print(i);
Serial.print(”: ");
pixy.ccc.blocks[i].print();
// for example…
x = Serial.println(pixy.ccc.blocks[i].m_x);
Serial.println(pixy.ccc.blocks[i].m_y); // etc…
}
}
else {
motor1.setSpeed(0); // Motor 1 stops.
motor2.setSpeed(0);
}

if (x= constrain(x, 136, 184)){
motor1.setSpeed(128); // Motor 1 runs backward at 50% speed.
motor2.setSpeed(128); // Motor 2 runs forward at 50% speed.
}

if(x < 136){
motor1.setSpeed(-128); // Motor 1 runs backward at 50% speed.
motor2.setSpeed(128); // Motor 2 runs forward at 50% speed.

}
if (x > 184){
motor1.setSpeed(128); // Motor 1 runs forward at 50% speed.
motor2.setSpeed(-128); // Motor 2 runs backward at 50% speed.
}

}

thank you

Hi, I think the issue is that your motor is using some of the same pins that Pixy2 uses for communication with Arduino. The pins Pixy uses are 10 - 13. Your motor 2 is using pin 10 for communication. Try using a different pin.

Can anyone solve the problem.Im doing similar project