---
# System prepended metadata

title: 1231動推

---

# 1231動推
[TOC]
### 目的
上次動推過程混亂、不夠嚴謹，這次計畫好後再次進行測試

### 儀器設備
* 推測平台本體與校正裝置
* AT3530馬達
* 14×7槳
* 電變:hobbywing 100A
* pixhawk 板
* 電流電壓調整裝置(電阻)
* 電流測量連接器
* 安裝推測軟體的筆電
* 6s 3300mAh、10000mAh、4200mAh 滿電電池
* 電池延長線
* 電路板接電腦的線
* c型夾
* 100A保險絲
* 小木塊(用來夾C型夾)

### 步驟
#### 木工廠預備
1. 確認要測的電池電量滿電
2. 將pixhawk接上電腦和電阻，使用QGround校正電壓和電流
3. 校正好推測平台
4. 使用舊電池簡單測試過一遍
#### 實驗室實驗
1. 裝置固定好
3. 推測平台、PIXHAWK接上電腦
4. 開啟QGROUND
5. 確認連接上PIXHAWK
6. 淨空，電腦操作員與預備拔電池人員就位
7. 馬達接上電源
8. 確認QGROUND有無報錯(先前實驗已關閉GPS和磁力計，compass報錯不用管)
9. 確認推測平台是否當掉(數值是否持續為0沒有變化)
10. QGROUND 切為 ARMED
11. 切到控制馬達頁面
12. 開始記錄數值(確認正在連續紀錄)
13. 手動拉油門到預備油門(50%，風速20m/s時為60%)
14. 馬達穩定後開啟風洞
15. 等待空速計穩定後再將馬達依設定拉至100%再拉至預備油門)
> [name=20林佳佑]要不要統一等待15秒方便資料分析
16. 馬達穩定後關閉風洞
17. 將馬達拉至0%
18. 確認馬達停止運作
19. 結束推測平台連續紀錄
20. QGROUND 切為 DISARMED
21. 拔電池
22. 拔電路板的線
23. 資料分析(每次做完一組數據紀錄時間、測試項目和下載log檔)

### 設定
風洞風速 :
1. 10 m/s
2. 15 m/s
3. 20 m/s

油門設定 : 
:::info 油門設定：
* 油門 秒數
* 預備油門 (開啟風洞)
* 等待空速計穩定
* 70% 3sec
* 80% 3sec
* 90% 3sec
* 100% 10sec
* 90% 3sec
* 80% 3sec
* 70% 3sec
* 預備油門 3sec
* 關閉風洞
* 0%
:::
* 預計實驗時間 46 秒 (假設等待空速計穩定花費15秒)
### 過程
* 風速10-1
    * 時間: 15:57
    * 風速: 10
    * 電池(電量變化): 4200(98%~83% (85%))
    * 測試過程描述: 
* 風速15-1
    * 時間: 16:05
    * 風速: 15
    * 電池(電量變化): 10000(99%~89%)
    * 測試過程描述:
* 風速20
    * 時間: 16:14
    * 風速: 20
    * 電池(電量變化):3300(99%~86%)
    * 測試過程描述:失敗

* 風速20-1
    * 時間: 16:21
    * 風速: 20
    * 電池(電量變化):3300(85%~55% (62%))
    * 測試過程描述:

* 風速10-2
    * 時間: 16:26
    * 風速: 10
    * 電池(電量變化):10000(92%~78% (82%))
    * 測試過程描述:

* 風速15-2
    * 時間: 16:36
    * 風速: 15
    * 電池(電量變化):4200(85%~56% (63%))
    * 測試過程描述:

* 風速20-2
    * 時間: 16:45
    * 風速: 20
    * 電池(電量變化):10000(83%~65% (69%))
    * 測試過程描述:

### code
:::spoiler

var test = [ [1400, 3], [1250, 3], [1000, 3]];
var stabilityTolerance = 0.15;
var conti=40;
var maxWaitTime = 25;
var count=0;
var time =0.025;
var settunneltime=0;
var ave=1;
var checkInterval=1;
// Test repeat
var repeat = 1; // set to 1 to run the sequence only once
var ramptime=2;
// ESC initialization
var minVal = 1000;  // ESC initialization value (us)
var initDur = 4; // ESC initialization time (s)
var mid=1300;
var midramptime=5;
var filePrefix = "CustomSequence"; 

///////////////// Beginning of the script //////////////////

// ESC initialization
rcb.console.print("Initializing ESC...");
rcb.output.set("esc",minVal);
rcb.wait(main, initDur);

// hide console debug info
rcb.console.setVerbose(false);

