致力于精密运动控制-智联微

使用TMC4671驱动直线电机-固件自适应

使用TMC4671驱动直线电机-固件自适应

在上一篇博文中,我们能够确定级联控制器回路的稳定P-I参数。有了这些知识,我们想向您展示我们是如何创建一个小的示例程序的,并放入Landungsrbücke的固件中。

此代码的基本功能是初始化步进电机控制的TMC4671。这是在init_Basics(…)中通过编写几个配置寄存器来完成的,而reset_Basics(…)将此工作中使用的所有寄存器重置为定义的0状态。这将取代IDE配置向导中使用默认按钮的第一步。

配置ABN(…)-功能将在功率因数调整转子至0后将ABN计数设置为0。要做到这一点,我们还需要对磁通施加电压。

init_PosMode(…)设置TMC4671进入位置模式的正确寄存器。

使用TMC4671_setAbsolutTargetPosition(…)将控制器的目标位置设置为所需值,使电机转动,直到达到目标位置。这里的绝对位置总是指我们在configure_ABN(…)函数中配置的零位置。

注:如果您希望相对于实际位置移动,可以使用函数TMC4671_setRelativeTargetPosition(…)。

为了找到我的设置的最小和最大位置,我在“查找目标位置”(…)中选择了两个无法到达的目标位置。对我来说,这是500000和-500000。控制器等待一定时间以确保它到达结束位置。然后用函数TMC4671_getActualPosition(…)保存实际位置。另一个方向也进行同样的设置。两个端点的值现在可以用于新的目标位置,可以再次使用TMC4671_setAbsolutTargetPosition(…)来设置。

运行时也可以使用线性坡道加速和减速, 使用函数TMC_ramp_linear_compute(…)和类型为TMC_LinearRamp的结构来实现这个功能(您可以在文件LinearRamp1.h和LinearRamp1.c中的API中找到更多信息)。这将在软件中创建一个包含我们的轨迹信息的斜坡。我还使用上述文件中的相应函数设置了结构的一些参数。我可以使用结构中的TMC_ramp_linear_set_target position(…)设置渐变的目标位置。之后,我使用TMC4671_setAbsolutTargetPosition(calculated_ramp)中计算出的斜坡位置, 循环工作直到达到实际目标位置,。

斜坡有什么作用?我们不是设定一条指令可以到达的绝对目标位置,而是将轨迹划分为多个子目标位置。在循环的每次迭代中,我们增加目标位置,控制器将调整到新的目标。然而,Landungsbrücke增加目标位置的速度比我们控制器的自适应速度高,因此随着时间的推移,目标位置和实际电机位置之间的差异增大。当实际位置和目标位置之间的偏移量增加时,这会导致电机加速。

减速则相反。Landungsbrücke将降低设定目标位置的速度,控制器将慢慢跟上,直到到达终点位置。

为了提高马达的速度,我把实际的斜坡位置乘以1024倍。这必须通过将软件斜坡的目标位置除以1024来补偿。这样我们就可以根据我们的应用来调整斜坡,并增加马达的加速度和速度。

为什么要使用(软件)渐变?基本上,它给了我们一个更稳定的方法来达到我们的目标位置,因为我们有一个确定的加速和减速的方法,它大大减少了超过目标的可能性。

Landungsbrücke在TMC4671寄存器中交替这些目标位置,因此电机将交替滑动的位置。

使用完成的代码,我为Landungsrbücke的引导加载程序生成一个十六进制文件,并使用TMCL-IDE更新它。

希望你能利用一些显示的例子,以便你转换数字信息为你的项目的物理运动!

使用以下代码,将初始化我的驱动器,执行编码器初始化,并在两个末端停止上执行重设原点。然后,执行来回运动。

我可以用TMCL-IDE将固件上传到Landungsbrücke,开机后它会自动启动。我可以通过RTMI监控系统行为。

代码示例:

#include "boards/Board.h"
#include "hal/derivative.h"
#include "hal/HAL.h"
#include "tmc/IdDetection.h"
#include "tmc/TMCL.h"
#include "tmc/VitalSignsMonitor.h"
#include "tmc/BoardAssignment.h"
#include "tmc/ramp/LinearRamp1.h"
#include "TMC-API/tmc/ic/TMC4671/TMC4671.h"
#include "TMC-API/tmc/ic/TMC4671/TMC4671_Register.h" //As I use the names of its registers this needs to be included

//mydefines
#define STATE_START_INIT       1
#define STATE_RUN_1			   2
#define STATE_RUN_2			   3

