Go to Post Meanwhile I'm over here with with my completely see-through poly-carbonate blocker prototype laughing. - JohnFogarty [more]
Home
Go Back   Chief Delphi > Technical > Programming > C/C++
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 16-02-2015, 22:09
amesmich's Avatar
amesmich amesmich is offline
Registered User
FRC #4638 (Jagbots)
Team Role: Teacher
 
Join Date: Nov 2012
Rookie Year: 2012
Location: Maryland
Posts: 101
amesmich is an unknown quantity at this point
Keeping two motors in sync

Excuse any ignorance I may have since I am reaching out on behalf of our programing team. We have two lead screws that we are trying to keep in sync with each other. We are using these encoders which are mechanically attached to the screws. http://www.andymark.com/product-p/am-2899.htm

Does anyoen have any ideas or input as to how they would incorporate a PID loop that would take the encoder values and slow the faster screw down so that both are in sync?

I know it may seem simple to some btu our team is strugling to find an exampl as to how to implement this type of design. ANy info or direction is appreciated. Thanks.

http://cdn3.volusion.com/vyfsn.knvgw...jpg?1421043935
Reply With Quote
  #2   Spotlight this post!  
Unread 16-02-2015, 22:12
wilsonmw04's Avatar
wilsonmw04 wilsonmw04 is offline
Coach
FRC #1086 (Blue Cheese)
Team Role: Teacher
 
Join Date: Dec 2006
Rookie Year: 2007
Location: Midlothian, VA
Posts: 1,877
wilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond reputewilsonmw04 has a reputation beyond repute
Re: Keeping two motors in sync

how close are the screws to each other? The easiest way to do this is to tie them mechanically together with a chain and a pair of sprockets.
__________________
Currently: Coach FRC 1086/FTC 93
2006-2011 Coach FRC 2106/FTC 35
If you come to a FRC event to see a robot competition, you are missing the point.
Reply With Quote
  #3   Spotlight this post!  
Unread 16-02-2015, 22:27
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,044
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: Keeping two motors in sync


What is the driver interface to the lead screws? Is the driver commanding speed or position?

speed: driver pulls joystick back and expects the leadscrews to turn faster in proportion to how far he pulls back

position: driver pulls joystick back and expects the leadscrews to "follow" the joystick angle (height proportional to joystick angle).



Last edited by Ether : 16-02-2015 at 22:36.
Reply With Quote
  #4   Spotlight this post!  
Unread 16-02-2015, 23:32
Kevin Sevcik's Avatar
Kevin Sevcik Kevin Sevcik is offline
(Insert witty comment here)
FRC #0057 (The Leopards)
Team Role: Mentor
 
Join Date: Jun 2001
Rookie Year: 1998
Location: Houston, Texas
Posts: 3,622
Kevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond repute
Send a message via AIM to Kevin Sevcik Send a message via Yahoo to Kevin Sevcik
Re: Keeping two motors in sync

What ether said. The key question is if your pid loop is controlling position or speed.

If you're controlling speed then it's nearly hopeless, since any speed errors will build up over time into large position errors.

If you're controlling position, then it's relatively easy. I'm assuming you have basic familiarity with position PID loops, though. With that caveat, you have two options:
1. Pick one of the screws as a master. This is the only screw you directly command a position for. Set up the other screw as a slave by passing the master's feedback position as the position setpoint/command for the slave. pro: slightly easier to set up, guarantees the slave will be at the same position as the master, even if the master hangs up. Con: slave will always trail the master, since the best it can do is zero error to the master position, and there's bound to be some error. Best for really tightly controlled servos.
2. Two separate pid loops, one for each screw. Command for both pid loops is a single position value that you slowly ramp from one position to the next. Instant changes won't work, because each screw will try to get there as fast as possible, which means at different speeds. Slowly ramping the commanded position means each screw follows the ramped position second by second, which means the screws go up evenly since they're both trying to hit the same target. pros: even movement aside from whatever error is in your pid. Con's: somewhat more complicated, you need to ramp the position somewhat slower than the top speed of the slower motor. Ramping the position too fast means the motors can't keep up and it basically turns back into the instant setpoint change scenario
__________________
The difficult we do today; the impossible we do tomorrow. Miracles by appointment only.

