当前位置:   article > 正文

STM32无刷电机全套开发资料(源码、原理图、PCB工程及说明文档)

STM32无刷电机全套开发资料(源码、原理图、PCB工程及说明文档)

目录

1、原理图、PCB、BOOM表

2、设计描述 

2.1 前言

2.2 设计电路规范

 3、代码

4、资料清单

资料下载地址:STM32无刷电机全套开发资料(源码、原理图、PCB工程及说明文档)

1、原理图、PCB、BOOM表

 

2、设计描述 

2.1 前言

        经过一个星期的画PCB,今天终于化了,整体看上去还比较满意,具体的性能基本满足需求

2.2 设计电路规范

 1、线间距。

      这里应该遵循3W规则,所谓3W就是为了减少线间串扰,应保证线间距足够大,当线中心不少于3倍线宽,则可 保持70%的电场不互相干扰。如要达到98%的电场不互相干扰,可使用10W的间距。——这是查阅华为PCB布线规则所得。

 

     2、电源线过细。

      这里我查阅了华为PCB教程得到了下面一个表格。这里线宽跟所能承受最大电流的关系表

  3、电源环路。(用图说明)

 3、代码

  1. /*
  2. This file is part of AutoQuad ESC32.
  3. AutoQuad ESC32 is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. AutoQuad ESC32 is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with AutoQuad ESC32. If not, see
  13. Copyright © 2011, 2012, 2013 Bill Nesbitt
  14. */
  15. #include "run.h"
  16. #include "main.h"
  17. #include "timer.h"
  18. #include "adc.h"
  19. #include "fet.h"
  20. #include "pwm.h"
  21. #include "cli.h"
  22. #include "binary.h"
  23. #include "config.h"
  24. #include "misc.h"
  25. #include "stm32f10x_exti.h"
  26. #include "stm32f10x_pwr.h"
  27. #include "stm32f10x_iwdg.h"
  28. #include "stm32f10x_dbgmcu.h"
  29. #include <math.h>
  30. uint32_t runMilis; //systick中断中自加.没有什么控制用途
  31. static uint32_t oldIdleCounter; //上次main函数中,死循环次数.
  32. float idlePercent; //空闲时间百分比(在main循环里,什么事情也不做.main死循环运行的时间)
  33. float avgAmps, maxAmps; //平均电流, 最大电流
  34. float avgVolts; //当前ADC采集转换后的电池电压(也就是12v)
  35. float rpm; //当前转速(1分钟多少转) 测量值 在runRpm函数中计算出来.在runThrotLim中还要继续使用.
  36. float targetRpm; //目标转速 设定值(只在闭环 或 闭环推力模式下使用此变量)
  37. static float rpmI;
  38. static float runRPMFactor;
  39. static float maxCurrentSQRT; //最大电流 平方根 后
  40. uint8_t disarmReason;//此变量没啥作用.只用于给上位机显示当前的 调试代码(或者说停止电机的原因)
  41. uint8_t commandMode; //串口通讯的模式, cli是ascii模式, binary是二进制通讯模式
  42. static uint8_t runArmCount;
  43. volatile uint8_t runMode;//运行模式 (开环模式, RPM模式, 推力模式, 伺服模式)
  44. static float maxThrust;
  45. //执行看门狗喂狗
  46. void runFeedIWDG(void) {
  47. #ifdef RUN_ENABLE_IWDG
  48. IWDG_ReloadCounter();
  49. #endif
  50. }
  51. // setup the hardware independent watchdog
  52. // 初始化并开启独立看门狗
  53. uint16_t runIWDGInit(int ms)
  54. {
  55. #ifndef RUN_ENABLE_IWDG
  56. return 0;
  57. #else
  58. uint16_t prevReloadVal;
  59. int reloadVal;
  60. IWDG_ReloadCounter();//喂狗
  61. DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);//当在jtag调试的时候.停止看门狗
  62. // IWDG timeout equal to 10 ms (the timeout may varies due to LSI frequency dispersion)
  63. // Enable write access to IWDG_PR and IWDG_RLR registers
  64. IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//允许访问IWDG_PR和IWDG_RLR寄存器
  65. // IWDG counter clock: LSI/4
  66. IWDG_SetPrescaler(IWDG_Prescaler_4);
  67. // Set counter reload value to obtain 10ms IWDG TimeOut.
  68. // Counter Reload Value = 10ms/IWDG counter clock period
  69. // = 10ms / (RUN_LSI_FREQ/4)
  70. // = 0.01s / (RUN_LSI_FREQ/4)
  71. // = RUN_LSI_FREQ/(4 * 100)
  72. // = RUN_LSI_FREQ/400
  73. reloadVal = RUN_LSI_FREQ*ms/4000;
  74. if (reloadVal < 1)
  75. reloadVal = 1;
  76. else if (reloadVal > 0xfff)
  77. reloadVal = 0xfff;
  78. prevReloadVal = IWDG->RLR;
  79. IWDG_SetReload(reloadVal);
  80. // Reload IWDG counter
  81. IWDG_ReloadCounter();
  82. // Enable IWDG (the LSI oscillator will be enabled by hardware)
  83. IWDG_Enable();
  84. return (prevReloadVal*4000/RUN_LSI_FREQ);
  85. #endif
  86. }
  87. //esc32 非正常停止运行 进入初始化
  88. void runDisarm(int reason) {
  89. fetSetDutyCycle(0); //fet占空比设置为0
  90. timerCancelAlarm2();
  91. state = ESC_STATE_DISARMED;
  92. pwmIsrAllOn();
  93. digitalHi(statusLed); // turn off
  94. digitalLo(errorLed); // turn on
  95. disarmReason = reason; // 设置停机原因.给上位机查看状态使用
  96. }
  97. //手动运行
  98. void runArm(void) {
  99. int i;
  100. fetSetDutyCycle(0);
  101. timerCancelAlarm2();
  102. digitalHi(errorLed);
  103. digitalLo(statusLed); // turn on
  104. if (runMode == SERVO_MODE) {
  105. state = ESC_STATE_RUNNING;
  106. }
  107. else {
  108. state = ESC_STATE_STOPPED;
  109. if (inputMode == ESC_INPUT_UART)
  110. runMode = OPEN_LOOP;
  111. fetSetBraking(0);
  112. }
  113. // extra beeps signifying run mode
  114. for (i = 0; i < runMode + 1; i++) {
  115. fetBeep(250, 600);
  116. timerDelay(10000);
  117. }
  118. // fetBeep(150, 800);
  119. }
  120. //电机开始运行
  121. void runStart(void) {
  122. // reset integral bevore new motor startup
  123. runRpmPIDReset();//先复位I值
  124. if ((p[START_ALIGN_TIME] == 0) && (p[START_STEPS_NUM] == 0)) {
  125. state = ESC_STATE_STARTING; //设置为准备启动状态
  126. fetStartCommutation(0);//换向启动
  127. }
  128. else {
  129. motorStartSeqInit();//普通启动
  130. }
  131. }
  132. //电机停止运行
  133. void runStop(void) {
  134. runMode = OPEN_LOOP;
  135. fetSetDutyCycle(0);
  136. }
  137. //设置运行的占空比 duty = 0~100
  138. uint8_t runDuty(float duty) {
  139. uint8_t ret = 0;
  140. if (duty >= 0.0f || duty <= 100.0f) {
  141. runMode = OPEN_LOOP;
  142. fetSetBraking(0);
  143. fetSetDutyCycle((uint16_t)(fetPeriod*duty*0.01f));//最大周期 * 占空比(0~100) / 100
  144. ret = 1;
  145. }
  146. return ret;
  147. }
  148. //pwm.c中断中调用 或 串口命令输入调用
  149. void runNewInput(uint16_t setpoint) {
  150. static uint16_t lastPwm;
  151. static float filteredSetpoint = 0;
  152. // Lowpass Input if configured
  153. // TODO: Make lowpass independent from pwm update rate
  154. if (p[PWM_LOWPASS]) {
  155. filteredSetpoint = (p[PWM_LOWPASS] * filteredSetpoint + (float)setpoint) / (1.0f + p[PWM_LOWPASS]);
  156. setpoint = filteredSetpoint;
  157. }
  158. if (state == ESC_STATE_RUNNING && setpoint != lastPwm)
  159. {
  160. if (runMode == OPEN_LOOP)
  161. {
  162. //开环模式
  163. fetSetDutyCycle(fetPeriod * (int32_t)(setpoint-pwmLoValue) / (int32_t)(pwmHiValue - pwmLoValue));
  164. }
  165. else if (runMode == CLOSED_LOOP_RPM)
  166. {
  167. //闭环转速模式
  168. float target = p[PWM_RPM_SCALE] * (setpoint-pwmLoValue) / (pwmHiValue - pwmLoValue);
  169. // limit to configured maximum
  170. targetRpm = (target > p[PWM_RPM_SCALE]) ? p[PWM_RPM_SCALE] : target;
  171. }
  172. // THRUST Mode
  173. else if (runMode == CLOSED_LOOP_THRUST)
  174. {
  175. //闭环推力模式
  176. float targetThrust; // desired trust
  177. float target; // target(rpm)
  178. // Calculate targetThrust based on input and MAX_THRUST
  179. targetThrust = maxThrust * (setpoint-pwmLoValue) / (pwmHiValue - pwmLoValue);
  180. // Workaraound: Negative targetThrust will screw up sqrtf() and create MAX_RPM on throttle min. Dangerous!
  181. if (targetThrust > 0.0f) {
  182. // Calculate target(rpm) based on targetThrust
  183. target = ((sqrtf(p[THR1TERM] * p[THR1TERM] + 4.0f * p[THR2TERM] * targetThrust) - p[THR1TERM] ) / ( 2.0f * p[THR2TERM] ));
  184. }
  185. // targetThrust is negative (pwm_in < pwmLoValue)
  186. else {
  187. target = 0.0f;
  188. }
  189. // upper limit for targetRpm is configured maximum PWM_RPM_SCALE (which is MAX_RPM)
  190. targetRpm = (target > p[PWM_RPM_SCALE]) ? p[PWM_RPM_SCALE] : target;
  191. }
  192. else if (runMode == SERVO_MODE)
  193. {
  194. //伺服模式下
  195. fetSetAngleFromPwm(setpoint);
  196. }
  197. lastPwm = setpoint;
  198. }
  199. else if ((state == ESC_STATE_NOCOMM || state == ESC_STATE_STARTING) && setpoint <= pwmLoValue)
  200. {
  201. fetSetDutyCycle(0);
  202. state = ESC_STATE_RUNNING;
  203. }
  204. else if (state == ESC_STATE_DISARMED && setpoint > pwmMinValue && setpoint <= pwmLoValue)
  205. {
  206. runArmCount++;
  207. if (runArmCount > RUN_ARM_COUNT)
  208. runArm();
  209. }
  210. else {
  211. runArmCount = 0;
  212. }
  213. if (state == ESC_STATE_STOPPED && setpoint >= pwmMinStart) {
  214. //电机开始运行
  215. runStart();
  216. }
  217. }
  218. //电调运行看门狗. 主要是判断电调的当前一些状态.做出停机等处理
  219. static void runWatchDog(void)
  220. {
  221. register uint32_t t, d, p;
  222. //__asm volatile ("cpsid i");
  223. //CPSID_I();
  224. __disable_irq();
  225. t = timerMicros; //当前的系统tick时间
  226. d = detectedCrossing;
  227. p = pwmValidMicros; //在PWM输入模式下.把timerMicros的时间赋值给此变量
  228. //__asm volatile ("cpsie i");
  229. //CPSIE_I();
  230. __enable_irq();
  231. if (state == ESC_STATE_STARTING && fetGoodDetects > fetStartDetects) //这里要检测到fetStartDetects好的检测,才允许切换电机状态
  232. {
  233. //是启动状态.切换到 运行状态
  234. state = ESC_STATE_RUNNING;
  235. digitalHi(statusLed); // turn off
  236. }
  237. else if (state >= ESC_STATE_STOPPED)
  238. {
  239. //运行模式状态下.会一直在这里检测状态.如果状态不对出错.会调用runDisarm函数停止
  240. // running or starting
  241. d = (t >= d) ? (t - d) : (TIMER_MASK - d + t);
  242. // timeout if PWM signal disappears
  243. if (inputMode == ESC_INPUT_PWM)
  244. {
  245. //PWM模式 判断PWM输入是否超时
  246. p = (t >= p) ? (t - p) : (TIMER_MASK - p + t);
  247. if (p > PWM_TIMEOUT)
  248. runDisarm(REASON_PWM_TIMEOUT);//pwm输入超时
  249. }
  250. if (state >= ESC_STATE_STARTING && d > ADC_CROSSING_TIMEOUT)
  251. {
  252. if (fetDutyCycle > 0) {
  253. runDisarm(REASON_CROSSING_TIMEOUT);//错误停止
  254. }
  255. else
  256. {
  257. runArm();//手动运行起来
  258. pwmIsrRunOn();//PWM开启输入比较
  259. }
  260. }
  261. else if (state >= ESC_STATE_STARTING && fetBadDetects > fetDisarmDetects) //运行状态中 检测到错误的个数后.进入这个判断
  262. {
  263. //在运行过程中,出现错误.停止运行
  264. if (fetDutyCycle > 0)
  265. runDisarm(REASON_BAD_DETECTS);//错误停止
  266. }
  267. else if (state == ESC_STATE_STOPPED)
  268. {
  269. //停止模式
  270. adcAmpsOffset = adcAvgAmps; // record current amperage offset
  271. }
  272. }
  273. else if (state == ESC_STATE_DISARMED && !(runMilis % 100))
  274. {
  275. //停止模式下
  276. adcAmpsOffset = adcAvgAmps; // record current amperage offset
  277. digitalTogg(errorLed);
  278. }
  279. }
  280. void runRpmPIDReset(void) {
  281. rpmI = 0.0f;
  282. }
  283. //这个应该是计算PID
  284. //rpm:测量的转速值
  285. //target:目标的转速值
  286. static int32_t runRpmPID(float rpm, float target) {
  287. float error;
  288. float ff, rpmP;
  289. float iTerm = rpmI;
  290. float output;
  291. // feed forward
  292. ff = ((target*target* p[FF1TERM] + target*p[FF2TERM]) / avgVolts) * fetPeriod;
  293. error = (target - rpm);//计算出偏差
  294. if (error > 1000.0f)
  295. error = 1000.0f;
  296. if (error > 0.0f) {
  297. rpmP = error * p[PTERM]; //P
  298. rpmI += error * p[ITERM]; //I
  299. }
  300. else {
  301. rpmP = error * p[PTERM] * p[PNFAC];
  302. rpmI += error * p[ITERM] * p[INFAC];
  303. }
  304. if (fetBrakingEnabled)
  305. {
  306. //开启了制动模式
  307. if (rpm < 300.0f) {
  308. fetSetBraking(0);
  309. }
  310. else if (error <= -100.0f) {
  311. fetSetBraking(1);
  312. }
  313. else if (fetBraking && error > -25.0f){
  314. fetSetBraking(0);
  315. }
  316. }
  317. output = ff + (rpmP + rpmI) * (1.0f / 1500.0f) * fetPeriod;
  318. // don't allow integral to continue to rise if at max output
  319. if (output >= fetPeriod)
  320. rpmI = iTerm;
  321. return output;
  322. }
  323. //计算出电机转速,根据当前转速计算出PID输出值,设置占空比
  324. static uint8_t runRpm(void)
  325. {
  326. if (state > ESC_STATE_STARTING)
  327. {
  328. //电机处于运行状态 计算出当前转速rpm
  329. // rpm = rpm * 0.90f + (runRPMFactor / (float)crossingPeriod) * 0.10f;
  330. // rpm -= (rpm - (runRPMFactor / (float)crossingPeriod)) * 0.25f;
  331. // rpm = (rpm + (runRPMFactor / (float)crossingPeriod)) * 0.5f;
  332. // rpm = (rpm + ((32768.0f * runRPMFactor) / (float)adcCrossingPeriod)) * 0.5f; // increased resolution, fixed filter here
  333. rpm = p[RPM_MEAS_LP] * rpm + ((32768.0f * runRPMFactor) / (float)adcCrossingPeriod) * (1.0f - p[RPM_MEAS_LP]); // increased resolution, variable filter here
  334. // run closed loop control
  335. if (runMode == CLOSED_LOOP_RPM)
  336. {
  337. //运行在闭环模式下
  338. fetSetDutyCycle(runRpmPID(rpm, targetRpm));
  339. return 1;
  340. }
  341. // run closed loop control also for THRUST mode
  342. else if (runMode == CLOSED_LOOP_THRUST)
  343. {
  344. //运行在闭环推力模式
  345. fetSetDutyCycle(runRpmPID(rpm, targetRpm));
  346. return 1;
  347. }
  348. else
  349. {
  350. return 0;
  351. }
  352. }
  353. else
  354. {
  355. //电机在停止状态下
  356. rpm = 0.0f;
  357. return 0;
  358. }
  359. }
  360. static void runSetupPVD(void) {
  361. EXTI_InitTypeDef EXTI_InitStructure;
  362. NVIC_InitTypeDef NVIC_InitStructure;
  363. // Configure EXTI Line16(PVD Output) to generate an interrupt on rising and falling edges
  364. EXTI_ClearITPendingBit(EXTI_Line16);
  365. EXTI_InitStructure.EXTI_Line = EXTI_Line16;
  366. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  367. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  368. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  369. EXTI_Init(&EXTI_InitStructure);
  370. // Enable the PVD Interrupt
  371. NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;
  372. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  373. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  374. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  375. NVIC_Init(&NVIC_InitStructure);
  376. // Configure the PVD Level to 2.2V
  377. PWR_PVDLevelConfig(PWR_PVDLevel_2V2);//配置pvd电压等级.当电压小于2.2V的时候产生中断
  378. // Enable the PVD Output
  379. PWR_PVDCmd(ENABLE);
  380. }
  381. void runInit(void) {
  382. runSetupPVD();
  383. runSetConstants();
  384. runMode = p[STARTUP_MODE];//启动 运行模式
  385. //系统tickcount时钟
  386. SysTick_Config(SystemCoreClock / 1000); // 1ms
  387. NVIC_SetPriority(SysTick_IRQn, 2); // lower priority
  388. // setup hardware watchdog
  389. runIWDGInit(20);
  390. }
  391. #define RUN_CURRENT_ITERM 1.0f
  392. #define RUN_CURRENT_PTERM 10.0f
  393. #define RUN_MAX_DUTY_INCREASE 1.0f
  394. float currentIState;
  395. //根据PID计算出PWM占空比的值
  396. static int32_t runCurrentPID(int32_t duty) {
  397. float error;
  398. float pTerm, iTerm;
  399. error = avgAmps - p[MAX_CURRENT];
  400. currentIState += error;
  401. if (currentIState < 0.0f)
  402. currentIState = 0.0f;
  403. iTerm = currentIState * RUN_CURRENT_ITERM;
  404. pTerm = error * RUN_CURRENT_PTERM;
  405. if (pTerm < 0.0f)
  406. pTerm = 0.0f;
  407. duty = duty - iTerm - pTerm;
  408. if (duty < 0)
  409. duty = 0;
  410. return duty;
  411. }
  412. //计算得到实际的占空比fetActualDutyCycle
  413. //参数duty:实际上就是fetDutyCycle传递进来的.想要运行的周期
  414. static void runThrotLim(int32_t duty)
  415. {
  416. float maxVolts; //最大的电压
  417. int32_t maxDuty;//最大的周期
  418. // only if a limit is set
  419. if (p[MAX_CURRENT] > 0.0f)
  420. {
  421. //如果实际的占空比和设置的占空比不一样.那么会实时改变CPU的PWM寄存器.
  422. // if current limiter is calibrated - best performance 使用电流限制器校准.性能最好
  423. if (p[CL1TERM] != 0.0f)
  424. {
  425. maxVolts = p[CL1TERM] + p[CL2TERM]*rpm + p[CL3TERM]*p[MAX_CURRENT] + p[CL4TERM]*rpm*maxCurrentSQRT + p[CL5TERM]*maxCurrentSQRT;
  426. maxDuty = maxVolts * (fetPeriod / avgVolts);
  427. if (duty > maxDuty)
  428. fetActualDutyCycle = maxDuty;
  429. else
  430. fetActualDutyCycle = duty;
  431. }
  432. // otherwise, use PID - less accurate, lower performance 使用PID来计算.不大准确.性能低
  433. else
  434. {
  435. fetActualDutyCycle += fetPeriod * (RUN_MAX_DUTY_INCREASE * 0.01f);
  436. if (fetActualDutyCycle > duty)
  437. fetActualDutyCycle = duty;
  438. fetActualDutyCycle = runCurrentPID(fetActualDutyCycle);//用PID来计算出当前要运行的占空比
  439. }
  440. }
  441. else {
  442. fetActualDutyCycle = duty;
  443. }
  444. //设置到CPU寄存器里.算出来的实际PWM占空比
  445. _fetSetDutyCycle(fetActualDutyCycle);
  446. }
  447. //系统tickcount中断
  448. void SysTick_Handler(void) {
  449. // reload the hardware watchdog
  450. runFeedIWDG();
  451. avgVolts = adcAvgVolts * ADC_TO_VOLTS; //转换后的电池电压(一般是12V) = ADC采集电压原始值 * 电压算法
  452. avgAmps = (adcAvgAmps - adcAmpsOffset) * adcToAmps; //平均电流 = (当前电流 - 停止时候的电流) * 转换公式
  453. maxAmps = (adcMaxAmps - adcAmpsOffset) * adcToAmps; //最大电流 = (最大电流 - 停止时候的电流) * 转换公式
  454. if (runMode == SERVO_MODE)
  455. {
  456. //伺服模式
  457. fetUpdateServo();
  458. }
  459. else
  460. {
  461. runWatchDog();//检测电调的状态.做出相应的停机处理
  462. runRpm(); //计算RPM,计算PID,设置运行PWM占空比
  463. runThrotLim(fetDutyCycle);//计算得到实际PWM占空比.如果有偏差.那么在这里会实时改变PWM的占空比值
  464. }
  465. //计算空闲时间百分比 通过串口发送给上位机 没什么用途
  466. idlePercent = 100.0f * (idleCounter-oldIdleCounter) * minCycles / totalCycles;
  467. // 空闲时间百分比 = 100 * (本次循环次数 - 上次循环次数) * 最小周期 / 总共周期
  468. oldIdleCounter = idleCounter;
  469. totalCycles = 0;
  470. //处理串口数据 和串口交互使用的
  471. if (commandMode == CLI_MODE)
  472. cliCheck(); //ascii模式
  473. else
  474. binaryCheck(); //二进制模式
  475. runMilis++;
  476. }
  477. //低电压中断
  478. void PVD_IRQHandler(void) {
  479. // voltage dropping too low
  480. if (EXTI_GetITStatus(EXTI_Line16) != RESET) {
  481. // shut everything down
  482. runDisarm(REASON_LOW_VOLTAGE);
  483. // turn on both LEDs
  484. digitalLo(statusLed);
  485. digitalLo(errorLed);
  486. EXTI_ClearITPendingBit(EXTI_Line16);
  487. }
  488. }
  489. void runSetConstants(void) {
  490. int32_t startupMode = (int)p[STARTUP_MODE];
  491. float maxCurrent = p[MAX_CURRENT];
  492. //运行模式
  493. if (startupMode < 0 || startupMode >= NUM_RUN_MODES)
  494. startupMode = 0;
  495. if (maxCurrent > RUN_MAX_MAX_CURRENT)
  496. maxCurrent = RUN_MAX_MAX_CURRENT;
  497. else if (maxCurrent < RUN_MIN_MAX_CURRENT)
  498. maxCurrent = RUN_MIN_MAX_CURRENT;
  499. runRPMFactor = (1e6f * (float)TIMER_MULT * 120.0f) / (p[MOTOR_POLES] * 6.0f);
  500. maxCurrentSQRT = sqrtf(maxCurrent);
  501. p[MOTOR_POLES] = (int)p[MOTOR_POLES];
  502. p[STARTUP_MODE] = startupMode;
  503. p[MAX_CURRENT] = maxCurrent;
  504. // Calculate MAX_THRUST from PWM_RPM_SCALE (which is MAX_RPM) and THRxTERMs
  505. // Based on "thrust = rpm * a1 + rpm^2 * a2"
  506. maxThrust = p[PWM_RPM_SCALE] * p[THR1TERM] + p[PWM_RPM_SCALE] * p[PWM_RPM_SCALE] * p[THR2TERM];
  507. }

4、资料清单

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/401643
推荐阅读
相关标签
  

闽ICP备14008679号