开箱:
收到了Let'sdo第4期的包裹,这次自己手头有电源和电机,所以只购买了开发板和电机驱动板。



项目介绍:
使用NXP FRDM-MCXA153开发板控制电机旋转。用到的主控为NXP FRDM-MCXA153开发板,核心为MCXA153系列微控制器,基于高效的Arm® Cortex®-M33内核。集成USB调试与供电接口,内置CMSIS-DAP调试器,开发便捷。开发板主要功能是输出PWM方波,提供交互接口,让用户来控制电机的转速和转动方向。
开发板不具备大电流控制能力,所以还需要使用到驱动板Adafruit TB6612 1.2A DC/Stepper Motor Driver Breakout Board。驱动芯片为TB6612,这是一款双路H桥型直流电机驱动芯片,能够同时驱动两个直流电机,且可以独立控制每个电机的转速和转动方向。
本项目还用到一个旋转电位器,通过电位器的旋转控制电机的旋转方向和转动速度。
基础任务:1.电机启停与方向控制:通过程序实现电机的启动、停止、正转和反转。2.电机调速控制:编写一个函数,可以通过输入参数(如0-100)来改变PWM的占空比,从而控制速度。PA0 PWMA 控制电机A的转速
PA1 AIN1 控制电机A的转动方向 PA2 AIN2 控制电机A的转动方向 PA3 PWMB 控制电机B的转速 PA4 BIN1 控制电机B的转动方向 PA5 BIN2 控制电机B的转动方向 PA6 STBY 待机控制 3.3V VCC 逻辑电源 GND GND 接地 外部电源 VM 电机电源
PA0 PWMA 控制电机A的转速 PA1 AIN1 控制电机A的转动方向 PA2 AIN2 控制电机A的转动方向 PA3 PWMB 控制电机B的转速 PA4 BIN1 控制电机B的转动方向 PA5 BIN2 控制电机B的转动方向 PA6 STBY 待机控制 3.3V VCC 逻辑电源 GND GND 接地 外部电源 VM 电机电源
使用NXP FRDM-MCXA153开发板控制电机旋转必然就要使用PWM方波,这里是控制一个电机,所以只需要提供一路PWM方波输出到驱动板的PWMA口即可。控制电机转动方向,则需要控制驱动板AIN1、AIN2两个口的高低电平。

