You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
9.3 KiB

#include <SPI.h>
#include "TMC2130Stepper.h"
#include "TMC2130Stepper_MACROS.h"
TMC2130Stepper::TMC2130Stepper(uint8_t pinEN, uint8_t pinDIR, uint8_t pinStep, uint8_t pinCS) {
_started = false;
this->_pinEN = pinEN;
this->_pinDIR = pinDIR;
this->_pinSTEP = pinStep;
this->_pinCS = pinCS;
begin();
}
void TMC2130Stepper::begin() {
#ifdef TMC2130DEBUG
Serial.println("TMC2130 Stepper driver library");
Serial.print("Enable pin: ");
Serial.println(_pinEN);
Serial.print("Direction pin: ");
Serial.println(_pinDIR);
Serial.print("Step pin: ");
Serial.println(_pinSTEP);
Serial.print("Chip select pin: ");
Serial.println(_pinCS);
#endif
//set pins
pinMode(_pinEN, OUTPUT);
pinMode(_pinDIR, OUTPUT);
pinMode(_pinSTEP, OUTPUT);
pinMode(_pinCS, OUTPUT);
digitalWrite(_pinEN, HIGH); //deactivate driver (LOW active)
digitalWrite(_pinDIR, LOW); //LOW or HIGH
digitalWrite(_pinSTEP, LOW);
digitalWrite(_pinCS, HIGH);
/*
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
digitalWrite(MOSI, LOW);
digitalWrite(MISO, HIGH);
digitalWrite(SCK, LOW);
SPI.begin();
*/
GCONF(GCONF_sr);
CHOPCONF(CHOPCONF_sr);
COOLCONF(COOLCONF_sr);
PWMCONF(PWMCONF_sr);
IHOLD_IRUN(IHOLD_IRUN_sr);
toff(8); //off_time(8);
tbl(1); //blank_time(24);
_started = true;
}
//uint32_t TMC2130Stepper::send2130(uint8_t addressByte, uint32_t *config, uint32_t value, uint32_t mask) {
void TMC2130Stepper::send2130(uint8_t addressByte, uint32_t *config) {
//uint8_t s;
SPI.begin();
SPI.beginTransaction(SPISettings(16000000/8, MSBFIRST, SPI_MODE3));
digitalWrite(_pinCS, LOW);
status_response = SPI.transfer(addressByte & 0xFF); // s =
#ifdef TMC2130DEBUG
Serial.println("## Received parameters:");
Serial.print("## Address byte: ");
Serial.println(addressByte, HEX);
Serial.print("## Config: ");
Serial.println(*config, BIN);
Serial.print("## status_response: ");
Serial.println(status_response, BIN);
#endif
if (addressByte >> 7) { // Check if WRITE command
//*config &= ~mask; // Clear bits being set
//*config |= (value & mask); // Set new values
SPI.transfer((*config >> 24) & 0xFF);
SPI.transfer((*config >> 16) & 0xFF);
SPI.transfer((*config >> 8) & 0xFF);
SPI.transfer(*config & 0xFF);
#ifdef TMC2130DEBUG
Serial.println("## WRITE cmd");
Serial.println("##########################");
#endif
} else { // READ command
SPI.transfer16(0x0000); // Clear SPI
SPI.transfer16(0x0000);
digitalWrite(_pinCS, HIGH);
digitalWrite(_pinCS, LOW);
SPI.transfer(addressByte & 0xFF); // Send the address byte again
*config = SPI.transfer(0x00);
*config <<= 8;
*config |= SPI.transfer(0x00);
*config <<= 8;
*config |= SPI.transfer(0x00);
*config <<= 8;
*config |= SPI.transfer(0x00);
#ifdef TMC2130DEBUG
Serial.println("## READ cmd");
Serial.print("## Received config: ");
Serial.println(*config, BIN);
Serial.println("##########################");
#endif
}
digitalWrite(_pinCS, HIGH);
SPI.endTransaction();
//return s;
}
bool TMC2130Stepper::checkOT() {
uint32_t response = DRV_STATUS();
if (response & OTPW_bm) {
flag_otpw = 1;
return true; // bit 26 for overtemperature warning flag
}
return false;
}
bool TMC2130Stepper::getOTPW() { return flag_otpw; }
void TMC2130Stepper::clear_otpw() { flag_otpw = 0; }
bool TMC2130Stepper::isEnabled() { return !digitalRead(_pinEN) && toff(); }
///////////////////////////////////////////////////////////////////////////////////////
// R+C: GSTAT
void TMC2130Stepper::GSTAT(uint8_t input){
GSTAT_sr = input;
WRITE_REG(GSTAT);
}
uint8_t TMC2130Stepper::GSTAT() { READ_REG_R(GSTAT); }
bool TMC2130Stepper::reset() { GET_BYTE(GSTAT, RESET); }
bool TMC2130Stepper::drv_err() { GET_BYTE(GSTAT, DRV_ERR); }
bool TMC2130Stepper::uv_cp() { GET_BYTE(GSTAT, UV_CP); }
///////////////////////////////////////////////////////////////////////////////////////
// R: IOIN
uint32_t TMC2130Stepper::IOIN() { READ_REG_R(IOIN); }
bool TMC2130Stepper::step() { GET_BYTE_R(IOIN, STEP); }
bool TMC2130Stepper::dir() { GET_BYTE_R(IOIN, DIR); }
bool TMC2130Stepper::dcen_cfg4() { GET_BYTE_R(IOIN, DCEN_CFG4); }
bool TMC2130Stepper::dcin_cfg5() { GET_BYTE_R(IOIN, DCIN_CFG5); }
bool TMC2130Stepper::drv_enn_cfg6() { GET_BYTE_R(IOIN, DRV_ENN_CFG6); }
bool TMC2130Stepper::dco() { GET_BYTE_R(IOIN, DCO); }
uint8_t TMC2130Stepper::version() { GET_BYTE_R(IOIN, VERSION); }
///////////////////////////////////////////////////////////////////////////////////////
// W: TPOWERDOWN
uint32_t TMC2130Stepper::TPOWERDOWN() { return TPOWERDOWN_sr; }
void TMC2130Stepper::TPOWERDOWN(uint32_t input) {
TPOWERDOWN_sr = input;
WRITE_REG(TPOWERDOWN);
}
///////////////////////////////////////////////////////////////////////////////////////
// R: TSTEP
uint32_t TMC2130Stepper::TSTEP() { READ_REG_R(TSTEP); }
///////////////////////////////////////////////////////////////////////////////////////
// W: TPWMTHRS
uint32_t TMC2130Stepper::TPWMTHRS() { return TPWMTHRS_sr; }
void TMC2130Stepper::TPWMTHRS(uint32_t input) {
TPWMTHRS_sr = input;
WRITE_REG(TPWMTHRS);
}
///////////////////////////////////////////////////////////////////////////////////////
// W: TCOOLTHRS
uint32_t TMC2130Stepper::TCOOLTHRS() { return TCOOLTHRS_sr; }
void TMC2130Stepper::TCOOLTHRS(uint32_t input) {
TCOOLTHRS_sr = input;
WRITE_REG(TCOOLTHRS);
}
///////////////////////////////////////////////////////////////////////////////////////
// W: THIGH
uint32_t TMC2130Stepper::THIGH() { return THIGH_sr; }
void TMC2130Stepper::THIGH(uint32_t input) {
THIGH_sr = input;
WRITE_REG(THIGH);
}
///////////////////////////////////////////////////////////////////////////////////////
// RW: XDIRECT
uint32_t TMC2130Stepper::XDIRECT() { READ_REG(XDIRECT); }
void TMC2130Stepper::XDIRECT(uint32_t input) {
XDIRECT_sr = input;
WRITE_REG(XDIRECT);
}
void TMC2130Stepper::coil_A(int16_t B) { MOD_REG(XDIRECT, COIL_A); }
void TMC2130Stepper::coil_B(int16_t B) { MOD_REG(XDIRECT, COIL_B); }
int16_t TMC2130Stepper::coil_A() { GET_BYTE_R(XDIRECT, COIL_A); }
int16_t TMC2130Stepper::coil_B() { GET_BYTE_R(XDIRECT, COIL_A); }
///////////////////////////////////////////////////////////////////////////////////////
// W: VDCMIN
uint32_t TMC2130Stepper::VDCMIN() { return VDCMIN_sr; }
void TMC2130Stepper::VDCMIN(uint32_t input) {
VDCMIN_sr = input;
WRITE_REG(VDCMIN);
}
///////////////////////////////////////////////////////////////////////////////////////
// R: PWM_SCALE
uint8_t TMC2130Stepper::PWM_SCALE() { READ_REG_R(PWM_SCALE); }
///////////////////////////////////////////////////////////////////////////////////////
// W: ENCM_CTRL
uint8_t TMC2130Stepper::ENCM_CTRL() { return ENCM_CTRL_sr; }
void TMC2130Stepper::ENCM_CTRL(uint8_t input) {
ENCM_CTRL_sr = input;
WRITE_REG(ENCM_CTRL);
}
void TMC2130Stepper::inv(bool B) { MOD_REG(ENCM_CTRL, INV); }
void TMC2130Stepper::maxspeed(bool B) { MOD_REG(ENCM_CTRL, MAXSPEED); }
bool TMC2130Stepper::inv() { GET_BYTE(ENCM_CTRL, INV); }
bool TMC2130Stepper::maxspeed() { GET_BYTE(ENCM_CTRL, MAXSPEED);}
///////////////////////////////////////////////////////////////////////////////////////
// R: LOST_STEPS
uint32_t TMC2130Stepper::LOST_STEPS() { READ_REG_R(LOST_STEPS); }
/**
* Helper functions
*/
/*
Requested current = mA = I_rms/1000
Equation for current:
I_rms = (CS+1)/32 * V_fs/(R_sense+0.02ohm) * 1/sqrt(2)
Solve for CS ->
CS = 32*sqrt(2)*I_rms*(R_sense+0.02)/V_fs - 1
Example:
vsense = 0b0 -> V_fs = 0.325V
mA = 1640mA = I_rms/1000 = 1.64A
R_sense = 0.10 Ohm
->
CS = 32*sqrt(2)*1.64*(0.10+0.02)/0.325 - 1 = 26.4
CS = 26
*/
void TMC2130Stepper::rms_current(uint16_t mA, float multiplier, float RS) {
Rsense = RS;
uint8_t CS = 32.0*1.41421*mA/1000.0*(Rsense+0.02)/0.325 - 1;
// If Current Scale is too low, turn on high sensitivity R_sense and calculate again
if (CS < 16) {
vsense(true);
CS = 32.0*1.41421*mA/1000.0*(Rsense+0.02)/0.180 - 1;
} else if(vsense()) { // If CS >= 16, turn off high_sense_r if it's currently ON
vsense(false);
}
irun(CS);
ihold(CS*multiplier);
val_mA = mA;
}
uint16_t TMC2130Stepper::rms_current() {
return (float)(irun()+1)/32.0 * (vsense()?0.180:0.325)/(Rsense+0.02) / 1.41421 * 1000;
}
void TMC2130Stepper::setCurrent(uint16_t mA, float R, float multiplier) { rms_current(mA, multiplier, R); }
uint16_t TMC2130Stepper::getCurrent() { return val_mA; }
void TMC2130Stepper::SilentStepStick2130(uint16_t current) { rms_current(current); }
void TMC2130Stepper::microsteps(uint16_t ms) {
switch(ms) {
case 256: mres(0); break;
case 128: mres(1); break;
case 64: mres(2); break;
case 32: mres(3); break;
case 16: mres(4); break;
case 8: mres(5); break;
case 4: mres(6); break;
case 2: mres(7); break;
case 0: mres(8); break;
default: break;
}
}
uint16_t TMC2130Stepper::microsteps() {
switch(mres()) {
case 0: return 256;
case 1: return 128;
case 2: return 64;
case 3: return 32;
case 4: return 16;
case 5: return 8;
case 6: return 4;
case 7: return 2;
case 8: return 0;
}
return 0;
}
void TMC2130Stepper::sg_current_decrease(uint8_t value) {
switch(value) {
case 32: sedn(0b00); break;
case 8: sedn(0b01); break;
case 2: sedn(0b10); break;
case 1: sedn(0b11); break;
}
}
uint8_t TMC2130Stepper::sg_current_decrease() {
switch(sedn()) {
case 0b00: return 32;
case 0b01: return 8;
case 0b10: return 2;
case 0b11: return 1;
}
return 0;
}