#define UD_EXT				   3202

//Torque-Flux Limits 15000
#define TORQUE_FLUX_LIMIT	   10000
//Velocity Limit 10000
#define VELOCITY_LIMIT		   10000
//P-I-defines
#define TORQUE_FLUX_P			4952
#define TORQUE_FLUX_I		   10939
#define VELOCITY_P				2200
#define VELOCITY_I				2000
#define POSITION_P				  45
#define POSITION_I				   0

//for checking motor supply voltage
#define VM_FACTOR              713
#define ADC_VM_RES 			   65535 //Landungsbruecke define -- change for Startrampe

//Software-Ramp defines
#define STEPDIR_FREQUENCY         (1 << 17)
#define STEPDIR_MAX_VELOCITY      (1 << 20)
#define STEPDIR_MAX_ACCELERATION  2147418111
#define STEPDIR_DEFAULT_ACCELERATION 100000
#define STEPDIR_DEFAULT_VELOCITY STEPDIR_MAX_VELOCITY
#define RAMP_SPEED_FACTOR			1024
//end mydefines


void init_PosMode(uint8_t motor)
{	//Set registers needed for position mode
	//tmc4671_writeInt(motor, TMC4671_VELOCITY_SELECTION, TMC4671_VELOCITY_PHI_M_ABN);
	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_TARGET_DDT_LIMITS, 32767);  //max
	tmc4671_writeInt(motor, TMC4671_PIDOUT_UQ_UD_LIMITS, 32767); 			    //max
	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_LIMITS, TORQUE_FLUX_LIMIT);
	tmc4671_writeInt(motor, TMC4671_PID_ACCELERATION_LIMIT, 2147483647);
	tmc4671_writeInt(motor, TMC4671_PID_VELOCITY_LIMIT, VELOCITY_LIMIT);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_LOW, 0x80000001);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_HIGH, 0x7FFFFFFF);
	tmc4671_writeInt(motor, TMC4671_PHI_E_SELECTION, 0x00000003);			  			//phi_e_abn
	tmc4671_writeInt(motor, TMC4671_VELOCITY_SELECTION, TMC4671_VELOCITY_PHI_M_ABN);
	tmc4671_writeInt(motor, TMC4671_POSITION_SELECTION, TMC4671_POSITION_PHI_M_ABN);	//phi_m_abn
	tmc4671_writeInt(motor, TMC4671_MODE_RAMP_MODE_MOTION, 0x00000003);		  			//position mode

	//The following gain-values were determined using the USB-2-RTMI and following the PI-tuning guide
	tmc4671_setTorqueFluxPI(motor, TORQUE_FLUX_P, TORQUE_FLUX_I); //(motor, P, I)
	tmc4671_setVelocityPI(motor, VELOCITY_P, VELOCITY_I);
	tmc4671_setPositionPI(motor, POSITION_P, POSITION_I);
}

//Check VM
uint32_t current_VM()
{
	uint32_t VM;

	VM = *HAL.ADCs->VM;              // read ADC value for motor supply VM
	VM = (VM*VM_FACTOR)/ADC_VM_RES;  // calculate voltage from ADC value

	return VM;
}
//End Check VM

