Compare commits
	
		
			2 Commits
		
	
	
		
			10525dcfcc
			...
			9b13d413c4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9b13d413c4 | |||
| cd0f51057a | 
							
								
								
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | # 默认忽略的文件 | ||||||
|  | /shelf/ | ||||||
|  | /workspace.xml | ||||||
|  | # 基于编辑器的 HTTP 客户端请求 | ||||||
|  | /httpRequests/ | ||||||
|  | # Datasource local storage ignored files | ||||||
|  | /dataSources/ | ||||||
|  | /dataSources.local.xml | ||||||
							
								
								
									
										100
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,3 +1,99 @@ | |||||||
| # pig-house-controller | # 猪舍主控 | ||||||
|  |  | ||||||
| 猪舍主控节点,根据上位机的指令控制当前猪舍内所有设备(传感器,阀门,电机等),并汇聚当前猪舍传感器数据统一上报 | ## 简介 | ||||||
|  |  | ||||||
|  | 猪舍主控系统根据上位机的指令控制当前猪舍内所有设备(传感器,阀门,电机等),并汇聚当前猪舍传感器数据统一上报。本系统作为猪场智能化管理的重要组成部分,实现了猪舍环境的自动化监控与调节。 | ||||||
|  |  | ||||||
|  | ## 功能概述 | ||||||
|  |  | ||||||
|  | ### 与上位机交互 | ||||||
|  | 1. 根据上位机指令定期采集栏内所有传感器的数据,并统一上报 | ||||||
|  | 2. 根据上位机指令启动或关闭栏内设备,上位机发送的启动指令分两种: | ||||||
|  |     - 常开指令:收到后启动设备,直到收到关闭指令后关闭设备 | ||||||
|  |     - 短暂开启指令:收到后启动设备,但需要上位机每过两秒发送一次指令,超过五秒没收到下一个开启指令或受到关闭指令将会关闭设备 | ||||||
|  | 3. 定期检查栏内设备状态,发现异常立即上报上位机 | ||||||
|  | 4. 定期向上位机发送心跳包 | ||||||
|  | 5. 接收上位机发送的总线上各机器的位置和类型 | ||||||
|  | 6. 根据上位机指令调整设备功率大小 | ||||||
|  | 7. 接收上位机批量控制指令并执行 | ||||||
|  | 8. 接收上位机发送的配置信息 | ||||||
|  |  | ||||||
|  | ### 与设备交互 | ||||||
|  | 1. 控制栏内设备启停 | ||||||
|  | 2. 调整风机等功率可调设备的功率 | ||||||
|  | 3. 定时检查栏内设备状态 | ||||||
|  | 4. 定时采集栏内数据 | ||||||
|  |  | ||||||
|  | ### 数据管理 | ||||||
|  | 1. 保存总线上各机器的位置和类型 | ||||||
|  | 2. 临时保存上位机发送的指令 | ||||||
|  | 3. 保存上位机发送的配置信息 | ||||||
|  | 4. 汇总栏内所有传感器数据 | ||||||
|  | 5. 临时保存栏内设备故障信息,直到上报成功后清除 | ||||||
|  | 6. 根据批量指令控制对应设备工作 | ||||||
|  |  | ||||||
|  | ## 系统架构 | ||||||
|  |  | ||||||
|  | ### 通信协议 | ||||||
|  | - 上位机和猪舍主控间通过LoRa协议互联 | ||||||
|  | - 主控与设备/传感器通过Modbus RTU协议通信 | ||||||
|  |  | ||||||
|  | ### 硬件组成 | ||||||
|  | - 主控制器:树莓派PICO RP2040 | ||||||
|  | - 通信接口:RS485总线、LoRa无线模块 | ||||||
|  | - 传感器:硫化氢、氨气、二氧化碳、光照、温度、湿度、风速、气压等 | ||||||
|  | - 执行设备:风机、水帘、喷淋系统、除臭水帘、刮粪机、电磁阀等 | ||||||
|  |  | ||||||
|  | ### 硬件拓扑图 | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | graph LR | ||||||
|  |     A[猪场主控] -->|LoRa| B[猪舍主控] | ||||||
|  |     B -->|Modbus RTU| C[RS485总线1] | ||||||
|  |     B -->|Modbus RTU| D[RS485总线2] | ||||||
|  |     C -->|Modbus RTU| E1[硫化氢传感器] | ||||||
|  |     C -->|Modbus RTU| E2[氨气传感器] | ||||||
|  |     C -->|Modbus RTU| E3[二氧化碳传感器] | ||||||
|  |     C -->|Modbus RTU| E4[光照传感器] | ||||||
|  |     C -->|Modbus RTU| E5[温度传感器] | ||||||
|  |     C -->|Modbus RTU| E6[湿度传感器] | ||||||
|  |     C -->|Modbus RTU| E7[风速传感器] | ||||||
|  |     C -->|Modbus RTU| E8[气压传感器] | ||||||
|  |     D -->|Modbus RTU| F[继电器] | ||||||
|  |     F -->|通/断电| G1[风机] | ||||||
|  |     F -->|通/断电| G2[水帘] | ||||||
|  |     F -->|通/断电| G3[栏内喷淋] | ||||||
|  |     F -->|通/断电| G4[除臭水帘] | ||||||
|  |     F -->|通/断电| G5[刮粪机] | ||||||
|  |     F -->|通/断电| H[电磁五通阀] | ||||||
|  |     H -->|通/断气| I[气动三通阀] | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## 使用说明 | ||||||
|  |  | ||||||
|  | ### 硬件准备 | ||||||
|  | 1. 树莓派 PICO RP2040 开发板 | ||||||
|  | 2. RS485 转 UART 模块 | ||||||
|  | 3. LoRa 模块 (如 SX1276/SX1278) | ||||||
|  | 4. 传感器和设备(如上述硬件拓扑图所示) | ||||||
|  |  | ||||||
|  | ### 安装步骤 | ||||||
|  | 1. 按照硬件拓扑图连接所有设备和传感器 | ||||||
|  | 2. 将程序上传到树莓派 PICO | ||||||
|  | 3. 配置系统参数和设备信息 | ||||||
|  | 4. 启动系统 | ||||||
|  |  | ||||||
|  | ### 启动系统 | ||||||
|  | ```bash | ||||||
|  | # 使用 mpremote 运行主程序 | ||||||
|  | mpremote connect [设备路径] run main.py | ||||||
|  | ``` | ||||||
|  | 或者直接将 main.py 设置为启动脚本,让 PICO 上电后自动运行 | ||||||
|  |  | ||||||
|  | ## 开发相关 | ||||||
|  |  | ||||||
|  | 详细的开发指南、项目结构、配置说明和技术规范请参考 [DEVELOPMENT.md](DEVELOPMENT.md) 文件。 | ||||||
|  |  | ||||||
|  | ## 许可证 | ||||||
|  |  | ||||||
|  | 禁止未经授权使用本项目代码,否则后果自负。 | ||||||
							
								
								
									
										1
									
								
								comms/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								comms/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 通信层 | ||||||
							
								
								
									
										1
									
								
								comms/base_comm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								comms/base_comm.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 通信接口 | ||||||
							
								
								
									
										1
									
								
								comms/lora.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								comms/lora.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # lora实现 | ||||||
							
								
								
									
										1
									
								
								core/command_handler.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								core/command_handler.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 处理接收的指令 | ||||||
							
								
								
									
										1
									
								
								core/heartbeat.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								core/heartbeat.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 心跳包 | ||||||
							
								
								
									
										1
									
								
								core/scheduler.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								core/scheduler.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 定时任务 | ||||||
							
								
								
									
										1
									
								
								devices/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								devices/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 设备驱动 | ||||||
							
								
								
									
										1
									
								
								devices/base_device.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								devices/base_device.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 设备抽象层 | ||||||
							
								
								
									
										1
									
								
								devices/feed_port.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								devices/feed_port.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 下料口 | ||||||
							
								
								
									
										1
									
								
								devices/temperature.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								devices/temperature.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 温度传感器 | ||||||
							
								
								
									
										1
									
								
								storage/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								storage/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 持久化存储 | ||||||
							
								
								
									
										11
									
								
								storage/base_storage.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								storage/base_storage.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | # 存储接口 | ||||||
