前言
恩智浦“FRDM-MCXN947”評測活動由安富利和與非網(wǎng)協(xié)同舉辦。本篇內(nèi)容由與非網(wǎng)用戶發(fā)布,已獲轉(zhuǎn)載許可。原文可在與非網(wǎng)(eefocus)工程師社區(qū)查看。
背景
01 直流電機驅(qū)動模塊L9110S
一個L9110S驅(qū)動可以控制一個電機,下圖中的GroundStudio L9110s模塊板載兩個L9110s芯片,可以驅(qū)動兩個直流電機。
02 引腳說明
此模塊有6根引腳,如下:
簡單來說L9110S的輸入輸出有以下四種情形:
從上圖可知,只需要給IN1和IN2管腳輸入不同的電平就能實現(xiàn)正轉(zhuǎn)、反轉(zhuǎn),輸入相同的電平就能停轉(zhuǎn)。
需要注意,不要直接由開發(fā)板來給模塊供電,因為L9110S模塊可能因為需求的驅(qū)動功率太高而導(dǎo)致板子上的供電不平衡。
03 MCXN947 PWM
從上表可知,使用GPIO給IN1和IN2也能驅(qū)動電機,但是不能控制速度。現(xiàn)在我們需要實現(xiàn)能控制速度的電機驅(qū)動。自然而然想到了PWM調(diào)速。
假設(shè)給IN2管腳用GPIO控制,拉低電平,只需要PWM往IN1灌高電平就可以驅(qū)動電機正轉(zhuǎn),調(diào)節(jié)PWM占空比就可以實現(xiàn)電機轉(zhuǎn)速;把IN2管腳拉高電平,用PMW往IN1灌低電平就可以實現(xiàn)電機反轉(zhuǎn),注意此時的占空比和轉(zhuǎn)速是反著的,即占空比越大,轉(zhuǎn)速越慢。
這里選擇eFlexPWM產(chǎn)生PWM1_A通道的PWM波來控制電機,另外一個管腳用GPIO來控制電平調(diào)節(jié)正反轉(zhuǎn)。
04 代碼實現(xiàn)
為了方便調(diào)試,先實現(xiàn)命令行接口,可以方便的通過串口輸入命令調(diào)節(jié)參數(shù)控制電機正反轉(zhuǎn)和轉(zhuǎn)速。然后實現(xiàn)對應(yīng)的電機驅(qū)動接口。
05 命令行接口
FreeRTOS-CLI新增命令行,支持如下的3種命令:
(滑動查看)
motor stop // 電機停轉(zhuǎn) motor left speed // 電機正轉(zhuǎn),speed 表示速度,取值范圍[0, 100] motor right speed // 電機反轉(zhuǎn),speed 表示范圍,取值范圍[0, 100]
當(dāng)前命令行的解析函數(shù)prvMotorCommand()如下,其實最終調(diào)用的函數(shù)是分別是motor_stop(),motor_left(speed)和motor_right(speed)這三個函數(shù)。
(滑動查看)
/** * @brief 直流電機命令的實現(xiàn) * * motor left/right speed 其中 speed 取值范圍是 [0, 100] * motor stop * * 示例: * motor left 0 * motor left 100 * motor right 20 * motor right 80 * motor stop 停轉(zhuǎn) * * @param pcWriteBuffer * @param xWriteBufferLen * @param pcCommandString * @return BaseType_t */ staticBaseType_tprvMotorCommand(char*pcWriteBuffer,size_txWriteBufferLen,constchar*pcCommandString ) { configASSERT(pcWriteBuffer); br /* param1: left/right/stop */ constchar*paramMotorCmd1 =NULL; BaseType_t paramMotorCmd1Length =0; br /* param2: speed */ constchar*paramMotorCmd2 =NULL; BaseType_t paramMotorCmd2Length =0; uint32_tspeed =0; br // 首先清除輸出緩沖區(qū)舊的內(nèi)容 memset(pcWriteBuffer,0, xWriteBufferLen); br /* arg0 arg1 arg2 */ /* 命令形式1:motor left/right speed */ /* 命令形式2:motor stop */ paramMotorCmd1 =FreeRTOS_CLIGetParameter(pcCommandString,1, ?mMotorCmd1Length); br if(strncmp("stop", paramMotorCmd1, strlen("stop")) ==0){ motor_stop(); sprintf(pcWriteBuffer," motor_stop() "); }else{ /* 獲取 speed */ paramMotorCmd2 =FreeRTOS_CLIGetParameter(pcCommandString,2, ?mMotorCmd2Length); if(paramMotorCmd2 !=NULL) { speed =strtoul(paramMotorCmd2,NULL,10); br if(speed >=100){ speed =99;/*NOTE:PWM 占空比 <= 100 但由于兩個高電平導(dǎo)致電機停轉(zhuǎn),所以占空比應(yīng)該 < 100 */ ? ? ? } ? ? } br ? ??if?(strncmp("left", paramMotorCmd1, strlen("left")) ==?0)?{ ? ? ??sprintf(pcWriteBuffer,?" motor_left(%u) ", speed); ? ? ??motor_left(speed); ? ? }?else?if?(strncmp("right", paramMotorCmd1,?strlen("right")) ==?0) { ? ? ??sprintf(pcWriteBuffer,?" motor_right(%u) ", speed); ? ? ??motor_right(speed); ? ? }?else?{ ? ? ??sprintf(pcWriteBuffer,?" Error: arg1 should be left/right "); ? ? } ? } br ??/* There is no more data to return after this single string, so return pdFALSE. */ ??return?pdFALSE; }
06 電機驅(qū)動實現(xiàn)
PWM和GPIO初始化
通過MCUXpresso Config Tools來實現(xiàn),配置J3.15為PWM1_A0,配置J3.13為GPIO輸出模式。生成代碼,自動保存在pin_mux.c文件中。
在MCUXpresso Config Tools中,點擊(1)處新建分組BOARD_MOTOR_Init,把電機相關(guān)的管腳都放在同一個組里初始化;
在(2)處可以看到J3.15配置為PWM1_A0信號,J3.13配置為PIO2_7且為輸出;
在(3)處給管腳添加標識符,會生成相對應(yīng)的宏定義。
對應(yīng)的管腳初始化代碼如下:
(滑動查看)
voidBOARD_MOTOR_Init(void) { /* Enables the clock for GPIO2: Enables clock */ CLOCK_EnableClock(kCLOCK_Gpio2); /* Enables the clock for PORT2: Enables clock */ CLOCK_EnableClock(kCLOCK_Port2); gpio_pin_config_t MOTOR_DIR_config = { .pinDirection= kGPIO_DigitalOutput, .outputLogic= 0U }; /* Initialize GPIO functionality on pin PIO2_7 (pin L2) */ GPIO_PinInit(MOTOR_MOTOR_DIR_GPIO,MOTOR_MOTOR_DIR_PIN, &MOTOR_DIR_config); /* PORT2_6 (pin K2) is configured as PWM1_A0 */ PORT_SetPinMux(MOTOR_MOTOR_SPEED_PORT,MOTOR_MOTOR_SPEED_PIN, kPORT_MuxAlt5); PORT2->PCR[6] = ((PORT2->PCR[6] & /* Mask bits to zero which are setting */ (~(PORT_PCR_IBE_MASK))) /* Input Buffer Enable: Enables. */ |PORT_PCR_IBE(PCR_IBE_ibe1)); /* PORT2_7 (pin L2) is configured as PIO2_7 */ PORT_SetPinMux(MOTOR_MOTOR_DIR_PORT,MOTOR_MOTOR_DIR_PIN, kPORT_MuxAlt0); PORT2->PCR[7] = ((PORT2->PCR[7] & /* Mask bits to zero which are setting */ (~(PORT_PCR_IBE_MASK))) /* Input Buffer Enable: Enables. */ |PORT_PCR_IBE(PCR_IBE_ibe1)); }
需要實現(xiàn)4個函數(shù),分別是:
motor_init()
motor_stop()
motor_left()
motor_right()
公共的類型和變量
(滑動查看)
#include"pin_mux.h" #include"fsl_gpio.h" #include"fsl_pwm.h" #include"bsp_motor.h" #include"fsl_debug_console.h" br /******************************************************************************* * Definitions ******************************************************************************/ /* The PWM base address */ #defineBOARD_PWM_BASEADDR PWM1 #definePWM_SRC_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk) #defineDEMO_PWM_FAULT_LEVEL true #defineAPP_DEFAULT_PWM_FREQUENCY (10000UL) /* Definition for default PWM frequence in hz. */ #ifndefAPP_DEFAULT_PWM_FREQUENCY #defineAPP_DEFAULT_PWM_FREQUENCY (1000UL) #endif br /* Macros ----------------------------------------------------------------------------------------*/ #defineMOTOR_DIR_SET_LEFT() GPIO_PinWrite(MOTOR_MOTOR_DIR_GPIO, MOTOR_MOTOR_DIR_GPIO_PIN, 0) #defineMOTOR_DIR_SET_RIGHT() GPIO_PinWrite(MOTOR_MOTOR_DIR_GPIO, MOTOR_MOTOR_DIR_GPIO_PIN, 1) br br /* Data Types ------------------------------------------------------------------------------------*/ br typedefenum{ MOTOR_DIR_LEFT =0, MOTOR_DIR_RIGHT =1, } motor_dir_e; br staticuint32_tpwmSourceClockInHz; staticuint32_tpwmFrequencyInHz; staticpwm_signal_param_tpwmSignal = {0}; staticmotor_dir_e m_motor_dir = MOTOR_DIR_LEFT;
motor_init()
(滑動查看)
staticvoidPWM_DRV_Init2PhPwm(void) { uint16_tdeadTimeVal; br /* Set deadtime count, we set this to about 650ns */ deadTimeVal = ((uint64_t)pwmSourceClockInHz *650) /1000000000; br pwmSignal.pwmChannel = kPWM_PwmA; pwmSignal.level = kPWM_HighTrue; pwmSignal.dutyCyclePercent =30;/* x percent dutycycle */ pwmSignal.deadtimeValue = deadTimeVal; pwmSignal.faultState = kPWM_PwmFaultState0; pwmSignal.pwmchannelenable =true; br /*********** PWMA_SM0 - phase A, configuration, setup 2 channel as an example ************/ PWM_SetupPwm(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmSignal,1, kPWM_SignedCenterAligned, pwmFrequencyInHz, pwmSourceClockInHz); } br /** * @brief 直流電機初始化,即 PWM1 的通道A和通道B初始化 * * @return int 0 on success, others on failure. */ intmotor_init(void) { pwm_config_tpwmConfig; pwm_fault_param_tfaultConfig; br pwmSourceClockInHz = PWM_SRC_CLK_FREQ; pwmFrequencyInHz = APP_DEFAULT_PWM_FREQUENCY; br SYSCON->PWM1SUBCTL |= SYSCON_PWM1SUBCTL_CLK0_EN_MASK;/* 只使能子模塊0 */ br PWM_GetDefaultConfig(&pwmConfig); br pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle; /* use full cycle reload */ pwmConfig.pairOperation = kPWM_Independent; /* PWM A & PWM B operate as 2 independent channels */ pwmConfig.enableDebugMode =true; br if(PWM_Init(BOARD_PWM_BASEADDR, kPWM_Module_0, &pwmConfig) == kStatus_Fail) { PRINTF("PWM initialization failed "); return1; } br PWM_FaultDefaultConfig(&faultConfig); br #ifdefDEMO_PWM_FAULT_LEVEL faultConfig.faultLevel = DEMO_PWM_FAULT_LEVEL; #endif br /* 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); br /* Set PWM fault disable mapping for submodule 0 */ PWM_SetupFaultDisableMap(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0, kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3); br /* Call the init function with demo configuration */ PWM_DRV_Init2PhPwm(); br /* Set the load okay bit for all submodules to load registers from their buffer */ PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true); br PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0); br motor_stop(); br return0; }
motor_stop()
(滑動查看)
voidmotor_stop(void) { if(m_motor_dir ==MOTOR_DIR_LEFT) { MOTOR_DIR_SET_LEFT(); PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned,0); /* Set the load okay bit for all submodules to load registers from their buffer */ PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true); }else{ MOTOR_DIR_SET_RIGHT(); PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned,100); /* Set the load okay bit for all submodules to load registers from their buffer */ PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true); } }
motor_left(speed)
(滑動查看)
/** *@brief正轉(zhuǎn) *@paramspeed 占空比,[0~100] */ voidmotor_left(uint32_t speed) { MOTOR_DIR_SET_LEFT(); m_motor_dir =MOTOR_DIR_LEFT; br PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned, speed); /* Set the load okay bit for all submodules to load registers from their buffer */ PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true); PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0); }
motor_right(speed)
(滑動查看)
/** * @brief 反轉(zhuǎn) * @param speed */ voidmotor_right(uint32_tspeed) { MOTOR_DIR_SET_RIGHT(); m_motor_dir = MOTOR_DIR_RIGHT; speed =100- speed; br PWM_UpdatePwmDutycycle(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_SignedCenterAligned, speed); // PWM_SetChannelOutput(BOARD_PWM_BASEADDR, kPWM_Module_0, kPWM_PwmA, kPWM_InvertState); /* Set the load okay bit for all submodules to load registers from their buffer */ PWM_SetPwmLdok(BOARD_PWM_BASEADDR, kPWM_Control_Module_0,true); br PWM_StartTimer(BOARD_PWM_BASEADDR, kPWM_Control_Module_0); }
驗證
01 示波器測量
上面黃色的是CH2,即PWM1_A信號(J3.15);
下面綠色的是CH1,即GPIO信號(J3.13);
電機正轉(zhuǎn)motor left時CH1輸出低電平;
電機反轉(zhuǎn)motor right時CH1輸出高電平。
motor stop
兩路信號都是低電平。電機停轉(zhuǎn)。
motor left 5
電機正轉(zhuǎn),速度為5。示波器觀測PWM1_A占空比為5。
motor left 70
電機正轉(zhuǎn),速度為70。示波器觀測PWM1_A占空比為70。
motor left 100
雖然PWM占空比可以設(shè)置成100%,但是兩個高電平導(dǎo)致電機停轉(zhuǎn),所以這里把占空比合理的范圍是[0,99]。
motor right 5
motor right 70
motor right 100
關(guān)于安富利
安富利是全球領(lǐng)先的技術(shù)分銷商和解決方案提供商,在過去一個多世紀里一直秉持初心,致力于滿足客戶不斷變化的需求。通過遍布全球的專業(yè)化和區(qū)域化業(yè)務(wù)覆蓋,安富利可在產(chǎn)品生命周期的每個階段為客戶和供應(yīng)商提供支持。安富利能夠幫助各種類型的公司適應(yīng)不斷變化的市場環(huán)境,在產(chǎn)品開發(fā)過程中加快設(shè)計和供應(yīng)速度。安富利在整個技術(shù)價值鏈中處于中心位置,這種獨特的地位和視角讓其成為了值得信賴的合作伙伴,能夠幫助客戶解決復(fù)雜的設(shè)計和供應(yīng)鏈難題,從而更快地實現(xiàn)營收。
-
驅(qū)動器
+關(guān)注
關(guān)注
54文章
8448瀏覽量
148271 -
恩智浦
+關(guān)注
關(guān)注
14文章
5918瀏覽量
110751 -
直流電機
+關(guān)注
關(guān)注
36文章
1715瀏覽量
71022 -
安富利
+關(guān)注
關(guān)注
6文章
434瀏覽量
62545
原文標題:用戶測評(五):MCXN947 PWM驅(qū)動直流電機L9110S驅(qū)動器
文章出處:【微信號:AvnetAsia,微信公眾號:安富利】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論