您尚未登录。

楼主 #1 2020-04-23 12:57:12

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

esp8266+arduino+modbus开发

一个特别简单的目的,就是让8266读取DDSU666的电表数据上传。


想偷懒用arduino里自带的modbus库文件用用(里面有例程可以抄),失败~~总是编译不过去~这个没定义那个没定义之类的~

大神们有什么好建议么?


也想过直接串口通讯,不过什么奇偶校验啊,CRC停止位啥的搞得很头大·~~,主要是懒~~~

离线

#2 2020-04-23 13:38:18

有梦的地方
会员
注册时间: 2020-03-17
已发帖子: 284
积分: 284

Re: esp8266+arduino+modbus开发

modbus很简单的一个协议,几行代码就搞定了,没不要去折腾库。

离线

楼主 #3 2020-04-23 15:01:23

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

欸,一点都偷不了懒么?~~~

离线

#4 2020-04-25 08:28:43

湘楚浪子
会员
注册时间: 2019-12-22
已发帖子: 40
积分: 39.5

Re: esp8266+arduino+modbus开发

离线

#5 2020-04-25 09:03:53

异乡是故乡
会员
注册时间: 2019-11-15
已发帖子: 74
积分: 73.5

Re: esp8266+arduino+modbus开发

湘楚浪子 说:

果然可以,以前modbus代码都是自己撸的,发现这个libmodbus更简洁:

简书上面找到一个demo




RTU:

#include <modbus.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>


