高级应用

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

字号+ 作者:duino123.com 来源:未知 2016-10-27 10:25 我要评论( )

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

本人理解的术语解析

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

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

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

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

485转ttl
485转ttl

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

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


Arduino代码:

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

#include <ModbusMaster.h>//modbusmaster库
#include <LiquidCrystal.h>//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 <LiquidCrystal.h>这是关于lcd的自带库直接用就行。   另一个是#include <ModbusMaster.h>   需要手动连网加载,否则程序会显示编译错误。


项目->管理库

库导入
 

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

搜索库
搜索库

  注意!!!!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变量)

效果图

效果图

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

如需更详细资料,如有好资源分享,请加入QQ交流群:214461008

欢迎阅读,欢迎转载,不用注明出处!本站只提供入门和进阶资料,做您学习的小伙伴!

老司机也欢迎光临指导!有好内容请加群:214461008 不要看声明了,看内容吧!

相关文章
网友点评
Arduino