// start new log file
rcb.files.newLogFile({prefix: filePrefix});
var thrust=0;
var unit=0;
// runs the sequence
var index = -1;
var total = repeat;
var totalTime = 0;
var steptimesum=0;
//var utcTime = new Date().getTime();
var recentReadings = [];
var current=0;

var stabilitySamples=40;
var allstartTimestamp = new Date().getTime();
var stableTimestamp=0;
var fluctuation = 0;
var record=function(){rcb.sensors.read(function(data){
                        data.time.displayValue = totalTime;
                        rcb.files.newLogEntry(data);
                        rcb.console.print("sample saved");
                    }, ave);
                    
};
function main(){

function callback(result){
    current = result.current.displayValue;
    unit = result.current.displayUnit;
   rcb.console.print("current: " + current + " " + unit); 
   //recentReadings.push(current);
        
        
    
       //rcb.console.print("diff" + recentReadings[stabilitySamples-1]-recentReadings[0] );
   if(Math.abs(current)>=stabilityTolerance){
            count+=1;
        }else{
            count=0;
        }
        
        // 如果陣列太長，移除最舊的數據 (保持滑動視窗大小)
        
        if ( count >= conti) {
            
            rcb.console.print(">>> 偵測到推力穩定！(波動 < " + stabilityTolerance + ")");
            stableTimestamp = new Date().getTime();
            sequence();
            return;

        } else {
            // 安全機制：檢查是否超時
            if( totalTime> maxWaitTime) {
                rcb.console.print("警告：等待穩定超時");
                rcb.output.ramp("esc",mid, minVal, midramptime );
                rcb.wait(function() {rcb.endScript();
                }, midramptime);
                return;
            } else {
                // 還沒穩定，等待一段時間後再次檢查 (迴圈)
                totalTime=(new Date().getTime() - allstartTimestamp)/1000;
                record();
                rcb.wait(checkStabilityLoop,time);
            }
        }

    }



    

rcb.output.ramp("esc",minVal, mid, midramptime );
    rcb.console.print("油門" +mid+ "%");
    // 呼叫偵測函數
rcb.wait( checkStabilityLoop,midramptime+settunneltime );
function checkStabilityLoop() {
    //rcb.console.print("123");
    // 讀取感應器數據
    rcb.sensors.read(callback,1);
}
function sequence(){
    if(index > -1){
        if(index === test.length){
            // end of sequence
            index = -1;
            sequence();
        }else{
            var elapsed=0;
            var stepduration = test[index][1];
            // get step info
            var pwm = test[index][0];
            var expwm=minVal;
            //test[index-1][0];
            if(index===0){
              rcb.output.ramp("esc", mid, pwm, ramptime );
            }else{
               expwm=test[index-1][0];
               rcb.output.ramp("esc", expwm, pwm, ramptime );
            }
            
             index ++;
            
            rcb.console.print("set esc time" +totalTime + " , " + pwm + " for " + stepduration + "s...");
            
            // set the output
            //
            
            var recordStep=function (){
                if(elapsed >= stepduration+ramptime){
                    //steptimesum+=stepduration;
                    //totalTime=steptimesum;
                    sequence();
                }else{
                    var remaining = stepduration - elapsed;
                    //var waitTime = Math.min(time, remaining);
                    var startTimestamp = new Date().getTime();
                    
                    
                    // take a sample
                    record();
                    var endTimestamp = new Date().getTime();
                    var functiontime=endTimestamp-startTimestamp;
                    elapsed += time;
                    totalTime +=time;
                    //rcb.console.print("sample time" +totalTime+" function time"+functiontime);
                    if(time < (functiontime/1000)*1.1){
                        rcb.output.ramp("esc", pwm, minVal, 5 );
                        rcb.console.print("sample time < function time, sample time has to bigger than " +functiontime/1000+ " ms" );
                        rcb.wait(5);
                        rcb.output.set("esc",minVal);
                        rcb.endScript();
                    }
                    rcb.wait(recordStep,Math.max(0,time-functiontime/1000));
                    }
                };

            recordStep();
        }
    }else{
        if(repeat > 0){
            rcb.console.print("Sequence " + (total-repeat+1) + " of " + total);
            repeat--;
            index++;
            sequence();
        }else{
            var allendTimestamp = new Date().getTime();
            rcb.console.print("real duration:" +(allendTimestamp-allstartTimestamp)/1000);
            rcb.console.print("end time" +totalTime);
            rcb.endScript();
            
        }
    }
}}




:::

:::spoiler


