Serial interface for controlling robotic arm.

Dependencies:   Axis mbed

This program uses a LPC1768 processor for controlling a robotic arm. The basis for the program is the Axis () class which uses a PID controller to actuate a DC motor with quadrature encoder feedback.

Youtube video of robotic arm using the 6-axis controller performing an internally programmed gate, then performing the home function.

https://developer.mbed.org/users/jebradshaw/code/Axis/

The Axis Class has 3 dependencies (MotCon, LS7366LIB, and PID). The class encapsulates the required functionality of controlling a DC motor with encoder feedback through pin assignments, an SPI bus, and a pointer for the limit switch source.

The LS7366 encoder interface IC off-loads the critical time and counting requirements from the processor using an SPI bus interface for the class. The Axis class then uses a state machine to perform trapezoidal movement profiles with a Ticker class. Parameters can be adjusted through the serial interface using a FT232RL USB to serial interface IC for computer communication.

The MotCon class is a basic class that defines a PWM output pin and a single direction signal intended to control an H-Bridge motor driver IC. I used an MC33926 motor driver for each motor which are rated at 5.0-28V and 5.0 amp peak, with an RDSon max resistance of 225 milli-ohms. This part also has 3.0V to 5V TTL/CMOS inputs logic levels and various protection circuitry on board. I also liked this particular motor driver chip because you can use a PWM frequency of up to 20KHz, getting the frequency out of the audio range.

/media/uploads/jebradshaw/axiscontroller_protoboardsmall.jpg

Above is the prototype for the controller. Originally, a PCF8574 I/O expander was used to read the limit switches by the I2C bus. This has now been re-written to use 6 external interrupts directly for the limit/homing switches. Six motor driver breakout boards using the MC33926 motor driver chip were used to drive the motors.

I use the mbed online compiler to generate the .bin file, use bin2hex to convert it and upload the hex file using Flash Magic to the processor with the serial bootloader. I prefer to use the FT232RL usb to serial converter IC for PC comms due to the high level of reliability and USB driver support (typically already built in Windows 7+). I've started putting this on a PCB and hope to finish by the end of the month (Dec 2015).

Well 3 months later, I've completed the first PCB prototype. A few minor errors but it's working!!

/media/uploads/jebradshaw/pcb_artwork.jpg Express PCB Artwork

/media/uploads/jebradshaw/6axiscontroller_innerpowerlayer.jpg Inner Power Layer Breakup for motor current

/media/uploads/jebradshaw/6axiscontroller_pcb_prototype_trimmed.jpg First Prototype

/media/uploads/jebradshaw/lpc1768_axiscontroller_part1_20161214.bmp

/media/uploads/jebradshaw/lpc1768_axiscontroller_part2_20161216.bmp

/media/uploads/jebradshaw/lpc1768_axiscontroller_part3_20161216.bmp

/media/uploads/jebradshaw/lpc1768_axiscontroller_part4_20190124_2.jpg

Latest documentation (schematic and parts layout) can be found here Download and open with Adobe /media/uploads/jebradshaw/axiscontroller_schematics_v2.0.pdf

Latest PCB File (Express PCB) /media/uploads/jebradshaw/lpc1768_axiscontroller_20161216.pcb

Parts Layout /media/uploads/jebradshaw/silkscreen_top_stencil.jpg /media/uploads/jebradshaw/axiscontroller_bottommirrorimage_20161216.jpg

Python script for converting mbed .bin output to intel hex format (no bin2hex 64K limit) https://pypi.python.org/pypi/IntelHex

