硬件成本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 即可

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

相关推荐
2401_882727972 小时前
web组态可视化编辑器
前端·后端·物联网·低代码·编辑器
神一样的老师4 小时前
AWS物联网连接的数据记录器在冰川环境中的性能比较:Campbell CR1000X与ESP32开源
物联网
Jzin18 小时前
【物联网】keil仿真环境设置 keilV5可以适用ARM7
物联网
不能只会打代码18 小时前
32单片机综合应用案例——物联网(IoT)环境监测站(四)(内附详细代码讲解!!!)
单片机·嵌入式硬件·物联网·32单片机
芯盾时代2 天前
智能网联汽车的数据脱敏
人工智能·物联网·安全·网络安全·信息与通信
SteveJrong2 天前
专题 - STM32
stm32·单片机·物联网
神一样的老师2 天前
基于智能物联网的肉鸡舍控制器:设计、实施、性能评估与优化
物联网
币圈小菜鸟2 天前
Gaea与物联网:构建去中心化AI的资源交换网络
人工智能·物联网·去中心化
codeBrute2 天前
基于Netty+InfluxDB+MQTT+Spring Boot的物联网(IoT)项目实现方案
spring boot·物联网
深圳启明云端科技2 天前
ESP RainMaker轻量级云平台方案,产品私有云部署,物联网无线应用
网络·物联网·wifi·智能家居