Pixy pet robot

Our weekly LIVE video chat. Every Wednesday at 8pm ET!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Pixy pet robot

Post by FutureEngineer »

I am working with pixy camera to implement the pixy pet robot linked below.

https://learn.adafruit.com/pixy-pet-rob ... m/overview

1. I thought pixy an object using the pixymon software, and it works perfectly.

2. I assembled the pan-tilt mechanism and it work's perfectly with arduino and pixymon.

3. I used the code at the pixy-pet-color-vision-follower with the zumo robot, it works perfectly.

4. Now I am modifying the code of the pixy-pet-color-vision-follower to control a car with two 1A/12volts motors
with Arduino motor shield and the results as follow:
the car moves straight,
turns to the left (when the object is located at the left of the camera)
but it never turns to the right even when the object is located to the right, it actually turns to the left again.

Please advise.

Please check the modification to the code:

Code: Select all

int rightSpeed = constrain(forwardSpeed + differential, -400, 400);
	int leftSpeed = constrain(forwardSpeed - differential, -400, 400);
        Serial.print("leftSpeed="); Serial.print(leftSpeed); 
        Serial.print("rightSpeed="); Serial.print(rightSpeed); 
        delay(1000); 

        digitalWrite(12, LOW);digitalWrite(9, LOW); analogWrite(3,rightSpeed  );  
        digitalWrite(13, LOW);digitalWrite(8, LOW); analogWrite(11,leftSpeed ); 

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

analogWrite takes a value from 0-255. The Zumo chassis motor speeds have a range of -400 to +400.

Not very familiar with the Arduino motor shield, but it looks like you are controlling the H-bridges directly. So you need to do 2 things:
1) re-map your speeds to -255 to +255 instead of -400 to +400.
2) Handle the forward and reverse cases separately.

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

Please clarify.

How do I re-map your speeds to -255 to +255 instead of -400 to +400.

What should I change in the code?

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

How do I re-map your speeds to -255 to +255 instead of -400 to +400.

Code: Select all

int rightSpeed = constrain(forwardSpeed + differential, -255, 255);
   int leftSpeed = constrain(forwardSpeed - differential, -255, 255);

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

I modified the code and now it's turning right and left correctly.

I have a few questions on the code itself:

Code: Select all

 forwardSpeed = constrain(400 - (size/256), -100, 400);  
Please explain the formula for calculating the forward speed, what are the "400, 256 and -100" values mean ?

What does

Code: Select all

RCS_CENTER_POS
variable mean ?

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

Please explain the formula for calculating the forward speed, what are the "400, 256 and -100" values mean ?[/quot
As discussed above, 400 is the upper range of the Zumo motor speed. -100 limits our reverse speed to 1/4 of full speed. The 256 is an arbitrary tuning constant to control how close the robot will get to the ball.
What does RCS_CENTER_POS variable mean ?
It is the servo center position as defined by the Zumo library.

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

adafruit_support_bill wrote:analogWrite takes a value from 0-255. The Zumo chassis motor speeds have a range of -400 to +400.

Not very familiar with the Arduino motor shield, but it looks like you are controlling the H-bridges directly. So you need to do 2 things:
1) re-map your speeds to -255 to +255 instead of -400 to +400.
2) Handle the forward and reverse cases separately.

I have two questions on your comments?
1. Should I remap the speed between -255 to 255, or from 0 to 255. Since analog pin ranges from 0 to 255 ?
2. Can you clarify the second point about handling the forward and the everse cases separately.

Waiting for your reply

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

Yes, 0-255 is the output range, so that is how you should re-map it.

And since you can't send a negative value to AnalogWrite, you need to handle the reversal by explicitly reversing the current flow through the H-Bridge. See the documentation for the Arduino Motor shield for details on what pins to set for that.

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

Hi,

I have more inquires about the pixy pet project.
As I mentioned earlier, I replaced the Zumo robot with two 2A motors and Arduino motor shield. I modified the code accordingly. It turns correctly to the right, but it does not go straight and it doesn't correctly turn to the left.

Please check the code:

Code: Select all

#include <SPI.h>  
#include <Pixy.h>
#include <ZumoMotors.h>

#define X_CENTER    160L
#define Y_CENTER    100L
#define RCS_MIN_POS     0L
#define RCS_MAX_POS     1000L
#define RCS_CENTER_POS	((RCS_MAX_POS-RCS_MIN_POS)/2)

//---------------------------------------
// Servo Loop Class
// A Proportional/Derivative feedback
// loop for pan/tilt servo tracking of
// blocks.
// (Based on Pixy CMUcam5 example code)
//---------------------------------------
class ServoLoop
{
public:
	ServoLoop(int32_t proportionalGain, int32_t derivativeGain);

