- Add support for L6470 Drivers.

- Both TMC, L6470 and pin-driven drivers work.
- All can be mixed and matched as needed.
2.0.x
domonoky 10 years ago
parent 5727cb3ed4
commit 443e7edef4

@ -0,0 +1,723 @@
////////////////////////////////////////////////////////////
//ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
//LIBRARY Created by Adam Meyer of bildr Aug 18th 2012
//Released as MIT license
////////////////////////////////////////////////////////////
#include <Arduino.h>
#include "L6470.h"
#include <SPI.h>
#define ENABLE_RESET_PIN 0
#define K_VALUE 100
L6470::L6470(int SSPin){
_SSPin = SSPin;
// Serial.begin(9600);
}
void L6470::init(int k_value){
// This is the generic initialization function to set up the Arduino to
// communicate with the dSPIN chip.
// set up the input/output pins for the application.
pinMode(SLAVE_SELECT_PIN, OUTPUT); // The SPI peripheral REQUIRES the hardware SS pin-
// pin 10- to be an output. This is in here just
// in case some future user makes something other
// than pin 10 the SS pin.
pinMode(_SSPin, OUTPUT);
digitalWrite(_SSPin, HIGH);
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
pinMode(BUSYN, INPUT);
#if (ENABLE_RESET_PIN == 1)
pinMode(RESET, OUTPUT);
// reset the dSPIN chip. This could also be accomplished by
// calling the "L6470::ResetDev()" function after SPI is initialized.
digitalWrite(RESET, HIGH);
delay(10);
digitalWrite(RESET, LOW);
delay(10);
digitalWrite(RESET, HIGH);
delay(10);
#endif
// initialize SPI for the dSPIN chip's needs:
// most significant bit first,
// SPI clock not to exceed 5MHz,
// SPI_MODE3 (clock idle high, latch data on rising edge of clock)
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV16); // or 2, 8, 16, 32, 64
SPI.setDataMode(SPI_MODE3);
// First things first: let's check communications. The CONFIG register should
// power up to 0x2E88, so we can use that to check the communications.
if (GetParam(CONFIG) == 0x2E88){
//Serial.println('good to go');
}
else{
//Serial.println('Comm issue');
}
#if (ENABLE_RESET_PIN == 0)
resetDev();
#endif
// First, let's set the step mode register:
// - SYNC_EN controls whether the BUSY/SYNC pin reflects the step
// frequency or the BUSY status of the chip. We want it to be the BUSY
// status.
// - STEP_SEL_x is the microstepping rate- we'll go full step.
// - SYNC_SEL_x is the ratio of (micro)steps to toggles on the
// BUSY/SYNC pin (when that pin is used for SYNC). Make it 1:1, despite
// not using that pin.
//SetParam(STEP_MODE, !SYNC_EN | STEP_SEL_1 | SYNC_SEL_1);
SetParam(KVAL_RUN, k_value);
SetParam(KVAL_ACC, k_value);
SetParam(KVAL_DEC, k_value);
SetParam(KVAL_HOLD, k_value);
// Set up the CONFIG register as follows:
// PWM frequency divisor = 1
// PWM frequency multiplier = 2 (62.5kHz PWM frequency)
// Slew rate is 290V/us
// Do NOT shut down bridges on overcurrent
// Disable motor voltage compensation
// Hard stop on switch low
// 16MHz internal oscillator, nothing on output
SetParam(CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_SR_290V_us| CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ);
// Configure the RUN KVAL. This defines the duty cycle of the PWM of the bridges
// during running. 0xFF means that they are essentially NOT PWMed during run; this
// MAY result in more power being dissipated than you actually need for the task.
// Setting this value too low may result in failure to turn.
// There are ACC, DEC, and HOLD KVAL registers as well; you may need to play with
// those values to get acceptable performance for a given application.
//SetParam(KVAL_RUN, 0xFF);
// Calling GetStatus() clears the UVLO bit in the status register, which is set by
// default on power-up. The driver may not run without that bit cleared by this
// read operation.
getStatus();
hardStop(); //engage motors
}
boolean L6470::isBusy(){
int status = getStatus();
return !((status >> 1) & 0b1);
}
void L6470::setMicroSteps(int microSteps){
byte stepVal = 0;
for(stepVal = 0; stepVal < 8; stepVal++){
if(microSteps == 1) break;
microSteps = microSteps >> 1;
}
SetParam(STEP_MODE, !SYNC_EN | stepVal | SYNC_SEL_1);
}
void L6470::setThresholdSpeed(float thresholdSpeed){
// Configure the FS_SPD register- this is the speed at which the driver ceases
// microstepping and goes to full stepping. FSCalc() converts a value in steps/s
// to a value suitable for this register; to disable full-step switching, you
// can pass 0x3FF to this register.
if(thresholdSpeed == 0.0){
SetParam(FS_SPD, 0x3FF);
}
else{
SetParam(FS_SPD, FSCalc(thresholdSpeed));
}
}
void L6470::setCurrent(int current){}
void L6470::setMaxSpeed(int speed){
// Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
// second allowed. You'll want to mess around with your desired application to see
// how far you can push it before the motor starts to slip. The ACTUAL parameter
// passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
// steps/s into an appropriate value for this function. Note that for any move or
// goto type function where no speed is specified, this value will be used.
SetParam(MAX_SPEED, MaxSpdCalc(speed));
}
void L6470::setMinSpeed(int speed){
// Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
// second allowed. You'll want to mess around with your desired application to see
// how far you can push it before the motor starts to slip. The ACTUAL parameter
// passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
// steps/s into an appropriate value for this function. Note that for any move or
// goto type function where no speed is specified, this value will be used.
SetParam(MIN_SPEED, MinSpdCalc(speed));
}
void L6470::setAcc(float acceleration){
// Configure the acceleration rate, in steps/tick/tick. There is also a DEC register;
// both of them have a function (AccCalc() and DecCalc() respectively) that convert
// from steps/s/s into the appropriate value for the register. Writing ACC to 0xfff
// sets the acceleration and deceleration to 'infinite' (or as near as the driver can
// manage). If ACC is set to 0xfff, DEC is ignored. To get infinite deceleration
// without infinite acceleration, only hard stop will work.
unsigned long accelerationBYTES = AccCalc(acceleration);
SetParam(ACC, accelerationBYTES);
}
void L6470::setDec(float deceleration){
unsigned long decelerationBYTES = DecCalc(deceleration);
SetParam(DEC, decelerationBYTES);
}
long L6470::getPos(){
unsigned long position = GetParam(ABS_POS);
return convert(position);
}
float L6470::getSpeed(){
/*
SPEED
The SPEED register contains the current motor speed, expressed in step/tick (format unsigned fixed point 0.28).
In order to convert the SPEED value in step/s the following formula can be used:
Equation 4
where SPEED is the integer number stored into the register and tick is 250 ns.
The available range is from 0 to 15625 step/s with a resolution of 0.015 step/s.
Note: The range effectively available to the user is limited by the MAX_SPEED parameter.
*/
return (float) GetParam(SPEED);
//return (float) speed * pow(8, -22);
//return FSCalc(speed); NEEDS FIX
}
void L6470::setOverCurrent(unsigned int ma_current){
// Configure the overcurrent detection threshold.
byte OCValue = floor(ma_current / 375);
if(OCValue > 0x0F)OCValue = 0x0F;
SetParam(OCD_TH, OCValue);
}
void L6470::setStallCurrent(float ma_current){
byte STHValue = (byte)floor(ma_current / 31.25);
if(STHValue > 0x80)STHValue = 0x80;
if(STHValue < 0)STHValue = 0;
SetParam(STALL_TH, STHValue);
}
void L6470::SetLowSpeedOpt(boolean enable){
// 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.
Xfer(SET_PARAM | MIN_SPEED);
if (enable) Param(0x1000, 13);
else Param(0, 13);
}
void L6470::run(byte dir, float spd){
// 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.
unsigned long speedVal = SpdCalc(spd);
Xfer(RUN | dir);
if (speedVal > 0xFFFFF) speedVal = 0xFFFFF;
Xfer((byte)(speedVal >> 16));
Xfer((byte)(speedVal >> 8));
Xfer((byte)(speedVal));
}
void L6470::Step_Clock(byte dir){
// 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.
Xfer(STEP_CLOCK | dir);
}
void L6470::move(long n_step){
// 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.
byte dir;
if(n_step >= 0){
dir = FWD;
}
else{
dir = REV;
}
long n_stepABS = abs(n_step);
Xfer(MOVE | dir); //set direction
if (n_stepABS > 0x3FFFFF) n_step = 0x3FFFFF;
Xfer((byte)(n_stepABS >> 16));
Xfer((byte)(n_stepABS >> 8));
Xfer((byte)(n_stepABS));
}
void L6470::goTo(long pos){
// 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.
Xfer(GOTO);
if (pos > 0x3FFFFF) pos = 0x3FFFFF;
Xfer((byte)(pos >> 16));
Xfer((byte)(pos >> 8));
Xfer((byte)(pos));
}
void L6470::goTo_DIR(byte dir, long pos){
// Same as GOTO, but with user constrained rotational direction.
Xfer(GOTO_DIR);
if (pos > 0x3FFFFF) pos = 0x3FFFFF;
Xfer((byte)(pos >> 16));
Xfer((byte)(pos >> 8));
Xfer((byte)(pos));
}
void L6470::goUntil(byte act, byte dir, unsigned long spd){
// 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.
Xfer(GO_UNTIL | act | dir);
if (spd > 0x3FFFFF) spd = 0x3FFFFF;
Xfer((byte)(spd >> 16));
Xfer((byte)(spd >> 8));
Xfer((byte)(spd));
}
void L6470::releaseSW(byte act, byte dir){
// 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.
Xfer(RELEASE_SW | act | dir);
}
void L6470::goHome(){
// 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().
Xfer(GO_HOME);
}
void L6470::goMark(){
// 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().
Xfer(GO_MARK);
}
void L6470::setMark(long value){
Xfer(MARK);
if (value > 0x3FFFFF) value = 0x3FFFFF;
if (value < -0x3FFFFF) value = -0x3FFFFF;
Xfer((byte)(value >> 16));
Xfer((byte)(value >> 8));
Xfer((byte)(value));
}
void L6470::setMark(){
long value = getPos();
Xfer(MARK);
if (value > 0x3FFFFF) value = 0x3FFFFF;
if (value < -0x3FFFFF) value = -0x3FFFFF;
Xfer((byte)(value >> 16));
Xfer((byte)(value >> 8));
Xfer((byte)(value));
}
void L6470::setAsHome(){
// Sets the ABS_POS register to 0, effectively declaring the current
// position to be "HOME".
Xfer(RESET_POS);
}
void L6470::resetDev(){
// Reset device to power up conditions. Equivalent to toggling the STBY
// pin or cycling power.
Xfer(RESET_DEVICE);
}
void L6470::softStop(){
// Bring the motor to a halt using the deceleration curve.
Xfer(SOFT_STOP);
}
void L6470::hardStop(){
// Stop the motor right away. No deceleration.
Xfer(HARD_STOP);
}
void L6470::softFree(){
// Decelerate the motor and disengage
Xfer(SOFT_HIZ);
}
void L6470::free(){
// disengage the motor immediately with no deceleration.
Xfer(HARD_HIZ);
}
int L6470::getStatus(){
// 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 temp = 0;
Xfer(GET_STATUS);
temp = Xfer(0)<<8;
temp |= Xfer(0);
return temp;
}
unsigned long L6470::AccCalc(float stepsPerSecPerSec){
// The value in the ACC register is [(steps/s/s)*(tick^2)]/(2^-40) where tick is
// 250ns (datasheet value)- 0x08A on boot.
// Multiply desired steps/s/s by .137438 to get an appropriate value for this register.
// This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
float temp = stepsPerSecPerSec * 0.137438;
if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
else return (unsigned long) long(temp);
}
unsigned long L6470::DecCalc(float stepsPerSecPerSec){
// The calculation for DEC is the same as for ACC. Value is 0x08A on boot.
// This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
float temp = stepsPerSecPerSec * 0.137438;
if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
else return (unsigned long) long(temp);
}
unsigned long L6470::MaxSpdCalc(float stepsPerSec){
// The value in the MAX_SPD register is [(steps/s)*(tick)]/(2^-18) where tick is
// 250ns (datasheet value)- 0x041 on boot.
// Multiply desired steps/s by .065536 to get an appropriate value for this register
// This is a 10-bit value, so we need to make sure it remains at or below 0x3FF
float temp = stepsPerSec * .065536;
if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF;
else return (unsigned long) long(temp);
}
unsigned long L6470::MinSpdCalc(float stepsPerSec){
// The value in the MIN_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
// 250ns (datasheet value)- 0x000 on boot.
// Multiply desired steps/s by 4.1943 to get an appropriate value for this register
// This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
float temp = stepsPerSec * 4.1943;
if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF;
else return (unsigned long) long(temp);
}
unsigned long L6470::FSCalc(float stepsPerSec){
// The value in the FS_SPD register is ([(steps/s)*(tick)]/(2^-18))-0.5 where tick is
// 250ns (datasheet value)- 0x027 on boot.
// Multiply desired steps/s by .065536 and subtract .5 to get an appropriate value for this register
// This is a 10-bit value, so we need to make sure the value is at or below 0x3FF.
float temp = (stepsPerSec * .065536)-.5;
if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF;
else return (unsigned long) long(temp);
}
unsigned long L6470::IntSpdCalc(float stepsPerSec){
// The value in the INT_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
// 250ns (datasheet value)- 0x408 on boot.
// Multiply desired steps/s by 4.1943 to get an appropriate value for this register
// This is a 14-bit value, so we need to make sure the value is at or below 0x3FFF.
float temp = stepsPerSec * 4.1943;
if( (unsigned long) long(temp) > 0x00003FFF) return 0x00003FFF;
else return (unsigned long) long(temp);
}
unsigned long L6470::SpdCalc(float stepsPerSec){
// When issuing RUN command, the 20-bit speed is [(steps/s)*(tick)]/(2^-28) where tick is
// 250ns (datasheet value).
// Multiply desired steps/s by 67.106 to get an appropriate value for this register
// This is a 20-bit value, so we need to make sure the value is at or below 0xFFFFF.
float temp = stepsPerSec * 67.106;
if( (unsigned long) long(temp) > 0x000FFFFF) return 0x000FFFFF;
else return (unsigned long)temp;
}
unsigned long L6470::Param(unsigned long value, byte bit_len){
// Generalization of the subsections of the register read/write functionality.
// We want the end user to just write the value without worrying about length,
// so we pass a bit length parameter from the calling function.
unsigned long ret_val=0; // We'll return this to generalize this function
// for both read and write of registers.
byte byte_len = bit_len/8; // How many BYTES do we have?
if (bit_len%8 > 0) byte_len++; // Make sure not to lose any partial byte values.
// Let's make sure our value has no spurious bits set, and if the value was too
// high, max it out.
unsigned long mask = 0xffffffff >> (32-bit_len);
if (value > mask) value = mask;
// The following three if statements handle the various possible byte length
// transfers- it'll be no less than 1 but no more than 3 bytes of data.
// L6470::Xfer() sends a byte out through SPI and returns a byte received
// over SPI- when calling it, we typecast a shifted version of the masked
// value, then we shift the received value back by the same amount and
// store it until return time.
if (byte_len == 3) {
ret_val |= long(Xfer((byte)(value>>16))) << 16;
//Serial.println(ret_val, HEX);
}
if (byte_len >= 2) {
ret_val |= long(Xfer((byte)(value>>8))) << 8;
//Serial.println(ret_val, HEX);
}
if (byte_len >= 1) {
ret_val |= Xfer((byte)value);
//Serial.println(ret_val, HEX);
}
// Return the received values. Mask off any unnecessary bits, just for
// the sake of thoroughness- we don't EXPECT to see anything outside
// the bit length range but better to be safe than sorry.
return (ret_val & mask);
}
byte L6470::Xfer(byte data){
// This simple function shifts a byte out over SPI and receives a byte over
// SPI. Unusually for SPI devices, the dSPIN requires a toggling of the
// CS (slaveSelect) pin after each byte sent. That makes this function
// a bit more reasonable, because we can include more functionality in it.
byte data_out;
digitalWrite(_SSPin,LOW);
// SPI.transfer() both shifts a byte out on the MOSI pin AND receives a
// byte in on the MISO pin.
data_out = SPI.transfer(data);
digitalWrite(_SSPin,HIGH);
return data_out;
}
void L6470::SetParam(byte param, unsigned long value){
Xfer(SET_PARAM | param);
ParamHandler(param, value);
}
unsigned long L6470::GetParam(byte param){
// Realize the "get parameter" function, to read from the various registers in
// the dSPIN chip.
Xfer(GET_PARAM | param);
return ParamHandler(param, 0);
}
long L6470::convert(unsigned long val){
//convert 22bit 2s comp to signed long
int MSB = val >> 21;
val = val << 11;
val = val >> 11;
if(MSB == 1) val = val | 0b11111111111000000000000000000000;
return val;
}
unsigned long L6470::ParamHandler(byte param, unsigned long value){
// 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 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
// 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 ABS_POS:
ret_val = 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 EL_POS:
ret_val = 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 MARK:
ret_val = Param(value, 22);
break;
// SPEED contains information about the current speed. It is read-only. It does
// NOT provide direction information.
case SPEED:
ret_val = 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 ACC:
ret_val = Param(value, 12);
break;
case DEC:
ret_val = 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 MAX_SPEED:
ret_val = 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. SetLowSpeedOpt() function exists to enable/disable the optimization feature.
case MIN_SPEED:
ret_val = 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 FS_SPD:
ret_val = 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 KVAL_HOLD:
ret_val = Xfer((byte)value);
break;
case KVAL_RUN:
ret_val = Xfer((byte)value);
break;
case KVAL_ACC:
ret_val = Xfer((byte)value);
break;
case KVAL_DEC:
ret_val = 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 INT_SPD:
ret_val = Param(value, 14);
break;
case ST_SLP:
ret_val = Xfer((byte)value);
break;
case FN_SLP_ACC:
ret_val = Xfer((byte)value);
break;
case FN_SLP_DEC:
ret_val = 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 K_THERM:
ret_val = 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 ADC_OUT:
ret_val = 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 OCD_TH:
ret_val = 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 STALL_TH:
ret_val = 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 STEP_MODE:
ret_val = 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 ALARM_EN:
ret_val = 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 CONFIG:
ret_val = 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 STATUS: // STATUS is a read-only register
ret_val = Param(0, 16);
break;
default:
ret_val = Xfer((byte)(value));
break;
}
return ret_val;
}