void init_Basics(uint8_t motor)
{
	//Configure basic registers like motor type, adc-offset

	tmc4671_writeInt(motor, TMC4671_MOTOR_TYPE_N_POLE_PAIRS, 0x00020032); //x0002 - Stepper, x0032 = 50 polepairs
	tmc4671_writeInt(motor, TMC4671_PWM_POLARITIES, 0x00000000);
	tmc4671_writeInt(motor, TMC4671_PWM_MAXCNT, 0x00000F9F); 			  //Maxcount of PWM-counter
	tmc4671_writeInt(motor, TMC4671_PWM_BBM_H_BBM_L, 0x00001919); 		  //Break before make times
	tmc4671_writeInt(motor, TMC4671_PWM_SV_CHOP, 0x00000007);			  //turn on PWM

	//Configure ADC -- Values were taken from the ide after the set offset option was used
	tmc4671_writeInt(motor, TMC4671_ADC_I_SELECT, 0x18000100); 			  // configure ADC-Inputs
	tmc4671_writeInt(motor, TMC4671_dsADC_MCFG_B_MCFG_A, 0x00100010);	  // configure ADCs
	tmc4671_writeInt(motor, TMC4671_dsADC_MCLK_A, 0x20000000);			  // turn on  clock-signal for group-A ADCs
	tmc4671_writeInt(motor, TMC4671_dsADC_MCLK_B, 0x00000000);			  // turn off clock-signal for group-B ADCs
	tmc4671_writeInt(motor, TMC4671_dsADC_MDEC_B_MDEC_A, 0x014E014E);	  // Constants for filter
	tmc4671_writeInt(motor, TMC4671_ADC_I0_SCALE_OFFSET, 0x01005D80); 	  // Fill in the offsets determined in the IDE
	tmc4671_writeInt(motor, TMC4671_ADC_I1_SCALE_OFFSET, 0x01005CEF); 	  // Fill in the offsets determined in the IDE

	// Open loop settings
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_MODE, 0x00000000);
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_ACCELERATION, 0x0000003C);
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_VELOCITY_TARGET, 0x00000000);
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_PHI, 0x00000000);

	// Feedback selection
	tmc4671_writeInt(motor, TMC4671_PHI_E_SELECTION, 0x00000000);
	tmc4671_writeInt(motor, TMC4671_MODE_RAMP_MODE_MOTION, 0x00000008);
	//tmc4671_writeInt(motor, TMC4671_UQ_UD_EXT, 0x00000F9F);
	tmc4671_writeInt(motor, TMC4671_ABN_DECODER_PPR, 0x00009C40);

	//Set Limits
	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_TARGET_DDT_LIMITS, 0x7FFF); //max
	tmc4671_writeInt(motor, TMC4671_PIDOUT_UQ_UD_LIMITS, 32767); 			    //max
	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_LIMITS, TORQUE_FLUX_LIMIT);
	tmc4671_writeInt(motor, TMC4671_PID_ACCELERATION_LIMIT, 2147483647);
	tmc4671_writeInt(motor, TMC4671_PID_VELOCITY_LIMIT, VELOCITY_LIMIT);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_LOW, 0x80000001);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_HIGH, 0x7FFFFFFF);

}

void reset_Basics(uint8_t motor)
{
	//reset registers of TMC4671 that will later be used to 0
	wait(1500);
	tmc4671_writeInt(motor, TMC4671_PWM_SV_CHOP, 0);
	tmc4671_writeInt(motor, TMC4671_MOTOR_TYPE_N_POLE_PAIRS, 0);
	tmc4671_writeInt(motor, TMC4671_PWM_POLARITIES, 0);
	tmc4671_writeInt(motor, TMC4671_PWM_MAXCNT, 0);
	tmc4671_writeInt(motor, TMC4671_PWM_BBM_H_BBM_L, 0);

	tmc4671_writeInt(motor, TMC4671_ADC_I_SELECT, 0);
	tmc4671_writeInt(motor, TMC4671_dsADC_MCFG_B_MCFG_A, 0);
	tmc4671_writeInt(motor, TMC4671_dsADC_MCLK_A, 0);
	tmc4671_writeInt(motor, TMC4671_dsADC_MCLK_B, 0);
	tmc4671_writeInt(motor, TMC4671_dsADC_MDEC_B_MDEC_A, 0);
	tmc4671_writeInt(motor, TMC4671_ADC_I0_SCALE_OFFSET, 0);
	tmc4671_writeInt(motor, TMC4671_ADC_I1_SCALE_OFFSET, 0);

	tmc4671_writeInt(motor, TMC4671_OPENLOOP_MODE, 0);
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_ACCELERATION, 0);
	tmc4671_writeInt(motor, TMC4671_OPENLOOP_VELOCITY_TARGET, 0);

	tmc4671_writeInt(motor, TMC4671_PHI_E_SELECTION, 0);
	tmc4671_writeInt(motor, TMC4671_MODE_RAMP_MODE_MOTION, 0);
	tmc4671_writeInt(motor, TMC4671_UQ_UD_EXT, 0);
	tmc4671_writeInt(motor, TMC4671_ABN_DECODER_PPR, 0);

	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_TARGET_DDT_LIMITS, 0);
	tmc4671_writeInt(motor, TMC4671_PIDOUT_UQ_UD_LIMITS, 0);
	tmc4671_writeInt(motor, TMC4671_PID_TORQUE_FLUX_LIMITS, 0);
	tmc4671_writeInt(motor, TMC4671_PID_ACCELERATION_LIMIT, 0);
	tmc4671_writeInt(motor, TMC4671_PID_VELOCITY_LIMIT, 0);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_LOW, 0);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_LIMIT_HIGH, 0);
	tmc4671_writeInt(motor, TMC4671_PHI_E_SELECTION, 0);
	tmc4671_writeInt(motor, TMC4671_VELOCITY_SELECTION, 0);
	tmc4671_writeInt(motor, TMC4671_POSITION_SELECTION, 0);
	tmc4671_writeInt(motor, TMC4671_MODE_RAMP_MODE_MOTION, 0);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_TARGET, 0);
	tmc4671_writeInt(motor, TMC4671_PID_POSITION_ACTUAL, 0);
	tmc4671_setTorqueFluxPI(motor, 0, 0); //(motor, P, I)
	tmc4671_setVelocityPI(motor, 0, 0); // (motor, P, I)
	tmc4671_setPositionPI(motor, 0, 0); // (motor, P, I)

}

