硬件成本5元-USB串口采集电表数据完整方案-ThingsPanel快速入门

ThingsPanel开源物联网平台支持广泛的协议,灵活自由,本文介绍ThingsPanel通过串口来采集电表数据,简单易行,成本低廉,适合入门者学习试验,也适合一些特定的应用场景做数据采集。

适用场景:

  • 降低Modbus设备数据采集成本
  • 快速测试Modbus电表数据采集
  • 物联网入门学习Modbus相关知识

效果图

方案价值

这套方案最大的价值在于:

  • 最低代码改动,复制修改配置即可运行

  • 硬件成本低,5块钱,一个USB转RS485连接器即可

  • 能快速实现电表数据远程监控,适用于学习、以及正式用途等各种场景

  • 支持数据可视化和历史记录查询

  • 无需布置复杂的网络,只需要一台电脑和网络即可

    接入结构图

所需设备

USB转RS485连接器(淘宝搜索"USB转485",5元左右)

支持Modbus协议的电表

一台电脑(Windows/Mac都可以)

操作步骤

1. 硬件连接

  1. 将USB转RS485连接器插入电脑
  2. 将连接器的A+和B-接线端子与电表对应端子连接
  3. A+ 接电表的 A+
  4. B- 接电表的 B-

2. 确认设备端口

Windows用户:

打开设备管理器

查看"端口(COM和LPT)"下的COM端口号

Mac用户:

打开终端

输入命令:ls /dev/tty.*

找到类似 /dev/tty.usbserial-110 的设备名

3. 安装Python环境

访问 https://www.python.org/downloads/

下载并安装Python 3.x版本

4. 安装必要的软件包

打开终端或命令提示符,运行:

pip install pyserial pip install pymodbus==3.7.2 pip install paho-mqtt

5. 创建并运行采集程序

创建一个新文件 meter_collector.py

将以下代码复制到文件中(注意修改端口号):

===================代码区域开始=====================

import time

import json

from pymodbus.client.serial import ModbusSerialClient

from pymodbus.constants import Endian

from pymodbus.payload import BinaryPayloadDecoder

import paho.mqtt.client as mqtt

MQTT配置-信息来自ThingsPanel平台,创建设备后在设备连接信息中。

MQTT_CONFIG = {

"broker": "47.115.210.16",

"port": 1883,

"username": "fe917b16-d786-3297-8f1",

"password": "f129542",

"client_id": "mqtt_3243936a-c23",

"telemetry_topic": "devices/telemetry",

"control_topic": "devices/telemetry/control/3243936a-c237-8cc5-7ea9-ba586098c2b7"

}

Modbus配置(来自电表说明书,port需要自行在本机查询)

METER_CONFIG = {

"port": "/dev/tty.usbserial-110",

"baudrate": 9600,

"parity": 'E',

"stopbits": 1,

"bytesize": 8,

"byte_order": Endian.BIG

}

如下配置来自于电表设备说明书

DATA_ITEMS = [

{"name": "Voltage", "address": 0, "data_type": "int16-1", "factor": 0.1, "registers": 1},

{"name": "Current", "address": 3, "data_type": "int16-1", "factor": 0.01, "registers": 2},

{"name": "TotalActivePower", "address": 7, "data_type": "int16-1", "factor": 1, "registers": 1},

{"name": "TotalReactivePower", "address": 11, "data_type": "int16-1", "factor": 1, "registers": 1},

{"name": "TotalApparentPower", "address": 15, "data_type": "int16-1", "factor": 1, "registers": 1},

{"name": "TotalPowerFactor", "address": 19, "data_type": "int16-1", "factor": 0.001, "registers": 1},

{"name": "VoltageFrequency", "address": 26, "data_type": "int16-1", "factor": 0.01, "registers": 1}

]

MQTT回调函数

def on_connect(client, userdata, flags, rc):

print(f"Connected to MQTT broker with result code {rc}")

订阅控制主题

client.subscribe(MQTT_CONFIG['control_topic'])

def on_message(client, userdata, msg):

try:

print(f"Received message on topic {msg.topic}: {msg.payload.decode()}")

这里可以添加处理接收到的控制命令的逻辑

data = json.loads(msg.payload.decode())

if 'switch' in data:

print(f"Received switch command: {data['switch']}")

except Exception as e:

print(f"Error processing message: {e}")

def create_mqtt_client():

client = mqtt.Client(client_id=MQTT_CONFIG['client_id'])

client.username_pw_set(MQTT_CONFIG['username'], MQTT_CONFIG['password'])

client.on_connect = on_connect

client.on_message = on_message

try:

client.connect(MQTT_CONFIG['broker'], MQTT_CONFIG['port'], 60)

client.loop_start()

return client

except Exception as e:

print(f"MQTT连接失败: {e}")

return None

Modbus函数(与之前相同)

def create_modbus_client():

return ModbusSerialClient(

port=METER_CONFIG['port'],

baudrate=METER_CONFIG['baudrate'],

parity=METER_CONFIG['parity'],

stopbits=METER_CONFIG['stopbits'],

bytesize=METER_CONFIG['bytesize'],

timeout=1,

retries=3

)

def read_meter_data(client, slave_id):

data = {}

for item in DATA_ITEMS:

try:

result = client.read_holding_registers(

address=item['address'],

count=item['registers'],

slave=slave_id

)

if result and not result.isError():

decoder = BinaryPayloadDecoder.fromRegisters(

result.registers,

byteorder=METER_CONFIG['byte_order'],

wordorder=Endian.BIG

)

if item['data_type'] == 'int16-1':

value = decoder.decode_16bit_int()

else:

value = decoder.decode_16bit_uint()

data[item['name']] = value * item['factor']

else:

data[item['name']] = None

except Exception as e:

print(f"读取 {item['name']} 时出错: {str(e)}")

data[item['name']] = None

return data

def main():

print("正在连接Modbus设备...")

modbus_client = create_modbus_client()

if not modbus_client.connect():

print("无法连接到Modbus设备")

return

print("正在连接MQTT服务器...")

mqtt_client = create_mqtt_client()

if not mqtt_client:

print("无法连接到MQTT服务器")

modbus_client.close()

return

print("开始数据采集和上报循环...")

try:

while True:

data = read_meter_data(modbus_client, slave_id=1)

过滤掉读取失败的数据

valid_data = {k: v for k, v in data.items() if v is not None}

if valid_data:

发布数据到MQTT

try:

mqtt_client.publish(

MQTT_CONFIG['telemetry_topic'],

json.dumps(valid_data)

)

print(f"数据已上报: {valid_data}")

except Exception as e:

print(f"MQTT发布失败: {e}")

等待10秒

time.sleep(10)

except KeyboardInterrupt:

print("\n程序终止...")

finally:

print("正在关闭连接...")

modbus_client.close()

mqtt_client.loop_stop()

mqtt_client.disconnect()

print("连接已关闭")

if name == "main":

main()

===================代码区域结束=====================

6. 运行程序

  • 打开终端或命令提示符
  • 进入程序所在目录
  • 运行命令:

python meter_collector.py

7. 查看数据

  • 登录 ThingsPanel 平台
  • 进入设备详情页面
  • 可以看到实时上报的电表数据

常见问题

连接不上设备?

  • 检查接线是否正确
  • 确认端口号是否正确
  • 验证电表波特率是否为9600

数据显示异常?

  • 确认电表地址是否为1
  • 检查接线是否松动

无法连接平台?

  • 检查网络连接
  • 验证MQTT配置信息是否正确

扩展功能

  • 可以通过修改代码中的 time.sleep(10) 来调整数据上报频率
  • 支持添加多个电表,只需修改 slave_id 即可

现在,您的电表数据就可以实时推送到云平台了!

相关推荐
安娜的信息安全说16 小时前
深入浅出 MQTT:轻量级消息协议在物联网中的应用与实践
开发语言·物联网·mqtt
Kandiy1802539818719 小时前
PHY6252国产蓝牙低成本透传芯片BLE5.2智能灯控智能家居
人工智能·物联网·智能家居·射频工程
卍郝凝卍21 小时前
物联网卡摄像头从前端至后台的实现过程
前端·物联网·视频解决方案
北京盛世宏博21 小时前
科技引领,档案管理更高效之智慧档案馆三维立体恒温恒湿消毒净化系统
科技·物联网·智慧档案·档案馆温湿度
明达智控技术1 天前
MR30分布式IO在自动上料机的应用
分布式·物联网·自动化
小莞尔1 天前
【51单片机】【protues仿真】基于51单片机简易电子琴系统(8键)
c语言·单片机·嵌入式硬件·物联网·51单片机
塔能物联运维1 天前
物联网设备物理环境自适应监控与运维策略优化
运维·物联网
塔能物联运维1 天前
物联网边缘节点数据缓存优化与一致性保障技术
java·后端·物联网·spring·缓存
北京阿尔泰科技厂家1 天前
从数据采集到智能诊断:阿尔泰科技实时高精度远距离管道状态监测全流程
物联网·安全·能源·信号采集·数据采集器·工业测试·管道监测
我先去打把游戏先2 天前
ESP32开发指南(基于IDF):连接AWS,乐鑫官方esp-aws-iot-master例程实验、跑通
开发语言·笔记·单片机·物联网·学习·云计算·aws