ESC32硬件---PCB小結(第一版) Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
0.png (53.61 KB, 下載次數: 128)
下載附件
2018-7-20 17:51 上傳
0.png (97.18 KB, 下載次數: 146)
下載附件
2018-7-20 17:51 上傳
0.png (19.17 KB, 下載次數: 127)
下載附件
2018-7-20 17:50 上傳
0.png (38.6 KB, 下載次數: 124)
下載附件
2018-7-20 17:51 上傳
經過一個星期的畫PCB,今天終于化了,整體看上去還比較滿意,具體的性能還得等后期制板、測試才知道。 這個電路屬于低頻功率型板,相對高頻板信號質量就要求不高了,所以也就不用考慮信號完整性等問題了。 等完成原理圖的設計之后,我就請教了好幾個人,在布線的時候需要注意的事項,但是沒有得到什么有價值的答案,原因是他們不了解我,只是站在自己的去看待這件事了,所以對于他們就沒什么難度了。 在原理圖的設計時,參照了“阿嘉”和“六哥”的方案,大體沒有太大的改動(六哥的已經商品化,相對有保證),只是完善了自己的接口和一些器件的選型。對于原理圖的分析請看前兩篇博客,有什么不對的地方歡迎指出。 原理圖設計完成之后,接下來就是為各個器件添加封裝了。這個過程我檢查的還是比較仔細的,因為上次已經在這里出現過一次問題了。對于電阻,電容的封裝大體選用0603,對于個別選用0805。對于重要的器件,參考了數據手冊和IPC-7351進行選擇,應該不會有問題。 接下來就是導入網表,開始布局。相對來說這個比較簡單所以布局也就比較隨意,基本原則就是按照功能模塊進行布局的。在布線的時候我更比較隨意了,也不想什么規則。當布到一半的時候,好多走線都無法完成了,連打過孔的機會都不給我了。我想肯定是出問題了,應該是布局的問題,大概看這個圖看了一天,光看不畫,看看哪里出問題了。于是就開始了第二版,有了第一次的不順利,第二次自然就順利了很多。大概用了不到一個星期就畫完了,這個圖我自己看上去很是滿意。 前面這些跟流水賬似的,沒有什么實質性的意思。 在畫之前我就找好了人幫我檢查這個圖了,周五我把圖發給我了相思谷(一個網友),把幫我之處了很多問題,下面就總結一下問題。 1、線間距。 這里應該遵循3W規則,所謂3W就是為了減少線間串擾,應保證線間距足夠大,當線中心不少于3倍線寬,則可 保持70%的電場不互相干擾。如要達到98%的電場不互相干擾,可使用10W的間距。——這是查閱華為PCB布線規則所得。 這里我就沒有遵循這個原則,我的線間距大概只有1倍線寬。 2、電源線過細。 這里我查閱了華為PCB教程得到了下面一個表格。這里線寬跟所能承受最大電流的關系表 3、電源環路。(用圖說明) 高亮部分的GND形成了一個環路而且是一個嚴重的閉環。在看看VS電源線環路 這是VS電源線沒有閉環,但是接近閉環了。
這里我就困惑了,如果整體敷銅接地,那在敷銅層也是閉環的GND,而且整體敷銅可增強抗干擾的能力。 這個問題“相思谷”沒有給我解答清楚。他讓我查閱一下資料,我查閱了很多資料最終未果。于是翻看自己的QQ好友看看誰能幫助我,看后傻了,全是軟件的,硬件方面的就有貓大,還沒在線。這時候突然想起了流星趕月了,這是個大神。于是就翻看貓大的群就找他了,還不錯這人挺熱心。下面就看看他的問題吧。 電源環路沒有問題,主要是低阻抗,電調的板子電流很多,不敷銅不合適。他又指出控制部分形成環路確實不好,線上分布電感明顯,應該盡量保證單面敷銅連續,就是盡量保證不出現死銅。我的電源環路最要是走線環路,沒有平面,是阻抗。
聽完他說的我還沒懂,只是迷迷糊糊有個印象。在繼續深問就會顯得自己弱智了,我也含糊的問答了一下,想不太明白,我在看看。這個原因剩下的就是繼續查資料吧。 在《電路設計技術與技巧》這本書中寫到:“地回路”會孕育一個低頻的電磁干擾。磁場在一個環形的、封閉的電路中,感應出一個感應電流。還有導線的低頻等效模型是一個電阻,由于高阻抗的作用,各個GND值就有會有壓差,而不是一個值了。這里指出了一個規則:永遠采用分社的電源地線,用不同的導線來分別承載由每個電源所提供的電源。如圖: 與使用分開的地線的原因相同:使用一條公用的電源供給線,會在電源電壓上形成一個公共的串聯電壓降,只是這里被加入到了電源供給線上。 我還問了他布線的技巧,讓他給我推薦一些資料。這個問題他給我的為回答是:整體鋪地,單點接地。雙層板要調整元件布局,使各個元件接地路勁最短,且地平面集中。泛泛看資料作用不大,很難推薦,布線技巧不是靠臨時看書就可以解決的,需要實際操練。 他的回答很簡單,但是很受用,解決了我好多困惑。 這些就是針對相思谷提出問題的理論補充了,看起來問題很是蠻多的,于是決定重新布局再畫一版。針對這次畫板,我打算請多個人檢查,初步打算有相思谷,華航申老師,貓大、流星。第一版的相思谷已經初驗了,還有工程已經發給申老師了還沒給我回復呢。第二版再去找貓大跟流星,針對他們提出的問題進行總結,然后修改。最后在拿去找老師檢查。估計周一申老師就會檢查完,到時候在把他提出的問題進行總結。 總結:上面檢查的方式太局限了,但這是非常有效的方法。通過他們的檢查我可以充分補充理論知識,而且這些人尤其是貓大跟流星在硬件方面的造詣很深。結識他們就相當找到了一個柱子,順著他們向上爬吧。這種方法是我看于爭的視頻想到的方法。他們的經驗轉換化自己的經驗,相信通過這兩天電路板肯定幫我在低頻電路設計提升一個層次。同時在跟他們的交流過程中發現了一個問題,貓大跟流星的理論基礎太厚了,他們很說空經驗,他們的經驗全是有理論支撐的。這個正好符合了于爭視頻的快速積累經驗的理論。
- /*
- This file is part of AutoQuad ESC32.
- AutoQuad ESC32 is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- AutoQuad ESC32 is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with AutoQuad ESC32. If not, see
- Copyright © 2011, 2012, 2013 Bill Nesbitt
- */
- #include "run.h"
- #include "main.h"
- #include "timer.h"
- #include "adc.h"
- #include "fet.h"
- #include "pwm.h"
- #include "cli.h"
- #include "binary.h"
- #include "config.h"
- #include "misc.h"
- #include "stm32f10x_exti.h"
- #include "stm32f10x_pwr.h"
- #include "stm32f10x_iwdg.h"
- #include "stm32f10x_dbgmcu.h"
- #include <math.h>
- uint32_t runMilis; //systick中斷中自加.沒有什么控制用途
- static uint32_t oldIdleCounter; //上次main函數中,死循環次數.
- float idlePercent; //空閑時間百分比(在main循環里,什么事情也不做.main死循環運行的時間)
- float avgAmps, maxAmps; //平均電流, 最大電流
- float avgVolts; //當前ADC采集轉換后的電池電壓(也就是12v)
- float rpm; //當前轉速(1分鐘多少轉) 測量值 在runRpm函數中計算出來.在runThrotLim中還要繼續使用.
- float targetRpm; //目標轉速 設定值(只在閉環 或 閉環推力模式下使用此變量)
- static float rpmI;
- static float runRPMFactor;
- static float maxCurrentSQRT; //最大電流 平方根 后
- uint8_t disarmReason;//此變量沒啥作用.只用于給上位機顯示當前的 調試代碼(或者說停止電機的原因)
- uint8_t commandMode; //串口通訊的模式, cli是ascii模式, binary是二進制通訊模式
- static uint8_t runArmCount;
- volatile uint8_t runMode;//運行模式 (開環模式, RPM模式, 推力模式, 伺服模式)
- static float maxThrust;
- //執行看門狗喂狗
- void runFeedIWDG(void) {
- #ifdef RUN_ENABLE_IWDG
- IWDG_ReloadCounter();
- #endif
- }
- // setup the hardware independent watchdog
- // 初始化并開啟獨立看門狗
- uint16_t runIWDGInit(int ms)
- {
- #ifndef RUN_ENABLE_IWDG
- return 0;
- #else
- uint16_t prevReloadVal;
- int reloadVal;
- IWDG_ReloadCounter();//喂狗
- DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);//當在jtag調試的時候.停止看門狗
- // IWDG timeout equal to 10 ms (the timeout may varies due to LSI frequency dispersion)
- // Enable write access to IWDG_PR and IWDG_RLR registers
- IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//允許訪問IWDG_PR和IWDG_RLR寄存器
- // IWDG counter clock: LSI/4
- IWDG_SetPrescaler(IWDG_Prescaler_4);
- // Set counter reload value to obtain 10ms IWDG TimeOut.
- // Counter Reload Value = 10ms/IWDG counter clock period
- // = 10ms / (RUN_LSI_FREQ/4)
- // = 0.01s / (RUN_LSI_FREQ/4)
- // = RUN_LSI_FREQ/(4 * 100)
- // = RUN_LSI_FREQ/400
- reloadVal = RUN_LSI_FREQ*ms/4000;
- if (reloadVal < 1)
- reloadVal = 1;
- else if (reloadVal > 0xfff)
- reloadVal = 0xfff;
- prevReloadVal = IWDG->RLR;
- IWDG_SetReload(reloadVal);
- // Reload IWDG counter
- IWDG_ReloadCounter();
- // Enable IWDG (the LSI oscillator will be enabled by hardware)
- IWDG_Enable();
- return (prevReloadVal*4000/RUN_LSI_FREQ);
- #endif
- }
- //esc32 非正常停止運行 進入初始化
- void runDisarm(int reason) {
- fetSetDutyCycle(0); //fet占空比設置為0
- timerCancelAlarm2();
- state = ESC_STATE_DISARMED;
- pwmIsrAllOn();
- digitalHi(statusLed); // turn off
- digitalLo(errorLed); // turn on
- disarmReason = reason; // 設置停機原因.給上位機查看狀態使用
- }
- //手動運行
- void runArm(void) {
- int i;
- fetSetDutyCycle(0);
- timerCancelAlarm2();
- digitalHi(errorLed);
- digitalLo(statusLed); // turn on
- if (runMode == SERVO_MODE) {
- state = ESC_STATE_RUNNING;
- }
- else {
- state = ESC_STATE_STOPPED;
- if (inputMode == ESC_INPUT_UART)
- runMode = OPEN_LOOP;
- fetSetBraking(0);
- }
- // extra beeps signifying run mode
- for (i = 0; i < runMode + 1; i++) {
- fetBeep(250, 600);
- timerDelay(10000);
- }
- // fetBeep(150, 800);
- }
- //電機開始運行
- void runStart(void) {
- // reset integral bevore new motor startup
- runRpmPIDReset();//先復位I值
- if ((p[START_ALIGN_TIME] == 0) && (p[START_STEPS_NUM] == 0)) {
- state = ESC_STATE_STARTING; //設置為準備啟動狀態
- fetStartCommutation(0);//換向啟動
- }
- else {
- motorStartSeqInit();//普通啟動
- }
- }
- //電機停止運行
- void runStop(void) {
- runMode = OPEN_LOOP;
- fetSetDutyCycle(0);
- }
- //設置運行的占空比 duty = 0~100
- uint8_t runDuty(float duty) {
- uint8_t ret = 0;
- if (duty >= 0.0f || duty <= 100.0f) {
- runMode = OPEN_LOOP;
- fetSetBraking(0);
- fetSetDutyCycle((uint16_t)(fetPeriod*duty*0.01f));//最大周期 * 占空比(0~100) / 100
- ret = 1;
- }
- return ret;
- }
- //pwm.c中斷中調用 或 串口命令輸入調用
- void runNewInput(uint16_t setpoint) {
- static uint16_t lastPwm;
- static float filteredSetpoint = 0;
- // Lowpass Input if configured
- // TODO: Make lowpass independent from pwm update rate
- if (p[PWM_LOWPASS]) {
- filteredSetpoint = (p[PWM_LOWPASS] * filteredSetpoint + (float)setpoint) / (1.0f + p[PWM_LOWPASS]);
- setpoint = filteredSetpoint;
- }
- if (state == ESC_STATE_RUNNING && setpoint != lastPwm)
- {
- if (runMode == OPEN_LOOP)
- {
- //開環模式
- fetSetDutyCycle(fetPeriod * (int32_t)(setpoint-pwmLoValue) / (int32_t)(pwmHiValue - pwmLoValue));
- }
- else if (runMode == CLOSED_LOOP_RPM)
- {
- //閉環轉速模式
- float target = p[PWM_RPM_SCALE] * (setpoint-pwmLoValue) / (pwmHiValue - pwmLoValue);
- // limit to configured maximum
- targetRpm = (target > p[PWM_RPM_SCALE]) ? p[PWM_RPM_SCALE] : target;
- }
- // THRUST Mode
- else if (runMode == CLOSED_LOOP_THRUST)
- {
- //閉環推力模式
- float targetThrust; // desired trust
- float target; // target(rpm)
- // Calculate targetThrust based on input and MAX_THRUST
- targetThrust = maxThrust * (setpoint-pwmLoValue) / (pwmHiValue - pwmLoValue);
- // Workaraound: Negative targetThrust will screw up sqrtf() and create MAX_RPM on throttle min. Dangerous!
- if (targetThrust > 0.0f) {
- // Calculate target(rpm) based on targetThrust
- target = ((sqrtf(p[THR1TERM] * p[THR1TERM] + 4.0f * p[THR2TERM] * targetThrust) - p[THR1TERM] ) / ( 2.0f * p[THR2TERM] ));
- }
- // targetThrust is negative (pwm_in < pwmLoValue)
- else {
- target = 0.0f;
- }
- // upper limit for targetRpm is configured maximum PWM_RPM_SCALE (which is MAX_RPM)
- targetRpm = (target > p[PWM_RPM_SCALE]) ? p[PWM_RPM_SCALE] : target;
- }
- else if (runMode == SERVO_MODE)
- {
- //伺服模式下
- fetSetAngleFromPwm(setpoint);
- }
- lastPwm = setpoint;
- }
- else if ((state == ESC_STATE_NOCOMM || state == ESC_STATE_STARTING) && setpoint <= pwmLoValue)
- {
- fetSetDutyCycle(0);
- state = ESC_STATE_RUNNING;
- }
- else if (state == ESC_STATE_DISARMED && setpoint > pwmMinValue && setpoint <= pwmLoValue)
- {
- runArmCount++;
- if (runArmCount > RUN_ARM_COUNT)
- runArm();
- }
- else {
- runArmCount = 0;
- }
- if (state == ESC_STATE_STOPPED && setpoint >= pwmMinStart) {
- //電機開始運行
- runStart();
- }
- }
- //電調運行看門狗. 主要是判斷電調的當前一些狀態.做出停機等處理
- static void runWatchDog(void)
- {
- register uint32_t t, d, p;
- //__asm volatile ("cpsid i");
- //CPSID_I();
- __disable_irq();
- t = timerMicros; //當前的系統tick時間
- d = detectedCrossing;
- p = pwmValidMicros; //在PWM輸入模式下.把timerMicros的時間賦值給此變量
- //__asm volatile ("cpsie i");
- //CPSIE_I();
- __enable_irq();
- if (state == ESC_STATE_STARTING && fetGoodDetects > fetStartDetects) //這里要檢測到fetStartDetects好的檢測,才允許切換電機狀態
- {
- //是啟動狀態.切換到 運行狀態
- state = ESC_STATE_RUNNING;
- digitalHi(statusLed); // turn off
- }
- else if (state >= ESC_STATE_STOPPED)
- {
- //運行模式狀態下.會一直在這里檢測狀態.如果狀態不對出錯.會調用runDisarm函數停止
- // running or starting
- d = (t >= d) ? (t - d) : (TIMER_MASK - d + t);
- // timeout if PWM signal disappears
- if (inputMode == ESC_INPUT_PWM)
- {
- //PWM模式 判斷PWM輸入是否超時
- p = (t >= p) ? (t - p) : (TIMER_MASK - p + t);
- if (p > PWM_TIMEOUT)
- runDisarm(REASON_PWM_TIMEOUT);//pwm輸入超時
- }
- if (state >= ESC_STATE_STARTING && d > ADC_CROSSING_TIMEOUT)
- {
- if (fetDutyCycle > 0) {
- runDisarm(REASON_CROSSING_TIMEOUT);//錯誤停止
- }
- else
- {
- runArm();//手動運行起來
- pwmIsrRunOn();//PWM開啟輸入比較
- }
- }
- else if (state >= ESC_STATE_STARTING && fetBadDetects > fetDisarmDetects) //運行狀態中 檢測到錯誤的個數后.進入這個判斷
- {
- //在運行過程中,出現錯誤.停止運行
- if (fetDutyCycle > 0)
- runDisarm(REASON_BAD_DETECTS);//錯誤停止
- }
- else if (state == ESC_STATE_STOPPED)
- {
- //停止模式
- adcAmpsOffset = adcAvgAmps; // record current amperage offset
- }
- }
- else if (state == ESC_STATE_DISARMED && !(runMilis % 100))
- {
- //停止模式下
- adcAmpsOffset = adcAvgAmps; // record current amperage offset
- digitalTogg(errorLed);
- }
- }
- void runRpmPIDReset(void) {
- rpmI = 0.0f;
- }
- //這個應該是計算PID
- //rpm:測量的轉速值
- //target:目標的轉速值
- static int32_t runRpmPID(float rpm, float target) {
- float error;
- float ff, rpmP;
- float iTerm = rpmI;
- float output;
- // feed forward
- ff = ((target*target* p[FF1TERM] + target*p[FF2TERM]) / avgVolts) * fetPeriod;
- error = (target - rpm);//計算出偏差
- if (error > 1000.0f)
- error = 1000.0f;
- if (error > 0.0f) {
- rpmP = error * p[PTERM]; //P
- rpmI += error * p[ITERM]; //I
- }
- else {
- rpmP = error * p[PTERM] * p[PNFAC];
- rpmI += error * p[ITERM] * p[INFAC];
- }
- if (fetBrakingEnabled)
- {
- //開啟了制動模式
- if (rpm < 300.0f) {
- fetSetBraking(0);
- }
- else if (error <= -100.0f) {
- fetSetBraking(1);
- }
- else if (fetBraking && error > -25.0f){
- fetSetBraking(0);
- }
- }
- output = ff + (rpmP + rpmI) * (1.0f / 1500.0f) * fetPeriod;
- // don't allow integral to continue to rise if at max output
- if (output >= fetPeriod)
- rpmI = iTerm;
- return output;
- }
- //計算出電機轉速,根據當前轉速計算出PID輸出值,設置占空比
- static uint8_t runRpm(void)
- {
- if (state > ESC_STATE_STARTING)
- {
- //電機處于運行狀態 計算出當前轉速rpm
- // rpm = rpm * 0.90f + (runRPMFactor / (float)crossingPeriod) * 0.10f;
- // rpm -= (rpm - (runRPMFactor / (float)crossingPeriod)) * 0.25f;
- // rpm = (rpm + (runRPMFactor / (float)crossingPeriod)) * 0.5f;
- // rpm = (rpm + ((32768.0f * runRPMFactor) / (float)adcCrossingPeriod)) * 0.5f; // increased resolution, fixed filter here
- rpm = p[RPM_MEAS_LP] * rpm + ((32768.0f * runRPMFactor) / (float)adcCrossingPeriod) * (1.0f - p[RPM_MEAS_LP]); // increased resolution, variable filter here
- // run closed loop control
- if (runMode == CLOSED_LOOP_RPM)
- {
- //運行在閉環模式下
- fetSetDutyCycle(runRpmPID(rpm, targetRpm));
- return 1;
- }
- // run closed loop control also for THRUST mode
- else if (runMode == CLOSED_LOOP_THRUST)
- {
- //運行在閉環推力模式
- fetSetDutyCycle(runRpmPID(rpm, targetRpm));
- return 1;
- }
- else
- {
- return 0;
- }
- }
- else
- {
- //電機在停止狀態下
- rpm = 0.0f;
- return 0;
- }
- }
- static void runSetupPVD(void) {
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- // Configure EXTI Line16(PVD Output) to generate an interrupt on rising and falling edges
- EXTI_ClearITPendingBit(EXTI_Line16);
- EXTI_InitStructure.EXTI_Line = EXTI_Line16;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure);
- // Enable the PVD Interrupt
- NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- // Configure the PVD Level to 2.2V
- PWR_PVDLevelConfig(PWR_PVDLevel_2V2);//配置pvd電壓等級.當電壓小于2.2V的時候產生中斷
- // Enable the PVD Output
- PWR_PVDCmd(ENABLE);
- }
- void runInit(void) {
- runSetupPVD();
- runSetConstants();
- runMode = p[STARTUP_MODE];//啟動 運行模式
- //系統tickcount時鐘
- SysTick_Config(SystemCoreClock / 1000); // 1ms
- NVIC_SetPriority(SysTick_IRQn, 2); // lower priority
- // setup hardware watchdog
- runIWDGInit(20);
- }
- #define RUN_CURRENT_ITERM 1.0f
- #define RUN_CURRENT_PTERM 10.0f
- #define RUN_MAX_DUTY_INCREASE 1.0f
- float currentIState;
- //根據PID計算出PWM占空比的值
- static int32_t runCurrentPID(int32_t duty) {
- float error;
- float pTerm, iTerm;
- error = avgAmps - p[MAX_CURRENT];
- currentIState += error;
- if (currentIState < 0.0f)
- currentIState = 0.0f;
- iTerm = currentIState * RUN_CURRENT_ITERM;
- pTerm = error * RUN_CURRENT_PTERM;
- if (pTerm < 0.0f)
- pTerm = 0.0f;
- duty = duty - iTerm - pTerm;
- if (duty < 0)
- duty = 0;
- return duty;
- }
- //計算得到實際的占空比fetActualDutyCycle
- //參數duty:實際上就是fetDutyCycle傳遞進來的.想要運行的周期
- static void runThrotLim(int32_t duty)
- {
- float maxVolts; //最大的電壓
- int32_t maxDuty;//最大的周期
- // only if a limit is set
- if (p[MAX_CURRENT] > 0.0f)
- {
- //如果實際的占空比和設置的占空比不一樣.那么會實時改變CPU的PWM寄存器.
- // if current limiter is calibrated - best performance 使用電流限制器校準.性能最好
- if (p[CL1TERM] != 0.0f)
- {
- maxVolts = p[CL1TERM] + p[CL2TERM]*rpm + p[CL3TERM]*p[MAX_CURRENT] + p[CL4TERM]*rpm*maxCurrentSQRT + p[CL5TERM]*maxCurrentSQRT;
- maxDuty = maxVolts * (fetPeriod / avgVolts);
- if (duty > maxDuty)
- fetActualDutyCycle = maxDuty;
- else
- fetActualDutyCycle = duty;
- }
- // otherwise, use PID - less accurate, lower performance 使用PID來計算.不大準確.性能低
- else
- {
- fetActualDutyCycle += fetPeriod * (RUN_MAX_DUTY_INCREASE * 0.01f);
- if (fetActualDutyCycle > duty)
- fetActualDutyCycle = duty;
- fetActualDutyCycle = runCurrentPID(fetActualDutyCycle);//用PID來計算出當前要運行的占空比
- }
- }
- else {
- fetActualDutyCycle = duty;
- }
- //設置到CPU寄存器里.算出來的實際PWM占空比
- _fetSetDutyCycle(fetActualDutyCycle);
- }
- //系統tickcount中斷
- void SysTick_Handler(void) {
- // reload the hardware watchdog
- runFeedIWDG();
- avgVolts = adcAvgVolts * ADC_TO_VOLTS; //轉換后的電池電壓(一般是12V) = ADC采集電壓原始值 * 電壓算法
- avgAmps = (adcAvgAmps - adcAmpsOffset) * adcToAmps; //平均電流 = (當前電流 - 停止時候的電流) * 轉換公式
- maxAmps = (adcMaxAmps - adcAmpsOffset) * adcToAmps; //最大電流 = (最大電流 - 停止時候的電流) * 轉換公式
- if (runMode == SERVO_MODE)
- {
- //伺服模式
- fetUpdateServo();
- }
- else
- {
- runWatchDog();//檢測電調的狀態.做出相應的停機處理
- runRpm(); //計算RPM,計算PID,設置運行PWM占空比
- runThrotLim(fetDutyCycle);//計算得到實際PWM占空比.如果有偏差.那么在這里會實時改變PWM的占空比值
- }
- //計算空閑時間百分比 通過串口發送給上位機 沒什么用途
- idlePercent = 100.0f * (idleCounter-oldIdleCounter) * minCycles / totalCycles;
- // 空閑時間百分比 = 100 * (本次循環次數 - 上次循環次數) * 最小周期 / 總共周期
- oldIdleCounter = idleCounter;
- totalCycles = 0;
- //處理串口數據 和串口交互使用的
- if (commandMode == CLI_MODE)
- cliCheck(); //ascii模式
- else
- binaryCheck(); //二進制模式
- runMilis++;
- }
- //低電壓中斷
- void PVD_IRQHandler(void) {
- // voltage dropping too low
- if (EXTI_GetITStatus(EXTI_Line16) != RESET) {
- // shut everything down
- runDisarm(REASON_LOW_VOLTAGE);
- // turn on both LEDs
- digitalLo(statusLed);
- digitalLo(errorLed);
- EXTI_ClearITPendingBit(EXTI_Line16);
- }
- }
- void runSetConstants(void) {
- int32_t startupMode = (int)p[STARTUP_MODE];
- float maxCurrent = p[MAX_CURRENT];
- //運行模式
- if (startupMode < 0 || startupMode >= NUM_RUN_MODES)
- startupMode = 0;
- if (maxCurrent > RUN_MAX_MAX_CURRENT)
- maxCurrent = RUN_MAX_MAX_CURRENT;
- else if (maxCurrent < RUN_MIN_MAX_CURRENT)
- maxCurrent = RUN_MIN_MAX_CURRENT;
- runRPMFactor = (1e6f * (float)TIMER_MULT * 120.0f) / (p[MOTOR_POLES] * 6.0f);
- maxCurrentSQRT = sqrtf(maxCurrent);
- p[MOTOR_POLES] = (int)p[MOTOR_POLES];
- p[STARTUP_MODE] = startupMode;
- p[MAX_CURRENT] = maxCurrent;
- // Calculate MAX_THRUST from PWM_RPM_SCALE (which is MAX_RPM) and THRxTERMs
- // Based on "thrust = rpm * a1 + rpm^2 * a2"
- maxThrust = p[PWM_RPM_SCALE] * p[THR1TERM] + p[PWM_RPM_SCALE] * p[PWM_RPM_SCALE] * p[THR2TERM];
- }
復制代碼
全部資料51hei下載地址:
相關設計文檔.zip
(7.71 MB, 下載次數: 643)
2018-7-21 03:20 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
ESC32 流程圖.rar
(68.45 KB, 下載次數: 612)
2018-7-21 03:20 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|