From 0c2020ddfb56fd7d066975208ad751c4d35c0fa2 Mon Sep 17 00:00:00 2001 From: helei Date: Sat, 15 Aug 2026 07:36:39 +0800 Subject: [PATCH] =?UTF-8?q?V1.5:=20=E4=BA=A7=E5=93=81=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=94=B9=E8=BF=90=E8=A1=8C=E6=97=B6=E5=8F=AF=E5=88=87(EEPROM17?= =?UTF-8?q?2+=E8=93=9D=E7=89=99SCALE/SCALE0/SCALE1=E5=91=BD=E4=BB=A4,?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E8=87=AA=E5=8A=A8=E9=87=8D=E5=90=AF);OLED?= =?UTF-8?q?=E6=AC=A2=E8=BF=8E=E9=A1=B5=E6=94=B9'=E7=BB=A7=E7=94=B5?= =?UTF-8?q?=E5=99=A8=E6=8E=A7=E5=88=B6=E7=BB=88=E7=AB=AF'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HardWare/FEED_SCALE/feed_scale.c | 32 +++++++++++++++---- .../HardWare/FEED_SCALE/feed_scale.h | 14 +++++--- .../STM32F103_App1/HardWare/NETWORK/network.c | 13 ++++---- V1.5/STM32F103_App1/HardWare/RELAY/relay.c | 28 ++++++++-------- .../HardWare/SYSINIT/app_loop.c | 5 ++- .../HardWare/USER_CMD/user_cmd.c | 22 ++++++++++++- V1.5/STM32F103_App1/README.md | 5 +++ V1.5/鐗堟湰璇存槑.md | 5 +++ 8 files changed, 91 insertions(+), 33 deletions(-) diff --git a/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.c b/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.c index b0790a4..77c455e 100644 --- a/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.c +++ b/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.c @@ -131,6 +131,26 @@ static void feed_scale_report_weight(const char *header) (float)zero_weight / 10.0f); } +uint8_t g_feed_scale_on = 0; + +/* 加载产品模式:EEPROM 空白时用编译宏做默认值 */ +void feed_scale_load_mode(void) +{ + uint8_t v = 0xFF; + eepromReadData(FEED_SCALE_MODE_ADDR, &v, 1); + if (v > 1) v = PRODUCT_WITH_FEED_SCALE; + g_feed_scale_on = v; + log_info("> 产品模式: %s", v ? "称重投料(带秤)" : "四路继电器(无秤)"); +} + +/* 蓝牙命令切换产品模式:写 EEPROM(重启后完全生效) */ +void feed_scale_set_mode(uint8_t on) +{ + on = on ? 1 : 0; + g_feed_scale_on = on; + eepromWriteData(FEED_SCALE_MODE_ADDR, &on, 1); +} + void feedScaleInit(void) { uint8_t tmp[2] = {0}; @@ -167,10 +187,10 @@ void feedScaleInit(void) } } -#if !FEED_SCALE_DISABLED - log_info("> FEED: 初始化, 去皮=%.1fKG, 单次投料=%.1fKG", - (float)zero_weight / 10.0f, (float)once_weight / 10.0f); -#endif + if (g_feed_scale_on) { + log_info("> FEED: 初始化, 去皮=%.1fKG, 单次投料=%.1fKG", + (float)zero_weight / 10.0f, (float)once_weight / 10.0f); + } } void feedScaleSetZero(uint16_t zero_100g) @@ -287,9 +307,7 @@ static void feed_scale_finish_error(const char *reason) void feedScaleProcess(void) { -#if FEED_SCALE_DISABLED - return; -#endif + if (!g_feed_scale_on) return; uint8_t rx_buf[32]; int len; diff --git a/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.h b/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.h index 380e2fb..3efa751 100644 --- a/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.h +++ b/V1.5/STM32F103_App1/HardWare/FEED_SCALE/feed_scale.h @@ -9,10 +9,16 @@ #define FEED_SCALE_ONCEWT_MAX 5000 /* 500.0 KG */ #define FEED_SCALE_WEIGHT_MAX 5000 /* 500.0 KG */ -/* 磅秤接入控制:由 main.h 的 PRODUCT_WITH_FEED_SCALE 决定,此处做反向映射。 - * 1=不接磅秤(基础四路继电器产品),feeding 指令直接控制继电器 1; - * 0=接入磅秤(智能水产投料机产品),使用称重定量自动投喂逻辑 */ -#define FEED_SCALE_DISABLED (!PRODUCT_WITH_FEED_SCALE) +/* 产品形态运行时可切换:EEPROM(偏移172) 存 0/1,空白(0xFF) 时用 + * main.h 的 PRODUCT_WITH_FEED_SCALE 编译宏做默认值。 + * 1=接入磅秤(智能水产投料机),称重定量自动投喂; + * 0=不接磅秤(基础四路继电器),feeding 指令直接控制继电器 1。 + * 蓝牙命令 SCALE 查询,SCALE0/SCALE1 切换(写入后自动重启生效) */ +extern uint8_t g_feed_scale_on; +void feed_scale_load_mode(void); /* app_init 早期调用,加载产品模式 */ +void feed_scale_set_mode(uint8_t on); /* 写 EEPROM 并更新全局(重启后完全生效) */ + +#define FEED_SCALE_MODE_ADDR 172 /* EEPROM 产品模式字节(164~171 为电能累计脉冲) */ /* 投喂状态 */ typedef enum { diff --git a/V1.5/STM32F103_App1/HardWare/NETWORK/network.c b/V1.5/STM32F103_App1/HardWare/NETWORK/network.c index 7c4e1ec..40e2abe 100644 --- a/V1.5/STM32F103_App1/HardWare/NETWORK/network.c +++ b/V1.5/STM32F103_App1/HardWare/NETWORK/network.c @@ -12,6 +12,7 @@ #include "network.h" #include "net_wifi.h" #include "hlw8032.h" +#include "feed_scale.h" #include "net_wifi_ota.h" #include "air780e.h" #include "led.h" @@ -264,24 +265,24 @@ void NET_publish_status(int sw1, int feeding, int sw2, int sw3, int sw4, * 两个字段都上报,平台的 sw1 开关和 feeding 状态才能同步刷新 */ /* 无秤模式(PRODUCT_WITH_FEED_SCALE=0)不上报 zero/onceWt 字段 */ if (s_backend == NET_BACKEND_4G) { -#if PRODUCT_WITH_FEED_SCALE + if (g_feed_scale_on) { CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22ver\\22:%u,\\22weight\\22:%.1f,\\22onceWt\\22:%.1f,\\22zero\\22:%.1f,\\22sw1\\22:%d,\\22feeding\\22:%d,\\22sw2\\22:%d,\\22sw3\\22:%d,\\22sw4\\22:%d}}\"", MqttInfoStr.ClientID, (unsigned)MqttInfoStr.Ver, zero_kg, once_wt_kg, weight_kg, sw1, feeding, sw2, sw3, sw4); -#else + } else { CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22ver\\22:%u,\\22weight\\22:%.1f,\\22sw1\\22:%d,\\22feeding\\22:%d,\\22sw2\\22:%d,\\22sw3\\22:%d,\\22sw4\\22:%d,\\22energy\\22:%.2f}}\"", MqttInfoStr.ClientID, (unsigned)MqttInfoStr.Ver, zero_kg, sw1, feeding, sw2, sw3, sw4, (double)hlw8032_get_energy_kwh()); -#endif + } } else { char json[256]; -#if PRODUCT_WITH_FEED_SCALE + if (g_feed_scale_on) { snprintf(json, sizeof(json), "{\"header\":\"iot.prop.post\",\"body\":{\"ver\":%u,\"weight\":%.1f,\"onceWt\":%.1f,\"zero\":%.1f,\"sw1\":%d,\"feeding\":%d,\"sw2\":%d,\"sw3\":%d,\"sw4\":%d}}", (unsigned)MqttInfoStr.Ver, zero_kg, once_wt_kg, weight_kg, sw1, feeding, sw2, sw3, sw4); -#else + } else { snprintf(json, sizeof(json), "{\"header\":\"iot.prop.post\",\"body\":{\"ver\":%u,\"weight\":%.1f,\"sw1\":%d,\"feeding\":%d,\"sw2\":%d,\"sw3\":%d,\"sw4\":%d,\"energy\":%.2f}}", (unsigned)MqttInfoStr.Ver, zero_kg, sw1, feeding, sw2, sw3, sw4, (double)hlw8032_get_energy_kwh()); -#endif + } net_wifi_publish_up(json); } net_at_unlock(); diff --git a/V1.5/STM32F103_App1/HardWare/RELAY/relay.c b/V1.5/STM32F103_App1/HardWare/RELAY/relay.c index d286392..db02155 100644 --- a/V1.5/STM32F103_App1/HardWare/RELAY/relay.c +++ b/V1.5/STM32F103_App1/HardWare/RELAY/relay.c @@ -110,13 +110,13 @@ void relayInit(void) * 称重投喂模式: 继电器 1 是投喂通道,不恢复且强制关闭,防止上电误投料浪费饲料 */ void relayRestoreState(void) { -#if FEED_SCALE_DISABLED +if (!g_feed_scale_on) { if (MqttInfoStr.Relay_State[1]) { Relay1_ON; log_info("SW1:开(恢复)"); } else { Relay1_OFF; log_info("SW1:关(恢复)"); } -#else +} else { MqttInfoStr.Relay_State[1] = 0; Relay1_OFF; log_info("SW1:关(不恢复,投喂安全保护)"); -#endif +} if (MqttInfoStr.Relay_State[2]) { Relay2_ON; log_info("SW2:开(恢复)"); } else { Relay2_OFF; log_info("SW2:关(恢复)"); } @@ -217,14 +217,14 @@ void relayAction(uint8_t *data) /* 控制继电器前先读取反馈电平 */ fb_before = relayReadFb(ch); -#if !FEED_SCALE_DISABLED +if (g_feed_scale_on) { /* 称重自动投喂模式下继电器 1 仅由 feeding 指令控制, sw1 直接忽略 */ if (ch == 1) { log_warn("> 继电器: 称重投喂模式下忽略 sw1,请用 feeding 指令"); NET_publish_response(CmdId, 0, "sw1 disabled, use feeding"); return; } -#endif +} relaySet(ch, (uint8_t)on); log_info("> SW%d %s", ch, on ? "开" : "关"); } else if (strstr((char *)data, "\"feeding\"")) { @@ -239,7 +239,7 @@ void relayAction(uint8_t *data) ch = 1; fb_before = relayReadFb(ch); -#if FEED_SCALE_DISABLED +if (!g_feed_scale_on) { if (value_true) { relaySet(1, 1); log_info("> 继电器: 手动投喂开(无秤)"); @@ -247,7 +247,7 @@ void relayAction(uint8_t *data) relaySet(1, 0); log_info("> 继电器: 手动投喂关(无秤)"); } -#else +} else { if (value_true) { /* 首次上电查询到有效重量前不允许启动投喂 */ if (feedScaleGetWeight() == 0) { @@ -274,14 +274,14 @@ void relayAction(uint8_t *data) log_info("> 继电器: 停止投喂"); feedScaleStop(); } -#endif +} } else if (proto_locate((char *)data, "onceWt")) { -#if FEED_SCALE_DISABLED +if (!g_feed_scale_on) { /* 无秤模式:无单次投喂量概念,拒绝设置 */ log_warn("> 继电器: 拒绝设置 onceWt(无秤)"); NET_publish_response(CmdId, 0, "no scale on this device"); return; -#else +} else { /* 单独设置单次投喂量, 持久化到 EEPROM */ uint16_t once_wt_100g = 0; proto_get_kg100((char *)data, "onceWt", &once_wt_100g); @@ -294,14 +294,14 @@ void relayAction(uint8_t *data) NET_publish_response(CmdId, 1, "OK"); relayStatueUpdata(); return; -#endif +} } else if (proto_locate((char *)data, "zero")) { -#if FEED_SCALE_DISABLED +if (!g_feed_scale_on) { /* 无秤模式:无去皮/空载重量概念,拒绝设置 */ log_warn("> 继电器: 拒绝设置 zero(无秤)"); NET_publish_response(CmdId, 0, "no scale on this device"); return; -#else +} else { /* 平台下发空载重量/去皮值,直接解析 value 并保存 */ uint16_t zero_100g = 0; proto_get_kg100((char *)data, "zero", &zero_100g); @@ -314,7 +314,7 @@ void relayAction(uint8_t *data) NET_publish_response(CmdId, 1, "OK"); relayStatueUpdata(); return; -#endif +} } else { log_warn("> 继电器: 未知指令(无 sw/feeding/zero)"); return; diff --git a/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c b/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c index 4f46475..43b44e8 100644 --- a/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c +++ b/V1.5/STM32F103_App1/HardWare/SYSINIT/app_loop.c @@ -83,6 +83,9 @@ void app_init(void) /* 继电器 GPIO(控制输出 + 反馈输入) */ relayInit(); + /* 产品模式(带秤/无秤,EEPROM 可切,默认跟编译宏) */ + feed_scale_load_mode(); + /* RS485 喂料秤控制模块 */ feedScaleInit(); @@ -98,7 +101,7 @@ void app_init(void) /* OLED 屏幕(128x64 + GB2312 字库 IC) */ oled_init(); - oled_locate(1, 0); oled_print("4路继电器控制终端"); + oled_locate(1, 1); oled_print("继电器控制终端"); oled_locate(2, 2); oled_print("V" FIRMWARE_VERSION_STR " RTOS"); log_info("> OLED: 初始化完成"); diff --git a/V1.5/STM32F103_App1/HardWare/USER_CMD/user_cmd.c b/V1.5/STM32F103_App1/HardWare/USER_CMD/user_cmd.c index d354bc2..96c522c 100644 --- a/V1.5/STM32F103_App1/HardWare/USER_CMD/user_cmd.c +++ b/V1.5/STM32F103_App1/HardWare/USER_CMD/user_cmd.c @@ -21,6 +21,7 @@ #include "net_wifi.h" #include "esp8266.h" #include "reset_log.h" +#include "feed_scale.h" /* 本地命令字符串不区分大小写比较 */ static int cmd_is(const char *a, const char *b) @@ -57,6 +58,25 @@ void process_usart1_command(void) const char *cmd = USART1_GetCommand(); if (!cmd) return; + /* 产品模式查询/切换:SCALE 查询,SCALE0=四路继电器(无秤),SCALE1=称重投料(带秤),切换后自动重启生效 */ + if (cmd_is(cmd, "SCALE")) { + log_info("> BT: 产品模式 %s", g_feed_scale_on ? "SCALE1 称重投料(带秤)" : "SCALE0 四路继电器(无秤)"); + return; + } + if (cmd_is(cmd, "SCALE0") || cmd_is(cmd, "SCALE1")) { + uint8_t on = (cmd[5] == '1') ? 1 : 0; + if (on == g_feed_scale_on) { + log_info("> BT: 已是该模式,无需切换"); + return; + } + feed_scale_set_mode(on); + log_warn("> BT: 产品模式已切到 %s,重启生效...", on ? "称重投料(带秤)" : "四路继电器(无秤)"); + reset_log_mark(RSN_CMD_RESET); + HAL_Delay(200); + NVIC_SystemReset(); + return; + } + if (cmd_is(cmd, "RESET")) { log_warn("> USART1: 收到 RESET 命令,正在重启..."); reset_log_mark(RSN_CMD_RESET); @@ -123,7 +143,7 @@ void process_usart1_command(void) log_info("> BT: 当前日志等级 %s", lvs[(int)log_get_level()]); } else if (cmd_is(cmd, "HELP")) { - log_info("BT CMD: RESET, INFO, STATUS, R1ON/R1OFF~R4ON/R4OFF, ALLON, ALLOFF, OTA, RECOVERY, BLESET, LOG, LOGTRACE, LOGDEBUG, LOGINFO, LOGWARN, LOGERROR, LOGFATAL, HELP"); + log_info("BT CMD: RESET, INFO, STATUS, R1ON/R1OFF~R4ON/R4OFF, ALLON, ALLOFF, OTA, RECOVERY, BLESET, SCALE, SCALE0, SCALE1, LOG, LOGTRACE, LOGDEBUG, LOGINFO, LOGWARN, LOGERROR, LOGFATAL, HELP"); } else { log_warn("> BT: 未知命令 %s", cmd); diff --git a/V1.5/STM32F103_App1/README.md b/V1.5/STM32F103_App1/README.md index c29866f..2f3deb1 100644 --- a/V1.5/STM32F103_App1/README.md +++ b/V1.5/STM32F103_App1/README.md @@ -317,6 +317,7 @@ W25Q64 澶栭儴 Flash锛8MB锛夛細 | 132~157 | 26B | 钃濈墮鍚嶇О閰嶇疆缂撳瓨锛堝懡涓垯寮鏈鸿烦杩囪摑鐗 AT 璁剧疆娴佺▼锛 | | 160 | 1B | 鏃ュ織绛夌骇锛0~5锛歍RACE/DEBUG/INFO/WARN/ERROR/FATAL锛 | | 164~171 | 8B | HLW8032 绱鑴夊啿鏁帮紙uint64锛屾瘡鏀 0.1kWh + 鏂數鍓嶅啓鍏ワ級 | +| 172 | 1B | 浜у搧妯″紡锛0=鍥涜矾缁х數鍣(鏃犵Г)锛1=绉伴噸鎶曟枡(甯︾Г)锛岀┖鐧芥椂鐢 main.h 瀹忛粯璁ゅ硷紙钃濈墮 SCALE0/SCALE1 鍒囨崲锛 | | 250 | 1B | 鎺㈡祴瀛楄妭锛堜笂鐢靛啓 0xA5 鍥炶锛岄獙璇 I2C 閫氫俊锛 | > 娉ㄦ剰锛氭敼 `MqttInfo_Str` 缁撴瀯浣撲細鏀瑰彉涓婅堪鍋忕Щ锛岀Г鍙傛暟锛120+锛夊拰鑱旂綉鏂瑰紡锛130锛夊湪 @@ -340,6 +341,10 @@ W25Q64 澶栭儴 Flash锛8MB锛夛細 涓嬭鎶ユ枃鐢 `m_app/proto.c` 鎸夐敭鍚嶅畾浣嶈В鏋愶紙`"sw2"` 涓嶄細璇腑 `"sw21"`锛屽叾浠栧瓧娈甸噷鐨 true/false 涓嶄細閫犳垚璇垽锛夈 +## 浜у搧妯″紡锛堝甫绉/鏃犵Г锛岃繍琛屾椂鍙垏锛 + +`PRODUCT_WITH_FEED_SCALE` 浠庣函缂栬瘧瀹忔敼涓**杩愯鏃跺彲鍒囨崲**锛氭ā寮忓瓨 EEPROM(172)锛岀┖鐧芥椂鐢 main.h 瀹忓仛榛樿鍊笺傝摑鐗欏懡浠わ細`SCALE` 鏌ヨ锛宍SCALE0`=鍥涜矾缁х數鍣(鏃犵Г)锛宍SCALE1`=绉伴噸鎶曟枡(甯︾Г)锛**鍒囨崲鍚庤嚜鍔ㄩ噸鍚敓鏁**锛堝垵濮嬪寲璺緞涓嶅悓锛屽繀椤婚噸鍚級銆傚奖鍝嶈寖鍥达細鐘舵佷笂鎶ュ瓧娈(zero/onceWt)銆乻w1/feeding 鎸囦护璇箟銆佺户鐢靛櫒 1 鏂數璁板繂绛栫暐銆佺Г杞寮鍏炽 + ## 涓插彛璋冭瘯鍛戒护 閫氳繃 USART1锛堣摑鐗欎覆鍙o級鍙戦侊細 diff --git a/V1.5/鐗堟湰璇存槑.md b/V1.5/鐗堟湰璇存槑.md index e3ae85a..a45a1db 100644 --- a/V1.5/鐗堟湰璇存槑.md +++ b/V1.5/鐗堟湰璇存槑.md @@ -121,3 +121,8 @@ - OLED 鐣岄潰閲嶆瀯锛氭湭鑱旂綉鍙樉绀鸿仈缃戣繘搴︼紙4G 鍚勯樁娈典腑鏂囨彁绀 / WiFi 鍥哄畾鐑偣鎼滅储鍊掕鏃 / SmartConfig"璇锋墦寮APP骞挎挱"鍊掕鏃讹級锛岃仈缃戝悗鎵嶆樉绀虹數鑳/寮鍏/缃戠粶/杩愯鏃堕棿锛 寮鍏崇姸鎬佹敼涓枃锛堝紑鍏:寮寮鍏冲叧锛夛紱闃茬儳灞忔瘡 10s 鍐呭鍙崇Щ 0/2/4px 杞崲 +- 浜у搧妯″紡 PRODUCT_WITH_FEED_SCALE 鏀逛负杩愯鏃跺彲鍒囷細EEPROM(172) 瀛 0/1锛堢┖鐧界敤 main.h 瀹忛粯璁わ級锛 + 钃濈墮鍛戒护 SCALE 鏌ヨ / SCALE0=鏃犵Г鍥涜矾缁х數鍣 / SCALE1=甯︾Г绉伴噸鎶曟枡锛屽垏鎹㈠悗鑷姩閲嶅惎鐢熸晥锛 + 鍘 9 澶 #if 缂栬瘧鍒嗘敮鍏ㄩ儴鏀硅繍琛屾椂鍒ゆ柇锛堢姸鎬佷笂鎶ュ瓧娈/sw1路feeding 璇箟/缁х數鍣1璁板繂/绉よ疆璇級 +- OLED 娆㈣繋椤垫敼"缁х數鍣ㄦ帶鍒剁粓绔 / V1.5.0 RTOS"锛涗慨澶 4G 闃诲寤洪摼鏈熼棿灞忓箷涓嶆樉绀鸿仈缃戣繘搴 + 锛坆g_delay 鎸傝皟搴﹀櫒鍚姩鍓嶇殑 500ms 鍒锋柊閽╁瓙锛