本帖最后由 okwh 于 2017-11-11 23:40 编辑
自平衡小车-3B 四路PWM控制两个轮前后转动 代码
代码设计: 目的: 四路PWM控制两个轮前后转动(转速、方向、同步) 基于例子SDK_2.2.1_LPCXpresso54114\boards\lpcxpresso54114\driver_examples\sctimer\simple_pwm修改。 配置管脚:Port 1的1/2/3/4对于SCTSCT0_OUT4-PWM4、SCT0_OUT5-PWM5、SCT0_OUT6-PWM6、SCT0_OUT7-PWM7, Port 0的25/26, 是LED6/7绿灯,亮用于标记两个轮子转动方向。增加到 pin_mux.c - #define PORT0_IDX 0u /*!< Port index */
- #define PORT1_IDX 1u /*!< Port index */
- #define PIN1_IDX 1u
- #define PIN2_IDX 2u
- #define PIN3_IDX 3u
- #define PIN4_IDX 4u
- const uint32_t port1_pin1_config = (
- IOCON_PIO_FUNC3 | /* Pin is configured as SCT0_OUT2 */
- IOCON_PIO_MODE_INACT | /* No addition pin function */
- IOCON_PIO_INV_DI | /* Input function is not inverted */
- IOCON_PIO_DIGITAL_EN | /* Enables digital function */
- IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
- IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
- );
- IOCON_PinMuxSet(IOCON, PORT1_IDX, PIN1_IDX, port1_pin1_config);
- IOCON_PinMuxSet(IOCON, PORT1_IDX, PIN2_IDX, port1_pin1_config);
- IOCON_PinMuxSet(IOCON, PORT1_IDX, PIN3_IDX, port1_pin1_config);
- IOCON_PinMuxSet(IOCON, PORT1_IDX, PIN4_IDX, port1_pin1_config);
- const uint32_t port0_pin25_config = (
- IOCON_FUNC0 | /*IO Pin is configured as FC4_CTS_SDA_SSEL0 */
- IOCON_GPIO_MODE | /* I2C mode */
- IOCON_MODE_PULLUP |
- // IOCON_PIO_INV_DI | /* Input function is not inverted */
- IOCON_PIO_DIGITAL_EN | /* Enables digital function */
- IOCON_PIO_INPFILT_OFF /* Input filter disabled */
- // IOCON_PIO_I2CDRIVE_LOW | /* Low drive: 4 mA */
- // IOCON_PIO_I2CFILTER_EN /* I2C 50 ns glitch filter enabled */
- );
- IOCON_PinMuxSet(IOCON, PORT0_IDX, 25, port0_pin25_config); /* PORT0 PIN25 */
- IOCON_PinMuxSet(IOCON, PORT0_IDX, 26, port0_pin25_config); /* PORT0 PIN26 */
复制代码
主要代码: SCT初始化;Port 1的1/2/3/4即SCT0_OUT-PWM4/5/6/7四管脚输出PWM配置:高有效、占空比、基本时钟记数频率、共同循环周期(频率48KHz) 以及每个对应的事件(其实就是脉冲发生和周期的记数匹配以产生PWM);最后开始SCT,就有PWM发生了。 注意一个PWM对应一个event标记,它们在改变占空比是要用。 - sctimer_config_t sctimerInfo;
- sctimer_pwm_signal_param_t pwmParam;
- uint32_t sctimerClock;
- ..........
- GPIO->DIR[0] |= 1U << 25;
- GPIO->DIR[0] |= 1U << 26;
- SCTIMER_GetDefaultConfig(&sctimerInfo);
- /* Initialize SCTimer module */
- SCTIMER_Init(SCT0, &sctimerInfo);
- /* Configure first PWM with frequency 24kHZ from output 4 5 kSCTIMER_CenterAlignedPwm kSCTIMER_EdgeAlignedPwm*/
- pwmParam.output = kSCTIMER_Out_4;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 40;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam,kSCTIMER_CenterAlignedPwm , 48000U, sctimerClock, &event4) == kStatus_Fail)
- {
- return -1;
- }
-
- pwmParam.output = kSCTIMER_Out_5;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 40;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 48000U, sctimerClock, &event5) == kStatus_Fail)
- {
- return -1;
- }
- /* Configure second PWM with different duty cycle but same frequency as before */
- pwmParam.output = kSCTIMER_Out_6;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 45;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 48000U, sctimerClock, &event6) == kStatus_Fail)
- {
- return -1;
- }
- pwmParam.output = kSCTIMER_Out_7;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 45;
- if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 48000U, sctimerClock, &event7) == kStatus_Fail)
- {
- return -1;
- }
-
- /* Start the timer */
- SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);
-
复制代码
另配置使用了一个CTIMER0记数匹配中断,用于定时中断更改占空比以改变电机转动的速度。
- #define CTIMER CTIMER0 /* Timer 0 */
- #define CTIMER_MAT_OUT kCTIMER_Match_0
- ctimer_config_t config;
- ctimer_match_config_t matchConfig;
- CTIMER_GetDefaultConfig(&config);
- CTIMER_Init(CTIMER, &config);
-
- matchConfig.enableCounterReset = true; //mat1 后复位 重记数 控制测量周期
- matchConfig.enableCounterStop = false;//true;// //mat后不停止
- matchConfig.matchValue = BUS_CLK_FREQ /2000;//200;//0 ; // BUS_CLK_FREQ/1 即1秒
- matchConfig.outControl = kCTIMER_Output_NoAction; //无输出关联
- matchConfig.outPinInitState = false; // 无效
- matchConfig.enableInterrupt = true;// //匹配不中断
- CTIMER_SetupMatch(CTIMER, kCTIMER_Match_1, &matchConfig); //Timer3 mat1 no out
- CTIMER_RegisterCallBack(CTIMER, &ctimer_callback_table[0], kCTIMER_SingleCallback);//kCTIMER_MultipleCallback); //kCTIMER_MultipleCallback); //echo fall intr
-
- CTIMER_StartTimer(CTIMER); //开始
复制代码
定时中断更改占空比以改变电机转动的速度、方向、LED灯同步指示。 1) 占空比以小间隔逐渐线性改变, 以实现较平滑的逐渐加减速和反向,而不是突然的改变。 2) Port 0的25/26,用分别对应正反转动方向,LED灯亮灭分别对应一个方向的加减速。
- void ctimer_match1_callback(uint32_t flags)
- {
- if(GorB==1)
- {
- if(GPIO->B[0][25] ==1)
- {
- PRINTF("\r\n int 1 outpu 0.25 0 \r\n");
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_6, sp/10+ad, event6); // 右轮 前进
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_7, 1, event7);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_5, sp/10, event5); // 左轮 前进
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_4, 1, event4);
- sp +=dsp ;
- if (sp>upsp)
- GPIO->B[0][25] =0;
- }
- else
- {
- PRINTF("\r\n int 0 outpu 0.25 1 \r\n");
- /* SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_4, sp, event4);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_5, 1, event5); // 左轮 后退
-
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_6, 1, event6); // 右轮 后退
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_7, sp, event7);
- */
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_6, sp/10+ad, event6); // 右轮 前进 +16
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_7, 1, event7);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_5, sp/10, event5); // 左轮 前进
-
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_4, 1, event4);
-
-
- sp -=dsp ;
- if (sp<lwsp)
- {
- GPIO->B[0][25] =1;
- GorB=0;
- }
- }
- }
- else
- if(GPIO->B[0][26] ==1)
- {
- PRINTF("\r\n int 1 outpu 0.26 0 \r\n");
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_7, sp/10+ad, event7);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_6, 1, event6); // 右轮 后退 +16
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_4, sp/10, event4);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_5, 1, event5); // 左轮 后退
-
- sp +=dsp ;
- if (sp>upsp)
- GPIO->B[0][26] =0;
- }
- else
- {
- PRINTF("\r\n int 0 outpu 0.26 1 \r\n");
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_7, sp/10+ad, event7);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_6, 1, event6); // 右轮 后退 +16
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_4, sp/10, event4);
- SCTIMER_UpdatePwmDutycycle(SCT0, kSCTIMER_Out_5, 1, event5); // 左轮 后退
-
- sp -=dsp ;
- if (sp<lwsp)
- {
- GPIO->B[0][26] =1;
- GorB=1;
- }
- }
-
-
- }
- ctimer_callback_t ctimer_callback_table[] =
- {
- ctimer_match1_callback,//NULL,
- // ctimer_cap_callback,
- NULL,
- NULL,//ctimer_match1_callback,
- NULL,
- NULL,
- //ctimer_cap_callback,
- NULL,
- NULL,
- NULL
- };
复制代码
注意事项和问题: 1) 更改占空比实际是在停止和再启SCT之间修改的,四线就这样了4次,应考虑不用库函数代码,在一次停启之间修改四个占空比; 2) SCT停止时,只是停的是记数器,有可能某管脚只好PWM处于高电位,这下电机会疯狂旋转! 3) 不能使用0和100做占空比,这里用的电机驱动不是用独立的线控制正反转方向,所以正反转动方向控制通过把对应2线之一的占空比设为1实现。 4) 电机通过减速齿轮带动轮子空转,发现旋转阻力不均,不仅占空比与转速不是线性关系,轮子和轴不同角度阻力也不相同(同占空比下转动也不均匀、不太重现)。这还是空转啊,实际岂不是更不均匀了。这个这个我不懂了,可能可能机械转动转动的世界不太理想。也许需要测速反馈控制才能定速控制(这个电机的测速分辨不高,而平衡车是微动,我很怀疑有没用用)。 5) 带动轮子的空转阻力也不小了,占空比20以下不转,30以上才算转,两个轮子阻力还不一样。 6) 看这个头重脚轻的东西,严重怀疑这个能否实现平衡车?? 7) 不知道,SCT是否能一个匹配触发多个输出呢?有空再研究吧。 现在论坛禁止上传视频文件,只好转为动态gif图吧。
倒置空转,正反转视频: 我临时使用一个手机电池(7.3V, 3400mAh)经升压模块(已经烧了一个了!)到10V供电机驱动。
先悬绳保持,观察正反转视频:(支架用废光盘做的)
系列:
|