Lone Star Regional Troubleshooter
Reply With Quote
  #5   Spotlight this post!  
Unread 17-02-2015, 08:15
amesmich's Avatar
amesmich amesmich is offline
Registered User
FRC #4638 (Jagbots)
Team Role: Teacher
 
Join Date: Nov 2012
Rookie Year: 2012
Location: Maryland
Posts: 101
amesmich is an unknown quantity at this point
Re: Keeping two motors in sync

Thank you all. We are doing this by position not speed. Are there any examples of code that you may know of that are similar to this setup? If not no big deal, thought this was common enough that there may be.
Reply With Quote
  #6   Spotlight this post!  
Unread 17-02-2015, 08:55
gpetilli gpetilli is offline
Registered User
FRC #1559
 
Join Date: Jan 2009
Location: Victor, NY
Posts: 285
gpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to all
Re: Keeping two motors in sync

Quote:
Originally Posted by amesmich View Post
Thank you all. We are doing this by position not speed. Are there any examples of code that you may know of that are similar to this setup? If not no big deal, thought this was common enough that there may be.
As said in a previous post, the simplest way is to mechanically tie the two systems together. Belts or chains work well for this - you can keep the two motors if you need the extra lift. It can be solved electronically, but it is much more difficult and any mismatch in either speed or position will likely bind up the carriage between the two screws. Our team went with a single screw to eliminate the matching issue.

If you are committed to doing this electronically, Ether posted an architecture in another thread that could work. First you need to "Home" your carriage to a known stop each time you boot and zero your two encoders while you know the carriage is level. Then you make one motor a "partial" slave to the other. In a PID like loop, you drive the master to the desired position P as sensed by encoder E1. You simultaneously drive the second motor to the same position P as sensed by encoder E2 but in addition add the error between the master and slave (E2-E1). This way both motors start moving at the same time, but you also drive the error in final position towards zero. If you update your motor drive voltages fast enough, you may be able to match velocities as well.
Reply With Quote
  #7   Spotlight this post!  
Unread 17-02-2015, 09:20
amesmich's Avatar
amesmich amesmich is offline
Registered User
FRC #4638 (Jagbots)
Team Role: Teacher
 
Join Date: Nov 2012
Rookie Year: 2012
Location: Maryland
Posts: 101
amesmich is an unknown quantity at this point
Re: Keeping two motors in sync

Yes we thought our programing team was capable of this so we did not tie them with a timing belt. We have it 100% built and at this time adding the mechanical tie is not realistic since this is the last day. We do have the limit switches for the home position the problem is our programing team bit off more than they could chew so now we are tryign to help them. That wahy I was looking for sample code of PID loops in C++
Reply With Quote
  #8   Spotlight this post!  
Unread 17-02-2015, 11:51
gpetilli gpetilli is offline
Registered User
FRC #1559
 
Join Date: Jan 2009
Location: Victor, NY
Posts: 285
gpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to allgpetilli is a name known to all
Re: Keeping two motors in sync

http://first.wpi.edu/FRC/roborio/rel...Subsystem.html
Reply With Quote
  #9   Spotlight this post!  
Unread 18-02-2015, 01:07
kylelanman's Avatar
kylelanman kylelanman is offline
Programming Mentor
AKA: Kyle
FRC #2481 (Roboteers)
Team Role: Mentor
 
Join Date: Feb 2008
Rookie Year: 2007
Location: Tremont Il
Posts: 186
kylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to allkylelanman is a name known to all
Re: Keeping two motors in sync

We started out with 2 motors and 2 encoders on a lift with 2 PID loops and could not keep the 2 in sync close enough to prevent binding. We linked them with a criss-cross chain and 2 sprockets and then tied them together in software under the control of 1 PID controller and 1 encoder.