void init_softwareRamp(TMC_LinearRamp *linearRamp)
{
	tmc_ramp_linear_init(linearRamp);
	tmc_ramp_linear_set_mode(linearRamp, TMC_RAMP_LINEAR_MODE_POSITION);
	tmc_ramp_linear_set_maxVelocity(linearRamp, STEPDIR_DEFAULT_VELOCITY);
	tmc_ramp_linear_set_acceleration(linearRamp, STEPDIR_DEFAULT_ACCELERATION);

}

void find_targetPositions(uint8_t motor, int32_t *lower_End, int32_t*upper_End)
{
	tmc4671_setAbsolutTargetPosition(motor, 500000); // ~ 7.5 motor turns
	wait(1500);
	/* After slide reached one end of the setup the absolute position is stored in memory
		For convenience I reduce the value of the target position to be saved a little,
	 *  as driving into the endposition with full force is annoyingly loud :)
	 *  if this is your goal just remove the +/- 1000 */
	*lower_End = (tmc4671_getActualPosition(motor)-1000);
	tmc4671_setAbsolutTargetPosition(motor, 0); //return to the starting position
	wait(1000);

	// Assumed an unreachable position so the slide reaches the other side of the setup
	tmc4671_setAbsolutTargetPosition(motor, -500000); // ~ -7.5 motor turns
	wait(1500);
	// After slide reached the other end of the setup the absolute position is stored in memory
	*upper_End = (tmc4671_getActualPosition(motor)+1000);
	tmc4671_setAbsolutTargetPosition(motor, 0);
	wait(1500);
}