|  |  | ||||||
|  | class BaseStorage: | ||||||
|  |     def save(self, key: str, value): | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |     def load(self, key: str, default=None): | ||||||
|  |         raise NotImplementedError | ||||||
|  |  | ||||||
|  |     def delete(self, key: str): | ||||||
|  |         raise NotImplementedError | ||||||
							
								
								
									
										40
									
								
								storage/json_storage.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								storage/json_storage.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | # json 文件实现 | ||||||
|  |  | ||||||
|  | import json | ||||||
|  |  | ||||||
|  | from storage.base_storage import BaseStorage | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class JSONStorage(BaseStorage): | ||||||
|  |     def __init__(self, filename="data.json"): | ||||||
|  |         self.filename = filename | ||||||
|  |         # 如果文件不存在,先创建空字典 | ||||||
|  |         try: | ||||||
|  |             with open(self.filename, "r") as f: | ||||||
|  |                 pass | ||||||
|  |         except OSError: | ||||||
|  |             with open(self.filename, "w") as f: | ||||||
|  |                 f.write("{}") | ||||||
|  |  | ||||||
|  |     def _read_all(self): | ||||||
|  |         with open(self.filename, "r") as f: | ||||||
|  |             return json.load(f) | ||||||
|  |  | ||||||
|  |     def _write_all(self, data): | ||||||
|  |         with open(self.filename, "w") as f: | ||||||
|  |             json.dump(data, f) | ||||||
|  |  | ||||||
|  |     def save(self, key, value): | ||||||
|  |         data = self._read_all() | ||||||
|  |         data[key] = value | ||||||
|  |         self._write_all(data) | ||||||
|  |  | ||||||
|  |     def load(self, key, default=None): | ||||||
|  |         data = self._read_all() | ||||||
|  |         return data.get(key, default) | ||||||
|  |  | ||||||
|  |     def delete(self, key): | ||||||
|  |         data = self._read_all() | ||||||
|  |         if key in data: | ||||||
|  |             del data[key] | ||||||
|  |             self._write_all(data) | ||||||
							
								
								
									
										1
									
								
								storage/memory_storage.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								storage/memory_storage.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 内存实现 | ||||||
							
								
								
									
										1
									
								
								tests/test_comm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/test_comm.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # | ||||||
							
								
								
									
										1
									
								
								tests/test_core.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/test_core.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 核心逻辑测试 | ||||||
							
								
								
									
										1
									
								
								tests/test_devices.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/test_devices.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # | ||||||
							
								
								
									
										1
									
								
								tests/test_storage.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/test_storage.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # | ||||||
							
								
								
									
										1
									
								
								utils/crc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								utils/crc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 校验工具 | ||||||
							
								
								
									
										57
									
								
								utils/fs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								utils/fs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | # 兼容PC和MicroPython的文件操作 | ||||||
