Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: PID LS7366LIB MotCon2
Axis.cpp
- Committer:
- jebradshaw
- Date:
- 2015-10-07
- Revision:
- 4:4079f92f9c26
- Parent:
- 3:71447d4fb4f0
- Child:
- 5:79dcaa63700c
File content as of revision 4:4079f92f9c26:
#include "Axis.h"
#include "LS7366.h"
#include "MotCon.h"
#include "PID.h"
Axis::Axis(SPI& spi, PinName cs, PinName pwm, PinName dir, PinName analog, int* limit, float totalCnts): _spi(spi), _cs(cs), _pwm(pwm), _dir(dir) , _analog(analog){
this->_cs = 1; // Initialize chip select as off (high)
this->_pwm = 0.0;
this->_dir = 0;
this->co = 0.0;
this->Tdelay = .01;
this->Pk = 120.0; //80.0; //rough gains, seem to work well but could use tuning
this->Ik = 55.0; //35.0;
this->Dk = 0.0;
this->set_point = 0.0;
this->set_point_last = 0.0;
this->pos = 0.0;
this->vel = 0.0;
this->acc = 0.0;
this->pos_cmd = 0.0;
this->vel_cmd = 0.0;
this->vel_avg_cmd = 0;
this->acc_cmd = 0.0;
this->vel_max = 2700.0 * Tdelay; //counts * Tdelay
this->acc_max = 1200.0 * Tdelay; //counts/sec/sec * Tdelay
this->p_higher = 0.0;
this->p_lower = 0.0;
this->vel_accum = 0.0;
this->moveTime = 0.0;
this->totalCounts = totalCnts;
this->enc = 0;
this->moveStatus = 0; //status flag to indicate state of profile movement
this->moveState = 0; //used for state machine in movement profiles
this->debug = 0;
this->update.attach(this, &Axis::paramUpdate, Tdelay);
this->axisState = 0;
this->pid = new PID(0.0,0.0,0.0,Tdelay); //Kc, Ti, Td, interval
this->ls7366 = new LS7366(spi, cs); //LS7366 encoder interface IC
this->motcon = new MotCon(pwm, dir);
this->ptr_limit = limit;
//start at 0
this->ls7366->LS7366_reset_counter();
this->ls7366->LS7366_quad_mode_x4();
this->ls7366->LS7366_write_DTR(0);
this->set_point = 0.0;
this->pid->setSetPoint(this->set_point);
this->enc = this->ls7366->LS7366_read_counter(); //update class variable
}
void Axis::init(void){
//resets the controllers internals
this->pid->reset();
//Encoder counts limit
this->pid->setInputLimits(-this->totalCounts, this->totalCounts);
//Pwm output from 0.0 to 1.0
this->pid->setOutputLimits(-1.0, 1.0);
//If there's a bias.
this->pid->setBias(0.0);
this->pid->setMode(AUTO_MODE);
this->pid->setInterval(this->Tdelay);
//start at 0
this->ls7366->LS7366_reset_counter();
this->ls7366->LS7366_quad_mode_x4();
this->ls7366->LS7366_write_DTR(0);
this->set_point = 0.0;
this->pid->setSetPoint(this->set_point);
this->enc = this->ls7366->LS7366_read_counter(); //update class variable
//resets the controllers internals
this->pid->reset();
//start at 0
this->set_point = 0.0;
this->pid->setSetPoint(0);
this->pid->setTunings(this->Pk, this->Ik, this->Dk); //turns on controller
}
void Axis::paramUpdate(void){
//testOut = 1;
this->enc = this->ls7366->LS7366_read_counter();
this->pos = (float)this->enc; // * this->countsPerDeg * PI/180.0; //times counts/degree and convert to radians
this->vel = (this->pos - this->pos_last) * this->Tdelay;
this->acc = (this->vel - this->vel_last);
this->pid->setSetPoint(this->set_point);
//Update the process variable.
this->pid->setProcessValue(this->pos);
//Set the new output.
this->co = this->pid->compute();
if(this->axisState)
this->motcon->mot_control(this->co); //send controller output to PWM motor control command
else{
this->co = 0.0;
this->motcon->mot_control(0.0); //turn off motor command
}
this->pos_last = this->pos;
this->vel_last = this->vel;
this->set_point_last = this->set_point;
//testOut = 0;
}
void Axis::center(void){
this->pid->setInputLimits(-this->totalCounts, this->totalCounts);
while(*this->ptr_limit == 1){ // && ({
this->set_point += 100;
this->pid->setSetPoint(this->set_point);
wait(.05);
if(this->debug)
printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
}
wait(.2);
this->set_point -= 1000;
this->pid->setSetPoint(this->set_point);
wait(.6);
while(*this->ptr_limit == 1){
this->set_point += 10;
this->pid->setSetPoint(this->set_point);
wait(.02);
if(this->debug)
printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
}
this->ls7366->LS7366_write_DTR(0); //zero encoder channel
this->set_point = 0.0;
this->pid->setSetPoint(this->set_point);
this->pid->setInputLimits(-(this->totalCounts)/2.0, 0.0); //reset span limits
for(int positionCmd = 0;positionCmd > -this->totalCounts/2.0;positionCmd-=30){
this->set_point = positionCmd; //move arm to center
wait(.01);
if(this->debug)
printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
}
this->set_point = -(this->totalCounts)/2.0;
this->pid->setSetPoint(this->set_point);
//let PID settle to set point
while((this->enc > (this->set_point + 100)) || (this->enc < (this->set_point - 100))){
if(this->debug)
printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
wait(.01);
}
//pc.printf("T=%.2f SP=%.3f co=%.3f enc=%d pos=%.3f Pk=%.2f Ik=%.2f vel=%.3f acc=%.3f\r\n", t.read(), this->set_point, this->co, this->enc, this->pos, this->Pk, this->Ik, this->vel, this->acc);
this->ls7366->LS7366_write_DTR(0); //zero encoder channel
this->set_point = 0.0;
this->pid->setSetPoint(this->set_point);
this->pid->setInputLimits(-(this->totalCounts)/2.0, (this->totalCounts)/2.0); //reset span limits
this->pid->setSetPoint(this->set_point);
if(this->debug)
printf("HOME END:T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
// pc.printf("End Home\r\n\r\n");
}
void Axis::moveUpdate(void){
if(*this->ptr_limit == 0){
this->moveState = 4; //terminate the move
printf("\r\nLimit reached on axis!\r\n");
}
if(this->debug)
printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f limit=%d motI=%.3f\r\n", t.read(), this->set_point, this->co, this->pos, this->vel, this->acc,*this->ptr_limit, this->_analog.read());
switch(this->moveState){
case 0:
break;
//accelerate
case 1:
//testOut = 1;
this->vel_accum += this->acc_cmd * this->Tdelay; //add acceleration to the velocity accumulator
if(this->vel_avg_cmd > 0.0){ //check the sign of the movement
if(this->vel_accum >= this->vel_cmd) //if the accumulator reaches or exceeds the velocity command
this->vel_accum = this->vel_cmd; // only add the velocity command to the accumulator
}
else{ //if the sign was negative
if(this->vel_accum <= this->vel_cmd)
this->vel_accum = this->vel_cmd;
}
//testOut = 0;
this->set_point += this->vel_accum;
//pc.printf("T=%.2f SP=%.3f co=%.3f enc=%d pos=%.3f vel=%.3f acc=%.3f vel_accum=%.2f accelCnt=%.2f \r\n", t.read(), con0.set_point, con0.co, con0.enc, con0.pos, con0.vel, con0.acc, vel_accum, accelCnt);
//pc.printf("acc_up,%.2f,%.3f,%.1f,%.3f,%.3f,%.2f,%.2f\r\n", this->t.read(), this->set_point, this->pos, this->vel, this->acc, this->vel_accum, this->acc_cmd);
if(this->t.read()>=(this->moveTime/3.0) || (abs(this->vel_accum) > abs(this->vel_cmd)))
this->moveState = 2;
break;
//constant velocity
case 2:
//testOut = 1;
//this->vel_accum += this->vel_cmd * this->Tdelay;
this->set_point += this->vel_cmd;
//testOut = 0;
//pc.printf("T=%.2f SP=%.3f co=%.3f enc=%d pos=%.3f vel=%.3f acc=%.3f vel_accum=%.2f accelCnt=%.2f \r\n", t.read(), con0.set_point, con0.co, con0.enc, con0.pos, con0.vel, con0.acc, vel_accum, accelCnt);
//pc.printf("vel_cn,%.2f,%.3f,%.1f,%.3f,%.3f,%.2f,%.2f\r\n", this->t.read(), this->set_point, this->pos, this->vel, this->acc, this->vel_accum, this->acc_cmd);
if(this->t.read()>=(2.0/3.0 * this->moveTime))
this->moveState = 3;
break;
//decelerate
case 3:
this->vel_accum -= this->acc_cmd * this->Tdelay;
this->set_point += this->vel_accum; //ramp down velocity by acceleration
//pc.printf("T=%.2f SP=%.3f co=%.3f enc=%d pos=%.3f vel=%.3f acc=%.3f vel_accum=%.2f accelCnt=%.2f \r\n", t.read(), con0.set_point, con0.co, con0.enc, con0.pos, con0.vel, con0.acc, vel_accum, accelCnt);
//pc.printf("acc_dn,%.2f,%.3f,%.1f,%.3f,%.3f,%.2f,%.2f\r\n", this->t.read(), this->set_point, this->pos, this->vel, this->acc, this->vel_accum, this->acc_cmd);
if(this->vel_avg_cmd > 0.0){
if(this->pos_cmd <= this->pos){
//finish with position command
this->set_point = this->pos_cmd;
this->moveState = 4;
}
}
else{
if(this->pos_cmd >= this->pos){
//finish with position command
this->set_point = this->pos_cmd;
this->moveState = 4;
}
}
if(this->t.read()>=this->moveTime){
//finish with position command
this->set_point = this->pos_cmd;
this->moveState = 4;
}
break;
case 4:
this->moveProfile.detach(); //turn off the trapazoidal update ticker
this->t.stop();
this->moveState = 0;
break;
}//switch moveStatus
return;
}
// position - encoder position to move to
// time - duration of the movement
void Axis::moveTrapezoid(float positionCmd, float time){
this->pos_cmd = positionCmd;
this->moveTime = time;
float enc_distance = this->pos_cmd - (float)this->enc;// * 1.0/con0.countsPerDeg * 180.0/PI;
this->vel_avg_cmd = enc_distance / time;
this->vel_cmd = 1.5 * this->vel_avg_cmd * this->Tdelay;
this->acc_cmd = 4.5 * (enc_distance / (this->moveTime * this->moveTime)) * this->Tdelay;
//pc.printf("tx=%f encdist=%.3f vAvg=%.3f vMax=%.3f Acc=%.3f \r\n", this->moveTime, enc_distance,this->vel_avg_cmd,this->vel_cmd,this->acc_cmd);
//establish encoder velocities and accelerations for position control per Tdelay
this->vel_accum = 0.0;
// this->set_point = this->pos;
this->moveState = 1;
this->t.reset();
this->t.start();
this->moveProfile.attach(this, &Axis::moveUpdate, this->Tdelay);
}
float Axis::readCurrent(void){
motCurrent = this->_analog.read() * 3.3;
return motCurrent;
}
void Axis::axisOff(void){
this->co = 0;
this->axisState = 0;
}
void Axis::axisOn(void){
this->co = 0.0;
this->pid->reset();
//start at 0
this->set_point = 0.0;
this->pid->setSetPoint(0);
this->pid->setTunings(this->Pk, this->Ik, this->Dk); //turns on controller
this->axisState = 1;
}