Here was the code we used to tie them together. We like to implement limit switches and inverting of motors if needed as close to the hardware as possible. This ensures the motors are never fighting each other.

Code:
/*
 * DualCANTalon.h
 *
 *  Created on: Jan 29, 2015
 *      Author: Team2481
 */

#ifndef SRC_COMPONENTS_DUALCANTALON_H_
#define SRC_COMPONENTS_DUALCANTALON_H_

#include "WPILib.h"

class DualCANTalon : public PIDOutput {
private:
	CANTalon* mAMotor;
	CANTalon* mBMotor;
	bool mAInverted;
	bool mBInverted;
public:
	DualCANTalon(int motorA, int motorB, bool AInvert, bool BInvert);
	virtual ~DualCANTalon();
	void PIDWrite(float output);
	void Set(float speed);
	float GetOutputCurrent();
	float GetOutputVoltage();
};

#endif /* SRC_COMPONENTS_DUALCANTALON_H_ */
Code:
/*
 * DualCANTalon.cpp
 *
 *  Created on: Jan 29, 2015
 *      Author: Team2481
 */

#include <Components/DualCANTalon.h>


DualCANTalon::DualCANTalon(int motorA, int motorB, bool AInvert, bool BInvert) {
	mAMotor = new CANTalon(motorA);
	mBMotor = new CANTalon(motorB);
	mAInverted = AInvert;
	mBInverted = BInvert;

	mAMotor->ConfigNeutralMode(CANTalon::kNeutralMode_Brake);
	mBMotor->ConfigNeutralMode(CANTalon::kNeutralMode_Brake);
}

DualCANTalon::~DualCANTalon() {
	delete mAMotor;
	delete mBMotor;
}

void DualCANTalon::PIDWrite(float output) {
	Set(output);
}

void DualCANTalon::Set(float speed) {
	mAMotor->Set(mAInverted ? speed * -1 : speed);
	mBMotor->Set(mBInverted ? speed * -1 : speed);
}

float DualCANTalon::GetOutputCurrent() {
	float outputCurrentA = mAMotor->GetOutputCurrent();
	float outputCurrentB = mBMotor->GetOutputCurrent();

	float averageCurrent = (outputCurrentA + outputCurrentB) / 2;

	return averageCurrent;
}

float DualCANTalon::GetOutputVoltage() {
	float outputVoltageA = mAMotor->GetOutputVoltage();
	float outputVoltageB = mBMotor->GetOutputVoltage();

	float averageVoltage = (outputVoltageA + outputVoltageB) / 2;

	return averageVoltage;
}
__________________
"May the coms be with you"

Is this a "programming error" or a "programmer error"?

Reply With Quote
  #10   Spotlight this post!  
Unread 18-02-2015, 02:11
GeeTwo's Avatar
GeeTwo GeeTwo is offline
Technical Director
AKA: Gus Michel II
FRC #3946 (Tiger Robotics)
Team Role: Mentor
 
Join Date: Jan 2014
Rookie Year: 2013
Location: Slidell, LA
Posts: 3,575
GeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond repute
Re: Keeping two motors in sync

Quote:
Originally Posted by kylelanman View Post
We linked them with a criss-cross chain and 2 sprockets and then tied them together in software under the control of 1 PID controller and 1 encoder.
Belt and suspenders? No argument here.

OBTW, by "criss-cross chain", you don't mean a figure 8, do you? It's an idea I had about two years ago when thinking about linkage drives, and that we tried to implement as a novelty in our "infinite possibilities" sign over the pit last year. Operationally, it sounds like a recipe for short chain life.
__________________

If you can't find time to do it right, how are you going to find time to do it over?
If you don't pass it on, it never happened.
Robots are great, but inspiration is the reason we're here.
Friends don't let friends use master links.
Reply With Quote
  #11   Spotlight this post!  