	void update(int32_t error);

	int32_t m_pos;
	int32_t m_prevError;
	int32_t m_proportionalGain;
	int32_t m_derivativeGain;
};

// ServoLoop Constructor
ServoLoop::ServoLoop(int32_t proportionalGain, int32_t derivativeGain)
{
	m_pos = RCS_CENTER_POS;
	m_proportionalGain = proportionalGain;
	m_derivativeGain = derivativeGain;
	m_prevError = 0x80000000L;
}

// ServoLoop Update 
// Calculates new output based on the measured
// error and the current state.
void ServoLoop::update(int32_t error)
{
	long int velocity;
	char buf[32];
	if (m_prevError!=0x80000000)
	{	
		velocity = (error*m_proportionalGain + (error - m_prevError)*m_derivativeGain)>>10;

		m_pos += velocity;
		if (m_pos>RCS_MAX_POS) 
		{
			m_pos = RCS_MAX_POS; 
		}
		else if (m_pos<RCS_MIN_POS) 
		{
			m_pos = RCS_MIN_POS;
		}
	}
	m_prevError = error;
}
// End Servo Loop Class
//---------------------------------------

Pixy pixy;  // Declare the camera object

ServoLoop panLoop(200, 200);  // Servo loop for pan
ServoLoop tiltLoop(150, 200); // Servo loop for tilt

ZumoMotors motors;  // declare the motors on the zumo

//---------------------------------------
// Setup - runs once at startup
//---------------------------------------
void setup()
{
	Serial.begin(9600);
	Serial.print("Starting...\n");
	pixy.init();
        //Setup Channel A
        pinMode(12, OUTPUT); //Initiates Motor Channel A pin
        pinMode(9, OUTPUT); //Initiates Brake Channel A pin
        pinMode(3,OUTPUT);  ////Speed
  
        //Setup Channel B
        pinMode(13, OUTPUT); //Initiates Motor Channel B pin
        pinMode(8, OUTPUT); //Initiates Brake Channel B pin
        pinMode(11,OUTPUT);  ////Speed
}

uint32_t lastBlockTime = 0;

//---------------------------------------
// Main loop - runs continuously after setup
//---------------------------------------
void loop()
{ 
	uint16_t blocks;
	blocks = pixy.getBlocks();

	// If we have blocks in sight, track and follow them
	if (blocks)
	{
		int trackedBlock = TrackBlock(blocks);
		FollowBlock(trackedBlock);
		lastBlockTime = millis();
	}  
	else if (millis() - lastBlockTime > 100)
	{
		//motors.setLeftSpeed(0);
                digitalWrite(13, LOW);digitalWrite(8, HIGH); analogWrite(11, 0); //forward direction B,no Brake, Spins motor at full speed (255)
		//motors.setRightSpeed(0);
                 digitalWrite(12, LOW);digitalWrite(9, HIGH);analogWrite(3, 0);  //forward direction A, no Brake, Spins motor at full speed (255)
		ScanForBlocks(); //Serial.println("Scan for blocks"); 


	}
}

int oldX, oldY, oldSignature;

//---------------------------------------
// Track blocks via the Pixy pan/tilt mech
// (based in part on Pixy CMUcam5 pantilt example)
//---------------------------------------
int TrackBlock(int blockCount)
{
	int trackedBlock = 0;
	long maxSize = 0;

	Serial.print("blocks =");
	Serial.println(blockCount);

	for (int i = 0; i < blockCount; i++)
	{
		if ((oldSignature == 0) || (pixy.blocks[i].signature == oldSignature))
		{
			long newSize = pixy.blocks[i].height * pixy.blocks[i].width;
			if (newSize > maxSize)
			{
				trackedBlock = i;
				maxSize = newSize;
			}
		}
	}

	int32_t panError = X_CENTER - pixy.blocks[trackedBlock].x;
	int32_t tiltError = pixy.blocks[trackedBlock].y - Y_CENTER;

	panLoop.update(panError);
	tiltLoop.update(tiltError);

	pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);

	oldX = pixy.blocks[trackedBlock].x;
	oldY = pixy.blocks[trackedBlock].y;
	oldSignature = pixy.blocks[trackedBlock].signature;
	return trackedBlock;
}

