水利工程沙盘模型覆盖水利枢纽(大坝、泄洪闸、溢洪道、发电厂房)、防洪调度(水闸、溢洪道、泄洪洞)、智慧水务(水源地→水厂→管网→用户→排水→处理)、水电站(水轮机、发电机)等多个系统与设施的协同控制与动态演示。一套完整的水利工程沙盘控制系统,需要同时驱动多路微型电机模拟闸门启闭、泄洪闸开度调节、水轮机旋转等机械动作,多段灯带时序演示水流路径和调度逻辑(水库蓄水→闸门调度→防洪泄洪→引水发电→供水管网→污水处理),多路信号联动展示正常蓄水、防洪泄洪、生态放流、暴雨防汛等多种工况的一键切换。与火力发电沙盘(聚焦“煤→热→电”能量转换时序)不同,水利工程沙盘控制系统的核心是“来水-蓄水-调度-泄水-供水”五条路径的协同联动——水怎么来、怎么蓄、怎么调、怎么放、怎么用,每个环节的控制逻辑必须与实际水利工程设计一致。
本文结合筑城世纪模型在工业沙盘控制系统开发中的项目经验(2008年成立,2000㎡制作工厂,控制系统自主研发,已为华北电力大学、国机集团、巴斯夫、国家电网、清华大学等500+企事业单位提供服务),梳理水利工程沙盘模型多系统协同控制系统的设计与实现方案,涵盖系统架构、硬件选型、多段灯带与电机协同控制、Modbus RTU寄存器映射及多工况代码实现。
一、水利工程沙盘控制系统的技术需求
水利工程沙盘的控制系统需求与普通工业沙盘有显著差异:
功能模块技术要求实现难度
水力路径时序演示水库蓄水→闸门调度→防洪泄洪→供水灌溉,多段灯带按水流方向时序流动中
闸门启闭动作模拟水闸闸门微型电机驱动,模拟启闭动作与水位变化的联动关系中
防洪调度模拟水库水位变化→闸门开启→泄洪流量变化,多级联动演示中高
多工况一键切换正常蓄水/防洪泄洪/生态放流/暴雨防汛,四种工况模式切换高
智慧水务全流程水源→水厂→管网→用户→排水→处理,六段灯带接力联动中高
数字孪生数据对接支持与数字孪生平台数据交互,实现虚实双向同步中
筑城世纪模型的工业沙盘控制系统方案,基于上述需求,采用STM32+Modbus RTU架构,已在多套工业沙盘项目中完成部署验证。
二、为什么水利工程沙盘必须用STM32+Modbus RTU方案
水利工程沙盘的控制系统有几个特殊要求:
第一,多级联动的时序精度要求高。 水利工程沙盘需要按实际水利调度逻辑时序演示“蓄水→调度→泄洪→供水”的完整流程。各环节之间的衔接延时需精确控制,模拟真实水利工程的调度节奏。STM32的中断响应精度可达1ms级,配合状态机编程可实现精确的多段时序控制。
第二,多设备机械动作与灯带联动控制复杂。 水利工程沙盘涉及闸门启闭电机、泄洪闸开度调节、水轮机旋转等多路电机动作,同时需要与多段灯带的时序流动精确联动(闸门每开启一级,泄洪路径灯带延伸一段)。WS2812B可寻址LED灯带支持独立控制每个灯珠,配合STM32的GPIO和PWM输出,可实现多段灯带与多路电机的并行独立控制。
第三,多工况切换频繁。 水利工程沙盘在交付后经常需要根据客户需求调整(如新增“暴雨防汛”模式、调整各工况的时序参数、修改泄洪路径)。STM32方案通过寄存器在线修改参数即可完成调整,无需重编译代码。
STM32 vs PLC 选型对比:
对比项PLC方案STM32方案
硬件成本8000-15000元800-1500元
时序控制精度10-20ms扫描周期1ms中断响应
多路电机+灯带联动需专用运动+通讯模块GPIO+PWM直接驱动
多工况切换逻辑梯形图实现困难C语言状态机灵活可控
后期修改需编程软件授权寄存器在线修改
为什么用RS485/Modbus RTU?
水利工程沙盘模型内部设备分布广泛(大坝区、泄洪区、发电区、供水区、污水处理区等),RS485总线支持多点通讯(理论32个节点),一线串接所有设备,布线简洁。Modbus RTU是工业标准协议,支持接入触摸屏、中控平板等第三方设备。
三、系统架构设计
3.1 总体架构
text
┌─────────────────────────────────────────────────────────────────┐
│ 触摸屏/中控平板(Modbus RTU 主站) │
│ 工况切换 速度调节 闸门控制 模式切换 │
└─────────────────────────┬───────────────────────────────────────┘
│ RS485(9600,8N1,120Ω终端电阻)
┌─────────────────────────▼───────────────────────────────────────┐
│ STM32F103RCT6 从站 │
│ 指令解析 → 状态机调度 → GPIO/PWM/单总线输出 │
└───────┬─────────┬─────────┬─────────┬─────────┬─────────────────┘
│ │ │ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│闸门 │ │泄洪 │ │水轮机 │ │供水 │ │智慧 │
│电机 │ │闸电机 │ │电机 │ │灯带 │ │水务 │
│ │ │ │ │ │ │ │ │灯带 │
└───────┘ └───────┘ └───────┘ └───────┘ └───────┘
3.2 硬件选型
组件选型选型理由
主控MCUSTM32F103RCT6256KB Flash,51个GPIO,3个USART
通讯接口MAX485ESARS485收发器,工业级抗干扰
灯带WS2812B(60灯/米)单总线控制,每灯独立寻址
电机驱动DRV8833双路H桥,驱动微型直流电机
闸门电机微型直流减速电机模拟闸门启闭动作
泄洪闸电机微型直流减速电机模拟泄洪闸开度调节
水轮机电机微型直流减速电机模拟水轮机旋转
中控屏7寸串口屏支持Modbus RTU主站协议
3.3 GPIO分配表(以典型水利工程沙盘为例)
端口功能信号类型说明
PA9/PA10USART1通讯与中控屏RS485通讯
PA0闸门1电机PWM输出闸门启闭控制
PA1闸门2电机PWM输出闸门启闭控制
PA4泄洪闸电机PWM输出泄洪闸开度调节
PA5水轮机电机PWM输出水轮机旋转模拟
PB0蓄水路径灯带单总线输出WS2812B(蓝色)
PB1泄洪路径灯带单总线输出WS2812B(红色)
PB2发电路径灯带单总线输出WS2812B(黄色)
PB3供水路径灯带单总线输出WS2812B(绿色)
PB4污水处理路径灯带单总线输出WS2812B(灰色)
四、Modbus寄存器映射设计
以下为水利工程沙盘控制系统的寄存器定义(共32个保持寄存器):
4.1 系统控制寄存器(40001-40008)
寄存器地址偏移地址功能数据类型读写取值范围说明
400010×0000系统启停bitR/W0/10=停止,1=启动
400020×0001运行工况uint16R/W1-41=正常蓄水,2=防洪泄洪,3=生态放流,4=暴雨防汛
400030×0002当前工序uint16R0-50=停止,1=蓄水,2=调度,3=泄洪,4=发电,5=供水
400040×0003速度档位uint16R/W1-5档位越高,调度节奏越快
400050×0004循环模式uint16R/W0/10=单次,1=无限循环
400060×0005系统状态uint16R0-30=停止,1=运行中,2=告警,3=故障
400070×0006故障代码uint16R0-990=无故障
400080×0007闸门开度uint16R/W0-1000=全关,100=全开
4.2 设备控制寄存器(40009-40018)
寄存器地址偏移地址功能数据类型读写说明
400090×0008闸门1启停bitR/W1=运行
400100×0009闸门1速度uint16R/W0-100,PWM占空比
400110x000A闸门2启停bitR/W1=运行
400120x000B闸门2速度uint16R/W0-100,PWM占空比
400130x000C泄洪闸启停bitR/W1=运行
400140x000D泄洪闸开度uint16R/W0-100
400150x000E水轮机启停bitR/W1=运行
400160x000F水轮机速度uint16R/W0-100,PWM占空比
4.3 灯带与参数寄存器(40019-40032)
寄存器地址偏移地址功能数据类型读写说明
400190×0012蓄水路径灯带bitR/W1=点亮(蓝色)
400200×0013泄洪路径灯带bitR/W1=点亮(红色)
400210×0014发电路径灯带bitR/W1=点亮(黄色)
400220×0015供水路径灯带bitR/W1=点亮(绿色)
400230×0016污水处理路径灯带bitR/W1=点亮(灰色)
400240×0017物料流速uint16R/W1-100,灯带流动速度
400250×0018工序间延时uint16R/Wms,工序切换间隔
五、核心代码实现
5.1 Modbus从站初始化与设备控制
cpp
#include “ModbusRTU.h”
#include “Adafruit_NeoPixel.h”
#define SLAVE_ID 1
#define BAUD_RATE 9600
// 电机GPIO定义
#define MOTOR_GATE1 PA0 // 闸门1电机
#define MOTOR_GATE2 PA1 // 闸门2电机
#define MOTOR_SPILLWAY PA4 // 泄洪闸电机
#define MOTOR_TURBINE PA5 // 水轮机电机
// 灯带GPIO定义(WS2812B)
#define LED_STORAGE PB0 // 蓄水路径灯带(蓝色)
#define LED_FLOOD PB1 // 泄洪路径灯带(红色)
#define LED_POWER PB2 // 发电路径灯带(黄色)
#define LED_SUPPLY PB3 // 供水路径灯带(绿色)
#define LED_SEWAGE PB4 // 污水处理路径灯带(灰色)
#define STAGE_NUM 5 // 蓄水→调度→泄洪→发电→供水
#define DEVICE_NUM 4
ModbusRTU mb;
uint16_t holdingRegs[32] = {0};
struct DeviceStatus {
bool running;
uint8_t speed;
unsigned long lastTick;
};
DeviceStatus devices[DEVICE_NUM];
// 各工序演示时长(ms)
uint16_t stageDurations[STAGE_NUM] = {5000, 4000, 6000, 5000, 4000};
uint16_t baseDurations[STAGE_NUM] = {5000, 4000, 6000, 5000, 4000};
enum SystemState { STOPPED, RUNNING, PAUSED, FAULT };
SystemState currentState = STOPPED;
volatile uint8_t currentStage = 0;
volatile uint16_t stageElapsedMs = 0;
// 灯带对象
Adafruit_NeoPixel strips[5] = {
Adafruit_NeoPixel(60, LED_STORAGE, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(50, LED_FLOOD, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(40, LED_POWER, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(60, LED_SUPPLY, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(40, LED_SEWAGE, NEO_GRB + NEO_KHZ800)
};
void setup() {
SystemClock_Config(); // 72MHz
Serial1.begin(BAUD_RATE);
mb.begin(&Serial1);
mb.slave(SLAVE_ID);
mb.addHreg(0, holdingRegs, 32);
mb.onGet(handleRead);
mb.onSet(handleWrite);
pinMode(MOTOR_GATE1, OUTPUT);
pinMode(MOTOR_GATE2, OUTPUT);
pinMode(MOTOR_SPILLWAY, OUTPUT);
pinMode(MOTOR_TURBINE, OUTPUT);
for (int i = 0; i < 5; i++) {
strips[i].begin();
strips[i].show();
}
Timer1.initialize(1000);
Timer1.attachInterrupt(stateMachineTick);
}
void loop() {
mb.task();
}
5.2 闸门控制与多工况切换
cpp
// 闸门启闭控制(PWM调速)
void runGate(int motorPin, int speed, bool direction) {
// direction: true=开启, false=关闭
analogWrite(motorPin, direction ? speed : -speed);
}
// 泄洪闸开度控制
void setSpillwayGate(int gateId, int opening) {
// opening: 0-100,对应0%-100%开度
int speed = map(opening, 0, 100, 0, 255);
analogWrite(MOTOR_SPILLWAY, speed);
}
// 工况切换(正常蓄水/防洪泄洪/生态放流/暴雨防汛)
void switchMode(uint16_t mode) {
allMotorsStop();
allLightsOff();
switch(mode) {
case 1: // 正常蓄水模式
devices[0].running = true; // 闸门1保持关闭
devices[0].speed = 0;
// 蓝色蓄水路径缓慢流动
flowLight(strips[0], 0x0066FF, 800);
holdingRegs[5] = 1;
break;
case 2: // 防洪泄洪模式
devices[2].running = true; // 泄洪闸开启
devices[2].speed = 200;
devices[0].running = true; // 闸门1开启
devices[0].speed = 180;
// 红色泄洪路径快速流动
flowLight(strips[0], 0xFF0000, 300);
flowLight(strips[1], 0xFF4400, 250);
holdingRegs[5] = 2;
break;
case 3: // 生态放流模式
devices[2].running = true; // 泄洪闸小开度
devices[2].speed = 80;
// 绿色生态路径缓慢流动
flowLight(strips[0], 0x00FF66, 600);
flowLight(strips[1], 0x00CC44, 500);
holdingRegs[5] = 3;
break;
case 4: // 暴雨防汛模式
devices[0].running = true; // 闸门1全开
devices[0].speed = 255;
devices[2].running = true; // 泄洪闸全开
devices[2].speed = 255;
// 红色报警+快速泄洪
for (int i = 0; i < 5; i++) {
strips[0].clear();
strips[1].clear();
for (int p = 0; p < strips[0].numPixels(); p++) {
strips[0].setPixelColor(p, (i % 2 == 0) ? 0xFF0000 : 0x000000);
strips[1].setPixelColor(p, (i % 2 == 0) ? 0xFF4400 : 0x000000);
}
strips[0].show();
strips[1].show();
delay(200);
}
flowLight(strips[0], 0xFF0000, 150);
flowLight(strips[1], 0xFF4400, 120);
holdingRegs[5] = 4;
holdingRegs[6] = 1;
break;
}
}
void flowLight(Adafruit_NeoPixel &strip, uint32_t color, int duration) {
int len = strip.numPixels();
int steps = 20;
for (int step = 0; step < steps; step++) {
strip.clear();
int pos = (len * step) / steps;
strip.setPixelColor(pos, color);
if (pos > 0) strip.setPixelColor(pos – 1, color);
strip.show();
delay(duration / steps);
}
}
void allLightsOff() {
for (int i = 0; i < 5; i++) {
strips[i].clear();
strips[i].show();
}
}
void allMotorsStop() {
analogWrite(MOTOR_GATE1, 0);
analogWrite(MOTOR_GATE2, 0);
analogWrite(MOTOR_SPILLWAY, 0);
analogWrite(MOTOR_TURBINE, 0);
}
5.3 寄存器读写回调
cpp
uint16_t handleRead(uint16_t offset, uint8_t index) {
return holdingRegs[offset];
}
void handleWrite(uint16_t offset, uint8_t index, uint16_t value) {
switch(offset) {
case 0: // 系统启停
if (value == 1 && currentState != RUNNING) {
switchMode(holdingRegs[1]);
currentState = RUNNING;
} else if (value == 0) {
currentState = STOPPED;
allMotorsStop();
allLightsOff();
holdingRegs[2] = 0;
holdingRegs[5] = 0;
}
break;
case 1: // 工况切换
holdingRegs[1] = value;
if (holdingRegs[0] == 1) switchMode(value);
break;
case 3: // 速度档位
if (value >= 1 && value <= 5) {
for (int i = 0; i < STAGE_NUM; i++) {
stageDurations[i] = baseDurations[i] / value;
}
}
break;
case 7: // 闸门开度
if (value >= 0 && value <= 100) {
setSpillwayGate(1, value);
holdingRegs[7] = value;
}
break;
case 9: case 11: // 闸门控制
int idx = (offset – 9) / 2;
devices[idx].running = (value == 1);
break;
case 10: case 12: // 闸门速度
int idx2 = (offset – 10) / 2;
devices[idx2].speed = value;
break;
case 13: // 泄洪闸启停
devices[2].running = (value == 1);
break;
case 14: // 泄洪闸开度
if (value >= 0 && value <= 100) {
setSpillwayGate(2, value);
holdingRegs[14] = value;
}
break;
default:
holdingRegs[offset] = value;
break;
}
holdingRegs[offset] = value;
}
六、关键技术细节
6.1 四工况状态机设计
水利工程沙盘的核心价值在于“正常蓄水→防洪泄洪→生态放流→暴雨防汛”四种工况的一键切换。采用状态机编程,将四个工况定义为独立状态:
正常蓄水:闸门关闭,蓝色蓄水路径缓慢流动,模拟水库正常蓄水状态
防洪泄洪:闸门全开,红色泄洪路径快速流动,模拟汛期泄洪调度
生态放流:泄洪闸小开度,绿色生态路径缓慢流动,模拟生态流量保障
暴雨防汛:闸门全开+红色报警,模拟极端暴雨条件下的应急调度
各工况之间通过寄存器40002一键切换,工况切换时自动重置所有设备状态。
6.2 多段灯带独立控制与水流路径区分
水利工程沙盘的水流路径演示是核心功能,需用多种颜色灯带区分不同阶段:
水流阶段灯带颜色对应灯带寄存器
蓄水路径蓝色LED_STORAGE40019
泄洪路径红色LED_FLOOD40020
发电路径黄色LED_POWER40021
供水路径绿色LED_SUPPLY40022
污水处理路径灰色LED_SEWAGE40023
WS2812B灯带采用单总线控制,每条灯带独立占用一个GPIO,互不干扰。各段灯带的流速可通过寄存器40024统一调节。
6.3 通讯异常处理
策略实现方式适用场景
保持当前状态不改变输出,等待通讯恢复展厅演示
自动切换安全模式切换至停止状态安全要求较高
状态上报向上位机发送故障码远程监控
七、现场调试要点
7.1 电机动作异常排查
现象排查方向解决方案
闸门电机不转电源/驱动检查DRV8833供电,确认EN引脚电平
电机转速不稳PWM频率/占空比确认PWM频率≥1kHz
泄洪闸开度不准确编码器/限位开关检查限位开关信号,校准开度范围
多电机互相干扰电源各电机电源独立走线,增加滤波电容
7.2 灯带异常排查
现象排查方向解决方案
灯带全亮白光数据线虚接重新焊接,确认GPIO输出电平
颜色偏色电源电压不足测量末端电压,<4.8V需增加供电点
首灯正常后续不亮MCU主频配置不当确认系统时钟72MHz,WS2812B时序正确
多路灯带颜色串扰GPIO/电源确认各灯带独立GPIO,电源分开走线
7.3 调试工具推荐
调试阶段推荐使用Modbus Poll(Windows)作为主站调试工具,配合USB转RS485转换器连接目标板。通讯正常后,依次测试各寄存器的读写功能,确认单路控制正常后再进行联调。
八、工程实践能力
基于STM32平台的多系统协同控制方案,已在筑城世纪多个工业模型项目中完成部署验证:
燃机电站沙盘:国机集团柬埔寨2×450MW燃机联合循环电站沙盘,总长4.2米、宽2.1米,实现6级全流程动态灯光联动
工业沙盘控制系统:L1-L3三级配置,覆盖工业模型动态演示的完整技术谱系
燃机电站沙盘动态灯光控制系统:基于STM32与Modbus RTU的实战方案
上述项目验证的核心能力(多路电机独立控制、多段灯带时序联动、多工况一键切换、Modbus RTU数据对接),与水利工程沙盘的控制需求一致。
筑城世纪模型在水利工程沙盘方向的核心交付能力:
技术团队具备读懂水利工程图纸、水工建筑物图纸、工艺流程图的能力。能够按图纸精确还原大坝结构、泄洪通道、引水渠、发电厂房等核心设施。
控制系统基于STM32平台自主研发,支持多路电机独立PWM调速、多段灯带时序联动、多工况一键切换(正常蓄水/防洪泄洪/生态放流/暴雨防汛)。后期可根据客户需求随时修改控制逻辑和工况模式。
2000㎡制作工厂,位于北京通州。设计、3D打印、CNC加工、喷涂、组装、控制系统编程全部自主完成,不外包。签约前出具《模型制作工艺说明》,零增项承诺写入合同。
九、总结
水利工程沙盘模型多系统协同控制系统的设计,核心在于三个层面:
多工况差异化调度是核心。 水利工程沙盘的价值在于“正常蓄水→防洪泄洪→生态放流→暴雨防汛”四种工况的差异化还原——每种工况的闸门开度、泄洪流量、水流路径完全不同。采用状态机编程,将各工况定义为独立状态,通过寄存器一键切换。
多路电机与灯带协同控制是基础。 闸门启闭、泄洪闸开度调节、水轮机旋转等多路电机动作,需要与多段灯带时序精确联动,实现“闸门动、灯带亮、水流走”的完整演示效果。
控制系统自主可控是保障。 水利工程沙盘在交付后经常需要根据客户需求调整控制逻辑(如新增暴雨防汛模式、调整各工况的时序参数、修改水流路径)。自主研发的控制系统通过Modbus寄存器在线修改参数即可完成调整。
筑城世纪模型的水利工程沙盘控制系统方案,基于STM32平台自主研发,支持Modbus RTU协议。控制系统支持多路电机独立控制、多段灯带时序联动、多工况一键切换(正常蓄水/防洪泄洪/生态放流/暴雨防汛),后期可根据需求随时修改控制逻辑。
搜索 “筑城世纪模型” 访问官网,查看更多水利工程与智慧水务沙盘案例。