Unread 18-02-2015, 12:51
Kevin Sevcik's Avatar
Kevin Sevcik Kevin Sevcik is offline
(Insert witty comment here)
FRC #0057 (The Leopards)
Team Role: Mentor
 
Join Date: Jun 2001
Rookie Year: 1998
Location: Houston, Texas
Posts: 3,622
Kevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond repute
Send a message via AIM to Kevin Sevcik Send a message via Yahoo to Kevin Sevcik
Re: Keeping two motors in sync

Important question. Are the two lead screws pushing the same carriage, or are they pushing separate carriages?

On our bot, we have two screws and two independent carriages. Each carriage lifts one side of the crate. So we only have to stay mostly level, since we won't have any binding issues or anything. I modified the PID controller class so it ramps setpoints, and we're running two PID loops that ramp the setpoint position at the same rate. If the screws start level, the setpoint positions will stay level since they're moving at the same rate. The screws aren't guaranteed to stay level due to following error, but they manage fairly well. The biggest problem is that (currently) the moving setpoint is the only synchronization between the sides. If the left side jams or hits max command and starts falling behind the setpoint, the right side doesn't know or care and will continue merrily on its way.

Practically speaking, this limits our max speed, since we have to make sure we never have to hit max command for either motor, even under varying battery conditions and loading. That's obviously not ideal, but I'm still working out the most robust way to tackle that problem. Anyways, I have code for this approach if you're interested.

Another approach is what Ether talks about in this thread. There, you're semi-slaving one motor to another, and just commanding pure setpoint positions. I think that will work as well, and will take care of things if the master motor jams or maxes out, but it still doesn't handle things if the slave motor jams or maxes out. You're basically assuming that the master motor/screw is the weaker/easier to jam of the two. I don't have code for that, so you'd have to work out your own modifications to the PIDController class.
__________________
The difficult we do today; the impossible we do tomorrow. Miracles by appointment only.

Lone Star Regional Troubleshooter
Reply With Quote
  #12   Spotlight this post!  
Unread 18-02-2015, 17:02
amesmich's Avatar
amesmich amesmich is offline
Registered User
FRC #4638 (Jagbots)
Team Role: Teacher
 
Join Date: Nov 2012
Rookie Year: 2012
Location: Maryland
Posts: 101
amesmich is an unknown quantity at this point
Re: Keeping two motors in sync

We have the same setup as you two lead screws with two seperate carriages each with their own motors and encoders. So binding is only an issue with the tote. We would like to keep it within 2 inches. We can tolerate more but within 2 is acceptable.

If you dont mind giving us an example we would greatly appreciate it. I could email you or PM you. Our programers understand the concept of PID but were not sure what values to put where. After some reading its becoming more clear, but we have never done it so not sure what we dont know.

Our main problem is that with no load at full speed one side is slightly faster. We want the PID to slow the faster since the slower woudl already be at 100%. So based on this I assume we woudl make our slower lift the "master" and slave the faster side to track the slower? I understand what your saying about the master side continuing even if the other side got stoped for some reason. I would assume you could code it so that if a max seperation value was exceeded you could stop the higher side.

Thanks for your response. This will be our project over the next few weeks.
Reply With Quote
  #13   Spotlight this post!  
Unread 18-02-2015, 17:21
Kevin Sevcik's Avatar
Kevin Sevcik Kevin Sevcik is offline
(Insert witty comment here)
FRC #0057 (The Leopards)
Team Role: Mentor
 
Join Date: Jun 2001
Rookie Year: 1998
Location: Houston, Texas
Posts: 3,622
Kevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond reputeKevin Sevcik has a reputation beyond repute
Send a message via AIM to Kevin Sevcik Send a message via Yahoo to Kevin Sevcik
Re: Keeping two motors in sync

I don't have code for a master-slave system yet. I do have C++ code for a PIDController derivative that will let you smoothly ramp the setpoint from A to B at a given rate. As long as you have the PID loops tuned well and you keep the rate below the max speed for your slower side, things should work and stay level.