//, [1500, 7], [1700, 5], [1850, 5], [1950, 5], [2000,7], [1750, 5], [1500, 5],
//[[1150, 3], [1250, 5], [1500, 5], [1750, 5], [1850, 3], [1950, 3], [2000,5], [1750, 3], [1500, 3], [1250, 3], [1000, 3]];
var test = [ [1400, 3], [1250, 3], [1000, 3]];
var stabilityTolerance = 1;
var maxWaitTime = 25;
var count=0;
var time =0.025;
var settunneltime=0;
var ave=1;
var checkInterval=1;
// Test repeat
var repeat = 1; // set to 1 to run the sequence only once
var ramptime=2;
// ESC initialization
var minVal = 1000;  // ESC initialization value (us)
var initDur = 4; // ESC initialization time (s)
var mid=1300;
var midramptime=5;
var filePrefix = "CustomSequence"; 

///////////////// Beginning of the script //////////////////

// ESC initialization
rcb.console.print("Initializing ESC...");
rcb.output.set("esc",minVal);
rcb.wait(main, initDur);

// hide console debug info
rcb.console.setVerbose(false);

// start new log file
rcb.files.newLogFile({prefix: filePrefix});
var thrust=0;
var unit=0;
// runs the sequence
var index = -1;
var total = repeat;
var totalTime = 0;
var steptimesum=0;
//var utcTime = new Date().getTime();
var recentReadings = [];

var stabilitySamples=10;
var allstartTimestamp = new Date().getTime();
var stableTimestamp=0;
var fluctuation = 0;
function callback(result){
    thrust = result.thrust.displayValue;
    unit = result.thrust.displayUnit;
   rcb.console.print("Thrust: " + thrust.toPrecision(3) + " " + unit); 
}

function main(){
    
var record=function(){rcb.sensors.read(function(data){
                        data.time.displayValue = totalTime;
                        rcb.files.newLogEntry(data);
                        //rcb.console.print("sample saved");
                    }, ave);
};
rcb.output.ramp("esc",minVal, mid, midramptime );
    rcb.console.print("油門" +mid+ "% - 開始偵測推力穩定度...");
    // 呼叫偵測函數
rcb.wait(
    checkStabilityLoop
,midramptime+settunneltime );
function checkStabilityLoop() {
    rcb.console.print("123");
    // 讀取感應器數據
    rcb.sensors.read(callback,1);
        rcb.console.print(thrust.toPrecision(3));
        if(thrust.toPrecision(3)>stabilityTolerance){
            count+=1;
        }else{
            count=0;
        }
        //recentReadings.push(thrust.toPrecision(3));
        
        // 如果陣列太長，移除最舊的數據 (保持滑動視窗大小)
        
        if ( count >= 10) {
            
            rcb.console.print(">>> 偵測到推力穩定！(波動 < " + stabilityTolerance + ")");
            stableTimestamp = new Date().getTime();
            sequence();

        } else {
            // 安全機制：檢查是否超時
            if( totalTime> maxWaitTime) {
                rcb.console.print("警告：等待穩定超時");
                rcb.output.ramp("esc",mid, minVal, midramptime );
                rcb.wait(function() {rcb.endScript();
                }, midramptime);
                return;
            } else {
                // 還沒穩定，等待一段時間後再次檢查 (迴圈)
                totalTime=(new Date().getTime() - allstartTimestamp)/1000;
                record();
                rcb.wait(checkStabilityLoop, checkInterval);
            }
        }
    }
}
function sequence(){
    if(index > -1){
        if(index === test.length){
            // end of sequence
            index = -1;
            sequence();
        }else{
            var elapsed=0;
            var stepduration = test[index][1];
            // get step info
            var pwm = test[index][0];
            var expwm=minVal;
            //test[index-1][0];
            if(index===0){
              rcb.output.ramp("esc", mid, pwm, ramptime );
            }else{
               expwm=test[index-1][0];
               rcb.output.ramp("esc", expwm, pwm, ramptime );
            }
            
             index ++;
            
            rcb.console.print("set esc time" +totalTime + " , " + pwm + " for " + stepduration + "s...");
            
            // set the output
            //
            
            var recordStep=function (){
                if(elapsed >= stepduration+ramptime){
                    //steptimesum+=stepduration;
                    //totalTime=steptimesum;
                    sequence();
                }else{
                    var remaining = stepduration - elapsed;
                    //var waitTime = Math.min(time, remaining);
                    var startTimestamp = new Date().getTime();
                    
                    
                    // take a sample
                    record();
                    var endTimestamp = new Date().getTime();
                    var functiontime=endTimestamp-startTimestamp;
                    elapsed += time;
                    totalTime +=time;
                    //rcb.console.print("sample time" +totalTime+" function time"+functiontime);
                    if(time < (functiontime/1000)*1.1){
                        rcb.output.ramp("esc", pwm, minVal, 5 );
                        rcb.console.print("sample time < function time, sample time has to bigger than " +functiontime/1000+ " ms" );
                        rcb.wait(5);
                        rcb.output.set("esc",minVal);
                        rcb.endScript();
                    }
                    rcb.wait(recordStep,Math.max(0,time-functiontime/1000));
                    }
                };

            recordStep();
        }
    }else{
        if(repeat > 0){
            rcb.console.print("Sequence " + (total-repeat+1) + " of " + total);
            repeat--;
            index++;
            sequence();
        }else{
            var allendTimestamp = new Date().getTime();
            rcb.console.print("real duration:" +(allendTimestamp-allstartTimestamp)/1000);
            rcb.console.print("end time" +totalTime);
            rcb.endScript();
            
        }
    }
}
:::