@ -0,0 +1,286 @@
////////////////////////////////////////////////////////////
//ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
//LIBRARY Created by Adam Meyer of bildr Aug 18th 2012
//Released as MIT license
////////////////////////////////////////////////////////////
#ifndef L6470_h
#define L6470_h
#include <Arduino.h>
#include <SPI.h>
#define SLAVE_SELECT_PIN 38 // Wire this to the CSN pin
// #define RESET 6 // Wire this to the STBY line
#define BUSYN 7 // Wire this to the BSYN line
// constant definitions for overcurrent thresholds. Write these values to
// register dSPIN_OCD_TH to set the level at which an overcurrent even occurs.
#define OCD_TH_375mA 0x00
#define OCD_TH_750mA 0x01
#define OCD_TH_1125mA 0x02
#define OCD_TH_1500mA 0x03
#define OCD_TH_1875mA 0x04
#define OCD_TH_2250mA 0x05
#define OCD_TH_2625mA 0x06
#define OCD_TH_3000mA 0x07
#define OCD_TH_3375mA 0x08
#define OCD_TH_3750mA 0x09
#define OCD_TH_4125mA 0x0A
#define OCD_TH_4500mA 0x0B
#define OCD_TH_4875mA 0x0C
#define OCD_TH_5250mA 0x0D
#define OCD_TH_5625mA 0x0E
#define OCD_TH_6000mA 0x0F
// STEP_MODE option values.
// First comes the "microsteps per step" options...
#define STEP_MODE_STEP_SEL 0x07 // Mask for these bits only.
#define STEP_SEL_1 0x00
#define STEP_SEL_1_2 0x01
#define STEP_SEL_1_4 0x02
#define STEP_SEL_1_8 0x03
#define STEP_SEL_1_16 0x04
#define STEP_SEL_1_32 0x05
#define STEP_SEL_1_64 0x06
#define STEP_SEL_1_128 0x07
// ...next, define the SYNC_EN bit. When set, the BUSYN pin will instead
// output a clock related to the full-step frequency as defined by the
// SYNC_SEL bits below.
#define STEP_MODE_SYNC_EN 0x80 // Mask for this bit
#define SYNC_EN 0x80
// ...last, define the SYNC_SEL modes. The clock output is defined by
// the full-step frequency and the value in these bits- see the datasheet
// for a matrix describing that relationship (page 46).
#define STEP_MODE_SYNC_SEL 0x70
#define SYNC_SEL_1_2 0x00
#define SYNC_SEL_1 0x10
#define SYNC_SEL_2 0x20
#define SYNC_SEL_4 0x30
#define SYNC_SEL_8 0x40
#define SYNC_SEL_16 0x50
#define SYNC_SEL_32 0x60
#define SYNC_SEL_64 0x70
// Bit names for the ALARM_EN register.
// Each of these bits defines one potential alarm condition.
// When one of these conditions occurs and the respective bit in ALARM_EN is set,
// the FLAG pin will go low. The register must be queried to determine which event
// caused the alarm.
#define ALARM_EN_OVERCURRENT 0x01
#define ALARM_EN_THERMAL_SHUTDOWN 0x02
#define ALARM_EN_THERMAL_WARNING 0x04
#define ALARM_EN_UNDER_VOLTAGE 0x08
#define ALARM_EN_STALL_DET_A 0x10
#define ALARM_EN_STALL_DET_B 0x20
#define ALARM_EN_SW_TURN_ON 0x40
#define ALARM_EN_WRONG_NPERF_CMD 0x80
// CONFIG register renames.
// Oscillator options.
// The dSPIN needs to know what the clock frequency is because it uses that for some
// calculations during operation.
#define CONFIG_OSC_SEL 0x000F // Mask for this bit field.
#define CONFIG_INT_16MHZ 0x0000 // Internal 16MHz, no output
#define CONFIG_INT_16MHZ_OSCOUT_2MHZ 0x0008 // Default; internal 16MHz, 2MHz output
#define CONFIG_INT_16MHZ_OSCOUT_4MHZ 0x0009 // Internal 16MHz, 4MHz output
#define CONFIG_INT_16MHZ_OSCOUT_8MHZ 0x000A // Internal 16MHz, 8MHz output
#define CONFIG_INT_16MHZ_OSCOUT_16MHZ 0x000B // Internal 16MHz, 16MHz output
#define CONFIG_EXT_8MHZ_XTAL_DRIVE 0x0004 // External 8MHz crystal
#define CONFIG_EXT_16MHZ_XTAL_DRIVE 0x0005 // External 16MHz crystal
#define CONFIG_EXT_24MHZ_XTAL_DRIVE 0x0006 // External 24MHz crystal
#define CONFIG_EXT_32MHZ_XTAL_DRIVE 0x0007 // External 32MHz crystal
#define CONFIG_EXT_8MHZ_OSCOUT_INVERT 0x000C // External 8MHz crystal, output inverted
#define CONFIG_EXT_16MHZ_OSCOUT_INVERT 0x000D // External 16MHz crystal, output inverted
#define CONFIG_EXT_24MHZ_OSCOUT_INVERT 0x000E // External 24MHz crystal, output inverted
#define CONFIG_EXT_32MHZ_OSCOUT_INVERT 0x000F // External 32MHz crystal, output inverted
// Configure the functionality of the external switch input
#define CONFIG_SW_MODE 0x0010 // Mask for this bit.
#define CONFIG_SW_HARD_STOP 0x0000 // Default; hard stop motor on switch.
#define CONFIG_SW_USER 0x0010 // Tie to the GoUntil and ReleaseSW
// commands to provide jog function.
// See page 25 of datasheet.
// Configure the motor voltage compensation mode (see page 34 of datasheet)
#define CONFIG_EN_VSCOMP 0x0020 // Mask for this bit.
#define CONFIG_VS_COMP_DISABLE 0x0000 // Disable motor voltage compensation.
#define CONFIG_VS_COMP_ENABLE 0x0020 // Enable motor voltage compensation.
// Configure overcurrent detection event handling
#define CONFIG_OC_SD 0x0080 // Mask for this bit.
#define CONFIG_OC_SD_DISABLE 0x0000 // Bridges do NOT shutdown on OC detect
#define CONFIG_OC_SD_ENABLE 0x0080 // Bridges shutdown on OC detect
// Configure the slew rate of the power bridge output
#define CONFIG_POW_SR 0x0300 // Mask for this bit field.
#define CONFIG_SR_180V_us 0x0000 // 180V/us
#define CONFIG_SR_290V_us 0x0200 // 290V/us
#define CONFIG_SR_530V_us 0x0300 // 530V/us
// Integer divisors for PWM sinewave generation
// See page 32 of the datasheet for more information on this.
#define CONFIG_F_PWM_DEC 0x1C00 // mask for this bit field
#define CONFIG_PWM_MUL_0_625 (0x00)<<10
#define CONFIG_PWM_MUL_0_75 (0x01)<<10
#define CONFIG_PWM_MUL_0_875 (0x02)<<10
#define CONFIG_PWM_MUL_1 (0x03)<<10
#define CONFIG_PWM_MUL_1_25 (0x04)<<10
#define CONFIG_PWM_MUL_1_5 (0x05)<<10
#define CONFIG_PWM_MUL_1_75 (0x06)<<10
#define CONFIG_PWM_MUL_2 (0x07)<<10
// Multiplier for the PWM sinewave frequency
#define CONFIG_F_PWM_INT 0xE000 // mask for this bit field.
#define CONFIG_PWM_DIV_1 (0x00)<<13
#define CONFIG_PWM_DIV_2 (0x01)<<13
#define CONFIG_PWM_DIV_3 (0x02)<<13
#define CONFIG_PWM_DIV_4 (0x03)<<13
#define CONFIG_PWM_DIV_5 (0x04)<<13
#define CONFIG_PWM_DIV_6 (0x05)<<13
#define CONFIG_PWM_DIV_7 (0x06)<<13
// Status register bit renames- read-only bits conferring information about the
// device to the user.
#define STATUS_HIZ 0x0001 // high when bridges are in HiZ mode
#define STATUS_BUSY 0x0002 // mirrors BUSY pin
#define STATUS_SW_F 0x0004 // low when switch open, high when closed
#define STATUS_SW_EVN 0x0008 // active high, set on switch falling edge,
// cleared by reading STATUS
#define STATUS_DIR 0x0010 // Indicates current motor direction.
// High is FWD, Low is REV.
#define STATUS_NOTPERF_CMD 0x0080 // Last command not performed.
#define STATUS_WRONG_CMD 0x0100 // Last command not valid.
#define STATUS_UVLO 0x0200 // Undervoltage lockout is active
#define STATUS_TH_WRN 0x0400 // Thermal warning
#define STATUS_TH_SD 0x0800 // Thermal shutdown
#define STATUS_OCD 0x1000 // Overcurrent detected
#define STATUS_STEP_LOSS_A 0x2000 // Stall detected on A bridge
#define STATUS_STEP_LOSS_B 0x4000 // Stall detected on B bridge
#define STATUS_SCK_MOD 0x8000 // Step clock mode is active
// Status register motor status field
#define STATUS_MOT_STATUS 0x0060 // field mask
#define STATUS_MOT_STATUS_STOPPED (0x0000)<<13 // Motor stopped
#define STATUS_MOT_STATUS_ACCELERATION (0x0001)<<13 // Motor accelerating
#define STATUS_MOT_STATUS_DECELERATION (0x0002)<<13 // Motor decelerating
#define STATUS_MOT_STATUS_CONST_SPD (0x0003)<<13 // Motor at constant speed
// Register address redefines.
// See the Param_Handler() function for more info about these.
#define ABS_POS 0x01
#define EL_POS 0x02
#define MARK 0x03
#define SPEED 0x04
#define ACC 0x05
#define DEC 0x06
#define MAX_SPEED 0x07
#define MIN_SPEED 0x08
#define FS_SPD 0x15
#define KVAL_HOLD 0x09
#define KVAL_RUN 0x0A
#define KVAL_ACC 0x0B
#define KVAL_DEC 0x0C
#define INT_SPD 0x0D
#define ST_SLP 0x0E
#define FN_SLP_ACC 0x0F
#define FN_SLP_DEC 0x10
#define K_THERM 0x11
#define ADC_OUT 0x12
#define OCD_TH 0x13
#define STALL_TH 0x14
#define STEP_MODE 0x16
#define ALARM_EN 0x17
#define CONFIG 0x18
#define STATUS 0x19
//dSPIN commands
#define NOP 0x00
#define SET_PARAM 0x00
#define GET_PARAM 0x20
#define RUN 0x50
#define STEP_CLOCK 0x58
#define MOVE 0x40
#define GOTO 0x60
#define GOTO_DIR 0x68
#define GO_UNTIL 0x82
#define RELEASE_SW 0x92
#define GO_HOME 0x70
#define GO_MARK 0x78
#define RESET_POS 0xD8
#define RESET_DEVICE 0xC0
#define SOFT_STOP 0xB0
#define HARD_STOP 0xB8
#define SOFT_HIZ 0xA0
#define HARD_HIZ 0xA8
#define GET_STATUS 0xD0
/* dSPIN direction options */
#define FWD 0x01
#define REV 0x00
/* dSPIN action options */
#define ACTION_RESET 0x00
#define ACTION_COPY 0x01
class L6470{
public:
L6470(int SSPin);
void init(int k_value);
void setMicroSteps(int microSteps);
void setCurrent(int current);
void setMaxSpeed(int speed);
void setMinSpeed(int speed);
void setAcc(float acceleration);
void setDec(float deceleration);
void setOverCurrent(unsigned int ma_current);
void setThresholdSpeed(float threshold);
void setStallCurrent(float ma_current);
unsigned long ParamHandler(byte param, unsigned long value);
void SetLowSpeedOpt(boolean enable);
void run(byte dir, float spd);
void Step_Clock(byte dir);
void goHome();
void setAsHome();
void goMark();
void move(long n_step);
void goTo(long pos);
void goTo_DIR(byte dir, long pos);
void goUntil(byte act, byte dir, unsigned long spd);
boolean isBusy();
void releaseSW(byte act, byte dir);
float getSpeed();
long getPos();
void setMark();
void setMark(long value);
void resetPos();
void resetDev();
void softStop();
void hardStop();
void softFree();
void free();
int getStatus();
void SetParam(byte param, unsigned long value);
private:
long convert(unsigned long val);
unsigned long GetParam(byte param);
unsigned long AccCalc(float stepsPerSecPerSec);
unsigned long DecCalc(float stepsPerSecPerSec);
unsigned long MaxSpdCalc(float stepsPerSec);
unsigned long MinSpdCalc(float stepsPerSec);
unsigned long FSCalc(float stepsPerSec);
unsigned long IntSpdCalc(float stepsPerSec);
unsigned long SpdCalc(float stepsPerSec);
unsigned long Param(unsigned long value, byte bit_len);
byte Xfer(byte data);
int _SSPin;
};
#endif