Example batch script for speeding up conversion process for FlashMagic (http://www.flashmagictool.com/) programming of board /media/uploads/jebradshaw/axisconvert.bat

https://os.mbed.com/users/jebradshaw/code/axis_ScorbotController_20180706/

Latest firmware: 20190823 - /media/uploads/jebradshaw/axis_scorbotcontroller_20190823_velocity_test.lpc1768.bin

lpc_axis.cpp

Committer:
jebradshaw
Date:
2015-12-28
Revision:
4:890c104546e9
Parent:
3:1892943e3f25

File content as of revision 4:890c104546e9:

// Test program for WSE-PROJ-SBC Scorbot Interface
// J Bradshaw
//lpc_axis.cpp

// 20150731
// 20150827 - Got Ticker Trapeziodal profile command working (moveTrapezoid, muveUpdate) 
// 20150924 - Port from the mbed to the LPC1768 processor for the 6 axis robotic arm controller
// 20151218 - Eliminated PCF8574 I2C I/O expander and attached limit switches to P0_22 - P0_17
//             pins as external interrupts.

#include "mbed.h"
#include "Axis.h"
#include "stdlib.h"

#include <string>

#define PI 3.14159
#define SP_TOL 100  // SET POINT TOLERANCE is +/- tolerance for set point command

// Assign interrupt function to pin P0_17 (mbed p12)

DigitalOut led1(P1_18); //blue
DigitalOut led2(P1_20); //
DigitalOut led3(P1_21);

Serial pc(P0_2, P0_3);    //pc serial interface (USB)
SPI spi(P0_9, P0_8, P0_7);        //MOSI, MISO, SCK

DigitalIn limit1_pin(P0_22);
DigitalIn limit2_pin(P0_21);
DigitalIn limit3_pin(P0_20);
DigitalIn limit4_pin(P0_19);
DigitalIn limit5_pin(P0_18);
DigitalIn limit6_pin(P0_17);

InterruptIn limit1_int(P0_22);
InterruptIn limit2_int(P0_21);
InterruptIn limit3_int(P0_20);
InterruptIn limit4_int(P0_19);
InterruptIn limit5_int(P0_18);
InterruptIn limit6_int(P0_17);

int limit1, limit2, limit3, limit4, limit5, limit6;         //global limit switch values
float axis1_I,axis2_I,axis3_I,axis4_I,axis5_I,axis6_I;
int streamFlag=0;
Timer t;
//instantiate axis object NAME(spi bus, LS7366_cs, pwm, dir, analog, limitSwitchAddress, TotalEncoderCounts/axis)
Axis axis1(spi, P1_24, P2_5, P1_0, P0_23, &limit1, 25000.0);   //base
Axis axis2(spi, P1_25, P2_4, P1_1, P0_24, &limit2, 17500);     //shoulder
Axis axis3(spi, P1_26, P2_3, P1_4, P0_25, &limit3, 20500);     //elbow
Axis axis4(spi, P1_27, P2_2, P1_8, P0_26, &limit4, 5000);      //pitch/roll
Axis axis5(spi, P1_28, P2_1, P1_9, P1_30, &limit5, 5000);      //pitch/roll
Axis axis6(spi, P1_29, P2_0, P1_10, P1_31, &limit6, 5400);     //grip

Ticker pulse;
Ticker colCheck;


void zero_axis(int axis){
    switch(axis){                                        
        case 1:
            axis1.zero();
        break;
        
        case 2:
            axis2.zero();
        break;
        
        case 3:
            axis3.zero();
        break;
        
        case 4:
            axis4.zero();
        break;
        
        case 5:
            axis5.zero();             
        break;
        
        case 6:
            axis6.zero();
        break;                                                                                                    
    }    
}

void zero_all(void){    
    for(int i=1;i<=6;i++){
        zero_axis(i);
        wait(.005);
    }
}
    
void alive(void){
    led1 = !led1;
    if(led1)
        pulse.attach(&alive, .2); // the address of the function to be attached (flip) and the interval (2 seconds)     
    else
        pulse.attach(&alive, 1.3); // the address of the function to be attached (flip) and the interval (2 seconds)
}

void collisionCheck(void){
    float stall_I = .3;
    
    axis1_I = axis1.readCurrent();
    axis2_I = axis2.readCurrent();
    axis3_I = axis3.readCurrent();
    axis4_I = axis4.readCurrent();        
    axis5_I = axis5.readCurrent();
    axis6_I = axis6.readCurrent();
//    pc.printf("%.3f %.3f %.3f %.3f %.3f %.3f \r\n", axis1_I, axis2_I, axis3_I, axis4_I, axis5_I, axis6_I);
        
    //analog channels 1 and 2 are damaged on initial prototype test bed
    if(axis1_I > stall_I){
        pc.printf("Axis 1 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();        
    }
    if(axis2_I > stall_I){
        pc.printf("Axis 2 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();        
    }
    if(axis3_I > stall_I){
        pc.printf("Axis 3 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();        
    }
    if(axis4_I > stall_I){
        pc.printf("Axis 4 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();        
    }
    if(axis5_I > stall_I){
        pc.printf("Axis 5 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();        
    }    
    if(axis6_I > stall_I){
        pc.printf("Axis 6 collision detected");
        axis1.axisOff();
        axis2.axisOff();
        axis3.axisOff();
        axis4.axisOff();
        axis5.axisOff();
        axis6.axisOff();
    }                      
}

void home_test(void){
    
    axis1.zero();
    axis2.zero();
    axis3.zero();
    
    axis1.pid->setInputLimits(-30000, 30000); 
    axis2.pid->setInputLimits(-30000, 30000); 
    axis3.pid->setInputLimits(-30000, 30000); 
        
    for(float delta=0.0;delta<200.0 && (*axis2.ptr_limit == 1) && (*axis3.ptr_limit == 1);delta+=100){
        axis3.set_point = delta;
        axis4.set_point = .23 * delta;
        axis5.set_point = .23 * -delta;
        wait(.5);        
    }
    zero_axis(3);
    
    for(float delta=0.0;delta>-13000.0 && (*axis3.ptr_limit == 1);delta-=100){
        axis3.set_point = delta;
        axis4.set_point = .249 * delta;
        axis5.set_point = .249 * -delta;
        wait(.5);        
    }             

    for(float delta=0.0;delta>-18000.0 && (*axis2.ptr_limit == 1);delta-=100){
        axis2.set_point = delta;
        axis3.set_point = -delta;
        axis4.set_point = .249 * delta;
        axis5.set_point += .249 * -delta;
        wait(.5);        
    }
    zero_axis(2);
    
    for(float delta=0.0;delta<300.0 ;delta-=10){
        axis3.set_point = delta;
        axis4.set_point = .249 *-delta;
        axis5.set_point = .249 * delta;
        wait(.1);        
    }
    zero_axis(2);
}

int home_pitch_wrist(void){        
    axis4.pid->setInputLimits(-50000, 50000); 
    axis5.pid->setInputLimits(-50000, 50000); 
    
    axis4.axisOn();
    axis5.axisOn();
    
    axis4.zero();
    axis5.zero();
    
    //first test to see if limit switch is already pressed
    if(limit4 == 0){
        pc.printf("Stage 1\r\n");
        pc.printf("Limit switch 4 is already closed, moving up to release switch\r\n");
        //move wrist up until limit switch is released again
        while(limit4 == 0){            
            pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit4, axis4.readCurrent(), axis5.readCurrent());
            axis4.set_point -= 10;
            axis5.set_point += 10;
            wait(.08);
        }
        pc.printf("Switched released\r\n");
        axis4.zero();
        axis5.zero();
        pc.printf("Encoders zeroed\r\n");
        wait(.02);
        
        pc.printf("Moving up to zero\r\n");
        axis4.set_point = -1350;
        axis5.set_point = 1350;
        
        wait(2.0);
        
        return 0;   //successful home of gripper                                
    }
    else{
        pc.printf("Stage 2\r\n");
        axis4.zero();   //zero wrist motors
        axis5.zero();
        pc.printf("Move down\r\n");
        while(limit4 == 1){
            pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit4, axis4.readCurrent(), axis5.readCurrent());
            axis4.set_point += 50;
            axis5.set_point -= 50;
            wait(.05);
            if(axis4.readCurrent() > .25){
                pc.printf("Over Current detected on Axis 3\r\n");
                axis4.zero();
                axis5.zero();
                
                axis4.set_point -= 3500;
                axis5.set_point += 3500;
                                        
                wait(2.0);
                
                axis4.zero();
                axis5.zero();
                
                return -1;    
            }
            if(axis5.readCurrent() > .25){
                pc.printf("Over Current detected on Axis 5\r\n");
                axis4.zero();
                axis5.zero();
                
                axis4.set_point -= 3500;
                axis5.set_point += 3500;
                                        
                wait(2.0);
                
                axis4.zero();
                axis5.zero();
                                             
                return -2;
            }                           
        }
        
        if(limit4 == 0){
            while(limit4 == 0){
                pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit4, axis4.readCurrent(), axis5.readCurrent()); 
                axis4.set_point -= 50;
                axis5.set_point += 50;
                wait(.08);
                if(axis4.readCurrent() > .25){
                    pc.printf("Over Current detected on Axis 4\r\n");
                    axis4.zero();
                    axis5.zero();
                    
                    axis4.set_point -= 3500;
                    axis5.set_point += 3500;
                                            
                    wait(2.0);
                    
                    axis4.zero();
                    axis5.zero();
                    
                    return -1;    
                }
                if(axis5.readCurrent() > .25){
                    pc.printf("Over Current detected on Axis 5\r\n");
                    axis4.zero();
                    axis5.zero();
                    
                    axis4.set_point -= 3500;
                    axis5.set_point += 3500;
                                            
                    wait(2.0);
                    
                    axis4.zero();
                    axis5.zero();
                                                 
                    return -2;
                }
            }            
            axis4.zero();
            axis5.zero();
            wait(.02);
        
            axis4.set_point = -1350;
            axis5.set_point = 1350;
        
            wait(1.2);
            axis4.zero();
            axis5.zero();
                        
            return 0;   //successful home of gripper                  
        }
    } 
    return -3;  //should have homed by now               
}

void home_rotate_wrist(void){
    axis4.axisOn();
    axis5.axisOn();
        
    while(limit5 == 0){
        axis4.set_point -= 100;
        axis5.set_point -= 100;
        wait(.05);
        pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit5, axis4.readCurrent(), axis5.readCurrent()); 
    }
    axis4.set_point -= 10;
    axis5.set_point -= 10;
    wait(.05);

    while(limit5 == 1){
        pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit5, axis4.readCurrent(), axis5.readCurrent()); 
        axis4.set_point += 10;
        axis5.set_point += 10;
        wait(.03);
    }
    
    axis4.zero();    
    axis5.zero();
    
    pc.printf("Find amount to rotate to after switch is high again...\r\n");
    wait(1.0);
    
    for(float pos=0;pos>-800.0;pos-=100){
        axis4.set_point = pos;
        axis5.set_point = pos;
        wait(.05);
        pc.printf("axis4=%.1f   axis5=%.1f   sw=%1d   I4=%f  I5=%f \r\n", axis4.pos, axis5.pos, limit5, axis4.readCurrent(), axis5.readCurrent()); 
    }
    axis4.zero();    
    axis5.zero();            
}

void cal_gripper(void){
    axis6.axisOn();
    pc.printf("\r\n Axis On, Homeing Gripper\r\n");
    pc.printf("axis6=%.1f  I6=%f \r\n", axis6.pos, axis6.readCurrent()); 
    axis6.zero();
    
    while((axis6.readCurrent() < .8) && (axis6.set_point > -6000)){
        axis6.set_point -= 10;
        wait(.01);
        pc.printf("axis6=%.1f I6=%f \r\n", axis6.pos, axis6.readCurrent()); 
    }
    axis6.set_point += 50;
    wait(.05);
    axis6.zero();
    wait(.02);
    
    while((axis6.readCurrent() < .8) && (axis6.set_point < 6000)){
        axis6.set_point += 10;
        wait(.01);
        pc.printf("axis6=%.1f I6=%f \r\n", axis6.pos, axis6.readCurrent()); 
    }
    
    axis6.totalCounts = axis6.set_point;
    wait(.05);                
    
    axis6.set_point = axis6.totalCounts/2.0; //~4500 total span, ~2200 to half close
    wait(2.0);
 //   axis6.zero();       //may remove later for 0 = grip closed    
}

void all_on(void){
    axis1.axisOn();
    axis2.axisOn();
    axis3.axisOn();
    axis4.axisOn();
    axis5.axisOn();
    axis6.axisOn();            
}

void all_off(void){
    axis1.axisOff();
    axis2.axisOff();
    axis3.axisOff();
    axis4.axisOff();
    axis5.axisOff();
    axis6.axisOff();     
}

void limit1_irq(void){
    limit1 = limit1_pin;
    
    if(limit1)
        limit1_int.fall(&limit1_irq);
    else
        limit1_int.rise(&limit1_irq);        
}

void limit2_irq(void){
    limit2 = limit2_pin;
    
    if(limit2)
        limit2_int.fall(&limit2_irq);
    else
        limit2_int.rise(&limit2_irq);
}

void limit3_irq(void){
    limit3 = limit3_pin;
    
    if(limit3)
        limit3_int.fall(&limit3_irq);
    else
        limit3_int.rise(&limit3_irq);
}

void limit4_irq(void){
    limit4 = limit4_pin;
    
    if(limit4)
        limit4_int.fall(&limit4_irq);
    else
        limit4_int.rise(&limit4_irq);
}

void limit5_irq(void){
    limit5 = limit5_pin;
    
    if(limit5)
        limit5_int.fall(&limit5_irq);
    else
        limit5_int.rise(&limit5_irq);
}

void limit6_irq(void){
    limit6 = limit6_pin;
    
    if(limit6)
        limit6_int.fall(&limit6_irq);
    else
        limit6_int.rise(&limit6_irq);
}
void init_limitSwitches(void){
    
    //Limit switch 1 initial state
    limit1 = limit1_pin;
    if(limit1)
        limit1_int.fall(&limit1_irq);
    else
        limit1_int.rise(&limit1_irq);
                
    //Limit switch 2 initial state
    limit2 = limit2_pin;
    if(limit2)
        limit2_int.fall(&limit2_irq);
    else
        limit2_int.rise(&limit2_irq);
        
    //Limit switch 3 initial state
    limit3 = limit3_pin;
    if(limit3)
        limit3_int.fall(&limit3_irq);
    else
        limit3_int.rise(&limit3_irq);

    //Limit switch 4 initial state
    limit4 = limit4_pin;
    if(limit4)
        limit4_int.fall(&limit4_irq);
    else
        limit4_int.rise(&limit4_irq);

    //Limit switch 5 initial state
    limit5 = limit5_pin;
    if(limit5)
        limit5_int.fall(&limit5_irq);
    else
        limit5_int.rise(&limit5_irq);

    //Limit switch 6 initial state
    limit6 = limit6_pin;
    if(limit6)
        limit6_int.fall(&limit6_irq);
    else
        limit6_int.rise(&limit6_irq);

}
//------------------- MAIN --------------------------------
int main()
{        
    wait(.5);
    pulse.attach(&alive, 2.0); // the address of the function to be attached (flip) and the interval (2 seconds)
 
    pc.baud(921600);
    pc.printf("\r\n%s\r\n", __FILE__); //display the filename (this source file)
    
    init_limitSwitches();   //get initial states of limit switches
      
    axis1.init();
    axis2.init();
    axis3.init();
    axis4.init();
    axis5.init();
    axis6.init();
    
    axis6.Pk = 40.0;
    axis6.Ik = 20.0;
    
 //   axis1.debug = 1;
 //   axis2.debug = 1;
 //   axis3.debug = 1;
 //   axis4.debug = 1;
 //   axis5.debug = 1;
 //   axis6.debug = 1;
    
    t.start();  // Set up timer 
        
    while(1){
        
        if(pc.readable())
        {
            char c = pc.getc();
            
            if(c == '?')    //get commands
            {
                pc.printf("? - This menu of commands\r\n");
                pc.printf("0 - Zero all encoder channels\r\n");
                pc.printf("A - All: Enable/Disable All axes. Then 'O' for On and 'F' for Off\r\n");                
                pc.printf("C - Current: Stream the Motor Currents\r\n");
                pc.printf("J - Stream Flag: Enable/Disable Stream. Then '1' for On and '0' for Off\r\n");
                pc.printf("W - Wrist: Home the Gripper Wrist\r\n");
                pc.printf("U - Up: Bring up from typical starting position (Not HOME!)\r\n");
                pc.printf("T - Trapezoidal Profile Move command\r\n");
                pc.printf("H- Home\r\n");
                pc.printf("S- Set point in encoder counts\r\n");
                pc.printf("Z - Zero Encoder channel\r\n");
                pc.printf("X - Excercise Robotic Arm\r\n");
                pc.printf("O - Axis to turn On \r\n");
                pc.printf("F - Axis to turn Off (Default)\r\n");
                pc.printf("\r\nP - Set Proportional Gain on an Axis\r\n");
                pc.printf("I - Set Integral Gain on an Axis\r\n");
                pc.printf("D - Set Derivative Gain on an Axis\r\n");                
                pc.printf("\r\nB - Pitch Gripper\r\n");
                pc.printf("N - Rotate Gripper\r\n");
                pc.printf("G - Home Gripper\r\n");
                pc.printf("spacebar - Emergency Stop\r\n");

                pc.printf("Press any key to continue.\r\n");
                
                pc.scanf("%c",&c);
                c = '\0';   //re-zero c                              
            }
            
            if(c == '0'){   //zero all encoders and channels
                zero_all();
            }
            // All: Enable/Disable ALL motors (On or Off)
            if((c == 'A') || (c == 'a')){
                pc.printf("All: 'o' for all On, 'f' for all off\r\n");
                
                pc.scanf("%c",&c);                
                if((c == 'O' || c == 'o')){
                    all_on();
                }
                if((c == 'F' || c == 'f')){
                    all_off();        
                }
                c = '\0';   //clear c
            }
            
            //Temporary command for Wrist Pitch
            if(c == 'B' || c == 'b'){
                pc.printf("Enter wrist pitch counts\r\n");        
                                           
                float counts;
                
                pc.scanf("%f",&counts);                
                axis4.set_point += counts;
                axis5.set_point += -counts;
                
                pc.printf("%f\r\n",counts);
                t.reset();
                while((axis4.pos > (axis4.set_point + SP_TOL) || 
                       axis4.pos < (axis4.set_point - SP_TOL)) &&
                       (axis5.pos > (axis5.set_point + SP_TOL) ||
                       axis5.pos < (axis5.set_point - SP_TOL))){
                    pc.printf("T=%.2f SP4=%.3f pos4=%.3f SP5=%.3f pos5=%.3f \r\n", t.read(), axis4.set_point, axis4.pos, axis5.set_point, axis5.pos); 
                    wait(.009);
                }                  
            }
            
            //wrist rotate
            if(c == 'N' || c == 'n'){
                pc.printf("Enter wrist rotate counts\r\n");        
                                           
                float counts;
                
                pc.scanf("%f",&counts);                
                axis4.set_point += counts;
                axis5.set_point += counts;
                
                pc.printf("%f\r\n",counts);
                t.reset();
                while((axis4.pos > (axis4.set_point + SP_TOL) || 
                       axis4.pos < (axis4.set_point - SP_TOL)) &&
                       (axis5.pos > (axis5.set_point + SP_TOL) ||
                       axis5.pos < (axis5.set_point - SP_TOL))){
                    pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f       \r\n", t.read(), axis4.set_point, axis4.enc, axis5.set_point, axis5.enc); 
                    wait(.009);
                }  
            }            
            
            //Current Measurement: Stream the motor currents
            if((c == 'C') || (c == 'c')){
                int analogFlag = 0;
                while(analogFlag == 0){
                    axis1.readCurrent();
                    axis2.readCurrent();
                    axis3.readCurrent();
                    axis4.readCurrent();
                    axis5.readCurrent();
                    axis6.readCurrent();
                    pc.printf("%.3f %.3f %.3f %.3f %.3f %.3f \r\n", axis1.motCurrent, axis2.motCurrent, axis3.motCurrent, axis4.motCurrent, axis5.motCurrent, axis6.motCurrent);
                    wait(.02);
                    
                    if(pc.readable()){      //if user types a 'q' or 'Q'
                        char c = pc.getc();
                        if(c == 'q' || c == 'Q') //quit after current movement
                            analogFlag = 1;
                    }
                }
            }
            
            //Limit: Limit Switch Monitor
            if((c == 'L') || (c == 'l')){
                int limitFlag = 1;
                
                while(limitFlag){                     
                    pc.printf("%1d %1d %1d %1d %1d %1d %1d\r\n", limit1, limit2, limit3, limit4, limit5, limit6);
                    wait(.02);
                    
                    if(pc.readable()){      //if user types a 'q' or 'Q'
                        char c = pc.getc();
                        if(c == 'q' || c == 'Q') //quit after current movement
                            limitFlag = 0;;
                    }
                }
            }            

            //W: Wrist home fuction                        
            if((c == 'W') || (c == 'w')){
                home_pitch_wrist();
                home_rotate_wrist();
            }
            
            //gripper home
            if((c == 'G') || (c == 'g')){
                cal_gripper();
            }
            
            //Up: Bring up from typical starting position
            if((c == 'U') || (c == 'u')){
                pc.printf("Bring up from typical unpowered position\r\n");
                
                axis1.zero();
                axis2.zero();
                axis3.zero();
                axis4.zero();
                axis5.zero();
                axis6.zero();
                
                all_on();
                axis2.set_point += 8000;
                wait(3.5);
                axis2.zero();
                axis3.set_point -= 4500;
                wait(2.5);
                axis3.zero();
                
                home_pitch_wrist();
                home_rotate_wrist();
                cal_gripper();
            }                
                                  
            //Exercise: Randomly exercise all axes
            if((c == 'X' || c == 'x'))    //Exercise all axes
            {
                pc.printf("\r\nPress q to quit Exercise\r\n");
                pc.printf("Received move test command\r\n"); 
                int qFlag=0;
                float lastmovetime = 0.0;
                while(qFlag==0){
                    t.reset();                                        
                    float movetime = rand() % 7;
                    movetime += 1.0;
                    lastmovetime = t.read() + movetime;
                                                          
                    axis1.moveTrapezoid((rand() % 2000) - 1000, movetime); 
                    wait(.05);
                    axis2.moveTrapezoid((rand() % 5000) - 2500, movetime);
                    wait(.05);
                    axis3.moveTrapezoid((rand() % 5000) - 2500, movetime); 
                    wait(.05);
                    axis4.moveTrapezoid((rand() % 3000) - 1500, movetime);
                    wait(.05);
                    axis5.moveTrapezoid((rand() % 3000) - 1500, movetime); 
                    wait(.05);
                    axis6.moveTrapezoid((rand() % 3000), movetime);                    
                    wait(.05);
                    
                    while(t.read() <= lastmovetime + 1.0){
                        //pc.printf("T=%.2f ax1SP=%.3f ax1pos=%.3f ax2SP=%.3f ax2pos=%.3f \r\n", t.read(), axis1.set_point, axis1.pos, axis2.set_point, axis2.pos);
                        pc.printf("%.2f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\r\n", t.read(), axis1.set_point, axis1.pos, axis2.set_point, axis2.pos,
                            axis3.set_point, axis3.pos, axis4.set_point, axis4.pos,axis5.set_point, axis5.pos, axis6.set_point, axis6.pos);
                        wait(.01);
                        
                        if(pc.readable()){      //if user types a 'q' or 'Q'
                            char c = pc.getc();
                            if(c == 'q' || c == 'Q') //quit after current movement
                                qFlag = 1;         //set the flag to terminate the excercise
                            if(c == ' '){           //stop immediately
                                axis1.moveState = 4;
                                axis2.moveState = 4;
                                axis3.moveState = 4;
                                axis4.moveState = 4;
                                axis5.moveState = 4;
                                axis6.moveState = 4;
                                qFlag = 1;         //set the flag to terminate the excercise
                                break;
                            }                                
                        }                                               
                    }                    
                }
            }
            
            //Trapazoid: move trapazoidal profile on Axis
            if(c == 'T' || c == 't'){    //move Trapazoid command
                float position = 0.0;
                float time = 0.0;
                
                pc.printf("Enter axis to move trapazoid\r\n");        
                pc.scanf("%c",&c);
                
                pc.printf("\r\n\r\nEnter position:");        
                pc.scanf("%f",&position);
                pc.printf("%f\r\n", position); 
                
                pc.printf("Enter time:");        
                pc.scanf("%f",&time);
                pc.printf("%f\r\n", time);
                                          
                switch(c){
                    case '1':
                        pc.printf("Moving Robotic Axis 1\r\n");        
                        axis1.moveTrapezoid(position, time);       
                    break; 
                    
                    case '2':
                        pc.printf("Moving Robotic Axis 2\r\n");        
                        axis2.moveTrapezoid(position, time);                                   
                    break;   
                    
                    case '3':
                        pc.printf("Moving Robotic Axis 3\r\n");        
                        axis3.moveTrapezoid(position, time);           
                    break;
                    
                    case '4':
                        pc.printf("Moving Robotic Axis 4\r\n");        
                        axis4.moveTrapezoid(position, time);           
                    break;   
                    
                    case '5':
                        pc.printf("Moving Robotic Axis 5\r\n");        
                        axis5.moveTrapezoid(position, time);           
                    break;

                    case '6':
                        pc.printf("Moving Robotic Axis 6\r\n");        
                        axis6.moveTrapezoid(position, time);           
                    break;
                }                               
            }           
            
            //Home: home command 
            if(c == 'H' || c == 'h'){
                pc.printf("Enter axis to home\r\n");        
                pc.scanf("%c",&c);          
                switch(c){
                    case '1':
                        pc.printf("Homing Robotic Axis 1\r\n");
                        axis1.center();           
                    break; 
                    case '2':
                        pc.printf("Homing Robotic Axis 2\r\n");
                        axis2.center();         
                    break;   
                    
                    case '3':
                        pc.printf("Homing Robotic Axis 3\r\n");
                        axis3.center();
                    break;
                    
                    case '4':
                        pc.printf("Homing Robotic Axis 4\r\n");
                        axis4.center();
                    break;
                    
                    case '5':
                        pc.printf("Homing Robotic Axis 5\r\n");
                        axis5.center();
                    break;
                    
                    case '6':
                        pc.printf("Homing Robotic Axis 6\r\n");
                        axis6.center();
                    break;
                }
            }    
            
            //Set Point:  Manually move to specific encoder position set point
            if(c == 'S' || c == 's'){
                pc.printf("Enter axis to give set point:");
                pc.scanf("%c",&c);
                pc.printf("Axis %c entered.\r\n", c);
                pc.printf("Enter value for set point axis %c\r\n", c);
                float temp_setpoint;
                pc.scanf("%f",&temp_setpoint);
                pc.printf("Axis%c set point %.1f\r\n", c, temp_setpoint);
                 
                switch(c){                                        
                    case '1':                                
                        axis1.set_point = temp_setpoint;

                        t.reset();
                        while((axis1.pos > (axis1.set_point + SP_TOL)) || (axis1.pos < (axis1.set_point - SP_TOL))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis1.set_point, axis1.co, axis1.pos, axis1.vel, axis1.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis1.set_point, axis1.co, axis1.pos, axis1.vel, axis1.acc);           

                    break;   
                    
                    case '2':
//                        float delta3 = axis2.pos - temp_setpoint;
//                        axis3.set_point += delta3;
                        
                        axis2.set_point = temp_setpoint;             
                        t.reset();
                        while((axis2.pos > (axis2.set_point + SP_TOL)) || (axis2.pos < (axis2.set_point - SP_TOL))){
                            pc.printf("T=%.2f %.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis2.set_point, axis2.pos, axis2.vel, axis2.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis2.set_point, axis2.co, axis2.pos, axis2.vel, axis2.acc);           
                    break;            
                    
                    case '3':
                        axis3.set_point = temp_setpoint;
                        t.reset();
                        while((axis3.pos > (axis3.set_point + SP_TOL)) || (axis3.pos < (axis3.set_point - SP_TOL))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis3.set_point, axis3.co, axis3.pos, axis3.vel, axis3.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis3.set_point, axis3.co, axis3.pos, axis3.vel, axis3.acc);           
                    break;                             

                    case '4':
                        axis4.set_point = temp_setpoint;
                        t.reset();
                        while((axis4.pos > (axis4.set_point + SP_TOL)) || (axis4.pos < (axis4.set_point - SP_TOL))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis4.set_point, axis4.co, axis4.pos, axis4.vel, axis4.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis4.set_point, axis4.co, axis4.pos, axis4.vel, axis4.acc);           
                    break;
                    
                    case '5':
                        axis5.set_point = temp_setpoint;
                        t.reset();
                        while((axis5.pos > (axis5.set_point + SP_TOL)) || (axis5.pos < (axis5.set_point - 50))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis5.set_point, axis5.co, axis5.pos, axis5.vel, axis5.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis5.set_point, axis5.co, axis5.pos, axis5.vel, axis5.acc);           
                    break;                    

                    case '6':
                        axis6.set_point = temp_setpoint;
                        t.reset();
                        while((axis6.pos > (axis6.set_point + SP_TOL)) || (axis6.pos < (axis6.set_point - SP_TOL))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis6.set_point, axis6.co, axis6.pos, axis6.vel, axis6.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis6.set_point, axis6.co, axis6.pos, axis6.vel, axis6.acc);           
                    break;
                }                
            }
            
            if(c == 'P' || c == 'p'){
                float temp_Pk;
                pc.printf("Enter axis to set Pk\r\n");        
                pc.scanf("%c",&c);
                
                pc.printf("Enter value for Axis%c Pk\r\n", c);
                pc.scanf("%f",&temp_Pk);                
                
                switch(c){
                    case 1:
                        axis1.Pk = temp_Pk;
                    break;
                    
                    case 2:
                        axis2.Pk = temp_Pk;
                    break;
                    
                    case 3:
                        axis3.Pk = temp_Pk;
                    break;
                    
                    case 4:
                        axis4.Pk = temp_Pk;
                    break;
                    
                    case 5:
                        axis5.Pk = temp_Pk;
                    break;
                    
                    case 6:
                        axis6.Pk = temp_Pk;
                    break;
                }
                pc.printf("Axis%c Pk set to %f\r\n", c, temp_Pk);                           
            }
            if(c == 'I' || c == 'i'){
                float temp_Ik;
                pc.printf("Enter axis to set Ik\r\n");        
                pc.scanf("%c",&c);
                
                pc.printf("Enter value for Axis%c Ik\r\n", c);
                pc.scanf("%f",&temp_Ik);                
                
                switch(c){
                    case 1:
                        axis1.Ik = temp_Ik;
                    break;
                    
                    case 2:
                        axis2.Ik = temp_Ik;
                    break;
                    
                    case 3:
                        axis3.Ik = temp_Ik;
                    break;
                    
                    case 4:
                        axis4.Ik = temp_Ik;
                    break;
                    
                    case 5:
                        axis5.Ik = temp_Ik;
                    break;
                    
                    case 6:
                        axis6.Ik = temp_Ik;
                    break;
                }
                pc.printf("Axis%c Ik set to %f\r\n", c, temp_Ik);
            }                             
            if(c == 'D' || c == 'd'){
                float temp_Dk;
                pc.printf("Enter axis to set Dk\r\n");        
                pc.scanf("%c",&c);
                
                pc.printf("Enter value for Axis%c Dk\r\n", c);
                pc.scanf("%f",&temp_Dk);                
                
                switch(c){
                    case 1:
                        axis1.Dk = temp_Dk;
                    break;
                    
                    case 2:
                        axis2.Dk = temp_Dk;
                    break;
                    
                    case 3:
                        axis3.Dk = temp_Dk;
                    break;
                    
                    case 4:
                        axis4.Dk = temp_Dk;
                    break;
                    
                    case 5:
                        axis5.Dk = temp_Dk;
                    break;
                    
                    case 6:
                        axis6.Dk = temp_Dk;
                    break;
                }
                pc.printf("Axis%c Ik set to %f\r\n", c, temp_Dk);            
            }             
            
            //Zero: Zero specific axis
            if(c == 'Z' || c == 'z'){
                pc.printf("Enter axis to Zero (1-6, or 'a' for all)\r\n");          
                pc.scanf("%c",&c);          
                switch(c){                                        
                    case '1':
                        axis1.zero();
                    break;

                    case '2':
                        axis2.zero();
                    break;
                    
                    case '3':
                        axis3.zero();
                    break;
                    
                    case '4':
                        axis4.zero();
                    break;
                    
                    case '5':
                        axis5.zero();
                    break;
                    
                    case '6':
                        axis6.zero();
                    break; 
                                                                                                                       
                    case 'a':   //for all
                        axis1.zero();
                        axis2.zero();
                        axis3.zero();
                        axis4.zero();
                        axis5.zero();                                                                                                                    
                        axis6.zero();
                    break; 
                }
                    
            }            
            if(c == 'O' || c == 'o'){
                pc.printf("Enter axis to turn On (1-6, or 'a' for all)\r\n");     
                pc.scanf("%c",&c);               
                
                switch(c){
                    case '1':
                        axis1.axisOn();
                    break;

                    case '2':
                        axis2.axisOn();
                    break;

                    case '3':
                        axis3.axisOn();
                    break;
                    
                    case '4':
                        axis4.axisOn();
                    break;

                    case '5':
                        axis5.axisOn();
                    break;

                    case '6':
                        axis6.axisOn();
                    break;                   
                    
                    case 'a':
                        axis1.axisOn();
                        axis2.axisOn();
                        axis3.axisOn();
                        axis4.axisOn();
                        axis5.axisOn();
                        axis6.axisOn();
                    break;                        
                }
                pc.printf("Axis%c On\r\n", c);
            }
            if(c == 'F' || c == 'f'){
                pc.printf("Enter axis to turn Off (1-6, or 'a' for all)\r\n");        
                pc.scanf("%c",&c);               
                
                switch(c){
                    case '1':
                        axis1.axisOff();
                    break;

                    case '2':
                        axis2.axisOff();
                    break;

                    case '3':
                        axis3.axisOff();
                    break;
                    
                    case '4':
                        axis4.axisOff();
                    break;

                    case '5':
                        axis5.axisOff();
                    break;

                    case '6':
                        axis6.axisOff();
                    break;                  
                    
                    case 'a':
                        axis1.axisOff();
                        axis2.axisOff();
                        axis3.axisOff();
                        axis4.axisOff();
                        axis5.axisOff();
                        axis6.axisOff();
                    break;                          
                }
                pc.printf("Axis%c Off\r\n", c);
            }            
            
            // Toggle Stream flag (for display purposes
            if(c == 'J' || c == 'j'){
                pc.printf("Enter 1 to turn stream On, 0 to turn Off:\r\n");
                pc.scanf("%c",&c);
                
                if(c == '1'){
                    streamFlag = 1;
                    pc.printf("Stream On\r\n");
                }
                if(c == '0'){
                    streamFlag = 0;
                    pc.printf("Stream Off\r\n");
                }
                c = '\0';
            }
            
            if(c == 'M' || c == 'm'){   //move axis (with joints combined)
                pc.printf("Enter axis to move\r\n");
                pc.scanf("%c",&c);
                pc.printf("Enter value for axis %c\r\n", c);
                float newPosition;
                switch(c){                                        
                    case '2':                                
                        pc.scanf("%f",&newPosition);
                        axis2.set_point += newPosition;
                        axis3.set_point += newPosition;
                        axis4.set_point += (65.5/127.0 * newPosition);
                        axis5.set_point -= (65.5/127.0 * newPosition);
                                        
                        
                        t.reset();
                        while((axis1.pos > (axis1.set_point + SP_TOL)) || (axis1.pos < (axis1.set_point - SP_TOL))){
                            pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n", t.read(), axis1.set_point, axis1.co, axis1.pos, axis1.vel, axis1.acc); 
                            wait(.009);
                            if(t.read() > 10.0){
                                pc.printf("Set point timeout!\r\n");
                                break;
                            }
                        }
                        pc.printf("T=%.2f SP=%.3f co=%.3f pos=%.3f vel=%.3f acc=%.3f\r\n\n", t.read(), axis1.set_point, axis1.co, axis1.pos, axis1.vel, axis1.acc);           

                    break;
                }                    
            }
        }//command was received
                                                   
        if((axis1.moveState==0) && (axis2.moveState==0) && (axis3.moveState==0) && (axis4.moveState==0) && (axis5.moveState==0) && (axis6.moveState==0)){
            pc.printf("%.2f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f   \r", (float)t.read(), (float)axis1.set_point, (float)axis1.pos, (float)axis2.set_point, (float)axis2.pos,
                (float)axis3.set_point, (float)axis3.pos, (float)axis4.set_point, (float)axis4.pos,(float)axis5.set_point, (float)axis5.pos, (float)axis6.set_point, (float)axis6.pos);                
                if(streamFlag)
                    pc.printf("\n");
            led2 = 0;
        }
        else
            led2 = 1;
 
//        pc.printf("Axis2: pos=%.1f co=%.1f setPoint=%.1f vel=%.1f\r\n", axis2.pos, axis2.co, axis2.set_point, axis2.vel);
        wait(.02);
    }//while(1)                        
}//main