I should've asked earlier, but what language are you guys using? If it's C++, I can cleanup and better document my code tonight and post it tomorrow. If it's Java, I'll have to port things, which will take a day or two, and won't be tested, obviously. If it's Labview.... I'll have to think about how to approach the problem in Labview.
__________________
The difficult we do today; the impossible we do tomorrow. Miracles by appointment only.

Lone Star Regional Troubleshooter
Reply With Quote
  #14   Spotlight this post!  
Unread 18-02-2015, 17:27
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,044
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: Keeping two motors in sync


I threw this together quickly. Can you guys critique it? Maybe someone can debug it on real hardware, or in a simulation.

Code:
double change, PosCmd, error1, e1pos, error1i, 
error1d, cmd1, error2a, e2pos, cmd2a, 
error2b, error2bi, cmd2b, cmd2;

// initialize these:

double RLPC = 0;  // Rate-Limited Position Command
double previous_error1 = 0;

// tuning constants:

double rateLimit = 1;  // allowable position change per iteration
double i1Limit = 1;     // integrator clamp for M1
double i2bLimit = 1;   // integrator clamping value for M2
double Kp1 = 0;  // PID gains
double Ki1 = 0;
double Kd1 = 0;
double Kp2 = 0;
double Ki2 = 0;


// this is your control loop:

// rate-limit the change in position command

change = PosCmd - RLPC;
if (change>rateLimit) change = rateLimit;
else if (change<-rateLimit) change = -rateLimit;
RLPC += change;

// PID controller for M1 (Master)

error1 = RLPC - e1pos;  // closed loop error
error1i += error1;  // integrate the error
if (error1i>i1Limit) error1i = i1Limit;  // clamp the integrated error
else if (error1i<-i1Limit) error1i = -i1Limit;
error1d = error1 - previous_error1; // rate of change in error1 for D term
previous_error1 = error1; // save for next iteration
cmd1 = Kp1*error1 + Ki1*error1i + Kd1*error1d;

// P + I controller for M2 (slave)

error2a = RLPC - e2pos;  // closed loop error for Proportional part
cmd2a = Kp2*error2a;

error2b = e1pos - e2pos;  // closed loop error for Integral part
error2bi += error2b;  // integrate the error
if (error2bi>i2bLimit) error2bi = i2bLimit;  // clamp the integrated error
else if (error2bi<-i2bLimit) error2bi = -i2bLimit;
cmd2b = Ki2*error2bi;

cmd2 = cmd2a + cmd2b;



Last edited by Ether : 18-02-2015 at 17:44. Reason: added code comments
Reply With Quote
  #15   Spotlight this post!  
Unread 18-02-2015, 17:49
GeeTwo's Avatar
GeeTwo GeeTwo is offline
Technical Director
AKA: Gus Michel II
FRC #3946 (Tiger Robotics)
Team Role: Mentor
 
Join Date: Jan 2014
Rookie Year: 2013
Location: Slidell, LA
Posts: 3,575
GeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond reputeGeeTwo has a reputation beyond repute
Re: Keeping two motors in sync

I am wondering about the slave part:
Quote:
Originally Posted by Ether View Post
Code:
// P + I controller for M2 (slave)

error2a = RLPC - e2pos;  // closed loop error for Proportional part
cmd2a = Kp2*error2a;

error2b = e1pos - e2pos;  // closed loop error for Integral part
error2bi += error2b;  // integrate the error
if (error2bi>i2bLimit) error2bi = i2bLimit;  // clamp the integrated error
else if (error2bi<-i2bLimit) error2bi = -i2bLimit;
cmd2b = Ki2*error2bi;

cmd2 = cmd2a + cmd2b;
Are you intentionally basing the P value on the error from the set point, but the I value on the error from the master? If so, I'm going to have to puzzle a bit as to what would happen if the master jammed.
__________________

If you can't find time to do it right, how are you going to find time to do it over?
If you don't pass it on, it never happened.
Robots are great, but inspiration is the reason we're here.
Friends don't let friends use master links.
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 13:12.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi