Skip to content

DS1603 超声波液位计接入 ThinkLink 对接文档

1. 传感器简介

DS1603 是深圳市星科创科技有限公司生产的一款 超声波液位计,采用非接触超声波穿透容器壁检测液位的原理,可输出 RS485(Modbus-RTU) 信号,适用于各类工业储罐、水处理池的液位连续监测。设备具备 IP67 防护等级,可穿透 ≤20mm 的非金属容器壁,不接触液体即可完成测量。

本次对接方案中,设备型号为 DS1603,业务代码为 22109,模板名称为 DS1603


2. 产品特点

根据厂家资料,DS1603 具备以下特点:

  • 非接触检测 — 穿透塑料、玻璃、陶瓷等非金属容器壁,无需开孔
  • 抗腐蚀 — 不接触强酸强碱等液体,寿命耐久
  • 抗干扰 — 针对工频干扰和共模干扰特殊处理
  • 高精度 — 毫米级分辨率(±1.5mm),实时连续输出
  • 液体普适性 — 不受液体密度、形状、杂质、泡沫、水垢影响
  • IP67 防护 — 适用于潮湿和户外环境
  • RS485 Modbus RTU — 支持多点串联(最多 32 点)

3. 适用范围

DS1603 可广泛应用于以下场景:

  • 工业储罐液位监测 — 化工厂、电镀厂酸/碱/溶剂储罐
  • 水处理液位监控 — 水塔、水箱、废水处理池液位实时监测
  • 多仓集中监控 — RS485 总线一主多从,集中管理多个储罐
  • 农业灌溉水位管理 — 大棚营养液罐、灌溉水箱液位监测

4. 采集器信息

4.1 硬件信息

本方案采集设备采用 KC21

  • 设备型号:KC21
  • 接口:RS-485
  • 供电方式:内置电池 10800mAH / DC 5-12V

4.2 接线信息

电源与通讯接口

DS1603 的 RS485 输出接线定义如下:

  • Pin 1:VCC(12-24V 电源正极)
  • Pin 2:GND(电源负极)
  • Pin 3:RS485 A (+)
  • Pin 4:RS485 B (-)

传感器接口

本方案中,DS1603 自带 RS485 输出接口,直接接入 KC21 的 RS485 接口即可。 接线端子为 2.54mm 间距 4pin 排针。


5. 数据采集

本方案中,通过 Modbus 读取以下寄存器:

  • 0x00:液位处理值,uint16BE,单位 mm(本集成仅采集此寄存器)

平台侧约定:

  • 上传/采集周期参数地址:70(共用同一周期)

5.1 寄存器定义

根据厂家 Modbus 寄存器表(功能码 03H 读 / 06H 写),寄存器定义如下:

地址项目描述数据类型读写说明
0x00液位处理值uint16BER多次采样处理后的稳定液位,单位 mm(本集成采集此点)
0x01液位实时值uint16BER每次采样的瞬时液位,单位 mm(本集成未采集)
0x04从机地址uint16BER/WModbus 从站地址,默认 1,范围 1-247,掉电保存
0x05测量介质uint16BER/W1=水,2=油,默认 1
0x06工作周期uint16BER/WN 秒工作一次,N=1-60s,默认 2s

注:设备无波特率寄存器,串口固定 9600,N,8,1。

支持的 Modbus 功能码:

  • 03H:读保持寄存器
  • 06H:写单个寄存器

5.2 通信示例

读取液位处理值 (0x00):

Request:  01 03 00 00 00 01 84 0A
Response: 01 03 02 00 DD F9 85   (示例: 处理值 = 0x00DD = 221mm)

写测量介质 (0x05) — 改为油:

Request:  01 06 00 05 00 02 18 0A
Response: 01 06 00 05 00 02 18 0A   (原帧回显 = 成功)

6. EdgeBus 模型

6.1 EB 配置参数

主要配置参数如下:

  • name: "xkc-ds1603"
  • port: 22
  • version: "0x87"
  • dataType: "0x10"
  • upPeriodIndex: 70
  • Modbus 默认串口参数:
    • BaudRate: 9600
    • StopBits: 1
    • DataBits: 8
    • Checkbit: NONE
  • BzType: 22109
  • BzVersion: 1

6.2 EB 代码

typescript
import { Buffer } from "buffer";
import { buildOtaFile } from "@EBSDK/run";
import { EBModel } from "@EBSDK/EBCompiler/EBModel/EBModel";
import { EventInfoItem } from "@EBSDK/EBCompiler/plugins/EBHelper";
import type { UserConfUPItem } from "@EBSDK/EBCompiler/plugins/EBHelper";
import { CheckbitEnum, getOtaConfig } from "@EBSDK/otaConfig";

const eventInfo: UserConfUPItem[] = [
  {
    name: "xkc-ds1603", port: 22, version: "0x87", dataType: "0x10", upPeriodIndex: 70,
    quInfo: [
      {
        protocol: "modbus", addr: "0x01", code: "0x03", periodIndex: 70,
        indexAPP: 150, indexCMD: 0, copySize: 1,
        listVal: [
          { start: "0", end: "1" }
        ]
      }
    ]
  }
];

