<< return to Pixycam.com

Integrating Pixy2 and line_zumo_demo code with different motor controller

Hello,

I’m trying to adapt the line_zumo_demo pid example code that comes with the Pixy2 library for my project that uses a Roboclaw 2x30A motor controller and arduino to control a skid-steer robot by pwm. The objective is to track a line on the floor using the pixy2 and use the pid algorithm to enable the robot to steer by pwm. I am however having trouble matching the various parameters so I can get my code working. I was hoping maybe someone could shed some light on how I could do so. Separately, the pixy2 and roboclaw motor controller communicate just fine with the arduino, and I have tested both. How can I adapt the line_zumo_code to work for my robot? I have attached some pictures of my robot setup. Also attached is the line_robo_demo code which is derived from the line zumo code but customized for the roboclaw controller (I commented out some of the line_zumo_demo code instead of deleting it). I have also added the link to the roboclaw.zip library and a copy of the error messages I’m getting while trying to run line_robo_demo. Any suggestions would be greatly appreciated!

Thanks,
Mark

roboclaw links:

http://www.basicmicro.com/downloads

line_robo_demo code:

//
// begin license header
//
// This file is part of Pixy CMUcam5 or “Pixy” for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// [email protected]. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//

#include <Pixy2.h>
#include <PIDLoop.h>
//Includes required to use Roboclaw library
#include <SoftwareSerial.h>
#include “RoboClaw.h”
//See limitations of Arduino SoftwareSerial
SoftwareSerial serial(10,11);
RoboClaw roboclaw(&serial,10000);
#define address 0x80
//#include <ZumoMotors.h>…previous zumo
//#include <ZumoBuzzer.h>…previous zumo

// Robo speeds, maximum allowed is 128
#define ROBO_FAST 64
#define ROBO_SLOW 24
#define X_CENTER (pixy.frameWidth/2)

Pixy2 pixy;
//RoboMotors roboclaw;

//ZumoMotors motors;…previous zumo
//ZumoBuzzer buzzer;…previous zumo

PIDLoop headingLoop(5000, 0, 0, false);

void setup()
{
//Open roboclaw serial ports
roboclaw.begin(38400);
Serial.begin(38400);
roboclaw.ForwardMixed(address,0);
roboclaw.TurnRightMixed(address,0);

Serial.print(“Starting…\n”);
//motors.setLeftSpeed(0);…previous zumo
//motors.setRightSpeed(0);…previous zumo

pixy.init();
// Turn on both lamps, upper and lower for maximum exposure
pixy.setLamp(1, 1);
// change to the line_tracking program. Note, changeProg can use partial strings, so for example,
// you can change to the line_tracking program by calling changeProg(“line”) instead of the whole
// string changeProg(“line_tracking”)
pixy.changeProg(“line”);

// look straight and down
pixy.setServos(500, 1000);
}

void loop()
{
int8_t res;
int32_t error;
int left, right;
char buf[96];

// Get latest data from Pixy, including main vector, new intersections and new barcodes.
res = pixy.line.getMainFeatures();

// If error or nothing detected, stop motors
if (res<=0)
{
roboclaw.ForwardMixed(address,0);
roboclaw.TurnRightMixed(address,0);
//motors.setLeftSpeed(0);
//motors.setRightSpeed(0);
//buzzer.playFrequency(500, 50, 15);
Serial.print("stop ");
Serial.println(res);
return;
}

// We found the vector…
if (res&LINE_VECTOR)
{
// Calculate heading error with respect to m_x1, which is the far-end of the vector,
// the part of the vector we’re heading toward.
error = (int32_t)pixy.line.vectors->m_x1 - (int32_t)X_CENTER;

pixy.line.vectors->print();

// Perform PID calcs on heading error.
headingLoop.update(error);

// separate heading into left and right wheel velocities.
left = headingLoop.m_command;
right = -headingLoop.m_command;

// If vector is heading away from us (arrow pointing up), things are normal.
if (pixy.line.vectors->m_y0 > pixy.line.vectors->m_y1)
{
  // ... but slow down a little if intersection is present, so we don't miss it.
  if (pixy.line.vectors->m_flags&LINE_FLAG_INTERSECTION_PRESENT)
  {
    left += ROBO_SLOW;
    right += ROBO_SLOW;
  }
  else // otherwise, pedal to the metal!
  {
    left += ROBO_FAST;
    right += ROBO_FAST;
  }    
}
else  // If the vector is pointing down, or down-ish, we need to go backwards to follow.
{
  left -= ROBO_SLOW;
  right -= ROBO_SLOW;  
} 
roboclaw.FowrwardMixed(address,left);
roboclaw.TurnRightMixed(address,right);

}

// If intersection, do nothing (we’ve already set the turn), but acknowledge with a beep.
if (res&LINE_INTERSECTION)
//{
// buzzer.playFrequency(1000, 100, 15);
// pixy.line.intersections->print();
// }

// If barcode, acknowledge with beep, and set left or right turn accordingly.
// When calling setNextTurn(), Pixy will “execute” the turn upon the next intersection,
// making the left or right branch in the intersection the new main vector, depending on
// the angle passed to setNextTurn(). The robot will then follow the branch.
// If the turn is not set, Pixy will choose the straight(est) path by default, but
// the default turn can be changed too by calling setDefaultTurn(). The default turn
// is normally 0 (straight).
//if (res&LINE_BARCODE)
//{
// buzzer.playFrequency(2000, 100, 15);
// pixy.line.barcodes->print();
// code==0 is our left-turn sign
// if (pixy.line.barcodes->m_code==0)
// pixy.line.setNextTurn(90); // 90 degrees is a left turn
// code==5 is our right-turn sign
// else if (pixy.line.barcodes->m_code==5)
// pixy.line.setNextTurn(-90); // -90 is a right turn
}
}