//---------------------------------------
// Follow blocks via the Zumo robot drive
//
// This code makes the robot base turn 
// and move to follow the pan/tilt tracking
// of the head.
//---------------------------------------
int32_t size = 200;
void FollowBlock(int trackedBlock)
{
	int32_t followError = RCS_CENTER_POS - panLoop.m_pos;  // How far off-center are we looking now?
        Serial.print("followError="); Serial.print(followError);
        int leftSpeed = 50; int rightSpeed=50; 
	// Size is the area of the object.
	// We keep a running average of the last 8.
	size += pixy.blocks[trackedBlock].width * pixy.blocks[trackedBlock].height; 
	size -= size >> 3;



        int forwardSpeed = constrain(255 - (size/100), 0, 255);     //// 156, -255 to 255
	int32_t differential = (followError + (followError * forwardSpeed))>>8;
        Serial.print(followError);
	//

        if (followError >15)  
          {
            Serial.print("followError="); Serial.print(followError); Serial.print("Turn left"); 
           digitalWrite(12, LOW);digitalWrite(9, LOW); analogWrite(3,constrain(forwardSpeed + differential, 0, 75));  
           digitalWrite(13, LOW);digitalWrite(8, HIGH); analogWrite(11,0 ); 
           delay(150); 
           digitalWrite(12, LOW);digitalWrite(9, HIGH); analogWrite(3,0  );
           digitalWrite(13, LOW);digitalWrite(8, HIGH); analogWrite(11,0 );  
           delay(150); 
          }
 
        
        
        
        if (followError <-15)   
        {
          Serial.print("followError="); Serial.print(followError); Serial.print("turn right"); 
           digitalWrite(12, LOW);digitalWrite(9, HIGH); analogWrite(3,0  );  
           digitalWrite(13, LOW);digitalWrite(8, LOW); analogWrite(11,constrain(forwardSpeed + differential, 0, 75)); 
           delay(150); 
           digitalWrite(12, LOW);digitalWrite(9, HIGH); analogWrite(3,0  );
           digitalWrite(13, LOW);digitalWrite(8, HIGH); analogWrite(11,0 ); 
           delay(150); 
        } 
         
        
        if (followError >-15  && followError < 15)   
        {
          Serial.print("followError="); Serial.print(followError); Serial.print("forward");
          digitalWrite(12, LOW);digitalWrite(9, LOW); analogWrite(3, 80); 
          digitalWrite(13, LOW);digitalWrite(8, LOW); analogWrite(11,80);
        } 
        
	
     
    
        
}

//---------------------------------------
// Random search for blocks
//
// This code pans back and forth at random
// until a block is detected
//---------------------------------------
int scanIncrement = (RCS_MAX_POS - RCS_MIN_POS) / 150;
uint32_t lastMove = 0;

void ScanForBlocks()
{
	if (millis() - lastMove > 20)
	{
		lastMove = millis();
		panLoop.m_pos += scanIncrement;
		if ((panLoop.m_pos >= RCS_MAX_POS)||(panLoop.m_pos <= RCS_MIN_POS))
		{
			tiltLoop.m_pos = random(RCS_MAX_POS * 0.6, RCS_MAX_POS);
			scanIncrement = -scanIncrement;
			if (scanIncrement < 0)
			{
		
                                digitalWrite(12, HIGH);digitalWrite(9, HIGH); analogWrite(3, 0);  //forward direction A, no Brake, Spins motor at full speed (255)
                                digitalWrite(13, HIGH);digitalWrite(8, HIGH); analogWrite(11,0); //forward direction B,no Brake, Spins motor at full speed (255)


			}
			else
			{

                                digitalWrite(12, HIGH);digitalWrite(9, HIGH); analogWrite(3, 0);  
                                digitalWrite(13, HIGH);digitalWrite(8, HIGH); analogWrite(11,0); 

			}
			delay(random(250, 500));
		}

		pixy.setServos(panLoop.m_pos, tiltLoop.m_pos);
	}
}

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

It turns correctly to the right, but it does not go straight and it doesn't correctly turn to the left.
What does it do when you expect it to go straight or to the left?

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

When turning to the left, it actually goes to the right.

When it's suppose to go straight, it has random movement and it keep spinning around itself.

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

Try reversing the leads to the right-side motor.

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

Is it possible to communicate via Skype,
because I don't think this is the problem.

Regards.

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Pixy pet robot

Post by adafruit_support_bill »

All of our support here is via the forums. The more precisely you can describe the problem, the more likely we will be able to assist.

User avatar
FutureEngineer
 
Posts: 54
Joined: Sat Dec 26, 2015 5:11 pm

Re: Pixy pet robot

Post by FutureEngineer »

Please check attached a screen shoot of the serial monitor.

The robot initialise going to the left, even when no object is present.
Even at the serial monitor, when it's written turn right (negative error), it still turn left.

What could be the error ?
Attachments
Pixy.pdf
(45.92 KiB) Downloaded 37 times

Locked
Please be positive and constructive with your questions and comments.

Return to “Ask an Engineer! VIDEO CHAT (closed)”