let otaConfig = getOtaConfig({
  BaudRate: 9600,
  StopBits: 1,
  DataBits: 8,
  Checkbit: CheckbitEnum.NONE,
  Battery: true,
  ConfirmDuty: 60,
  BzType: 22109,
  BzVersion: 1
});

const MODBUS_TT = (ebModel: EBModel) => {
  for (let i = 0; i < eventInfo.length; i++) {
    let event = new EventInfoItem(eventInfo[i]);
    event.upEventSetup();
    event.eventInstall();
  }
  return JSON.stringify(ebModel, null, 2);
};
buildOtaFile(__filename, otaConfig, MODBUS_TT);

6.3 说明

当前 EB 逻辑说明:

  • EdgeBus 通过 Port 22 上报业务数据。
  • 读取寄存器 0x00(共 1 个寄存器),获取液位处理值。
  • 上传周期与采集周期相同,均由 APP 参数 70 管理。
  • Modbus 地址由 APP 参数 150 管理。

7. 物模型

7.1 物模型基本信息

数据物模型

  • 名称:[DS1603]
  • id Name:ds1603_22109

参数物模型

  • 名称:[DS1603-PARA]
  • id Name:ds1603_para_22109

7.2 上行帧结构

数据上行帧结构如下:

typescript
let frameInfo = {
    port: 22, dataLen: 8, rssi: true, battery: 4,
    tagList: [{index: 0, tag: 0x87}, {index: 1, tag: 0x10}]
}

字段定义如下:

  • index 6levelProcessed,uint16BE,液位处理值(mm)

说明:设备 Modbus 有处理值(0x00)和实时值(0x01)两个寄存器,但本集成 EB 仅读取 0x00 处理值,因此物模型只有 levelProcessed 一个遥测点,不采集 levelRealtime

7.3 物模型脚本

7.3.1 数据物模型脚本

typescript
let port = msg?.userdata?.port || null;
if (port !== 22) return null
let frameInfo = {
    port: 22, dataLen: 8, rssi: true, battery: 4,
    tagList: [{index: 0, tag: 0x87}, {index: 1, tag: 0x10}]
}
let appInfo = [
    {name: "levelProcessed", field_name: "levelProcessed", unit: "mm", index: 6, type: "uint16BE"},
]
let payParser = new PayloadParser({
    device: device,
    msg: msg,
    frameInfo: frameInfo,
    appInfo: appInfo,
})
let tdata = payParser.telemetry()
if ((tdata?.status & 0x02) === 0x02) {
    const status = tdata.status
    tdata = {...(device.telemetry_data?.[thingModelId] ?? {})}
    tdata.status = status
}
return {
    telemetry_data: tdata,
    server_attrs: null,
    shared_attrs: null
}

7.3.2 参数物模型脚本

typescript
let port = msg?.userdata?.port || null;
const rpcName = "ds1603_set_22109"
let paraDef = {
    app_70: {name: "period_up", field_name: "period_up", unit: "s", type: "uint32LE"},
    app_150: {name: "modbus_addr", field_name: "modbus_addr", unit: "", type: "uint8"}
}
if (port !== 214) {
    let checkData = Utils.paraCheck(rpcName, device.server_attrs, device.shared_attrs)
    return {
        server_attrs: checkData.sdata,
        actions: checkData.actions,
    }
}
let pdata = (new PayloadParser({
    device: device,
    msg: msg,
    paraInfo: paraDef,
})).paras()
let checkData = Utils.paraCheck(rpcName, device.server_attrs, pdata)
return {
    telemetry_data: pdata,
    server_attrs: checkData.sdata,
    shared_attrs: pdata,
    actions: checkData.actions,
}

8. 第三方平台数据订阅

8.1 MQTT Topic

/v32/{Organization Account}/tkl/up/telemetry/{eui}

8.2 上报示例数据

根据本模板的物模型字段,整理后的示例数据如下:

json
{
    "eui": "6353012af10a9429",
    "active_time": "2026-05-11T08:35:48.000Z",
    "thingModelId": "22109",
    "thingModelIdName": "ds1603_22109",
    "telemetry_data": {
        "snr": 11.8,
        "rssi": -37,
        "battery": 3.65,
        "levelProcessed": 221
    }
}

说明:

  • thingModelId 实际应以平台生成值为准,这里用业务代码 22109 作示例。
  • thingModelIdName 对应数据物模型 ds1603_22109
  • levelProcessed 为超声波传感器到液面的处理后液位值,单位 mm。

9. RPC

9.1 RPC 名称

配置参数 RPC

  • 名称:[DS1603 SET] 22109
  • id Name:ds1603_set_22109

读取参数 RPC

  • 名称:[DS1603 GET] 22109
  • id Name:ds1603_get_22109

