for controlling stepper motor with A4980

Dependents:   HIDTympDeviceWithPIDController

Revision:
0:9156e6b6bf46
diff -r 000000000000 -r 9156e6b6bf46 motorControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/motorControl.cpp	Mon Oct 06 11:57:45 2014 +0000
@@ -0,0 +1,509 @@
+/*
+############################################
+##           motorControl v0.1 Library    ##
+##          created by Peter Ilsoee       ##
+############################################
+        ---- piniels@gmail.com -----
+This library was made for 4-Phase Stepper Motors
+I don't take any resposability for the damage caused to your equipment.
+
+*/
+
+#include "motorControl.h"
+
+#include "mbed.h"
+#include "globalt.h"
+
+
+SPI spi(PTE1, PTE3, PTE2); // mosi, miso, sclk
+DigitalOut cs(PTE4);
+//struct for holding run register information
+
+//GPIO
+DigitalOut valve(PTD0);
+DigitalIn centerInput(PTD4);
+
+//Ticker for running at a specified speed
+Ticker runTickMotorControl;
+
+
+
+
+
+/**
+ * ! @brief Construct including the pins for "manual(not SPI cmd)" control of A4980
+ * @param step Step logic input. Motor advances on rising edge. Filtered input with hysteresis.
+ * @param dir Direction logic input. Direction changes on the next STEP rising edge. When high, the Phase Angle Number is increased
+ *            on the rising edge of STEP. Has no effect when using the serial
+ *            interface. Filtered input with hysteresis.
+ * @param ms1 Microstep resolution select input.
+ * @param ms0 Microstep resolution select input.
+ * @param enable Controls activity of bridge outputs. When held low, deactivates the outputs, that is, turns off all output bridge FETs.
+ *               Internal logic continues to follow input commands.
+ * @param reset Resets faults when pulsed low. Forces low-power shutdown(sleep) when held low for more than the Reset Shutdown
+ *              Width, tRSD . Can be pulled to VBB with 30 kΩ resistor.
+ * @param diag  Diagnostic output. Function selected via the serial interface,
+ *              setting Configuration Register 1. Default is Fault output.
+ */
+motorControl::motorControl(int numberOfSteps, PinName step, PinName dir, PinName ms1, PinName ms0, PinName enable, PinName reset, PinName diag): _Number_OF_STEPS(numberOfSteps), _STEP(step), _DIR(dir), _MS1(ms1), _MS0(ms0), _ENABLE(enable), _RESET(reset), _DIAG(diag){
+
+    this->_RESET = 0;
+    this->_STEP = 0; // duty cycle on 50 %
+    this->_DIR = 0;
+    this->_MS1 = 0;
+    this->_MS0 = 0;
+    this->_ENABLE = 0;
+    //Setting default values to run regi
+    this->_REGI_RUN.B.sc = 0x1; //1 steps positive value
+    this->_REGI_RUN.B.dcy = 0x1; // bit7-6 Decay mode selection 00=Slow, *01=Mixed-PFD fixed, 10=Mixed-PFD auto, 11=Fast
+    this->_REGI_RUN.B.brk = 0x0; // bit8 Brake enable *0=Normal operation 1=Brake active
+    this->_REGI_RUN.B.slew = 0x1; // bit9 Slew rate control 0=Disable *1=Enable
+    this->_REGI_RUN.B.hlr = 0x0; // bit10. Selects slow decay and brake recirculation path *0=High side, 1=Low side
+    this->_REGI_RUN.B.ol = 0x1; // bit12-11. Open load current threshold as a percentage of maximum current defined by ISMAX and MXI[1..0] 00=20%, *01=30%, 10=40%, 11=50%
+    this->_REGI_RUN.B.en = 1; // bit13. Phase current enable OR with ENABLE pin *0=Output bridges disabled if ENABLE pin = 0, 1=Output bridges enabled
+    this->_REGI_RUN.B.addr = 0x2; // bit15-14 Address run = 0b10
+    //Setting default value to control regi. 0
+    this->_REGI_0.B.pwm = 0x0;
+    this->_REGI_0.B.tofFrq = 0x6;
+    this->_REGI_0.B.tbk = 0x1;
+    this->_REGI_0.B.pfd = 0x4;
+    this->_REGI_0.B.mx = 0x03; // bit10-9. Max phase current as a percentage of I(SMAX) 00=25% 01=50% 10=75% *11=100%
+    this->_REGI_0.B.ms = 0x0;
+    this->_REGI_0.B.syr = 0x1;
+    this->_REGI_0.B.addr = 0x0;
+    //Setting default value to control regi. 1
+    this->_REGI_1.B.diag = 0x0;
+    this->_REGI_1.B.cd = 0x8;
+    this->_REGI_1.B.notInUse = 0x0;
+    this->_REGI_1.B.tsc = 0x2;
+    this->_REGI_1.B.osc = 0x0;
+    this->_REGI_1.B.addr = 0x1;
+    wait(0.1);
+    this->_RESET = 1;
+    this->_Step_Counter = 0;
+    
+    
+
+}
+
+
+void motorControl::initSpi() { // rotate the motor 1 step anticlockwise
+cs = 1;
+spi.format(8,3);
+spi.frequency(1000000);
+
+}
+
+/**
+ * ! @brief set the step counter
+ * @param value an int counting the steps
+ */
+void motorControl::setStepCount(int value)
+{
+    this->_Step_Counter = value;
+    
+}
+
+/**
+ * ! @brief get the step counter
+ * @return an int counting the steps
+ */
+int motorControl::getStepCount()
+{
+    return this->_Step_Counter;
+    
+}
+
+/**
+ * ! @brief set configuration and control register 0
+ * @param t_config_control_regi_0 an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+int motorControl::setConfigRegi0(t_config_control_regi_0 value)
+{
+    this->_REGI_0 = value;
+    cs = 0;
+    int response = (spi.write(value.I >> 8)) << 8;
+    response |= spi.write(value.I & 0xff);
+    cs = 1;
+    return response;
+}
+
+/**
+ * ! @brief get configuration and control register 0
+ * @return t_config_control_regi_0 an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+t_config_control_regi_0 motorControl::getConfigRegi0()
+{
+    return this->_REGI_0;
+}
+
+/**
+ * ! @brief open or close the GPIO controlling the valve
+ * @parm openTrue Boolean true for open
+ */
+void motorControl::openCloseValve(bool openTrue)
+{
+    if(openTrue)
+    {
+        valve = 0;
+    }
+    else
+    {
+        valve = 1;
+    }
+}
+
+/**
+ * ! @brief set configuration and control register 1
+ * @param t_config_control_regi_1 an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+int motorControl::setConfigRegi1(t_config_control_regi_1 value)
+{
+    this->_REGI_1 = value;
+    cs = 0;
+    int response = (spi.write(value.I >> 8)) << 8;
+    response |= spi.write(value.I & 0xff);
+    cs = 1;
+    return response;
+}
+
+/**
+ * ! @brief set micro step bits
+ * @param int from 0 to 3
+ */
+void motorControl::setMicroSteps(int value)
+{
+    printf("Value for microsteps: %i",value);
+    printf("\r\n");
+    this->_MS1 = (value & 0x2) >> 1;
+    this->_MS0 = value & 0x1;
+    
+}
+
+/**
+ * ! @brief get micro step bits
+ * @param int from 0 to 3
+ */
+int motorControl::getMicroSteps()
+{
+    return this->_MS1 << 1 | this->_MS0;
+    
+}
+
+
+/**
+ * ! @brief get configuration and control register 1
+ * @return t_config_control_regi_1 an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+t_config_control_regi_1 motorControl::getConfigRegi1()
+{
+    return this->_REGI_1;
+}
+
+/**
+ * ! @brief set configuration and run register
+ * @param t_run_regi an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+int motorControl::setRunRegi(t_run_regi value)
+{
+    this->_REGI_RUN = value;
+    cs = 0;
+    int response = (spi.write(value.I >> 8)) << 8;
+    response |= spi.write(value.I & 0xff);
+    cs = 1;
+    return response;
+}
+
+/**
+ * ! @brief get run control register
+ * @return t_run_regi an union with represents some seetings (see datasheet A4980 data sheet)
+ */
+t_run_regi motorControl::getRunRegi()
+{
+    return this->_REGI_RUN;
+}
+
+/**
+ * ! @brief Run at a specified speed, none blocking
+ * @param startStop If true start moter if false stop motor
+ * @param whatSpeed speed in RPM
+ * @param direction if 1 then postive phase, if 0 negative phase
+ */
+// 
+void motorControl::runStepperAtSpeed(bool startStop, int whatSpeed, int direction)
+{
+    this->_DIR = direction;
+    this->step_delay = calculateStepDelay(whatSpeed);
+    
+    if(this->step_delay > MAX_STEP_DELAY)
+    {
+        this->step_delay = MAX_STEP_DELAY;
+    }
+    else if(this->step_delay < MIN_STEP_DELAY)
+    {
+        this->step_delay = MIN_STEP_DELAY;
+    }
+    
+    
+    
+    if(startStop)
+    {
+        this->_ENABLE = 1;
+        _STEP = 0.5; //duty cycle 50%
+        _STEP.period_us((int) this->step_delay);
+        
+    }
+    else
+    {
+        _STEP = 0; //Duty-cycle 0
+        _ENABLE = 0;
+        _STEP = 0;
+        
+    }
+}
+
+void motorControl::doRamp(int numberOfRampsteps,float endDelay)
+{
+    //Test do ramping
+    
+    int delay_us_start = 10000;
+    int diff_delay_us = delay_us_start - endDelay;
+    int ramping_step_us = diff_delay_us/numberOfRampsteps;
+    int delay_ramp = 0;
+     
+    
+    for(int i = 0;i < numberOfRampsteps; i++)
+    {
+           delay_ramp = delay_us_start - (i*ramping_step_us);
+           printf("Ramping Delay is in  us: %i", delay_ramp);
+           printf("\r\n");
+           _STEP.period_us(delay_ramp);
+           wait_us(delay_ramp);
+    }
+}
+
+float motorControl::calculateStepDelay(int whatSpeed)
+{
+   if(whatSpeed != 0)
+    {
+        this->step_delay = 60L * 1000000L / ((float)this->_Number_OF_STEPS * (float)whatSpeed);
+        int microStep = getMicroSteps();
+        if(microStep > 0)
+        {
+           if(microStep == 1)
+           {
+            this->step_delay = this->step_delay/2;  
+            }
+            else if(microStep == 2)
+            {
+                this->step_delay = this->step_delay/4;  
+            }
+            else
+            {
+                this->step_delay = this->step_delay/16;  
+            }
+           
+        }
+        
+    }
+    else
+    {
+        this->step_delay = 60L * 1000L / (float) this->_Number_OF_STEPS / (float) 1;
+    }
+    
+    return this->step_delay;
+}
+
+// tick event handler for running the motor at a specified speed
+void motorControl::runMotor(void)
+{
+    setRunRegi(this->_REGI_RUN); //1 steps positive value
+    if(this->_Bool_Direction)
+    {
+        this->_Step_Counter++;
+    }
+    else
+    {
+        this->_Step_Counter--;
+    }
+    
+    
+    
+}
+
+ void motorControl::goToZeroPosition(int whatSpeed)
+ {
+    float step_delay = (60 / (float)this->_Number_OF_STEPS / (float)whatSpeed);
+    bool runMotorBool = true;
+    bool runMotorBack = false;
+    openCloseValve(true);
+    
+    while(runMotorBool)//this->_Step_Counter != 0 || centerInput )
+    {
+        this->_REGI_RUN.B.en = 1;
+        if(whatSpeed > 0)
+        {
+            this->_Bool_Direction = true;
+            this->_REGI_RUN.B.sc = 0x10; // 1 steps positive value
+            runMotor();
+            wait(step_delay);
+            if(centerInput)
+            {
+                runMotorBool = false;
+                this->_Step_Counter = 0;
+                
+            }
+        }
+        else
+        {
+            this->_Bool_Direction = false;
+            this->_REGI_RUN.B.sc = 0x30; // 1 steps positive value
+            runMotor();
+            wait(-1*step_delay);
+            if(centerInput)
+            {
+                runMotorBack = true;
+            }
+            else if(runMotorBack && !centerInput)
+            {
+                runMotorBool = false;
+                this->_Step_Counter = 0;
+            }
+            
+        }
+       
+        
+    } 
+    this->_REGI_RUN.B.en = 0;    
+
+}
+
+// Run at a specified speed, no blocking
+void motorControl::runStepperAtSpeedWithSPI(bool startStop, int whatSpeed, int direction)
+{
+    
+    
+    if(whatSpeed != 0)
+    {
+        this->step_delay = (60L * 1000000L / this->_Number_OF_STEPS / whatSpeed);
+        
+    }
+    else
+    {
+        this->step_delay = 60L * 1000000L / this->_Number_OF_STEPS / 1;
+        
+    }
+    //pc.printf("Step dealy: %d",this->step_delay);
+    //pc.printf("\r\n");
+    if(direction)
+    {
+        this->_Bool_Direction = true;
+        if(whatSpeed > 50)//HACK: for testing micro step
+        {
+            this->_REGI_RUN.B.sc = 0x10; // 1 steps positive value
+        }
+        else
+        {
+            this->_REGI_RUN.B.sc = 0x10; // 1 steps positive value
+            //this->_REGI_RUN.B.sc = 0x4; // 1/8 steps positive value
+            //this->step_delay = this->step_delay/4;
+            printf("Step dealy micro step: %d",this->step_delay);
+            printf("\r\n");
+        }
+        
+    }
+    else
+    {
+        this->_Bool_Direction = false;;
+        
+        if(whatSpeed > 50) //HACK: for testing micro step
+        {
+            this->_REGI_RUN.B.sc = 0x30; // 1 steps negative value
+        }
+        else
+        {
+            this->_REGI_RUN.B.sc = 0x30; // 1 steps negative value
+            //this->_REGI_RUN.B.sc = 0x3C; // 1/16 steps negative value
+            //this->step_delay = this->step_delay/4;
+            printf("Step dealy micro step: %d",this->step_delay);
+            printf("\r\n");
+        }
+        //
+        
+    }
+
+    if(startStop)
+    {
+        this->_REGI_RUN.B.en = 1;
+        runTickMotorControl.attach_us(this, &motorControl::runMotor, (this->step_delay)); // the address of the function to be attached
+    }
+    else
+    {
+        this->_REGI_RUN.B.en = 0;
+        setRunRegi(this->_REGI_RUN);
+        runTickMotorControl.detach();
+        
+    }
+}
+
+
+
+void motorControl::step(int num_steps, int delay, bool direction) {// steper function: number of steps, direction (0- right, 1- left), 
+
+    this->_REGI_RUN.B.en = 1;
+
+    
+    
+    if(direction)
+    {
+        if(getMicroSteps() == 0)
+        {
+            this->_REGI_RUN.B.sc = 0x10; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 1)
+        {
+            this->_REGI_RUN.B.sc = 0x8; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 2)
+        {
+            this->_REGI_RUN.B.sc = 0x4; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 3)
+        {
+            this->_REGI_RUN.B.sc = 0x2; // 1 steps positive value
+        }
+        
+        
+    }
+    else
+    {
+        if(getMicroSteps() == 0)
+        {
+            this->_REGI_RUN.B.sc = 0x30; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 1)
+        {
+            this->_REGI_RUN.B.sc = 0x38; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 2)
+        {
+            this->_REGI_RUN.B.sc = 0x3C; // 1 steps positive value
+        }
+        else if(getMicroSteps() == 3)
+        {
+            this->_REGI_RUN.B.sc = 0x3E; // 1 steps positive value
+        }
+    }
+
+ 
+    
+    for(int i = 0;i < num_steps;i++)
+    {
+        setRunRegi(this->_REGI_RUN); //1 steps positive value
+         wait_ms(delay);
+    }
+    
+    this->_REGI_RUN.B.en = 0;
+    setRunRegi(this->_REGI_RUN); //1 steps positive value
+
+}