Эх сурвалжийг харах

1. 加入最小二乘观察总电压,最小电芯电压的变化斜率
2. 更新soc
3. 更新health的判断

Signed-off-by: huhui <huhui@sharkgulf.com>

huhui 5 жил өмнө
parent
commit
eac395b703

+ 46 - 11
Application/app/sox/Least_Square.c

@@ -1,21 +1,54 @@
 #include <stdio.h>
-#include "libs/logger.h"
+#include "Least_Square.h"
 
-//y = ax + b
-typedef struct {
-	double x;
-	double y;
-}smaple_t;
+//y = Cbx + Ka
+void least_square_init(least_square_t *ls, int samples){
+	ls->max_samples = samples;
+	ls->num_samples = 0;
+	ls->Cb = 0;
+	ls->Ka = 0;
+	ls->mul_xx = 0;
+	ls->mul_xy = 0;
+	ls->sum_x = 0;
+	ls->sum_y = 0;
+}
+int least_square_put(least_square_t *ls, double x, double y){
+	if (ls->num_samples < ls->max_samples){
+		ls->num_samples ++;
+		ls->last_x = x;
+		ls->last_y = y;
+		ls->mul_xx += x * x;
+		ls->mul_xy += x * y;
+		ls->sum_x += x;
+		ls->sum_y += y;
+		return 0;
+	}else {
+		ls->Cb = (ls->max_samples * ls->mul_xy - ls->sum_x * ls->sum_y) / (ls->max_samples * ls->mul_xx - ls->sum_x * ls->sum_x);
+		ls->Ka = ls->sum_y / ls->max_samples - ls->Cb * ls->sum_x / ls->max_samples;
+		ls->mul_xx += x * x;
+		ls->mul_xy += x * y;
+		ls->sum_x += x;
+		ls->sum_y += y;
 
-static smaple_t samples[5];
-static int sample_count;
-static float AA, BB;
+		ls->mul_xx -= ls->last_x * ls->last_x;
+		ls->mul_xy -= ls->last_x * ls->last_y;
+		ls->sum_x -= ls->last_x;
+		ls->sum_y -= ls->last_y;
+		ls->last_x = x;
+		ls->last_y = y;
+		return 1;
+	}
+}
 
+double get_y_by_x(least_square_t *ls, double x){
+	return ls->Cb * x + ls->Ka;
+}
 
+#if 0
 void Least_square_method(void)
 {
 	int i=0;
-	double K = 0, A = 0, B = 0, C = 0, D = 0;	
+	double A = 0, B = 0, C = 0, D = 0;	
 	for(i=0;i<sample_count;i++) {
 		A += samples[i].x * samples[i].y;
 		B += samples[i].x;
@@ -23,7 +56,7 @@ void Least_square_method(void)
 		D += samples[i].x * samples[i].x;
 	}
 	AA = (sample_count * A - B * C) / ( sample_count * D - B * B);
-	BB = C / sample_count - K * B / sample_count;
+	BB = C / sample_count - AA * B / sample_count;
 	sys_debug("Gain = %f, zero Off = %f\n", AA, BB);
 }
 
@@ -38,3 +71,5 @@ void add_smaple(float x, float y){
 		Least_square_method();
 	}
 }
+#endif
+

+ 19 - 0
Application/app/sox/Least_Square.h

@@ -0,0 +1,19 @@
+#pragma once
+
+typedef struct {
+	int max_samples;
+	int num_samples;
+	double last_x;
+	double last_y;
+	double mul_xx;
+	double mul_xy;
+	double sum_x;
+	double sum_y;
+	double Ka;
+	double Cb;
+}least_square_t;
+
+void least_square_init(least_square_t *ls, int samples);
+int least_square_put(least_square_t *ls, double x, double y);
+double get_y_by_x(least_square_t *ls, double x);
+

+ 5 - 5
Application/app/sox/health.c

@@ -14,14 +14,14 @@
 #define SIGLE_CELL_LOWER_DISCHARGER_VOLTAGE (1820) //最小允许的电芯放电电压 1.8v, 考虑到采样的误差取 1.82
 #endif
 
-static int8_t charger_normal_low_temp[PACK_TEMPS_NUM] = {0,0,0,0}; //正常的充电最低温度
+static int8_t charger_normal_low_temp[PACK_TEMPS_NUM] = {0,0,0,-5}; //正常的充电最低温度
 static int8_t charger_normal_high_temp[PACK_TEMPS_NUM] = {50,50,50,55}; //正常的充电最高温度
-static int8_t charger_lower_low_temp[PACK_TEMPS_NUM] = {-5,-5,-5,0}; //需要停止充电的最低温度
+static int8_t charger_lower_low_temp[PACK_TEMPS_NUM] = {-1,-1,-1,-6}; //需要停止充电的最低温度
 static int8_t charger_higher_high_temp[PACK_TEMPS_NUM] = {55,55,55,60}; //需要停止充电的最高温度
 
-static int8_t discharger_normal_low_temp[PACK_TEMPS_NUM] = {-10,-10,-10,-5};//正常的放电最低温度
+static int8_t discharger_normal_low_temp[PACK_TEMPS_NUM] = {-20,-20,-20,-25};//正常的放电最低温度
 static int8_t discharger_normal_high_temp[PACK_TEMPS_NUM] = {50,50,50,55};//正常的放电最高温度
-static int8_t discharger_lower_low_temp[PACK_TEMPS_NUM] = {-15,-15,-15,-10}; //需要停止放电的最低温度
+static int8_t discharger_lower_low_temp[PACK_TEMPS_NUM] = {-25,-25,-25,-30}; //需要停止放电的最低温度
 static int8_t discharger_higher_high_temp[PACK_TEMPS_NUM] = {55,55,55,60};//需要停止放电的最高温度
 static int8_t work_lower_temp[PACK_TEMPS_NUM] = {0,0,0,5};
 /*定义低温和正常温度下的电池保护参数, [0]低温参数, [1]常温参数 */