@ -0,0 +1,53 @@
#######################################################
# keywords.txt - keywords file for the L6470 library
#
# ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
# Library by Adam Meyer of bildr Aug 18th 2012
#
# Released as MIT license
#######################################################
#######################################
# Datatypes (KEYWORD1)
#######################################
L6470 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
L6470 KEYWORD2
init KEYWORD2
setMicroSteps KEYWORD2
setCurrent KEYWORD2
setMaxSpeed KEYWORD2
setMinSpeed KEYWORD2
setAcc KEYWORD2
setDec KEYWORD2
setOverCurrent KEYWORD2
setThresholdSpeed KEYWORD2
setStallCurrent KEYWORD2
ParamHandler KEYWORD2
SetLowSpeedOpt KEYWORD2
run KEYWORD2
Step_Clock KEYWORD2
goHome KEYWORD2
goMark KEYWORD2
move KEYWORD2
goTo KEYWORD2
goTo_DIR KEYWORD2
goUntil KEYWORD2
isBusy KEYWORD2
releaseSW KEYWORD2
resetPos KEYWORD2
resetDev KEYWORD2
softStop KEYWORD2
hardStop KEYWORD2
softHiZ KEYWORD2
hardHiZ KEYWORD2
getStatus KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

@ -467,61 +467,135 @@ const unsigned int dropsegments=5; //everything with less than this number of st
* you need to import the TMC26XStepper library into the arduino IDE for this
******************************************************************************/
#define HAVE_TMCDRIVER
//#define HAVE_TMCDRIVER
#ifdef HAVE_TMCDRIVER
#define X_IS_TMC
#define X_MAX_CURRENT 2000 //in mA
// #define X_IS_TMC
#define X_MAX_CURRENT 1000 //in mA
#define X_SENSE_RESISTOR 91 //in mOhms
#define X_MICROSTEPS 16 //number of microsteps
// #define X2_IS_TMC
#define X2_MAX_CURRENT 2000 //in mA
#define X2_MAX_CURRENT 1000 //in mA
#define X2_SENSE_RESISTOR 91 //in mOhms
#define X2_MICROSTEPS 16 //number of microsteps
#define Y_IS_TMC
#define Y_MAX_CURRENT 2000 //in mA
// #define Y_IS_TMC
#define Y_MAX_CURRENT 1000 //in mA
#define Y_SENSE_RESISTOR 91 //in mOhms
#define Y_MICROSTEPS 16 //number of microsteps
// #define Y2_IS_TMC
#define Y2_MAX_CURRENT 2000 //in mA
#define Y2_MAX_CURRENT 1000 //in mA
#define Y2_SENSE_RESISTOR 91 //in mOhms
#define Y2_MICROSTEPS 16 //number of microsteps
#define Z_IS_TMC
#define Z_MAX_CURRENT 2000 //in mA
// #define Z_IS_TMC
#define Z_MAX_CURRENT 1000 //in mA
#define Z_SENSE_RESISTOR 91 //in mOhms
#define Z_MICROSTEPS 16 //number of microsteps
// #define Z2_IS_TMC
#define Z2_MAX_CURRENT 2000 //in mA
#define Z2_MAX_CURRENT 1000 //in mA
#define Z2_SENSE_RESISTOR 91 //in mOhms
#define Z2_MICROSTEPS 16 //number of microsteps
#define E0_IS_TMC
#define E0_MAX_CURRENT 2000 //in mA
// #define E0_IS_TMC
#define E0_MAX_CURRENT 1000 //in mA
#define E0_SENSE_RESISTOR 91 //in mOhms
#define E0_MICROSTEPS 16 //number of microsteps
#define E1_IS_TMC
#define E1_MAX_CURRENT 2000 //in mA
// #define E1_IS_TMC
#define E1_MAX_CURRENT 1000 //in mA
#define E1_SENSE_RESISTOR 91 //in mOhms
#define E1_MICROSTEPS 16 //number of microsteps
// #define E2_IS_TMC
#define E2_MAX_CURRENT 2000 //in mA
#define E2_MAX_CURRENT 1000 //in mA
#define E2_SENSE_RESISTOR 91 //in mOhms
#define E2_MICROSTEPS 16 //number of microsteps
// #define E3_IS_TMC
#define E3_MAX_CURRENT 2000 //in mA
#define E3_MAX_CURRENT 1000 //in mA
#define E3_SENSE_RESISTOR 91 //in mOhms
#define E3_MICROSTEPS 16 //number of microsteps
#endif
/******************************************************************************\
* enable this section if you have L6470 motor drivers.
* you need to import the L6470 library into the arduino IDE for this
******************************************************************************/
//#define HAVE_L6470DRIVER
#ifdef HAVE_L6470DRIVER
// #define X_IS_L6470
#define X_MICROSTEPS 16 //number of microsteps
#define X_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define X_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define X_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define X2_IS_L6470
#define X2_MICROSTEPS 16 //number of microsteps
#define X2_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define X2_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define X2_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define Y_IS_L6470
#define Y_MICROSTEPS 16 //number of microsteps
#define Y_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define Y_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define Y_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define Y2_IS_L6470
#define Y2_MICROSTEPS 16 //number of microsteps
#define Y2_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define Y2_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define Y2_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define Z_IS_L6470
#define Z_MICROSTEPS 16 //number of microsteps
#define Z_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define Z_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define Z_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define Z2_IS_L6470
#define Z2_MICROSTEPS 16 //number of microsteps
#define Z2_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define Z2_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define Z2_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define E0_IS_L6470
#define E0_MICROSTEPS 16 //number of microsteps
#define E0_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define E0_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define E0_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define E1_IS_L6470
#define E1_MICROSTEPS 16 //number of microsteps
#define E1_MICROSTEPS 16 //number of microsteps
#define E1_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define E1_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define E1_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define E2_IS_L6470
#define E2_MICROSTEPS 16 //number of microsteps
#define E2_MICROSTEPS 16 //number of microsteps
#define E2_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define E2_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define E2_STALLCURRENT 1500 //current in mA where the driver will detect a stall
// #define E3_IS_L6470
#define E3_MICROSTEPS 16 //number of microsteps
#define E3_MICROSTEPS 16 //number of microsteps
#define E3_K_VAL 50 // 0 - 255, Higher values, are higher power. Be carefull not to go too high
#define E3_OVERCURRENT 2000 //maxc current in mA. If the current goes over this value, the driver will switch off
#define E3_STALLCURRENT 1500 //current in mA where the driver will detect a stall
#endif
//===========================================================================
//============================= Define Defines ============================
//===========================================================================