我使用的编程工具是MCUXpresso IDE 。参考官方例程“frdmmcxa153_pwm”来实现PWM的输出。首先编辑管脚功能,将PWM0打开,保留通道A(这样PWM信号通过P3_6输出);打开GPIO口控制,使得P3_12,P3_13两个GPIO口做输出控制。同时这两个GPIO口,也是板子上LED红色、绿色的控制端口。
#define APP_DEFAULT_PWM_FREQUENCY (1000UL)
static void PWM_DRV_InitSinglePwm(void)
{
pwm_signal_param_t pwmSignal;
uint32_t pwmSourceClockInHz;
uint32_t pwmFrequencyInHz = APP_DEFAULT_PWM_FREQUENCY;
pwmSourceClockInHz = PWM_SRC_CLK_FREQ;
/* 配置PWM A信号参数 */
pwmSignal.pwmChannel = kPWM_PwmA;
pwmSignal.level = kPWM_HighTrue;
pwmSignal.dutyCyclePercent = 0; /* 50 percent dutycycle */
pwmSignal.deadtimeValue = 0; /* 不需要死区时间 */
pwmSignal.faultState = kPWM_PwmFaultState0;
pwmSignal.pwmchannelenable = true;
/*********** 配置PWM模块0的PWM A通道 ************/
PWM_SetupPwm(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmSignal, 1,
kPWM_SignedCenterAligned, pwmFrequencyInHz, pwmSourceClockInHz);
} // 初始化LED引脚
GPIO_PinInit(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, &p_config);
GPIO_PinInit(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, &p_config);
/*初始化PWM*/
PWM_GetDefaultConfig(&pwmConfig);
pwmConfig.prescale = DEMO_PWM_CLOCK_DEVIDER; // 保留
/* Use full cycle reload */
pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
/* 独立模式 - 不使用互补输出 */
pwmConfig.pairOperation = kPWM_Independent;
pwmConfig.enableDebugMode = true;
/* Initialize submodule 0 */
if (PWM_Init(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmConfig) == kStatus_Fail)
{
PRINTF("PWM initialization failedn");
return 1;
}
PWM_FaultDefaultConfig(&faultConfig);
faultConfig.faultLevel = DEMO_PWM_FAULT_LEVEL;
/* Sets up the PWM fault protection */
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_0, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_1, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_2, &faultConfig);
PWM_SetupFaults(BOARD_PWM_BASEADDR, kPWM_Fault_3, &faultConfig);
PWM_DRV_InitSinglePwm();
/* Set the load okay bit for submodule 0 to load registers from their buffer */
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0, true);
/* Start the PWM generation from Submodule 0 only */
PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0);这里使用1KHz做为PWM的输出频率,使用单通道输出PWM波。写一个任务函数,专门控制电机的旋转。
/* 任务2:电机调速控制:编写一个函数,可以通过输入参数(如0-100)来改变PWM的占空比,从而控制速度。 */
void task2(uint8_t direction, int speed)
{
// status_t result;
// PRINTF("Motor task2: direction=%d, speed=%drn", direction, speed);
/* 设置马达方向 */
if (direction == 1)
{
// PRINTF("Motor task2: forwardrn");
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, 1);
GPIO_PinWrite(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, 0);
}
else if (direction == 2)
{
// PRINTF("Motor task2: backwardrn");
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, 0);
GPIO_PinWrite(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, 1);
}
else
{
// PRINTF("Motor task2: stoprn");
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, 1);
GPIO_PinWrite(BOARD_LED_GREEN_GPIO, BOARD_LED_GREEN_GPIO_PIN, 1);
}
/* 设置马达速度 */
if (speed >= 0)
{
/* 更新PWM占空比 */
PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,
kPWM_SignedCenterAligned, speed);
}
else
{
/* 更新PWM占空比 */
PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA,
kPWM_SignedCenterAligned, 0);
}
/* 子模块0设置加载 */
PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0, true);
}再写一个方法,来通过调用上边的控制电机函数,开实现一段电机动作的展示。这里因为电源输入是12V,当电机全功率运行,转速太快,有点吓人,所以自动展示中,最大只跑到全功率的30%。
/* 任务1:电机启停与方向控制:通过程序实现电机的启动、停止、正转和反转。 */
void task1(void)
{
/* 马达控制测试 */
PRINTF("nTesting Motor Control...rn");
task2(0, 0); /* 停止电机 */
/* 等待5秒 */
SDK_DelayAtLeastUs(1 * 1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
task2(1, 10); /* 正转10% */
SDK_DelayAtLeastUs(5 * 1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
task2(1, 30); /* 正转30% */
SDK_DelayAtLeastUs(5 * 1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
task2(0, 0); /* 停止电机 */
SDK_DelayAtLeastUs(1 * 1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
task2(2, 10);
SDK_DelayAtLeastUs(5 * 1000000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
task2(2, 30);
task2(0, 0); /* 停止电机 */
}


进阶任务:1.基于电位器的模拟调速系统:使用一个旋转电位器作为输入,实时无级地控制电机的速度和方向。2.实现一个通过串口发送高级指令来控制电机的系统:创建一个简单的指令集,让上位机(如串口助手)可以通过发送特定格式的字符串命令,来执行电机的动作。
启用板子的ADC0中的A通道,即使用P2_0做为ADC的输入。


再参考着群里老师的串口接收命令字代码的功能,实现了串口控制,和电位器控制电机的功能。

通过串口可以接收命令字.
指令说明:
* `help` 表示显示帮助信息,
* `motor stop` 表示停止电机运行。
* `motor <forward/backward> <0-100>` 表示设置电机速度,0表示最慢,100表示最大速度。
* `motor <turn> <on/off>` 表示使用启用或关闭摇杆电位器来控制电机方向和速度。
输入“motor turn on”就可以调整到,通过电位器控制电机。将电位器的值(0~4096)映射到0~100,然后40~60之间是电机停止。40~0之间是控制电机正转,值越小转速越快。同样60~100是倒转,值越大,转速越快。


演示视频:
我要赚赏金