void configure_ABN(uint8_t motor, uint16_t startVoltage)
{
	// set ABN_DECODER_PHI_E_OFFSET to zero
	tmc4671_writeRegister16BitValue(motor, TMC4671_ABN_DECODER_PHI_E_PHI_M_OFFSET, BIT_16_TO_31, 0);
	// select phi_e_ext
	tmc4671_writeRegister16BitValue(motor, TMC4671_PHI_E_SELECTION, BIT_0_TO_15, 1);
	// set an initialization voltage on UD_EXT (to the flux, not the torque!)
	tmc4671_writeRegister16BitValue(motor, TMC4671_UQ_UD_EXT, BIT_16_TO_31, 0);
	tmc4671_writeRegister16BitValue(motor, TMC4671_UQ_UD_EXT, BIT_0_TO_15, startVoltage);
	// set the "zero" angle
	tmc4671_writeRegister16BitValue(motor, TMC4671_PHI_E_EXT, BIT_0_TO_15, 0);
	tmc4671_writeInt(motor, TMC4671_ABN_DECODER_MODE, 0x00001000);
	//Set PHI_E to 0° angle so the rotor alignes itself with it
	tmc4671_writeInt(motor, TMC4671_PHI_E_SELECTION, 0x00000000);
	wait(4000);
	tmc4671_readRegister16BitValue(motor, TMC4671_ABN_DECODER_PHI_E_PHI_M, BIT_16_TO_31);
	//After the rotor has aligned this will set the ABN_DECODER_COUNT to 0 so there is a defined 0-position
	tmc4671_writeInt(motor, TMC4671_ABN_DECODER_COUNT, 0);
}
void tmc4671setPositionModeAndRun(uint8_t motor, uint8_t *initState, uint16_t startVoltage, int32_t *upper_End, int32_t *lower_End, TMC_LinearRamp *linearRamp)
{
	/*State Machine with state-pointer *initState and 3 states
	 * STATE_START_INIT: Sets TMC4671-registers for my application and configures the ABN-Encoder
	 * 					 Drives to the ends of the track to get the actual min/max position values
	 * 					 Drives to the first end position
	 *
	 * STATE_RUN_1:		 Drives to one end and changes direction when the *lower_End is reached
	 *
	 * STATE_RUN_2:		 Drives to the other end and changes direction when *upper_End is reached
	 */
	switch (*initState)
	{
	case STATE_START_INIT:
		//reset TMC4671 registers
		reset_Basics(motor);
		//set TMC4671 registers with basic data like motortype, number of polepairs and so on
		init_Basics(motor);

		//initialize the software ramp
		init_softwareRamp(linearRamp);
		//configure ABN
		configure_ABN(motor, startVoltage);

		//Enter position-Mode
		init_PosMode(motor);

		//configure the end positions and store them in *lower_End and *upper_End
		find_targetPositions(motor, lower_End, upper_End);

		*initState = STATE_RUN_1;
		//set the first target position using the software ramp
		tmc_ramp_linear_set_targetPosition(linearRamp, (*lower_End/RAMP_SPEED_FACTOR));
		break;
	case STATE_RUN_1:

		//drive from one end to the other: positive direction
		tmc_ramp_linear_compute(linearRamp);
		tmc4671_setAbsolutTargetPosition(motor, (RAMP_SPEED_FACTOR*tmc_ramp_linear_get_rampPosition(linearRamp)));
		//When the target position is reached we will change direction
		if(tmc4671_getActualPosition(motor) >= (*lower_End-RAMP_SPEED_FACTOR))
		{
			wait(50);
			*initState = STATE_RUN_2;
			tmc_ramp_linear_set_targetPosition(linearRamp, (*upper_End/RAMP_SPEED_FACTOR));
			break;
		}
		*initState = STATE_RUN_1;
		break;
	case STATE_RUN_2:
		//drive from one end to the other: negative direction
		tmc_ramp_linear_compute(linearRamp);
		tmc4671_setAbsolutTargetPosition(motor, (RAMP_SPEED_FACTOR*tmc_ramp_linear_get_rampPosition(linearRamp)));
		//When the target position is reached we will change direction
		if(tmc4671_getActualPosition(motor) <= (*upper_End + RAMP_SPEED_FACTOR))
		{
			wait(50);
			*initState = STATE_RUN_1;
			tmc_ramp_linear_set_targetPosition(linearRamp, (*lower_End/RAMP_SPEED_FACTOR));
			break;
		}
		*initState = STATE_RUN_2;
		break;
	default:
		*initState = 0;
		break;
	}
}

const char *VersionString = MODULE_ID"V308"; // module id and version of the firmware shown in the TMCL-IDE

/* Keep as is! These lines are important for the update functionality. */
#if defined(Landungsbruecke)
	const uint8_t Protection[] __attribute__ ((section(".cfmconfig")))=
	{
		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  //Backdoor key
		0xFF, 0xFF, 0xFF, 0xFF,                          //Flash protection (FPPROT)
		0x7E,                                            //Flash security   (FSEC)
		0xF9,                                            //Flash option     (FOPT)
		0xFF,                                            //reserved
		0xFF                                             //reserved
	};

	struct BootloaderConfig {
		uint32_t BLMagic;
		uint32_t drvEnableResetValue;
	};

	// This struct gets placed at a specific address by the linker
	struct BootloaderConfig __attribute__ ((section(".bldata"))) BLConfig;
#endif


/* Check if jumping into bootloader is forced                                           */
/*                                                                                      */
/* In order to jump to bootloader e.g. because of an accidental infinite loop           */
/* in a modified firmware you may short ID_CLK and ID_CH0 pins on start up.             */
/* This will force the entrance into bootloader mode and allow to replace bad firmware. */
void shallForceBoot()
{
	// toggle each pin and see if you can read the state on the other
	// leave if not, because this means that the pins are not tied together
	HAL.IOs->config->toOutput(&amp;HAL.IOs->pins->ID_CLK);
	HAL.IOs->config->toInput(&amp;HAL.IOs->pins->ID_CH0);

	HAL.IOs->config->setHigh(&amp;HAL.IOs->pins->ID_CLK);
	if(!HAL.IOs->config->isHigh(&amp;HAL.IOs->pins->ID_CH0))
		return;

	HAL.IOs->config->setLow(&amp;HAL.IOs->pins->ID_CLK);
	if(HAL.IOs->config->isHigh(&amp;HAL.IOs->pins->ID_CH0))
		return;

	HAL.IOs->config->toOutput(&amp;HAL.IOs->pins->ID_CH0);
	HAL.IOs->config->toInput(&amp;HAL.IOs->pins->ID_CLK);

	HAL.IOs->config->setHigh(&amp;HAL.IOs->pins->ID_CH0);
	if(!HAL.IOs->config->isHigh(&amp;HAL.IOs->pins->ID_CLK))
		return;

	HAL.IOs->config->setLow(&amp;HAL.IOs->pins->ID_CH0);
	if(HAL.IOs->config->isHigh(&amp;HAL.IOs->pins->ID_CLK))
		return;

	// not returned, this means pins are tied together
	tmcl_boot();
}