@ -59,3 +59,8 @@
#include <SPI.h>
#include <TMC26XStepper.h>
#endif
#ifdef HAVE_L6470DRIVER
#include <SPI.h>
#include <L6470.h>
#endif

@ -842,6 +842,11 @@ void st_init()
#ifdef HAVE_TMCDRIVER
tmc_init();
#endif
// initialise L6470 Steppers
#ifdef HAVE_L6470DRIVER
L6470_init();
#endif
//Initialize Dir Pins
#if defined(X_DIR_PIN) && X_DIR_PIN > -1

@ -103,4 +103,122 @@ void tmc_init()
stepperE3.start();
#endif
}
#endif
#endif
// L6470 Driver objects and inits
#ifdef HAVE_L6470DRIVER
#include <SPI.h>
#include <L6470.h>
#endif
// L6470 Stepper objects
#ifdef X_IS_L6470
L6470 stepperX(X_ENABLE_PIN);
#endif
#ifdef X2_IS_L6470
L6470 stepperX2(X2_ENABLE_PIN);
#endif
#ifdef Y_IS_L6470
L6470 stepperY(Y_ENABLE_PIN);
#endif
#ifdef Y2_IS_L6470
L6470 stepperY2(Y2_ENABLE_PIN);
#endif
#ifdef Z_IS_L6470
L6470 stepperZ(Z_ENABLE_PIN);
#endif
#ifdef Z2_IS_L6470
L6470 stepperZ2(Z2_ENABLE_PIN);
#endif
#ifdef E0_IS_L6470
L6470 stepperE0(E0_ENABLE_PIN);
#endif
#ifdef E1_IS_L6470
L6470 stepperE1(E1_ENABLE_PIN);
#endif
#ifdef E2_IS_L6470
L6470 stepperE2(E2_ENABLE_PIN);
#endif
#ifdef E3_IS_L6470
L6470 stepperE3(E3_ENABLE_PIN);
#endif
// init routine
#ifdef HAVE_L6470DRIVER
void L6470_init()
{
#ifdef X_IS_L6470
stepperX.init(X_K_VAL);
stepperX.softFree();
stepperX.setMicroSteps(X_MICROSTEPS);
stepperX.setOverCurrent(X_OVERCURRENT); //set overcurrent protection
stepperX.setStallCurrent(X_STALLCURRENT);
#endif
#ifdef X2_IS_L6470
stepperX2.init(X2_K_VAL);
stepperX2.softFree();
stepperX2.setMicroSteps(X2_MICROSTEPS);
stepperX2.setOverCurrent(X2_OVERCURRENT); //set overcurrent protection
stepperX2.setStallCurrent(X2_STALLCURRENT);
#endif
#ifdef Y_IS_L6470
stepperY.init(Y_K_VAL);
stepperY.softFree();
stepperY.setMicroSteps(Y_MICROSTEPS);
stepperY.setOverCurrent(Y_OVERCURRENT); //set overcurrent protection
stepperY.setStallCurrent(Y_STALLCURRENT);
#endif
#ifdef Y2_IS_L6470
stepperY2.init(Y2_K_VAL);
stepperY2.softFree();
stepperY2.setMicroSteps(Y2_MICROSTEPS);
stepperY2.setOverCurrent(Y2_OVERCURRENT); //set overcurrent protection
stepperY2.setStallCurrent(Y2_STALLCURRENT);
#endif
#ifdef Z_IS_L6470
stepperZ.init(Z_K_VAL);
stepperZ.softFree();
stepperZ.setMicroSteps(Z_MICROSTEPS);
stepperZ.setOverCurrent(Z_OVERCURRENT); //set overcurrent protection
stepperZ.setStallCurrent(Z_STALLCURRENT);
#endif
#ifdef Z2_IS_L6470
stepperZ2.init(Z2_K_VAL);
stepperZ2.softFree();
stepperZ2.setMicroSteps(Z2_MICROSTEPS);
stepperZ2.setOverCurrent(Z2_OVERCURRENT); //set overcurrent protection
stepperZ2.setStallCurrent(Z2_STALLCURRENT);
#endif
#ifdef E0_IS_L6470
stepperE0.init(E0_K_VAL);
stepperE0.softFree();
stepperE0.setMicroSteps(E0_MICROSTEPS);
stepperE0.setOverCurrent(E0_OVERCURRENT); //set overcurrent protection
stepperE0.setStallCurrent(E0_STALLCURRENT);
#endif
#ifdef E1_IS_L6470
stepperE1.init(E1_K_VAL);
stepperE1.softFree();
stepperE1.setMicroSteps(E1_MICROSTEPS);
stepperE1.setOverCurrent(E1_OVERCURRENT); //set overcurrent protection
stepperE1.setStallCurrent(E1_STALLCURRENT);
#endif
#ifdef E2_IS_L6470
stepperE2.init(E2_K_VAL);
stepperE2.softFree();
stepperE2.setMicroSteps(E2_MICROSTEPS);
stepperE2.setOverCurrent(E2_OVERCURRENT); //set overcurrent protection
stepperE2.setStallCurrent(E2_STALLCURRENT);
#endif
#ifdef E3_IS_L6470
stepperE3.init(E3_K_VAL);
stepperE3.softFree();
stepperE3.setMicroSteps(E3_MICROSTEPS);
stepperE3.setOverCurrent(E3_OVERCURRENT); //set overcurrent protection
stepperE3.setStallCurrent(E3_STALLCURRENT);
#endif
}
#endif

