Unipolar Stepper Motor Library

UniStepperMotor.cpp

Committer:
bant62
Date:
2012-07-16
Revision:
1:ce3991daa407
Child:
2:abb7425e1a5b

File content as of revision 1:ce3991daa407:

/**
 *****************************************************************************
 * File Name    : UniStepperMotor.cpp
 *
 * Title        : Unipolar Stepper Motor Class Source File
 * Revision     : 0.1
 * Notes        :
 * Target Board : mbed NXP LPC1768
 * Tool Chain   : ????
 *
 * Revision History:
 * When         Who         Description of change
 * -----------  ----------- -----------------------
 * 2012/07/8    Hiroshi M   init
 *****************************************************************************
 *
 * Copyright (C) 2012 Hiroshi M, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **/

/* Includes ----------------------------------------------------------------- */
#include "UniStepperMotor.h"
#include "mbed.h"

/* Private typedef ---------------------------------------------------------- */
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */

static uint8_t ptn_ClockWise_1x1[]     = {0x01, 0x02, 0x04, 0x08};
static uint8_t ptn_AntiClockWise_1x1[] = {0x08, 0x04, 0x02, 0x01};

static uint8_t ptn_ClockWise_2x2[]     = {0x03, 0x06, 0x0C, 0x09};
static uint8_t ptn_AntiClockWise_2x2[] = {0x09, 0x0C, 0x06, 0x03};

static uint8_t ptn_ClockWise_1x2[]     = {0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09, 0x01};
static uint8_t ptn_AntiClockWise_1x2[] = {0x01, 0x09, 0x08, 0x0C, 0x04, 0x06, 0x02, 0x03};

#if 0
static speed_data_t speed_data [] = {
    {  1,  0,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 0
    {500,  4,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 1 500*2 => 1000
    {250,  4,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 2 250*2 => 500
    {166,  4,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 3 166*2 => 332
    {125,  6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 4 125*2 => 250
    {100,  6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},   // 5 100*2 => 200
    {167,  8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},   // 6 
    {143,  8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},   // 7
    {125,  9,ptn_ClockWise_1x1,ptn_AntiClockWise_2x2,4},   // 8
    {111, 10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},   // 9
    {100, 10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4}    // 10
};
#endif

static speed_data_t speed_data [] = {
    {1,0,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {3150,2,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {1575,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {1050,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {788,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {630,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {525,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {450,3,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {394,4,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {350,4,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {315,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {286,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {263,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {242,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {225,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {210,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {197,5,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {185,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {175,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {166,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {158,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {150,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {143,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {137,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {131,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {126,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {121,6,ptn_ClockWise_1x2,ptn_AntiClockWise_1x2,8},
    {233,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {225,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {217,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {210,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {203,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {197,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {191,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {185,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {180,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {175,7,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {170,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {166,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {162,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {158,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {154,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {150,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {147,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {143,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {140,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {137,8,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {134,9,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {131,9,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {129,9,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {126,9,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {124,9,ptn_ClockWise_1x1,ptn_AntiClockWise_1x1,4},
    {121,9,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {119,9,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {117,9,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {115,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {113,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {111,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {109,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {107,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {105,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {103,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {102,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4},
    {100,10,ptn_ClockWise_2x2,ptn_AntiClockWise_2x2,4}
};


/* member fanctions --------------------------------------------------------- */

// Constractor
StepperMotor::StepperMotor(PinName x_pin_no, PinName y_pin_no, PinName nx_pin_no, PinName ny_pin_no, motor_dir set_direction)
        : _x(x_pin_no), _y(y_pin_no), _nx(nx_pin_no), _ny(ny_pin_no) {
    direction = forward_direction;
    forward_direction = set_direction;
    backward_direction = (forward_direction == CLOCK_WISE) ? ANTI_CLOCK_WISE : CLOCK_WISE;
}

//  Destrutctor
StepperMotor::~StepperMotor() {
}

//
void StepperMotor::PulseEnable(void) {
    Pulse.attach_us(this,&StepperMotor::SetPulse14us,PULSE_INTERVAL);
}

//
void StepperMotor::PulseDisable(void) {
    Pulse.detach();
}

void StepperMotor::SetSpeed(int speed) {
    direction = (speed >= 0) ? forward_direction : backward_direction;

    speed = abs(speed);
    if (speed > 63) speed = 63;

    pwm_ratio = speed_data[speed].pwm_ratio;
    max_pulse_count = speed_data[speed].max_pulse_count;

    if (direction == CLOCK_WISE) {
        ptn = speed_data[speed].clockwise_ptn;
    } else {
        ptn = speed_data[speed].anticlockwise_ptn;
    }
    ptn_count = speed_data[speed].ptn_count;
 
    pulse_count = 0;
    ptn_index = 0;

    pwm_on_count = pwm_ratio;
    pwm_off_count = 10 - pwm_ratio;

    state = PWM_ON;
}


/* private functions */

void StepperMotor::SetPulse14us(void) {

    if (++pulse_count == max_pulse_count) {
        pulse_count = 0;

        if (++ptn_index == ptn_count) {
            ptn_index = 0;
        }
        ptn_data = ptn[ptn_index];
    }

    if (pwm_ratio == 10) {
        PulseOut();
    } else if (pwm_ratio == 0) {
        PulseStop();
    } else {
        switch (state) {
            case PWM_ON:
                if (--pwm_on_count !=0) {
                    PulseOut();
                } else {
                    pwm_on_count = pwm_ratio;
                    state = PWM_OFF;
                }
                break;
            case PWM_OFF:
                if (--pwm_off_count != 0) {
                    PulseStop();
                } else {
                    pwm_off_count = 10 - pwm_ratio;
                    state = PWM_ON;
                }
                break;
        }
    }
}

void StepperMotor::PulseOut(void) {
    //X
    if ((ptn_data & 0x01) == 0x01) {
        _x = 1;
    } else {
        _x = 0;
    }
    //Y
    if ((ptn_data & 0x02) == 0x02) {
        _y = 1;
    } else {
        _y = 0;
    }
    //Negative X
    if ((ptn_data & 0x04) == 0x04) {
        _nx = 1;
    } else {
        _nx = 0;
    }
    //Negative Y
    if ((ptn_data & 0x08) == 0x08) {
        _ny = 1;
    } else {
        _ny = 0;
    }
}

void StepperMotor::PulseStop(void) {
    _x = 0;
    _y = 0;
    _nx = 0;
    _ny = 0;
}