352 lines
14 KiB
Arduino
352 lines
14 KiB
Arduino
|
//dSPIN_commands.ino - Contains high-level command implementations- movement
|
||
|
// and configuration commands, for example.
|
||
|
|
||
|
// Realize the "set parameter" function, to write to the various registers in
|
||
|
// the dSPIN chip.
|
||
|
void dSPIN_SetParam(byte param, unsigned long value)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_SET_PARAM | param);
|
||
|
dSPIN_ParamHandler(param, value);
|
||
|
}
|
||
|
|
||
|
// Realize the "get parameter" function, to read from the various registers in
|
||
|
// the dSPIN chip.
|
||
|
unsigned long dSPIN_GetParam(byte param)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_GET_PARAM | param);
|
||
|
return dSPIN_ParamHandler(param, 0);
|
||
|
}
|
||
|
|
||
|
// Much of the functionality between "get parameter" and "set parameter" is
|
||
|
// very similar, so we deal with that by putting all of it in one function
|
||
|
// here to save memory space and simplify the program.
|
||
|
unsigned long dSPIN_ParamHandler(byte param, unsigned long value)
|
||
|
{
|
||
|
unsigned long ret_val = 0; // This is a temp for the value to return.
|
||
|
// This switch structure handles the appropriate action for each register.
|
||
|
// This is necessary since not all registers are of the same length, either
|
||
|
// bit-wise or byte-wise, so we want to make sure we mask out any spurious
|
||
|
// bits and do the right number of transfers. That is handled by the dSPIN_Param()
|
||
|
// function, in most cases, but for 1-byte or smaller transfers, we call
|
||
|
// dSPIN_Xfer() directly.
|
||
|
switch (param)
|
||
|
{
|
||
|
// ABS_POS is the current absolute offset from home. It is a 22 bit number expressed
|
||
|
// in two's complement. At power up, this value is 0. It cannot be written when
|
||
|
// the motor is running, but at any other time, it can be updated to change the
|
||
|
// interpreted position of the motor.
|
||
|
case dSPIN_ABS_POS:
|
||
|
ret_val = dSPIN_Param(value, 22);
|
||
|
break;
|
||
|
// EL_POS is the current electrical position in the step generation cycle. It can
|
||
|
// be set when the motor is not in motion. Value is 0 on power up.
|
||
|
case dSPIN_EL_POS:
|
||
|
ret_val = dSPIN_Param(value, 9);
|
||
|
break;
|
||
|
// MARK is a second position other than 0 that the motor can be told to go to. As
|
||
|
// with ABS_POS, it is 22-bit two's complement. Value is 0 on power up.
|
||
|
case dSPIN_MARK:
|
||
|
ret_val = dSPIN_Param(value, 22);
|
||
|
break;
|
||
|
// SPEED contains information about the current speed. It is read-only. It does
|
||
|
// NOT provide direction information.
|
||
|
case dSPIN_SPEED:
|
||
|
ret_val = dSPIN_Param(0, 20);
|
||
|
break;
|
||
|
// ACC and DEC set the acceleration and deceleration rates. Set ACC to 0xFFF
|
||
|
// to get infinite acceleration/decelaeration- there is no way to get infinite
|
||
|
// deceleration w/o infinite acceleration (except the HARD STOP command).
|
||
|
// Cannot be written while motor is running. Both default to 0x08A on power up.
|
||
|
// AccCalc() and DecCalc() functions exist to convert steps/s/s values into
|
||
|
// 12-bit values for these two registers.
|
||
|
case dSPIN_ACC:
|
||
|
ret_val = dSPIN_Param(value, 12);
|
||
|
break;
|
||
|
case dSPIN_DEC:
|
||
|
ret_val = dSPIN_Param(value, 12);
|
||
|
break;
|
||
|
// MAX_SPEED is just what it says- any command which attempts to set the speed
|
||
|
// of the motor above this value will simply cause the motor to turn at this
|
||
|
// speed. Value is 0x041 on power up.
|
||
|
// MaxSpdCalc() function exists to convert steps/s value into a 10-bit value
|
||
|
// for this register.
|
||
|
case dSPIN_MAX_SPEED:
|
||
|
ret_val = dSPIN_Param(value, 10);
|
||
|
break;
|
||
|
// MIN_SPEED controls two things- the activation of the low-speed optimization
|
||
|
// feature and the lowest speed the motor will be allowed to operate at. LSPD_OPT
|
||
|
// is the 13th bit, and when it is set, the minimum allowed speed is automatically
|
||
|
// set to zero. This value is 0 on startup.
|
||
|
// MinSpdCalc() function exists to convert steps/s value into a 12-bit value for this
|
||
|
// register. SetLSPDOpt() function exists to enable/disable the optimization feature.
|
||
|
case dSPIN_MIN_SPEED:
|
||
|
ret_val = dSPIN_Param(value, 12);
|
||
|
break;
|
||
|
// FS_SPD register contains a threshold value above which microstepping is disabled
|
||
|
// and the dSPIN operates in full-step mode. Defaults to 0x027 on power up.
|
||
|
// FSCalc() function exists to convert steps/s value into 10-bit integer for this
|
||
|
// register.
|
||
|
case dSPIN_FS_SPD:
|
||
|
ret_val = dSPIN_Param(value, 10);
|
||
|
break;
|
||
|
// KVAL is the maximum voltage of the PWM outputs. These 8-bit values are ratiometric
|
||
|
// representations: 255 for full output voltage, 128 for half, etc. Default is 0x29.
|
||
|
// The implications of different KVAL settings is too complex to dig into here, but
|
||
|
// it will usually work to max the value for RUN, ACC, and DEC. Maxing the value for
|
||
|
// HOLD may result in excessive power dissipation when the motor is not running.
|
||
|
case dSPIN_KVAL_HOLD:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
case dSPIN_KVAL_RUN:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
case dSPIN_KVAL_ACC:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
case dSPIN_KVAL_DEC:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
// INT_SPD, ST_SLP, FN_SLP_ACC and FN_SLP_DEC are all related to the back EMF
|
||
|
// compensation functionality. Please see the datasheet for details of this
|
||
|
// function- it is too complex to discuss here. Default values seem to work
|
||
|
// well enough.
|
||
|
case dSPIN_INT_SPD:
|
||
|
ret_val = dSPIN_Param(value, 14);
|
||
|
break;
|
||
|
case dSPIN_ST_SLP:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
case dSPIN_FN_SLP_ACC:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
case dSPIN_FN_SLP_DEC:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
// K_THERM is motor winding thermal drift compensation. Please see the datasheet
|
||
|
// for full details on operation- the default value should be okay for most users.
|
||
|
case dSPIN_K_THERM:
|
||
|
ret_val = dSPIN_Xfer((byte)value & 0x0F);
|
||
|
break;
|
||
|
// ADC_OUT is a read-only register containing the result of the ADC measurements.
|
||
|
// This is less useful than it sounds; see the datasheet for more information.
|
||
|
case dSPIN_ADC_OUT:
|
||
|
ret_val = dSPIN_Xfer(0);
|
||
|
break;
|
||
|
// Set the overcurrent threshold. Ranges from 375mA to 6A in steps of 375mA.
|
||
|
// A set of defined constants is provided for the user's convenience. Default
|
||
|
// value is 3.375A- 0x08. This is a 4-bit value.
|
||
|
case dSPIN_OCD_TH:
|
||
|
ret_val = dSPIN_Xfer((byte)value & 0x0F);
|
||
|
break;
|
||
|
// Stall current threshold. Defaults to 0x40, or 2.03A. Value is from 31.25mA to
|
||
|
// 4A in 31.25mA steps. This is a 7-bit value.
|
||
|
case dSPIN_STALL_TH:
|
||
|
ret_val = dSPIN_Xfer((byte)value & 0x7F);
|
||
|
break;
|
||
|
// STEP_MODE controls the microstepping settings, as well as the generation of an
|
||
|
// output signal from the dSPIN. Bits 2:0 control the number of microsteps per
|
||
|
// step the part will generate. Bit 7 controls whether the BUSY/SYNC pin outputs
|
||
|
// a BUSY signal or a step synchronization signal. Bits 6:4 control the frequency
|
||
|
// of the output signal relative to the full-step frequency; see datasheet for
|
||
|
// that relationship as it is too complex to reproduce here.
|
||
|
// Most likely, only the microsteps per step value will be needed; there is a set
|
||
|
// of constants provided for ease of use of these values.
|
||
|
case dSPIN_STEP_MODE:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
// ALARM_EN controls which alarms will cause the FLAG pin to fall. A set of constants
|
||
|
// is provided to make this easy to interpret. By default, ALL alarms will trigger the
|
||
|
// FLAG pin.
|
||
|
case dSPIN_ALARM_EN:
|
||
|
ret_val = dSPIN_Xfer((byte)value);
|
||
|
break;
|
||
|
// CONFIG contains some assorted configuration bits and fields. A fairly comprehensive
|
||
|
// set of reasonably self-explanatory constants is provided, but users should refer
|
||
|
// to the datasheet before modifying the contents of this register to be certain they
|
||
|
// understand the implications of their modifications. Value on boot is 0x2E88; this
|
||
|
// can be a useful way to verify proper start up and operation of the dSPIN chip.
|
||
|
case dSPIN_CONFIG:
|
||
|
ret_val = dSPIN_Param(value, 16);
|
||
|
break;
|
||
|
// STATUS contains read-only information about the current condition of the chip. A
|
||
|
// comprehensive set of constants for masking and testing this register is provided, but
|
||
|
// users should refer to the datasheet to ensure that they fully understand each one of
|
||
|
// the bits in the register.
|
||
|
case dSPIN_STATUS: // STATUS is a read-only register
|
||
|
ret_val = dSPIN_Param(0, 16);
|
||
|
break;
|
||
|
default:
|
||
|
ret_val = dSPIN_Xfer((byte)(value));
|
||
|
break;
|
||
|
}
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
// Enable or disable the low-speed optimization option. If enabling,
|
||
|
// the other 12 bits of the register will be automatically zero.
|
||
|
// When disabling, the value will have to be explicitly written by
|
||
|
// the user with a SetParam() call. See the datasheet for further
|
||
|
// information about low-speed optimization.
|
||
|
void SetLSPDOpt(boolean enable)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_SET_PARAM | dSPIN_MIN_SPEED);
|
||
|
if (enable) dSPIN_Param(0x1000, 13);
|
||
|
else dSPIN_Param(0, 13);
|
||
|
}
|
||
|
|
||
|
// RUN sets the motor spinning in a direction (defined by the constants
|
||
|
// FWD and REV). Maximum speed and minimum speed are defined
|
||
|
// by the MAX_SPEED and MIN_SPEED registers; exceeding the FS_SPD value
|
||
|
// will switch the device into full-step mode.
|
||
|
// The SpdCalc() function is provided to convert steps/s values into
|
||
|
// appropriate integer values for this function.
|
||
|
void dSPIN_Run(byte dir, unsigned long spd)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_RUN | dir);
|
||
|
if (spd > 0xFFFFF) spd = 0xFFFFF;
|
||
|
dSPIN_Xfer((byte)(spd >> 16));
|
||
|
dSPIN_Xfer((byte)(spd >> 8));
|
||
|
dSPIN_Xfer((byte)(spd));
|
||
|
}
|
||
|
|
||
|
// STEP_CLOCK puts the device in external step clocking mode. When active,
|
||
|
// pin 25, STCK, becomes the step clock for the device, and steps it in
|
||
|
// the direction (set by the FWD and REV constants) imposed by the call
|
||
|
// of this function. Motion commands (RUN, MOVE, etc) will cause the device
|
||
|
// to exit step clocking mode.
|
||
|
void dSPIN_Step_Clock(byte dir)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_STEP_CLOCK | dir);
|
||
|
}
|
||
|
|
||
|
// MOVE will send the motor n_step steps (size based on step mode) in the
|
||
|
// direction imposed by dir (FWD or REV constants may be used). The motor
|
||
|
// will accelerate according the acceleration and deceleration curves, and
|
||
|
// will run at MAX_SPEED. Stepping mode will adhere to FS_SPD value, as well.
|
||
|
void dSPIN_Move(byte dir, unsigned long n_step)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_MOVE | dir);
|
||
|
if (n_step > 0x3FFFFF) n_step = 0x3FFFFF;
|
||
|
dSPIN_Xfer((byte)(n_step >> 16));
|
||
|
dSPIN_Xfer((byte)(n_step >> 8));
|
||
|
dSPIN_Xfer((byte)(n_step));
|
||
|
}
|
||
|
|
||
|
// GOTO operates much like MOVE, except it produces absolute motion instead
|
||
|
// of relative motion. The motor will be moved to the indicated position
|
||
|
// in the shortest possible fashion.
|
||
|
void dSPIN_GoTo(unsigned long pos)
|
||
|
{
|
||
|
|
||
|
dSPIN_Xfer(dSPIN_GOTO);
|
||
|
if (pos > 0x3FFFFF) pos = 0x3FFFFF;
|
||
|
dSPIN_Xfer((byte)(pos >> 16));
|
||
|
dSPIN_Xfer((byte)(pos >> 8));
|
||
|
dSPIN_Xfer((byte)(pos));
|
||
|
}
|
||
|
|
||
|
// Same as GOTO, but with user constrained rotational direction.
|
||
|
void dSPIN_GoTo_DIR(byte dir, unsigned long pos)
|
||
|
{
|
||
|
|
||
|
dSPIN_Xfer(dSPIN_GOTO_DIR);
|
||
|
if (pos > 0x3FFFFF) pos = 0x3FFFFF;
|
||
|
dSPIN_Xfer((byte)(pos >> 16));
|
||
|
dSPIN_Xfer((byte)(pos >> 8));
|
||
|
dSPIN_Xfer((byte)(pos));
|
||
|
}
|
||
|
|
||
|
// GoUntil will set the motor running with direction dir (REV or
|
||
|
// FWD) until a falling edge is detected on the SW pin. Depending
|
||
|
// on bit SW_MODE in CONFIG, either a hard stop or a soft stop is
|
||
|
// performed at the falling edge, and depending on the value of
|
||
|
// act (either RESET or COPY) the value in the ABS_POS register is
|
||
|
// either RESET to 0 or COPY-ed into the MARK register.
|
||
|
void dSPIN_GoUntil(byte act, byte dir, unsigned long spd)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_GO_UNTIL | act | dir);
|
||
|
if (spd > 0x3FFFFF) spd = 0x3FFFFF;
|
||
|
dSPIN_Xfer((byte)(spd >> 16));
|
||
|
dSPIN_Xfer((byte)(spd >> 8));
|
||
|
dSPIN_Xfer((byte)(spd));
|
||
|
}
|
||
|
|
||
|
// Similar in nature to GoUntil, ReleaseSW produces motion at the
|
||
|
// higher of two speeds: the value in MIN_SPEED or 5 steps/s.
|
||
|
// The motor continues to run at this speed until a rising edge
|
||
|
// is detected on the switch input, then a hard stop is performed
|
||
|
// and the ABS_POS register is either COPY-ed into MARK or RESET to
|
||
|
// 0, depending on whether RESET or COPY was passed to the function
|
||
|
// for act.
|
||
|
void dSPIN_ReleaseSW(byte act, byte dir)
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_RELEASE_SW | act | dir);
|
||
|
}
|
||
|
|
||
|
// GoHome is equivalent to GoTo(0), but requires less time to send.
|
||
|
// Note that no direction is provided; motion occurs through shortest
|
||
|
// path. If a direction is required, use GoTo_DIR().
|
||
|
void dSPIN_GoHome()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_GO_HOME);
|
||
|
}
|
||
|
|
||
|
// GoMark is equivalent to GoTo(MARK), but requires less time to send.
|
||
|
// Note that no direction is provided; motion occurs through shortest
|
||
|
// path. If a direction is required, use GoTo_DIR().
|
||
|
void dSPIN_GoMark()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_GO_MARK);
|
||
|
}
|
||
|
|
||
|
// Sets the ABS_POS register to 0, effectively declaring the current
|
||
|
// position to be "HOME".
|
||
|
void dSPIN_ResetPos()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_RESET_POS);
|
||
|
}
|
||
|
|
||
|
// Reset device to power up conditions. Equivalent to toggling the STBY
|
||
|
// pin or cycling power.
|
||
|
void dSPIN_ResetDev()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_RESET_DEVICE);
|
||
|
}
|
||
|
|
||
|
// Bring the motor to a halt using the deceleration curve.
|
||
|
void dSPIN_SoftStop()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_SOFT_STOP);
|
||
|
}
|
||
|
|
||
|
// Stop the motor with infinite deceleration.
|
||
|
void dSPIN_HardStop()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_HARD_STOP);
|
||
|
}
|
||
|
|
||
|
// Decelerate the motor and put the bridges in Hi-Z state.
|
||
|
void dSPIN_SoftHiZ()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_SOFT_HIZ);
|
||
|
}
|
||
|
|
||
|
// Put the bridges in Hi-Z state immediately with no deceleration.
|
||
|
void dSPIN_HardHiZ()
|
||
|
{
|
||
|
dSPIN_Xfer(dSPIN_HARD_HIZ);
|
||
|
}
|
||
|
|
||
|
// Fetch and return the 16-bit value in the STATUS register. Resets
|
||
|
// any warning flags and exits any error states. Using GetParam()
|
||
|
// to read STATUS does not clear these values.
|
||
|
int dSPIN_GetStatus()
|
||
|
{
|
||
|
int temp = 0;
|
||
|
dSPIN_Xfer(dSPIN_GET_STATUS);
|
||
|
temp = dSPIN_Xfer(0)<<8;
|
||
|
temp |= dSPIN_Xfer(0);
|
||
|
return temp;
|
||
|
}
|
||
|
|