|  |  | ||||||
|  | # compat_fs.py | ||||||
|  | try: | ||||||
|  |     import uos as os  # MicroPython | ||||||
|  |     MICROPYTHON = True | ||||||
|  | except ImportError: | ||||||
|  |     import os         # CPython | ||||||
|  |     MICROPYTHON = False | ||||||
|  |  | ||||||
|  | def list_dir(path="."): | ||||||
|  |     """列出目录内容""" | ||||||
|  |     return os.listdir(path) | ||||||
|  |  | ||||||
|  | def make_dir(path): | ||||||
|  |     """创建目录""" | ||||||
|  |     if MICROPYTHON: | ||||||
|  |         os.mkdir(path) | ||||||
|  |     else: | ||||||
|  |         os.makedirs(path, exist_ok=True) | ||||||
|  |  | ||||||
|  | def remove_file(path): | ||||||
|  |     """删除文件""" | ||||||
|  |     os.remove(path) | ||||||
|  |  | ||||||
|  | def read_file(path, mode="r"): | ||||||
|  |     """读取文件内容""" | ||||||
|  |     with open(path, mode) as f: | ||||||
|  |         return f.read() | ||||||
|  |  | ||||||
|  | def write_file(path, data, mode="w"): | ||||||
|  |     """写入文件内容""" | ||||||
|  |     with open(path, mode) as f: | ||||||
|  |         f.write(data) | ||||||
|  |  | ||||||
|  | def is_file(path): | ||||||
|  |     """判断是否是文件""" | ||||||
|  |     try: | ||||||
|  |         st = os.stat(path) | ||||||
|  |         # MicroPython: stat()[0] >> 14 & 0xF == 8 表示普通文件 | ||||||
|  |         if MICROPYTHON: | ||||||
|  |             return (st[0] >> 14) & 0xF == 8 | ||||||
|  |         else: | ||||||
|  |             return os.path.isfile(path) | ||||||
|  |     except OSError: | ||||||
|  |         return False | ||||||
|  |  | ||||||
|  | def is_dir(path): | ||||||
|  |     """判断是否是目录""" | ||||||
|  |     try: | ||||||
|  |         st = os.stat(path) | ||||||
|  |         if MICROPYTHON: | ||||||
|  |             return (st[0] >> 14) & 0xF == 2 | ||||||
|  |         else: | ||||||
|  |             return os.path.isdir(path) | ||||||
|  |     except OSError: | ||||||
|  |         return False | ||||||
							
								
								
									
										1
									
								
								utils/logger.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								utils/logger.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 日志 | ||||||
							
								
								
									
										1
									
								
								utils/parser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								utils/parser.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | # 数据解析工具 | ||||||
		Reference in New Issue
	
	Block a user