int main(void)
{
    modbus_t *ctx=NULL;     // context
    int addr=0;             // address
    int rc=0;               // received
    int nb = 3;             // the number of bit

    uint16_t *tab_rq_registers=NULL;
    uint16_t *tab_rp_registers=NULL;

    /* RTU */
    ctx = modbus_new_rtu("/dev/ttySAC3",9600,'N',8,1);
    modbus_set_debug(ctx, TRUE);
    modbus_set_slave(ctx, 0x01);  // 设置从机地址

    // connect
    if (-1 == modbus_connect(ctx))
    {
        fprintf(stderr, "Conncetion failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    // 读取数据
    uint16_t tab_reg[2];  // 存放要读的数据
    int regs=modbus_read_registers(ctx,0,2,tab_reg);

    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

TCP:

/*
 * The client of modbus tcp.
 * test 2 register
 *
 * 2017-10-26
 */

#include <modbus.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>


int main(void)
{
    modbus_t *ctx=NULL;     // context
    int addr=0;             // address
    int rc=0;               // received
    int nb = 3;             // the number of bit

    uint16_t *tab_rq_registers=NULL;
    uint16_t *tab_rp_registers=NULL;

    /* TCP */
    ctx = modbus_new_tcp("192.168.2.29", 1502);
    modbus_set_debug(ctx, TRUE);
    // connect
    if (-1 == modbus_connect(ctx))
    {
        fprintf(stderr, "Conncetion failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /* Allocate and initialize the memory spaces. */
    tab_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
    memset(tab_rq_registers, 0, nb * sizeof(uint16_t));
    tab_rp_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
    memset(tab_rp_registers, 0, nb * sizeof(uint16_t));


    // write
    tab_rq_registers[0] = 25;
    tab_rq_registers[1] = 2;
    tab_rq_registers[2] = 88;


    rc = modbus_write_registers(ctx, addr, nb, tab_rq_registers);
    if (rc != nb)
    {
        printf("ERROR modbus_write_bits single (%d)\n", rc);
        printf("address = %d\n", addr);
    }

    // read
    rc = modbus_read_registers(ctx, addr, nb, tab_rp_registers);
    if (rc != nb)
    {
        printf("ERROR modbus_read_bits single (%d)\n", rc);
        printf("address = %d\n", addr);
    }
    for (int i = 0; i < nb; ++i)
    {
        printf("%d%c", tab_rp_registers[i], (i==nb-1)?'\n':' ');
    }   
        
    free(tab_rq_registers);
    free(tab_rp_registers);
    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);
    
    return 0;
}   

离线

#6 2020-04-25 10:39:52

异乡是故乡
会员
注册时间: 2019-11-15
已发帖子: 74
积分: 73.5

Re: esp8266+arduino+modbus开发

zeesser 说:

欸,一点都偷不了懒么?~~~

应该可以偷懒了:

Small Modbus slave, RTU (serial) for Arduino (arduino modbus从机):
https://github.com/stephane/modbusino

Simple Makefile to compile and upload Arduino sketches:
https://github.com/stephane/arduinoMakefile

离线

#7 2020-04-26 14:47:56

xiaobai
会员
注册时间: 2020-04-26
已发帖子: 2
积分: 2

Re: esp8266+arduino+modbus开发

这个代码移植stm32要自己实现好多东西么

离线

楼主 #8 2020-04-27 09:40:07

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

湘楚浪子 说:

赞赞赞~

离线

楼主 #9 2020-04-27 09:40:44

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

异乡是故乡 说:

应该可以偷懒了:

Small Modbus slave, RTU (serial) for Arduino (arduino modbus从机):
https://github.com/stephane/modbusino

Simple Makefile to compile and upload Arduino sketches:
https://github.com/stephane/arduinoMakefile

这个更省事顺手!

离线

楼主 #10 2020-04-27 09:46:47

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

Simple Makefile to compile and upload Arduino sketches:
https://github.com/stephane/arduinoMakefile



“Windows users: sorry, please use a better OS.”

这哥们挺逗~

离线

#11 2020-04-27 09:49:06

异乡是故乡
会员
注册时间: 2019-11-15
已发帖子: 74
积分: 73.5

Re: esp8266+arduino+modbus开发

这个 libmodbus 我在 NUC972 + Linux非常好用, 我把原来自己撸的代码替换了, 测试了两天, 已经小批量发货给客户了。

离线

楼主 #12 2020-04-27 10:52:45

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

异乡是故乡 说:

这个 libmodbus 我在 NUC972 + Linux非常好用, 我把原来自己撸的代码替换了, 测试了两天, 已经小批量发货给客户了。


NUC972性价比是不是要好一些?

离线

#13 2020-04-27 10:56:01

异乡是故乡
会员
注册时间: 2019-11-15
已发帖子: 74
积分: 73.5

Re: esp8266+arduino+modbus开发

zeesser 说:

NUC972性价比是不是要好一些?

要看和谁比,应用场景是什么。
300Mhz主频有点鸡肋,内置DRAM, 引脚超级多,UART也多。

离线

楼主 #14 2020-04-27 10:58:37

zeesser
会员
注册时间: 2020-03-10
已发帖子: 36
积分: 8.5

Re: esp8266+arduino+modbus开发

异乡是故乡 说:

要看和谁比,应用场景是什么。
300Mhz主频有点鸡肋,内置DRAM, 引脚超级多,UART也多。


我学习下,我这UART用的多。

离线

#15 2024-01-30 00:10:11

迪卡
会员
所在地: 河北
注册时间: 2018-11-02
已发帖子: 916
积分: 903
个人网站

Re: esp8266+arduino+modbus开发

我也是要读这个电表,真是太tmd坎坷了。
本来用的天问的asrpro模块,想着它带喇叭可以语音说话,我想做个当电流超多少时自动语音报警(因为家里是速热热水器,开起来最大到32A,我限制了水流到20A,家里总断路器才32A的,如果这时候烧水或是干啥容易超电流跳闸,我自己会注意,家人不太懂电这东西),结果他们的芯片有问题,偶校验2400波特率走modbus模块,发送数据是正常的,但收数据就是大概率误码,如果我读电量,电流电压功率,大概率电压能读出来,如果我只读电压,是一次正确一次误码。后来测试自收自发还误码,真狗,浪费了2天休息日的大好时光。然后图省事,试了试手里的arduino nano,和nodemcu8266,但都是只有一个串口,没法看调试信息,后来用nano那一个串口测试,和esp8266测试,都是用的arduino,也是不行,真狗,这两个模块用示波器测了下,原来是rx脚被板载USB串口芯片的tx拉高了,果断把nano上的ch340焊下来。果然好了,太tm坎坷了。
代码我是直接对AI提的编程需求,粘上就能用。问法如下。我的硬件是Arduino Nano。我需要使用串口以MODBUS RTU协议读取电表的电压 电流 功率 电量。电量的地址是0x0000,数据长度为2。电压的地址是0x0300,数据长度为1。电流的地址是0x0303,数据长度为1。功率的地址是0x0306,数据长度为1。modbus的读参量用03H号命令。电表的modbus地址为15。电量数据是高位在前,低位在后,若读出值为0012D687H(1234567),则电能计量值为 1234567×0.01=12345.67kWh。电能表中所测电压值固定为 1 位小数,数据格式为 XXX.X,单位为 V,若通讯读出,电压值为 0897H(2199),则电压的实际值为 219.9V;所测电流值固定为 2 位小数数据格式为 XXX.XX,单位 A,若通讯读出电流值为 0096H(150), 则电流的实际值为 1.50A。电能表的有功率值固定为 2 位小数,数据格式为 XXX.XX,单位为 kW, 若通讯读出有功功
率值为 0020H(32),则有功率的实际值为 0.32kW。 帮我写出对应功能的arduino程序。 调试信息不打印。注意,接电表的串口使用偶校验。当电流大于1A时,控制4脚输出高,低于1A时输出低。请不要使用modbus库,请使用代码实现modbus的发送及接收。

离线

#16 2024-01-30 00:14:52

迪卡
会员
所在地: 河北
注册时间: 2018-11-02
已发帖子: 916
积分: 903
个人网站

Re: esp8266+arduino+modbus开发

ai代码如下

#include <Arduino.h>

#define SLAVE_ID 15
#define BAUDRATE 2400
#define TIMEOUT 1000
#define TX_ENABLE_PIN  4

// MODBUS function codes
#define READ_HOLDING_REGISTERS 0x03

// Registers addresses
#define ADDR_ENERGY 0x0000
#define ADDR_VOLTAGE 0x0300
#define ADDR_CURRENT 0x0303
#define ADDR_POWER 0x0306

// Registers lengths
#define LEN_ENERGY 2
#define LEN_VOLTAGE 1
#define LEN_CURRENT 1
#define LEN_POWER 1

void setup() {
  Serial.begin(BAUDRATE, SERIAL_8E1); // 偶校验
  pinMode(TX_ENABLE_PIN, OUTPUT);
}

void loop() {
  float energy = readRegister(ADDR_ENERGY, LEN_ENERGY) * 0.01; // kWh
  float voltage = readRegister(ADDR_VOLTAGE, LEN_VOLTAGE) * 0.1; // V
  float current = readRegister(ADDR_CURRENT, LEN_CURRENT) * 0.01; // A
  float power = readRegister(ADDR_POWER, LEN_POWER) * 0.01; // kW

  if (current > 1.0) {
    digitalWrite(TX_ENABLE_PIN, HIGH);
  } else {
    digitalWrite(TX_ENABLE_PIN, LOW);
  }

  // 延时一段时间后再次读取
  delay(5000);
}

long readRegister(unsigned int addr, unsigned char len) {
  unsigned char buf[8];
  buf[0] = SLAVE_ID; // Slave Address
  buf[1] = READ_HOLDING_REGISTERS; // Function Code
  buf[2] = highByte(addr); // Starting Address High
  buf[3] = lowByte(addr);  // Starting Address Low
  buf[4] = 0x00;          // Number of Registers High
  buf[5] = len;           // Number of Registers Low
  unsigned int crc = calculateCRC(buf, 6);
  buf[6] = lowByte(crc);  // CRC Low
  buf[7] = highByte(crc); // CRC High

  sendRequest(buf, 8);
  delay(100);

  if (Serial.available()) {
    // Read the response
    // TODO: Add code to parse the response
  }

  return 0; // Placeholder for actual value
}

void sendRequest(unsigned char *packet, unsigned char packetLength) {
  digitalWrite(TX_ENABLE_PIN, HIGH);
  for (unsigned char i = 0; i < packetLength; i++) {
    Serial.write(packet[i]);
  }
  Serial.flush();
  digitalWrite(TX_ENABLE_PIN, LOW);
}

unsigned int calculateCRC(unsigned char *buf, unsigned char len) {
  unsigned int crc = 0xFFFF;
  for (unsigned int pos = 0; pos < len; pos++) {
    crc ^= (unsigned int)buf[pos];
    for (int i = 8; i != 0; i--) {
      if ((crc & 0x0001) != 0) {
        crc >>= 1;
        crc ^= 0xA001;
      } else {
        crc >>= 1;
      }
    }
  }
  return crc;
}

最近编辑记录 迪卡 (2024-01-30 00:15:27)

离线

#17 2024-01-30 07:06:53

迪卡
会员
所在地: 河北
注册时间: 2018-11-02
已发帖子: 916
积分: 903
个人网站

Re: esp8266+arduino+modbus开发

@迪卡
代码需要微调

离线

#18 2024-01-31 23:48:29

迪卡
会员
所在地: 河北
注册时间: 2018-11-02
已发帖子: 916
积分: 903
个人网站

Re: esp8266+arduino+modbus开发

Screenshot_2024-01-31-23-34-47-48_a1a18631cab6998b72f68221d27e0bbf.jpgIMG20240131233538.jpg

离线

#19 2024-02-22 15:59:00

rainwwww
会员
注册时间: 2024-02-22
已发帖子: 2
积分: 2

Re: esp8266+arduino+modbus开发

现在是不是python也可以了

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn