From c0f76986c5c4ec62eed0e4b9180cd9459fba77fd Mon Sep 17 00:00:00 2001
From: YunHorn Technology <dp.s@yunhorn.com>
Date: Tue, 9 Jan 2024 19:41:21 +0800
Subject: [PATCH] refine human detection logic,start of thermal detection tag

---
 Core/Inc/yunhorn_sts_sensors.h  |  2 ++
 LoRaWAN/App/lora_app.c          | 13 +++++++++--
 mlx90640/mlx90640_lcd_display.c | 41 ++++++++++++++++++++++++++-------
 3 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/Core/Inc/yunhorn_sts_sensors.h b/Core/Inc/yunhorn_sts_sensors.h
index 5b87750..34cce29 100644
--- a/Core/Inc/yunhorn_sts_sensors.h
+++ b/Core/Inc/yunhorn_sts_sensors.h
@@ -245,6 +245,7 @@ typedef struct
 typedef struct
 {
 	uint16_t waterSpillCount;		/* count of water spillage */
+	uint16_t humanSpotCount;		/* count of human body spot */
 	float averageTemp;			/* 0-120 C */
 	float maxTemp;				/* 0-120 C */
 	float minTemp;				/* 0-120 C */
@@ -252,6 +253,7 @@ typedef struct
 	float averageTempInner;		/* 0-120 C */
 	uint16_t spot_cnt;			/* 0-20  max of v_water_cnt h_water_cnt */
 	uint16_t spillage_level;		/* 0-99%,  out of 768 dots */
+	uint16_t humanSpot_level;
 	uint16_t v_water_cnt;
 	uint16_t h_water_cnt;
 
diff --git a/LoRaWAN/App/lora_app.c b/LoRaWAN/App/lora_app.c
index 2c01a12..46de03d 100644
--- a/LoRaWAN/App/lora_app.c
+++ b/LoRaWAN/App/lora_app.c
@@ -67,6 +67,7 @@ extern volatile uint8_t waterTempThreshold;
 extern volatile uint8_t humanTempThreshold;
 extern volatile uint8_t averageTempThreshold;
 extern volatile uint8_t emmisivityThreshold;
+extern volatile uint8_t thermalDetectTag;
 #endif
 volatile uint8_t heart_beat_timer =0;
 char outbuf[128]="";
@@ -1836,6 +1837,7 @@ P  # # A # #
                     'A': Average Temperature
                     'H': Human Body Temperature
                     'E': EMMISIVITY Threshold
+                    'T': Thermal Detect Tag, water (0x01) or human 0x02
          + -------- MSB OF PARAMETER
            + ------ LSB OF PARAMTER
 
@@ -1863,6 +1865,10 @@ P  # # A # #
 								//volatile uint8_t waterTempThreshold=15, normalWaterTemp=25;
 								waterTempThreshold = cmdValue;
 								break;
+							case 'T':
+								// 0x01 water detection, 0x02 human body detection
+								thermalDetectTag = cmdValue;
+								break;
 							default:
 								invalid_flag = 1;
 								break;
@@ -1870,7 +1876,7 @@ P  # # A # #
 
 							uint8_t j=0;
 
-							sts_cfg_nvm.p[j++]   = (uint8_t)'A';
+							sts_cfg_nvm.p[j++] = (uint8_t)'A';
 							sts_cfg_nvm.p[j++] = (uint8_t)(averageTempThreshold)&0xFF;
 							sts_cfg_nvm.p[j++] = (uint8_t)'E';
 							sts_cfg_nvm.p[j++] = (uint8_t)(emmisivityThreshold)&0xFF;
@@ -1878,6 +1884,8 @@ P  # # A # #
 							sts_cfg_nvm.p[j++] = (uint8_t)(humanTempThreshold)&0xFF;
 							sts_cfg_nvm.p[j++] = (uint8_t)'W';
 							sts_cfg_nvm.p[j++] = (uint8_t)(waterTempThreshold)&0xFF;
+							sts_cfg_nvm.p[j++] = (uint8_t)'T';
+							sts_cfg_nvm.p[j++] = (uint8_t)(thermalDetectTag)&0xFF;
 
 
 							//STS_PRESENCE_SENSOR_NVM_CFG_SIMPLE();
@@ -1891,7 +1899,7 @@ P  # # A # #
 							outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD5];
 							outbuf[i++] = (uint8_t) tlv_buf[CFG_CMD6];
 
-							APP_LOG(TS_OFF, VLEVEL_L, "###### CFG Received =%s  Cmd=%02x  Value=%2d\r\n",(char*)outbuf, tlv_buf[CFG_CMD4], cmdValue);
+							APP_LOG(TS_OFF, VLEVEL_L, "###### CFG Received =%s  Cmd=%02x  Value=%2d   Invalid Flag=%u \r\n",(char*)outbuf, tlv_buf[CFG_CMD4], cmdValue, invalid_flag);
 
 
 							// Step 2: Save valid config to NVM
@@ -2210,6 +2218,7 @@ void OnRestoreSTSCFGContextProcess(void)
 	emmisivityThreshold  	= (float) sts_cfg_nvm.p[3];
 	humanTempThreshold      = (float) sts_cfg_nvm.p[5];
 	waterTempThreshold		= (float) sts_cfg_nvm.p[7];
+	thermalDetectTag		= (uint8_t) sts_cfg_nvm.p[9];
 
 #endif
 
diff --git a/mlx90640/mlx90640_lcd_display.c b/mlx90640/mlx90640_lcd_display.c
index 07628e1..caf56b3 100644
--- a/mlx90640/mlx90640_lcd_display.c
+++ b/mlx90640/mlx90640_lcd_display.c
@@ -18,6 +18,8 @@
 #define	 RefreshRate FPS4HZ //FPS1HZ   //was FPS2HZ
 #define EMMISIVITY 0.96f		//water Emisivity=0.96,  human body == 0.92f
 #define TA_SHIFT 8 //Default shift for MLX90640 in open air
+#define  WATER_DETECT 0x01
+#define  HUMAN_DETECT 0x02
 
 paramsMLX90640 mlx90640;
 static uint16_t eeMLX90640[832];  
@@ -29,6 +31,7 @@ volatile uint8_t averageTempThreshold;
 volatile uint8_t emmisivityThreshold= (EMMISIVITY*100);		// 96/100 = 0.96f
 volatile uint8_t humanTempThreshold = 32;
 volatile uint8_t waterTempThreshold=15;   //15/10= 1.5 C
+volatile uint8_t thermalDetectTag = WATER_DETECT;
 // The Above  be stored in NVM
 
 volatile uint8_t normalWaterTemp=25;   // 25 C
@@ -41,6 +44,7 @@ volatile float centerTemp=0.0f;
 volatile float averageTemp=0.0f;
 volatile float averageTempInner=0.0f;
 volatile uint16_t waterSpillCount=0;
+volatile uint16_t humanSpotCount=0;
 extern volatile uint8_t sensor_data_ready;
 extern volatile float env_temperature;
 char tempBuffer[256];
@@ -202,20 +206,32 @@ static void sortFocusAreas(void)
 		  blackOutTag =0;
 	}
 	  // ignore edge of FOV
-	  waterSpillCount =0;
+	  waterSpillCount = 0;
+	  humanSpotCount  = 0;
 	  for (y=1; y<ROW; y++)
 	  {
 			for (x=1; x<COL; x++)
 			{
-				temp1  = (float)tempValues[(x)   + (y*COL)];
+				temp1  = (float)tempValues[(x)+(y*COL)];
 
-				if ((temp1 + (float)(waterTempThreshold / 10.0)) <  (float)(min(averageTemp, env_temperature)))   // was max(averageTemp, env_temperature))
+
+				if (thermalDetectTag == WATER_DETECT)
 				{
-					if (blackOutTag == 0) {
-						zoneMask[y*COL+x] ++;
+					if ((temp1 + (float)(waterTempThreshold / 10.0)) <  (float)(min(averageTemp, env_temperature)))   // was max(averageTemp, env_temperature))
+					{
+						if (blackOutTag == 0)
+						{
+							zoneMask[y*COL+x] ++;
+							upMask[(uint8_t)(y/3)][(uint8_t)(x/3)] ++;		 //translate to 11*8 matrix for upload
+							waterSpillCount ++;
+						}
+					}
+				} else if (thermalDetectTag == HUMAN_DETECT) {
+					if ((temp1 > (float) humanTempThreshold)&&(temp1 <(float) (humanTempThreshold+6.0))) {
 
+						zoneMask[y*COL+x] ++;
 						upMask[(uint8_t)(y/3)][(uint8_t)(x/3)] ++;		 //translate to 11*8 matrix for upload
-						waterSpillCount ++;
+						humanSpotCount ++;
 					}
 				}
 			}
@@ -228,6 +244,8 @@ void STS_M1A_SENSOR_Read(STS_M1A_SensorDataTypeDef *m1a_data)
 {
 
     m1a_data->waterSpillCount = blackOutTag==0?waterSpillCount:0;
+    m1a_data->humanSpotCount = humanSpotCount;
+    m1a_data->humanSpot_level = (uint8_t)((m1a_data->humanSpotCount)*99/768.0);
     m1a_data->spillage_level = (uint8_t)((m1a_data->waterSpillCount)*99/768.0); //((ROW-2)*(COL-2)));   // (24-4) * (32 -4) minus edge dots
 	m1a_data->averageTemp = averageTemp;
 	m1a_data->averageTempInner = averageTempInner;
@@ -254,8 +272,10 @@ void STS_M1A_SENSOR_Read(STS_M1A_SensorDataTypeDef *m1a_data)
     memcpy((void *)m1a_data->order, (const void *)order, sizeof(order));
 	memset(tempBuffer,0x0,sizeof(tempBuffer));
 
-	sprintf(tempBuffer,(char *)"\r\n## Blackout=%u ######\n##Read Sensor Spot CNT=%4d (areas), \r\n Env_Temp =%02.2f C,\r\n## V_cnt=%2d (lane),  H_cnt=%2d (lane), \r\n## Spillage Level =%u %, \r\n## averageTempInner=%02.2f C, averageTemp=%02.2f C, centerTemp=%.2f C, MinTemp=%02.2f C, maxTemp=%02.2f C, \r\n ######## Gap_Average= %02.2fC,    Gap_Inner = %02.2fC \r\n",
-			(uint8_t)blackOutTag, (uint16_t)(m1a_data->waterSpillCount), (float)env_temperature, (int)v_water_cnt, (int)h_water_cnt, (uint8_t)(m1a_data->spillage_level), (float)averageTempInner, (float)averageTemp, (float)centerTemp, (float)minTemp, (float)maxTemp, (float)(averageTemp - minTemp),(float)(averageTempInner - minTemp));
+	sprintf(tempBuffer,(char *)"\r\n## Blackout=%u ######\n##Read Sensor Spot CNT=%4d (areas), \r\n Env_Temp =%2.2f C \r\n## V_cnt=%2d (lane) H_cnt=%2d (lane)\r\n## Spillage Level =%u %% \r\n## averageTempInner=%02.2f C averageTemp=%02.2f C, centerTemp=%2.2f C  MinTemp=%2.2f C  maxTemp=%2.2f C \r\n",
+			(uint8_t)blackOutTag, (uint16_t)(m1a_data->waterSpillCount), (float)env_temperature, (int)v_water_cnt, (int)h_water_cnt, (uint8_t)(m1a_data->spillage_level), (float)averageTempInner, (float)averageTemp, (float)centerTemp, (float)minTemp, (float)maxTemp);
+	APP_LOG(TS_OFF, VLEVEL_H,(char *)tempBuffer);
+	sprintf(tempBuffer,(char *)"\r\n######## Gap_Average= %2.2f C   Gap_Inner =%2.2f C\r\n",(float)(averageTemp - minTemp),(float)(averageTempInner - minTemp));
 	APP_LOG(TS_OFF, VLEVEL_H,(char *)tempBuffer);
 
 	if ((m1a_data->spot_cnt !=0 ) && (blackOutTag == 0))
@@ -279,6 +299,7 @@ void mlx90640_display_process(void)
 
 	 detectCycle = 0;
 	 uint16_t spillcountTemp =0, spot_cntTemp=0;
+	 uint16_t humanspotcountTemp =0;
 
 	 do {
 		readTempValues();
@@ -287,17 +308,21 @@ void mlx90640_display_process(void)
 		findFocusArea();
 
 		spillcountTemp += waterSpillCount;
+		humanspotcountTemp += humanSpotCount;
 		spot_cntTemp += spot_cnt;
 
 	 } while (++detectCycle < DetectCycleCount);
 
 	 waterSpillCount = (uint16_t) (spillcountTemp/DetectCycleCount);
+	 humanSpotCount = (uint16_t) (humanspotcountTemp/DetectCycleCount);
+
 	 spot_cnt /= DetectCycleCount ; //max(v_water_cnt, h_water_cnt);
 
 
 		if (blackOutTag == 0)
 		{
 			APP_LOG(TS_OFF, VLEVEL_H, "Water Spill Detected Level = %u of 768 \r\n", (uint16_t)waterSpillCount);
+			APP_LOG(TS_OFF, VLEVEL_H, "Human Spot Detected Level = %u of 768 \r\n", (uint16_t)humanSpotCount);
 		}
 }