@ -160,38 +160,9 @@
#include <SPI.h>
#include <TMC26XStepper.h>
#ifdef X_IS_TMC
extern TMC26XStepper stepperX;
#endif
#ifdef X2_IS_TMC
extern TMC26XStepper stepperX2;
#endif
#ifdef Y_IS_TMC
extern TMC26XStepper stepperY;
#endif
#ifdef Y2_IS_TMC
extern TMC26XStepper stepperY2;
#endif
#ifdef Z_IS_TMC
extern TMC26XStepper stepperZ;
#endif
#ifdef Z2_IS_TMC
extern TMC26XStepper stepperZ2;
#endif
#ifdef E0_IS_TMC
extern TMC26XStepper stepperE0;
#endif
#ifdef E1_IS_TMC
extern TMC26XStepper stepperE1;
#endif
#ifdef E2_IS_TMC
extern TMC26XStepper stepperE2;
#endif
#ifdef E3_IS_TMC
extern TMC26XStepper stepperE3;
#endif
void tmc_init();
#ifdef X_IS_TMC
extern TMC26XStepper stepperX;
#undef X_ENABLE_INIT
#define X_ENABLE_INIT ((void)0)
@ -200,8 +171,10 @@
#undef X_ENABLE_READ
#define X_ENABLE_READ stepperX.isEnabled()
#endif
#ifdef X2_IS_TMC
extern TMC26XStepper stepperX2;
#undef X2_ENABLE_INIT
#define X2_ENABLE_INIT ((void)0)
@ -212,6 +185,7 @@
#define X2_ENABLE_READ stepperX2.isEnabled()
#endif
#ifdef Y_IS_TMC
extern TMC26XStepper stepperY;
#undef Y_ENABLE_INIT
#define Y_ENABLE_INIT ((void)0)
@ -222,6 +196,7 @@
#define Y_ENABLE_READ stepperY.isEnabled()
#endif
#ifdef Y2_IS_TMC
extern TMC26XStepper stepperY2;
#undef Y2_ENABLE_INIT
#define Y2_ENABLE_INIT ((void)0)
@ -232,6 +207,7 @@
#define Y2_ENABLE_READ stepperY2.isEnabled()
#endif
#ifdef Z_IS_TMC
extern TMC26XStepper stepperZ;
#undef Z_ENABLE_INIT
#define Z_ENABLE_INIT ((void)0)
@ -242,6 +218,7 @@
#define Z_ENABLE_READ stepperZ.isEnabled()
#endif
#ifdef Z2_IS_TMC
extern TMC26XStepper stepperZ2;
#undef Z2_ENABLE_INIT
#define Z2_ENABLE_INIT ((void)0)
@ -252,6 +229,7 @@
#define Z2_ENABLE_READ stepperZ2.isEnabled()
#endif
#ifdef E0_IS_TMC
extern TMC26XStepper stepperE0;
#undef E0_ENABLE_INIT
#define E0_ENABLE_INIT ((void)0)
@ -262,6 +240,7 @@
#define E0_ENABLE_READ stepperE0.isEnabled()
#endif
#ifdef E1_IS_TMC
extern TMC26XStepper stepperE1;
#undef E1_ENABLE_INIT
#define E1_ENABLE_INIT ((void)0)
@ -272,6 +251,7 @@
#define E1_ENABLE_READ stepperE1.isEnabled()
#endif
#ifdef E2_IS_TMC
extern TMC26XStepper stepperE2;
#undef E2_ENABLE_INIT
#define E2_ENABLE_INIT ((void)0)
@ -282,6 +262,7 @@
#define E2_ENABLE_READ stepperE2.isEnabled()
#endif
#ifdef E3_IS_TMC
extern TMC26XStepper stepperE3;
#undef E3_ENABLE_INIT
#define E3_ENABLE_INIT ((void)0)
@ -291,6 +272,221 @@
#undef E3_ENABLE_READ
#define E3_ENABLE_READ stepperE3.isEnabled()
#endif
#endif
#endif // HAVE_TMCDRIVER
//////////////////////////////////
// Pin redefines for L6470 drivers.
// L640 drivers have step on normal pins, but dir and everything else via SPI
//////////////////////////////////
#ifdef HAVE_L6470DRIVER
#include <SPI.h>
#include <L6470.h>
void L6470_init();
#ifdef X_IS_L6470
extern L6470 stepperX;
#undef X_ENABLE_INIT
#define X_ENABLE_INIT ((void)0)
#undef X_ENABLE_WRITE
#define X_ENABLE_WRITE(STATE) {if(STATE) stepperX.Step_Clock(stepperX.getStatus() & STATUS_HIZ); else stepperX.softFree();}
#undef X_ENABLE_READ
#define X_ENABLE_READ (stepperX.getStatus() & STATUS_HIZ)
#undef X_DIR_INIT
#define X_DIR_INIT ((void)0)
#undef X_DIR_WRITE
#define X_DIR_WRITE(STATE) stepperX.Step_Clock(STATE)
#undef X_DIR_READ
#define X_DIR_READ (stepperX.getStatus() & STATUS_DIR)
#endif
#ifdef X2_IS_L6470
extern L6470 stepperX2;
#undef X2_ENABLE_INIT
#define X2_ENABLE_INIT ((void)0)
#undef X2_ENABLE_WRITE
#define X2_ENABLE_WRITE(STATE) (if(STATE) stepperX2.Step_Clock(stepperX2.getStatus() & STATUS_HIZ); else stepperX2.softFree();)
#undef X2_ENABLE_READ
#define X2_ENABLE_READ (stepperX2.getStatus() & STATUS_HIZ)
#undef X2_DIR_INIT
#define X2_DIR_INIT ((void)0)
#undef X2_DIR_WRITE
#define X2_DIR_WRITE(STATE) stepperX2.Step_Clock(STATE)
#undef X2_DIR_READ
#define X2_DIR_READ (stepperX2.getStatus() & STATUS_DIR)
#endif
#ifdef Y_IS_L6470
extern L6470 stepperY;
#undef Y_ENABLE_INIT
#define Y_ENABLE_INIT ((void)0)
#undef Y_ENABLE_WRITE
#define Y_ENABLE_WRITE(STATE) (if(STATE) stepperY.Step_Clock(stepperY.getStatus() & STATUS_HIZ); else stepperY.softFree();)
#undef Y_ENABLE_READ
#define Y_ENABLE_READ (stepperY.getStatus() & STATUS_HIZ)
#undef Y_DIR_INIT
#define Y_DIR_INIT ((void)0)
#undef Y_DIR_WRITE
#define Y_DIR_WRITE(STATE) stepperY.Step_Clock(STATE)
#undef Y_DIR_READ
#define Y_DIR_READ (stepperY.getStatus() & STATUS_DIR)
#endif
#ifdef Y2_IS_L6470
extern L6470 stepperY2;
#undef Y2_ENABLE_INIT
#define Y2_ENABLE_INIT ((void)0)
#undef Y2_ENABLE_WRITE
#define Y2_ENABLE_WRITE(STATE) (if(STATE) stepperY2.Step_Clock(stepperY2.getStatus() & STATUS_HIZ); else stepperY2.softFree();)
#undef Y2_ENABLE_READ
#define Y2_ENABLE_READ (stepperY2.getStatus() & STATUS_HIZ)
#undef Y2_DIR_INIT
#define Y2_DIR_INIT ((void)0)
#undef Y2_DIR_WRITE
#define Y2_DIR_WRITE(STATE) stepperY2.Step_Clock(STATE)
#undef Y2_DIR_READ
#define Y2_DIR_READ (stepperY2.getStatus() & STATUS_DIR)
#endif
#ifdef Z_IS_L6470
extern L6470 stepperZ;
#undef Z_ENABLE_INIT
#define Z_ENABLE_INIT ((void)0)
#undef Z_ENABLE_WRITE
#define Z_ENABLE_WRITE(STATE) (if(STATE) stepperZ.Step_Clock(stepperZ.getStatus() & STATUS_HIZ); else stepperZ.softFree();)
#undef Z_ENABLE_READ
#define Z_ENABLE_READ (stepperZ.getStatus() & STATUS_HIZ)
#undef Z_DIR_INIT
#define Z_DIR_INIT ((void)0)
#undef Z_DIR_WRITE
#define Z_DIR_WRITE(STATE) stepperZ.Step_Clock(STATE)
#undef Y_DIR_READ
#define Y_DIR_READ (stepperZ.getStatus() & STATUS_DIR)
#endif
#ifdef Z2_IS_L6470
extern L6470 stepperZ2;
#undef Z2_ENABLE_INIT
#define Z2_ENABLE_INIT ((void)0)
#undef Z2_ENABLE_WRITE
#define Z2_ENABLE_WRITE(STATE) (if(STATE) stepperZ2.Step_Clock(stepperZ2.getStatus() & STATUS_HIZ); else stepperZ2.softFree();)
#undef Z2_ENABLE_READ
#define Z2_ENABLE_READ (stepperZ2.getStatus() & STATUS_HIZ)
#undef Z2_DIR_INIT
#define Z2_DIR_INIT ((void)0)
#undef Z2_DIR_WRITE
#define Z2_DIR_WRITE(STATE) stepperZ2.Step_Clock(STATE)
#undef Y2_DIR_READ
#define Y2_DIR_READ (stepperZ2.getStatus() & STATUS_DIR)
#endif
#ifdef E0_IS_L6470
extern L6470 stepperE0;
#undef E0_ENABLE_INIT
#define E0_ENABLE_INIT ((void)0)
#undef E0_ENABLE_WRITE
#define E0_ENABLE_WRITE(STATE) (if(STATE) stepperE0.Step_Clock(stepperE0.getStatus() & STATUS_HIZ); else stepperE0.softFree();)
#undef E0_ENABLE_READ
#define E0_ENABLE_READ (stepperE0.getStatus() & STATUS_HIZ)
#undef E0_DIR_INIT
#define E0_DIR_INIT ((void)0)
#undef E0_DIR_WRITE
#define E0_DIR_WRITE(STATE) stepperE0.Step_Clock(STATE)
#undef E0_DIR_READ
#define E0_DIR_READ (stepperE0.getStatus() & STATUS_DIR)
#endif
#ifdef E1_IS_L6470
extern L6470 stepperE1;
#undef E1_ENABLE_INIT
#define E1_ENABLE_INIT ((void)0)
#undef E1_ENABLE_WRITE
#define E1_ENABLE_WRITE(STATE) (if(STATE) stepperE1.Step_Clock(stepperE1.getStatus() & STATUS_HIZ); else stepperE1.softFree();)
#undef E1_ENABLE_READ
#define E1_ENABLE_READ (stepperE1.getStatus() & STATUS_HIZ)
#undef E1_DIR_INIT
#define E1_DIR_INIT ((void)0)
#undef E1_DIR_WRITE
#define E1_DIR_WRITE(STATE) stepperE1.Step_Clock(STATE)
#undef E1_DIR_READ
#define E1_DIR_READ (stepperE1.getStatus() & STATUS_DIR)
#endif
#ifdef E2_IS_L6470
extern L6470 stepperE2;
#undef E2_ENABLE_INIT
#define E2_ENABLE_INIT ((void)0)
#undef E2_ENABLE_WRITE
#define E2_ENABLE_WRITE(STATE) (if(STATE) stepperE2.Step_Clock(stepperE2.getStatus() & STATUS_HIZ); else stepperE2.softFree();)
#undef E2_ENABLE_READ
#define E2_ENABLE_READ (stepperE2.getStatus() & STATUS_HIZ)
#undef E2_DIR_INIT
#define E2_DIR_INIT ((void)0)
#undef E2_DIR_WRITE
#define E2_DIR_WRITE(STATE) stepperE2.Step_Clock(STATE)
#undef E2_DIR_READ
#define E2_DIR_READ (stepperE2.getStatus() & STATUS_DIR)
#endif
#ifdef E3_IS_L6470
extern L6470 stepperE3;
#undef E3_ENABLE_INIT
#define E3_ENABLE_INIT ((void)0)
#undef E3_ENABLE_WRITE
#define E3_ENABLE_WRITE(STATE) (if(STATE) stepperE3.Step_Clock(stepperE3.getStatus() & STATUS_HIZ); else stepperE3.softFree();)
#undef E3_ENABLE_READ
#define E3_ENABLE_READ (stepperE3.getStatus() & STATUS_HIZ)
#undef E3_DIR_INIT
#define E3_DIR_INIT ((void)0)
#undef E3_DIR_WRITE
#define E3_DIR_WRITE(STATE) stepperE3.Step_Clock(STATE)
#undef E3_DIR_READ
#define E3_DIR_READ (stepperE3.getStatus() & STATUS_DIR)
#endif
#endif //HAVE_L6470DRIVER
#endif // STEPPER_INDIRECTION_H
Loading…
Cancel
Save