通过modbus协议实现arduino与电能表串口通信(仅03功能)

作者

胡子阳

请注意阅读顺序一定要从头到尾!!否则容易忽略一些小细节!!

本人理解的术语解析

  ModbusRS485:一种通信协议,另一种RS232已被淘汰。
  Modbus主站(modbusMaster):主动发出指令,要求读取数据的一端(此实验中为arduino)。
  Modbus从站(modbusslaver):被动接收指令,并随指令读自己寄存器内的信息给主站,或是改写寄存器内的信息(此实验中为DDS283-1ZN电能表)。

相关器件与它们之间的接法

1. DDS283-1ZN电能表(你可以选用其他任意表,只要支持ModbusRS485的都行)图中两根线分别是RS485A与RS485B

RS485B
通过modbus协议实现arduino与电能表串口通信(仅03功能)_第1张图片

2. RS485转TTL模块
  这个模块与上图电能表的连接方式如图左侧所示。如果你需要远程读表,建议你在RS485A与RS485B之间加一个75欧姆电阻。图的右侧是此模块与Arduino的接法,注意tx要接arduino的rx,rx要接arduino的tx!!!!
另外我想说,看准这块板,成功的关键点在于你是否买对这块板,它的价格在12元左右。不推荐使用其他便宜的板,那会导致数据传输不稳定。

485转ttl
通过modbus协议实现arduino与电能表串口通信(仅03功能)_第2张图片

3. arduinoUNO板 这是最常见的板,无图不解释。

4. Lcd1602液晶显示屏(无图)
这款显示屏是日本人发明的,只支持显示英文和日文以及数字,字符等。
关于这款液晶屏的用法,详见我的另一篇文章。本实验lcd1602的接法与那文章中介绍的接法一模一样。
5. 面包板与面包线(无图)
本实验线路复杂,最好使用面包板与面包线。
Arduino代码:

/*
此例子是modbus03功能(读取功能)的lcd1602打印实现。
用arduinoIDE 1.6.7编译通过 ,在在uno板上成功运行。
*/

#include //modbusmaster库
#include //arduino自带的库
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);//定义一些引脚接法

uint16_t m_startAddress = 12;//要读取的从站起始地址
uint8_t m_length = 1;//从从站起始地址开始你需要读取的数据的长度
uint8_t result;//串口通信结果,不用明白是什么,只要知道这不是你最终需要的数据就行

ModbusMaster node(1);//对1号从站进行通信

void setup() {
  node.begin(9600);//定义arduino与从站之间的串口波特率
  lcd.begin(16, 2);//初始化lcd1602
}

void loop() {  

  result = node.readHoldingRegisters(m_startAddress, m_length);//调用相关函数
  if (result == node.ku8MBSuccess) {//如果通信成功
    lcd.setCursor(0, 0);//打印lcd第1行信息
    lcd.print("DATA:");
    for (uint8_t j = 0; j < m_length; j++)
    {
      lcd.print( node.getResponseBuffer(j), DEC );//以DEC(十)进制显示你要的数据
    }
  }
  else {
    lcd.setCursor(0, 1);//打印lcd第2行信息
    lcd.print("ERROR:");
    lcd.print(result, HEX);//以HEX(16)进制显示错误信息(E2:你的TX,RX断线,E0:你的485转ttl板子有问题)
  }
delay(500);//延时500毫秒
lcd.clear();//lcd清屏,所以屏幕会闪属正常现象
}

/*
以上代码中的注释仅为个人有限水平的理解,如果有什么说的不对的地方欢迎改写。
*/

  上述代码需要加载两个库。
  一个是#include 这是关于lcd的自带库直接用就行。
  另一个是#include
  需要手动连网加载,否则程序会显示编译错误。

项目->管理库
通过modbus协议实现arduino与电能表串口通信(仅03功能)_第3张图片

  搜索modbusmaster选择版本0.11.0,点安装。
然后它会自动下载这个库。

搜索库
通过modbus协议实现arduino与电能表串口通信(仅03功能)_第4张图片

  注意!!!!Very important!!!!在上传数据的时候要先断开rx与tx!!!!

其他要点:

  无论你的从站是电能表还是其他的,你一定要知道它们的每个寄存器里面放的都是什么类型的内容。比如我这个电能表的寄存器情况:
  

地址Address 变量名称 Variable 读写属性Belong to R/W 数据格式Data format 符号sign 数据类型DataModel
0000H
0001H
当前总电能
Current total energy
R 每个电能占用4个字节
Each electric energy occupy 4 byte
无符号
unsigned
Dword
0002H
0003H
保留
Reserved
保留
Reserved
保留
Reserved
无符号
unsigned
Dword
0004H
0005H
保留
Reserved
保留
Reserved
保留
Reserved
无符号
unsigned
Dword
0006H
0007H
保留
Reserved
保留
Reserved
保留
Reserved
无符号
unsigned
Dword
0008H
0009H
当前反向电能
Current reversing energy
R 每个电能占用4个字节
Each electric energy occupy 4 byte
无符号
unsigned
Dword
000AH
000BH
当前正向电能
Current_forword_energy
R 每个电能占用4个字节
Each electric energy occupy 4 byte
无符号
unsigned
Dword
000CH 电压
Voltage
R XXX.X_V 无符号
unsigned
Word
000DH 电流
Current
R XX.XX_A 无符号
unsigned
Word
000EH 有功功率
Active power
R XX.XXX_KW 有符号
signed
Word
000FH 无功功率
Reactive power
R XX.XXX_Kvar 有符号
signed
Word
0010H 功率因数
Power factor
R X.XXX 无符号
unsigned
Word
0011H 频率
Frequency
R XX.XX_ 无符号
unsigned
Word
0012H 保留
Reserved
保留
Reserved
保留
Reserved
无符号 unsigned Word
0013H 保留
Reserved
保留
Reserved
保留 Reserved 无符号
unsigned
Word
0014H 保留
Reserved
保留
Reserved
保留 Reserved 无符号
unsigned
Word
0015H
高字节
High Byte
通信地址
Communication address
R/W 001-247 无符号
unsigned
Char
0015H
低字节
Low byte
通信波特率
Communication baudrate
R/W 01–9600bps
(默认)(default)
02-4800bps
03–2400bps
04–1200bps
无符号
unsigned
Char

  从中可以看出地址为000CH也就是12号地址的寄存器放的是电压的情况。所以代码中uint16_t m_startAddress = 12;m_startAddress写成地址12 (16位)
uint8_t m_length = 1;读取1个地址的信息(8位)这样就可以愉快地读电压了。(uint16_t 与uint8_t是类型名,类似与int,float….就比如说0100 1001就是一个uint8_t变量,0010 0011 1100 1111 就是一个uint16_t变量)

效果图

通过modbus协议实现arduino与电能表串口通信(仅03功能)_第5张图片

  这是另一个类似的代码实现的,图中“D:2279”表示此时的电压是227.9v “82”是我用于调试的一个无关数据。

你可能感兴趣的:(硬件传感器)