测量介质 RPC(Action)

  • 名称:[DS1603 SET MEDIUM] 22109
  • id Name:ds1603_set_medium_22109

9.2 参数定义

参数地址名称field_name单位类型说明
app_70period_upperiod_upsuint32LE上传/采集周期
app_150modbus_addrmodbus_addruint8Modbus 地址

9.3 RPC 代码

配置参数 RPC

typescript
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
let intervalms = classMode === "ClassA" ? 0 : 2000;
const rpcName = "ds1603_set_22109"
let paraDef = {
    app_70: {name: "period_up", field_name: "period_up", unit: "s", type: "uint32LE"},
    app_150: {name: "modbus_addr", field_name: "modbus_addr", unit: "", type: "uint8"}
}
let frames = RPCHelper.buildFrame({
    paraDef: paraDef,
    params: params
})
let redoBuffer = RPCHelper.redo()
let dnBuffer = Buffer.alloc(frames.writeBuffer.length + frames.readBuffer.length);
frames.writeBuffer.copy(dnBuffer, 0)
frames.readBuffer.copy(dnBuffer, frames.writeBuffer.length)
logger.info("set para")
let msgQue = Utils.makeParaSetMSG({
    device: device,
    classMode: classMode,
    rpcName: rpcName,
    params: params,
    paraDownBuffer: dnBuffer,
    extraAppBuffer: redoBuffer
})
if (msgQue.length == 0) return null
return msgQue

读取参数 RPC

typescript
let classMode = (device && device.shared_attrs && device.shared_attrs.class_mode) || "ClassA";
let sleepMs = classMode === "ClassA" ? 500 : 5000;
let paraDef = {
    app_70: {name: "period_up", field_name: "period_up", unit: "s", type: "uint32LE"},
    app_150: {name: "modbus_addr", field_name: "modbus_addr", unit: "", type: "uint8"}
}
let frames = RPCHelper.buildFrame({
    paraDef: paraDef,
    params: params
})
let msg = RPCHelper.makeMSG({
    msgType: Utils.msgType.paras,
    device: device,
    dnBuffer: frames.readBuffer,
    sleepTime: sleepMs,
})
return [msg]

9.4 测量介质 RPC(Action)

通过透明通道向设备寄存器 0x05 写测量介质(Modbus 功能码 06H),并校验设备回显、同步共享属性。

参数定义

参数field_name类型取值说明
mediummediumnumber1=水 / 2=油测量介质(下拉选择),默认 1=水

读取路径:设置成功后 medium 同步到共享属性,下次打开表单自动回填当前值(无独立 get RPC)。

RPC 代码

typescript
let classMode = (device?.shared_attrs?.class_mode) || "ClassA";
let addr_modbus = device.shared_attrs?.addr_modbus ?? device.shared_attrs?.addr ?? 1;
let rpcName = "ds1603_set_medium_22109";

// 测量介质:寄存器 0x05,FC06 写。1=水,2=油(其他值无效)
if (params.medium === undefined) return null;
let checkVal = Number(params.medium);
if (checkVal !== 1 && checkVal !== 2) return null;

let dnBuffer = RPCHelper.modbusAction(addr_modbus, 6, 0x0005, checkVal);

let checkInfo = {
    frameInfo: {port: 51, dataLen: 8},
    appInfo: [{field_name: "medium", index: 4, type: "uint16BE", val: checkVal}],
    telemetry_data: {medium: checkVal},
    server_attrs: null,
    shared_attrs: {medium: checkVal}
};
let msgQue = Utils.makeParaSetMSG({
    msgType: Utils.msgType.transParent,
    checkInfo: checkInfo,
    device: device,
    classMode: classMode,
    rpcName: rpcName,
    params: params,
    paraDownBuffer: dnBuffer,
    timeout: 3000,
    maxRetries: 3
});
if (msgQue.length === 0) return null;
return msgQue;

Modbus 报文示例(写测量介质=油)

Request:  01 06 00 05 00 02 18 0A
Response: 01 06 00 05 00 02 18 0A   (原帧回显 = 成功)

10. 模板选择

在 ThinkLink 平台中搜索模板: DS1603

或按业务类型查找: 22109 / 超声波液位计 / RS485 Modbus 液位采集


补充说明

  1. 厂家默认 Modbus 参数为:
    • 地址:1
    • 波特率:9600
    • 数据位:8
    • 停止位:1
    • 校验:无校验 这些参数可通过上位机工具修改。
  2. DS1603 采用非接触测量原理,传感器探头安装于容器外壁,穿透非金属壁进行液位检测,适用于强酸、强碱等腐蚀性液体的储罐监测。
  3. 设备支持 RS485 一主多从模式(最多 32 点),可通过单个 KC21 集中管理多个储罐液位。
  4. 厂家文档给出的 Modbus 报文示例:
    • 读液位处理值:01 03 00 00 00 01 84 0A
    • 写从机地址(改为 0x02):01 06 00 04 00 02 49 CA
    • 写测量介质(改为油):01 06 00 05 00 02 18 0A