/* Call all standard initialization routines. */
static void init()
{
#if defined(Landungsbruecke)
	// Default value: Driver enable gets set high by the bootloader
	BLConfig.drvEnableResetValue = 1;
#endif

	HAL.init();                  // Initialize Hardware Abstraction Layer
	IDDetection_init();          // Initialize board detection
	tmcl_init();                 // Initialize TMCL communication

	tmcdriver_init();            // Initialize dummy driver board --> preset EvalBoards.ch2
	tmcmotioncontroller_init();  // Initialize dummy motion controller board  --> preset EvalBoards.ch1

	VitalSignsMonitor.busy = 1;  // Put state to busy
	Evalboards.driverEnable = DRIVER_ENABLE;

	Evalboards.ch1.id = 0;       // preset id for driver board to 0 --> error/not found
	Evalboards.ch2.id = 0;       // preset id for driver board to 0 --> error/not found

	// We disable the drivers before configurating anything
	HAL.IOs->config->toOutput(&amp;HAL.IOs->pins->DIO0);
	HAL.IOs->config->setHigh(&amp;HAL.IOs->pins->DIO0);

	IdAssignmentTypeDef ids = { 0 };
	IDDetection_initialScan(&amp;ids);  // start initial board detection
	IDDetection_initialScan(&amp;ids);  // start second time, first time not 100% reliable, not sure why - too fast after startup?
	if(!ids.ch1.id &amp;&amp; !ids.ch2.id)
	{
		shallForceBoot();           // only checking to force jump into bootloader if there are no boards attached
		HAL.IOs->config->toOutput(&amp;HAL.IOs->pins->ID_CLK);
		HAL.IOs->config->toInput(&amp;HAL.IOs->pins->ID_CH0);
	}
	Board_assign(&amp;ids);             // assign boards with detected id

	VitalSignsMonitor.busy 	= 0;    // not busy any more!
}

/* main function */
int main(void)
{
	//initialise some pointers
	//state pointer for fsm
	uint8_t   init_State = STATE_START_INIT;
	uint8_t  *initState;
	initState = &amp;init_State;

	//store one end of the track
	int32_t   upper_end = 0;
	int32_t  *upper_End;
	upper_End= &amp;upper_end;

	//store the other end
	int32_t   lower_end = 0;
	int32_t  *lower_End;
	lower_End= &amp;lower_end;

	//convenience
	uint8_t motor = 0;

	//"flipflop"
	uint8_t block = 0;

	//struct used for the software ramp - see \TMC-API\tmc\ramp\LinearRamp1.h for typedef etc.
	TMC_LinearRamp adressRamp;
	TMC_LinearRamp *aRamp;
	aRamp = &adressRamp;

	init();

	// Main loop
	while(1)
	{
		// Check all parameters and life signs and mark errors
		vitalsignsmonitor_checkVitalSigns();
		// Perodic jobs of Motion controller/Driver boards
		Evalboards.ch1.periodicJob(systick_getTick());

		Evalboards.ch2.periodicJob(systick_getTick());
		// Process TMCL communication
		tmcl_process();

		if (Evalboards.ch1.id != ID_TMC4671)
			continue;

		if(current_VM()<20){
			tmc4671_writeInt(motor, TMC4671_PWM_SV_CHOP, 0); // Turn off PWM after unexpected reset
			reset_Basics(motor);							 // Set the registers needed in this example to a defined default state
			continue;
		}

		if(block == 0)
		{
			tmc4671_writeInt(motor, TMC4671_PWM_SV_CHOP, 0);	//Turn of PWM-Register after SPI was initialized
			reset_Basics(motor);
			block = 1;
		}
		tmc4671setPositionModeAndRun(motor, initState, UD_EXT, lower_End, upper_End, aRamp);
	}

	return 0;
}
赞(0)
未经允许不得转载:TMC,TRINAMIC,步进电机驱动-深圳市智联微电子有限公司 » 使用TMC4671驱动直线电机-固件自适应

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址