### 結果
完啦
1. 不知什麼原因，電流資料未被記錄，無法得知電流與功耗。
2. 對於所有測試，10000mAh推力表現皆較差，其推力不如 4200 or 3300 的新電池
3. 對於唯一一次油門到100%的狀況，其推力並未明顯增加，最大僅 2.9091 kgf(甚至比3300那顆的88%還低)，比AT3530的2827g大不了多少，但沒有功耗資料無法比較其效率

|Thrust|AT3530(100%)|XM5050(88%)|
|--|------|------|
| 0m/s|4686|4554 |
|10m/s|4175|4549 |
|15m/s|3712|3782 |
|20m/s|2827|2910 |
|製造商|4805|4791 |

![image](https://hackmd.io/_uploads/S19uVc8EZl.png)
![image](https://hackmd.io/_uploads/SJuyB5UVbl.png)

### 分析電池壓降


#### 3300:
:::spoiler
可用靜推資料:
> 1203145946
> 1203152250

![image](https://hackmd.io/_uploads/ryync1KEbx.png)
壓降/電流:4.939/53.528
風速20-1:
![image](https://hackmd.io/_uploads/HJwmskYEWx.png)
峰值壓降:5.07 :arrow_right: 峰值電流:54.948 :arrow_right: 峰值功率:1041.8 W
推力:2.9099；power/thrust = 358.0 (W/kg)
:::

#### 10000:
:::spoiler
可用靜推資料:
> 1203132838
> 1124130928

![image](https://hackmd.io/_uploads/BJSDAJtVZg.png)
壓降/電流:5.06/49.674
20-2
![image](https://hackmd.io/_uploads/r1sFAJKN-e.png)
峰值壓降:5.69 :arrow_right: 峰值電流:55.859 :arrow_right: 峰值功率:1004.7 W
推力:2.9091；power/thrust = 345.4 (W/kg)

15-1
![image](https://hackmd.io/_uploads/SJT_1gt4-l.png)
峰值壓降:6.145 :arrow_right: 峰值電流:60.325 :arrow_right: 峰值功率:1119.1 W
推力:3.3865；power/thrust = 330.5 (W/kg)

10-2
![image](https://hackmd.io/_uploads/rksGeeF4be.png)
峰值壓降:5.79 :arrow_right: 峰值電流:56.840 :arrow_right: 峰值功率:1049.1 W
推力:3.9892；power/thrust = 263.0 (W/kg)
:::

#### 4200
:::spoiler
![image](https://hackmd.io/_uploads/SJLnRGKEWl.png)
壓降/電流:3.80/55.131

10-1
![image](https://hackmd.io/_uploads/ryX1xXKNbe.png)
峰值壓降:4.80 :arrow_right: 峰值電流:69.639 :arrow_right: 峰值功率:1378 W
推力:4.5493；power/thrust = 302.9 (W/kg)

15-2
![image](https://hackmd.io/_uploads/BkxSe7F4-e.png)

峰值壓降:4.77 :arrow_right: 峰值電流:69.204 :arrow_right: 峰值功率:1333.4 W
推力:3.7817；power/thrust = 352.56 (W/kg)
:::
---
|Power/Thrust|AT3530(100%)|XM5050(88%)|
|--|------|------|
| 0m/s|233.7|246.1 |
|10m/s|273.6|263.0 |
|15m/s|301.7|330.5 |
|20m/s|359.4|358.0 |
|製造商|262.9|258.5 |

:warning: :warning: :warning: :warning: 
> XM5050估計值較為樂觀(最悲觀為上述*1.08)