@@ -279,7 +279,7 @@ static int _is_over_temp(int8_t *temps){
 
 static int _is_low_temp(int8_t *temps){
 	for (int i = 0; i < PACK_TEMPS_NUM; i++){
-		if (measure_value()->pack_temp[i] <= temps[i]){
+		if (measure_value()->pack_temp[i] < temps[i]){
 			return 1;
 		}
 	}

+ 2 - 2
Application/app/sox/measure.c

@@ -67,7 +67,7 @@ static void current_10x_calibrate(void){
 	/* calibrate the 10x gain */
 	ML5238_IMON_OUT_ZERO_10X();
 	vim0_10x = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
-#if 0	
+#if 0
 	ML5238_IMON_OUT_V2000_10X();
 	float vim1 = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
 	ML5238_IMON_OUT_V100_10X();
@@ -87,7 +87,7 @@ static void current_50x_calibrate(void){
 	float vim1 = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
 	ML5238_IMON_OUT_V20_50X();
 	float vr = adc_sample_avg(ADC_CHAN_IMON, GD32_ADC_READ_TIMES);
-	imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr);
+	imon_gain_50x = ML5238_GAIN(vim0_50x, vim1, vr) * 0.948f;
 #else
 	imon_gain_50x = 50.0f;
 #endif

+ 1 - 1
Application/app/sox/measure_task.c

@@ -38,7 +38,7 @@ measure_value_t * measure_value(void){
 void measure_log(void){
 	measure_debug("Current %.4f -- %.4f\n", (float)_measure_value.load_current/1000.0f, (float)_measure_value.current_5238/1000.0f);
 	for (int i = 0; i < CELLS_NUM; i++){
-		measure_debug("Cell[%d]: %.3fv\n", i, _measure_value.cell_vol[i]/1000.0f);
+		//measure_debug("Cell[%d]: %.3fv\n", i, _measure_value.cell_vol[i]/1000.0f);
 	}
 	measure_debug("Gain:%f, Off %f\n", get_ml5238_gain(), get_ml5238_vos());
 }

+ 64 - 17
Application/app/sox/soc.c

@@ -3,9 +3,12 @@
 #include "app/sox/measure_task.h"
 #include "app/nv_storage.h"
 #include "libs/logger.h"
+#include "Least_Square.h"
 #include "health.h"
 #include "state.h"
 
+#define LEAST_SQUARE 0
+
 static soc_t _soc;
 static uint8_t chargering = 0;
 static u64     time_ms = 0;
@@ -14,14 +17,25 @@ static float     max_soc_delta_time = 0;
 static float _charger_coefficient = 1.0f;
 static float _discharger_coefficient = 1.0f;
 static uint8_t is_force_full = 0;
+static uint8_t is_force_empty = 0;
 uint32_t charger_remain_time = 0;
-#define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
 
+#define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
+#define DEFALUT_MIN_COULOMB (25.0f * 3600.0f)
 static void calibrate_soc_by_ocv(void);
 
-
+#if LEAST_SQUARE==1
+static void _least_square_timer_handler(shark_timer_t *timer);
+static least_square_t discharger_vol_coef;
+static least_square_t discharger_cell_coef;
+static least_square_t discharger_capacity_coef;
+static shark_timer_t least_square_timer = {.handler = _least_square_timer_handler};
+static int least_square_time = 0;
+#define LEAST_SQUARE_STEP_TIME 1000
+#endif
 void soc_init(void){
 	set_log_level(MOD_SOC, L_debug);
+	
 	time_ms = shark_get_mseconds();
 	if (nv_restore_soc() != 0){
 		soc_warning("SOC: nv storage is not inited, use default value!!\n");
@@ -41,8 +55,31 @@ void soc_init(void){
 	soc_log();
 }
 
-#define TOHA(x) (float)(x/3600.0f)
+#if LEAST_SQUARE==1
+static void start_least_square(void){
+	least_square_init(&discharger_vol_coef, 10);
+	least_square_init(&discharger_cell_coef, 10);
+	least_square_init(&discharger_capacity_coef, 10);
+	least_square_time = 0;
+	shark_timer_post(&least_square_timer, LEAST_SQUARE_STEP_TIME);
+}
+
+static void _least_square_timer_handler(shark_timer_t *timer){
+	if (least_square_put(&discharger_vol_coef, least_square_time, bms_state_get()->pack_voltage/1000.0f) == 1) {
+		soc_error("voltage: A = %f, B = %f, v: %f\n", discharger_vol_coef.Cb, discharger_vol_coef.Ka, get_y_by_x(&discharger_vol_coef, least_square_time));
+	}
+	if (least_square_put(&discharger_cell_coef, least_square_time, bms_state_get()->cell_min_vol/1000.0f) == 1) {
+		soc_error("cell: A = %f, B = %f, v: %f\n", discharger_cell_coef.Cb, discharger_cell_coef.Ka, get_y_by_x(&discharger_cell_coef, least_square_time));
+	}
+	if (least_square_put(&discharger_capacity_coef, least_square_time, _soc.coulomb_now/3600.0f) == 1) {
+		soc_error("capacity: A = %f, B = %f, c: %f\n", discharger_capacity_coef.Cb, discharger_capacity_coef.Ka, get_y_by_x(&discharger_capacity_coef, least_square_time));
+	}
+	least_square_time ++;
+	shark_timer_post(&least_square_timer, LEAST_SQUARE_STEP_TIME);
+}
+#endif
 
+#define TOHA(x) (float)(x/3600.0f)
 void soc_log(void){
 	soc_debug("C flags 0x%x\n", _soc.flags);
 	soc_debug("C now: %.4f\n", TOHA(_soc.coulomb_now));
@@ -100,14 +137,17 @@ int soc_update_by_ocv(void){
 	int changed = 0;
 	if (_soc.flags & SOC_FLAG_CALIBRATED){
 		if (!chargering){
-			if (bms_health()->powerdown_lower_voltage && bms_health()->is_work_temp_normal) {
-				_soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池在常温下进入powerdown,最小容量修正为当前容量
-				_soc.capacity = 0;
-				soc_warning("current coulomb %f\n", _soc.coulomb_now);
+			if (bms_health()->is_work_temp_normal) {
+				if (!is_force_empty && (bms_health()->powerdown_lower_voltage || bms_health()->sigle_cell_lower_voltage || bms_health()->discharger_lower_voltage)) {
+					_soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池在常温下进入powerdown,最小容量修正为当前容量
+					_soc.capacity = 0;
+					is_force_empty = 1;
+					changed = 1;
+					soc_warning("current coulomb %f\n", _soc.coulomb_now);
+				}
 			}
-			changed = 1;
 		}
-		if (chargering){
+		if (chargering && !is_force_full){
 			if (bms_state_get()->pack_voltage >= (53500) && (measure_value()->load_current <= 500.0f)){
 				_soc.capacity = 100;
 				is_force_full = 1;
@@ -123,7 +163,7 @@ static void soc_calibrate(uint8_t prev_charge_status){
 	static int cali_full_count = 0;
 	if (!(_soc.flags & SOC_FLAG_CALIBRATED)){
 		if (chargering){//用ocv进行严格校准
-			if ((measure_value()->load_current <= 500.0f) && (bms_state_get()->pack_voltage >= 53500)){				
+			if (!is_force_full && (measure_value()->load_current <= 500.0f) && (bms_state_get()->pack_voltage >= 53500)){				
 				cali_full_count ++;
 				if (cali_full_count == 10) {
 					soc_debug("calibrate Capacity to 100, measure_value()->load_current %d\n", measure_value()->load_current);
@@ -132,7 +172,7 @@ static void soc_calibrate(uint8_t prev_charge_status){
 				}
 			}
 		}else if (prev_charge_status){
-			if(bms_state_get()->pack_voltage >= 53500){
+			if(!is_force_full && (bms_state_get()->pack_voltage >= 53500)){
 				soc_debug("calibrate Capacity to 100\n");
 				_soc.capacity = 100;
 				is_force_full = 1;
@@ -178,17 +218,21 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
 	}
 	_soc.coulomb_now = _soc.coulomb_now + delta_q; //充电加, 放电减
 
-	if (_soc.coulomb_now < _soc.coulomb_min){
-		_soc.coulomb_now = _soc.coulomb_min;
+	if (_soc.coulomb_now < 0){
+		_soc.coulomb_now = 0;
 	}
 	uint8_t old_cap = _soc.capacity;
-	_soc.capacity = ((_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
+	if ((_soc.coulomb_now - _soc.coulomb_min) >= 0){
+		_soc.capacity = ((_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
+	}else {
+		_soc.capacity = 0;
+	}
 	if (_soc.capacity > 100){
 		_soc.capacity = 100;
 	}
 	if (chargering && (_soc.capacity == 100) && (!is_force_full)){
 		_soc.capacity = 99;//充电的时候必须通过ocv才能把电量校准到100
-	}else if (!chargering && (_soc.capacity == 0)){
+	}else if (!chargering && (_soc.capacity == 0) && !is_force_empty){
 		_soc.capacity = 1;
 	}
 	//通过电压校准SOC,只能在电压范围的两端校准
@@ -204,8 +248,10 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
 			soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
 		}else { //如果校准过,单电芯过压,100%的容量,设置最大容量为当前容量
 			if (bms_health()->sigle_cell_over_voltage){
-				_soc.coulomb_max = _soc.coulomb_now;
-				soc_warning("signal cell over vol, cap full, reset coul max to coul now: %f\n", _soc.coulomb_max);
+				if ((_soc.coulomb_now >= DEFALUT_MIN_COULOMB) && (_soc.coulomb_now <= DEFALUT_MAX_COULOMB)) {
+					_soc.coulomb_max = _soc.coulomb_now;
+					soc_warning("signal cell over vol, cap full, reset coul max to coul now: %f\n", _soc.coulomb_max);
+				}
 			}
 		}
 	}
@@ -227,6 +273,7 @@ void soc_update(void){
 		_soc.charger_coulomb = 0;//clear charing
 		_soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
 		chargering = 1;
+		is_force_empty = 0;
 		if (_soc.capacity < 100) {
 			is_force_full = 0;
 		}

+ 13 - 4
Application/app/sox/state.c

@@ -84,18 +84,23 @@ int bms_work_mode_set(int mode, int start){
 }
 
 void bms_state_log(void){
-	state_warning("Life Time: %d\n", shark_get_seconds());
-	state_warning("Sleep Time: %ds\n", get_system_sleep_time());
-	state_warning("ml5238 cali: %d\n", ml5238_cali_count);
+	state_debug("Life Time: %d\n", shark_get_seconds());
+	state_debug("Sleep Time: %ds\n", get_system_sleep_time());
+	state_debug("ml5238 cali: %d\n", ml5238_cali_count);
+#if 0
 	state_debug("Charging: %d\n", _bms_state.charging);
 	state_debug("WorkMode %d\n", _bms_state.work_mode);
 	state_debug("DMos: %d\n", ml5238_is_discharging());
 	state_debug("CMos: %d\n", ml5238_is_charging());
 	state_debug("AuxPower: %d\n", AUX_VOL_IS_OPEN());
 	state_debug("WorkMode:0x%x\n", _bms_state.work_mode);
+#endif
 }
-static int _log_count = 0;
+
 static void _debug_timer_handler(shark_timer_t *t){
+#if 0
+	static int _log_count = 0;
+
 	int mod = _log_count % 4;
 	if (mod == 0){
 		bms_state_log();
@@ -110,6 +115,10 @@ static void _debug_timer_handler(shark_timer_t *t){
 		measure_log();
 	}
 	_log_count ++;
+#else
+	bms_state_log();
+	measure_log();
+#endif
 	shark_timer_post(&_debug_timer, 2000);
 }
 

+ 56 - 44
Project/SP700.uvoptx

@@ -396,6 +396,18 @@
       <RteFlg>0</RteFlg>
       <bShared>0</bShared>
     </File>
+    <File>
+      <GroupNumber>2</GroupNumber>
+      <FileNumber>15</FileNumber>
+      <FileType>1</FileType>
+      <tvExp>0</tvExp>
+      <tvExpOptDlg>0</tvExpOptDlg>
+      <bDave2>0</bDave2>
+      <PathWithFileName>..\Application\app\sox\Least_Square.c</PathWithFileName>
+      <FilenameWithoutPath>Least_Square.c</FilenameWithoutPath>
+      <RteFlg>0</RteFlg>
+      <bShared>0</bShared>
+    </File>
   </Group>
 
   <Group>
@@ -406,7 +418,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>15</FileNumber>
+      <FileNumber>16</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -418,7 +430,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>16</FileNumber>
+      <FileNumber>17</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -430,7 +442,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>17</FileNumber>
+      <FileNumber>18</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -442,7 +454,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>18</FileNumber>
+      <FileNumber>19</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -454,7 +466,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>19</FileNumber>
+      <FileNumber>20</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -466,7 +478,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>20</FileNumber>
+      <FileNumber>21</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -478,7 +490,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>21</FileNumber>
+      <FileNumber>22</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -490,7 +502,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>22</FileNumber>
+      <FileNumber>23</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -502,7 +514,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>23</FileNumber>
+      <FileNumber>24</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -514,7 +526,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>24</FileNumber>
+      <FileNumber>25</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -526,7 +538,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>25</FileNumber>
+      <FileNumber>26</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -538,7 +550,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>26</FileNumber>
+      <FileNumber>27</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -550,7 +562,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>27</FileNumber>
+      <FileNumber>28</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -562,7 +574,7 @@
     </File>
     <File>
       <GroupNumber>3</GroupNumber>
-      <FileNumber>28</FileNumber>
+      <FileNumber>29</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -582,7 +594,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>29</FileNumber>
+      <FileNumber>30</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -594,7 +606,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>30</FileNumber>
+      <FileNumber>31</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -606,7 +618,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>31</FileNumber>
+      <FileNumber>32</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -618,7 +630,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>32</FileNumber>
+      <FileNumber>33</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -630,7 +642,7 @@
     </File>
     <File>
       <GroupNumber>4</GroupNumber>
-      <FileNumber>33</FileNumber>
+      <FileNumber>34</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -650,7 +662,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>34</FileNumber>
+      <FileNumber>35</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -662,7 +674,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>35</FileNumber>
+      <FileNumber>36</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -674,7 +686,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>36</FileNumber>
+      <FileNumber>37</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -686,7 +698,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>37</FileNumber>
+      <FileNumber>38</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -698,7 +710,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>38</FileNumber>
+      <FileNumber>39</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -710,7 +722,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>39</FileNumber>
+      <FileNumber>40</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -722,7 +734,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>40</FileNumber>
+      <FileNumber>41</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -734,7 +746,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>41</FileNumber>
+      <FileNumber>42</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -746,7 +758,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>42</FileNumber>
+      <FileNumber>43</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -758,7 +770,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>43</FileNumber>
+      <FileNumber>44</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -770,7 +782,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>44</FileNumber>
+      <FileNumber>45</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -782,7 +794,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>45</FileNumber>
+      <FileNumber>46</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -794,7 +806,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>46</FileNumber>
+      <FileNumber>47</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -806,7 +818,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>47</FileNumber>
+      <FileNumber>48</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -818,7 +830,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>48</FileNumber>
+      <FileNumber>49</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -830,7 +842,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>49</FileNumber>
+      <FileNumber>50</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -842,7 +854,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>50</FileNumber>
+      <FileNumber>51</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -854,7 +866,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>51</FileNumber>
+      <FileNumber>52</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -866,7 +878,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>52</FileNumber>
+      <FileNumber>53</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -878,7 +890,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>53</FileNumber>
+      <FileNumber>54</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -890,7 +902,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>54</FileNumber>
+      <FileNumber>55</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -902,7 +914,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>55</FileNumber>
+      <FileNumber>56</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -914,7 +926,7 @@
     </File>
     <File>
       <GroupNumber>5</GroupNumber>
-      <FileNumber>56</FileNumber>
+      <FileNumber>57</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -934,7 +946,7 @@
     <RteFlg>0</RteFlg>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>57</FileNumber>
+      <FileNumber>58</FileNumber>
       <FileType>2</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>
@@ -946,7 +958,7 @@
     </File>
     <File>
       <GroupNumber>6</GroupNumber>
-      <FileNumber>58</FileNumber>
+      <FileNumber>59</FileNumber>
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <tvExpOptDlg>0</tvExpOptDlg>

+ 5 - 0
Project/SP700.uvprojx

@@ -458,6 +458,11 @@
               <FileType>1</FileType>
               <FilePath>..\Application\app\sox\soc.c</FilePath>
             </File>
+            <File>
+              <FileName>Least_Square.c</FileName>
+              <FileType>1</FileType>
+              <FilePath>..\Application\app\sox\Least_Square.c</FilePath>
+            </File>
           </Files>
         </Group>
         <Group>