ESP32+485(MODBUS RTU)

2023-05-16

1、背景

需要采集功率表的功率及电量数据,考虑采用ESP32采集数据后发送给服务器。

所需硬件:ESP32开发板、485从机、232转485芯片。

图1、连接示意图

2、实现

数字功率表采用Modbus RTU模式进行数据的传输,通过查看附带的说明书可以知道,数据的传输格式,1个起始位,8个数据位,2个停止位,在编程时需要使用。下面使用ESP32读取数字功率表的通讯地址。

图2、数显功率表的通信格式

图3、数显功率表读取信息地址

通过说明书可以得知我们的通讯格式为:0x02,0x03,0x00,0x08,0x00,0x01,0x05,0xFB

0x02:通讯从机地址,是我们自己设置的数显功率表通讯地址。

0x03:命令字,读数显功率表寄存器。

0x00,0x08:需要读取的寄存器起始地址,从图3中可以看出,读波特率为0x0008。

0x00,0x01:需要读取的寄存器数量,我们只读取0x0008开始的一个字节的数据。

0x05,0xFB:CRC校验和。

图4连接方式

图5数据收发

上图中使用电脑通过USB转485方式与功率表通信,读取波特率设置值。

图6、测试使用ESP32发送命令

从上图中能发现数显功率表一直在返回波特率的设置值,程序中是一直发送固定的命令,下面为全部的代码。

3、代码

参考代码为乐鑫ESP32 SDK:https://www.espressif.com/zh-hans/support/download/sdks-demos?keys=&field_type_tid%5B%5D=624&field_type_tid%5B%5D=13

程序目录为:examples/peripherals/uart/uart_echo_rs485/

/* Uart Events Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "driver/gpio.h"

/**
 * This is a example which echos any data it receives on UART back to the sender using RS485 interface in half duplex mode.
*/
#define TAG "RS485_ECHO_APP"

// Note: Some pins on target chip cannot be assigned for UART communication.
// Please refer to documentation for selected board and target to configure pins using Kconfig.
#define ECHO_TEST_TXD   (CONFIG_ECHO_UART_TXD)
#define ECHO_TEST_RXD   (CONFIG_ECHO_UART_RXD)

// RTS for RS485 Half-Duplex Mode manages DE/~RE
#define ECHO_TEST_RTS   (CONFIG_ECHO_UART_RTS)

// CTS is not used in RS485 Half-Duplex Mode
#define ECHO_TEST_CTS   (UART_PIN_NO_CHANGE)

#define BUF_SIZE        (127)
#define BAUD_RATE       (CONFIG_ECHO_UART_BAUD_RATE)

// Read packet timeout
#define PACKET_READ_TICS        (100 / portTICK_RATE_MS)
#define ECHO_TASK_STACK_SIZE    (2048)
#define ECHO_TASK_PRIO          (10)
#define ECHO_UART_PORT          (CONFIG_ECHO_UART_PORT_NUM)

// Timeout threshold for UART = number of symbols (~10 tics) with unchanged state on receive pin
#define ECHO_READ_TOUT          (3) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks

static void echo_send(const int port, const char * str, uint8_t length) 
{    
    if (uart_write_bytes(port, str, length) != length) {
        ESP_LOGE(TAG, "Send data critical failure.");
        // add your code to handle sending failure here
        abort();
    }
}

// An example of echo test with hardware flow control on UART
static void echo_task(void *arg)
{
    const int uart_num = ECHO_UART_PORT;
    uart_config_t uart_config = { //串口信息配置,需要与从机的通讯协议一致
        .baud_rate = BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_2,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .rx_flow_ctrl_thresh = 122,
        .source_clk = UART_SCLK_APB,
    };
    
    // Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    
    ESP_LOGI(TAG, "Start RS485 application test and configure UART.");

    // Install UART driver (we don't need an event queue here)
    // In this example we don't even use a buffer for sending data.
    ESP_ERROR_CHECK(uart_driver_install(uart_num, BUF_SIZE * 2, 0, 0, NULL, 0));

    // Configure UART parameters
    ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
    
    ESP_LOGI(TAG, "UART set pins, mode and install driver.");

    // Set UART pins as per KConfig settings
    ESP_ERROR_CHECK(uart_set_pin(uart_num, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));

    // Set RS485 half duplex mode
    ESP_ERROR_CHECK(uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX));
    
    // Set read timeout of UART TOUT feature
    ESP_ERROR_CHECK(uart_set_rx_timeout(uart_num, ECHO_READ_TOUT));

    // Allocate buffers for UART
    //uint8_t* data = (uint8_t*) malloc(BUF_SIZE);
    uint8_t data[] = {0x02,0x03,0x00,0x08,0x00,0x01,0x05,0xFB}; //固定的命令
    uint8_t recbuf[128]={0x00};//接收数据变量
    ESP_LOGI(TAG, "UART start recieve loop.\r\n");

    while(1) {
      gpio_set_level(16,0);
      echo_send(uart_num, (const char*)data, 8);
	  gpio_set_level(16,1);

      vTaskDelay(200 / portTICK_PERIOD_MS);
	  int len = uart_read_bytes(uart_num, recbuf, 128, PACKET_READ_TICS);
	if(len>0)
	{
		//printf("recv data len=%d\n",len);
         for(int i=0;i<len;i++)
	 {
	 	printf("0x%.2X ", (uint8_t)recbuf[i]);//打印收到的数据
	 }
	}
                printf("\n");
	vTaskDelay(3000 / portTICK_PERIOD_MS);//每个3s查询一次数据
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    //GPIO16脚为控制引脚,控制数据的收发方向
	gpio_pad_select_gpio(16); //
    gpio_set_direction(16, GPIO_MODE_OUTPUT);
    //A uart read/write example without event queue;
    xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, ECHO_TASK_PRIO, NULL);//创建任务
}

只是做了最简单的命令收发,希望对大家有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP32+485(MODBUS RTU) 的相关文章

  • 又搞定一块屏幕 micropython 驱动 sharp memory lcd

    先来学学C是怎么写的 核心代码 void lcd refresh void uint16 t i 0 ln 0 SCS 1 delay us 5 write byte 0x80 for ln 0 ln lt 128 ln write byt
  • 【ESP32】VSCode添加驱动文件

    1 创建文件夹并添加驱动文件 2 修改main文件夹下的 CMakeLists txt
  • ESP32调试笔记

    1 现象 上电后一直复位 rst 0x3 SW RESET boot 0x13 SPI FAST FLASH BOOT 原因 Flash烧录时 ota data和app0位置错了 解决 把ota data和app0位置烧录正确即可 位置从分
  • ESP32的液晶中文显示

    上一篇简单说明了ESP32进行SSD1306的液晶显示 然后希望显示字符 使用前一篇的SSD1306是一个入门 但是不能显示中文 因此本篇主要演示显示中文 在arduino中有一个u8g2库 当时用UNO时使用过该库 但是用在ESP32上
  • ESP32-C3 应用 篇(实例二、通过蓝牙将传感器数据发送给手机,手机端控制 SK6812 LED)

    ESP32 C3 蓝牙部分我们学习了GATT 本文尝试使用蓝牙做一个简单的小应用 目录 前言 一 整体框架 二 数据传输部分 2 1 添加温湿度驱动组件 2 2 传感器数据传输程序 再次说明 ESP GATTS READ EVT 事件 2
  • ESP32开发板手动更换外置的flash

    ESP32开发板手动更换外置的flash 实物板 风险提示 操作有风险 需谨慎 新手请勿模仿 第一步拿下屏蔽罩 用热风枪 360 吹下来的 第二步 更换flash芯片 ESP32 D0WDQ6芯片下方那个就是flash芯片了型号 25VQ3
  • 启明云端分享

    提示 启明云端从2013年起就作为Espressif 乐鑫科技 大中华区合作伙伴 我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程 同时也用心推出了基于乐鑫的相关应用方案 希望你能第一时间了解并快速用上好的方案和产品
  • ESP32-C3 应用程序的启动流程

    网上说明一大堆 基本是官网文档复制没有额外解释 对于ESP32 C3的 risc v 内核 是我选择他的原因之一 了解芯片上电后的启动流程 有利于我们更加深入理解芯片 目录 前言 一 应用程序启动阶段 1 1 app main c 1 2
  • arduino+ESP32 web配网演示代码

    include
  • ESP32(Micro Python) LVGL 传感器数值显示

    本程序用于显示SR04超声波传感器和BMP280气压温度传感器的读数 由于高度数值类型不符合要求 BMP280改为显示气压和温度值 气压值分两部分显示 分别为千帕值 100 避免超出表盘显示范围 和千帕值的两位小数 由于标签不能显示动态数值
  • 还是 “月饼” 后续,玩转炫彩 “月饼” 之 问题说明

    画一个 月饼 陪我过中秋 开发板后续问题跟进说明 目录 前言 一 出现问题 二 寻求办法 三 若有所思 四 问题测试 结语 悬赏送开发板 前言 本文有纯理论玩家是永远不会经历的实际问题 嵌入式工程师不动手永远出不了作品 本文最后有送开发板的
  • SimpleFOC无刷电机平衡小车

    前言 本科毕业于自动化 期间学习了各种电机运动控制原理 自动控制原理 但是只会考试而未究其理 最近接触到simplefoc这个基于arduino的开源无刷电机驱动库 想正好借此机会将本科学到的内容用于实际 于是就有了这个小项目 基于无刷电机
  • ESP32-CAM配置开发环境并烧录程序运行

    环境准备 ESP32 CAM开发板 烧录器 摄像头和一根USB线束连接电脑即可 Arduino下载完成后打开 不同版本的菜单栏可能稍微不同 仔细找即可 选择下面的选项 联网自动下载ESP32 CAM的 环境 端口和当前的一致即可 正常连接应
  • Arduino for ESP8266&ESP32适用库ESPAsyncWebServer:快速入门

    文章目录 目的 特征 安装 快速体验 注意事项 总结 目的 Arduino for ESP8266 和 Arduino for ESP32 中默认就有WebServer 不过这些WebServer都是同步的 不支持同时处理多个连接 这在很多
  • 小白也能快速学会的Micropython编译指南

    小白也能快速学会的Micropython编译指南 大家好 我是CSDN上的 上坂龍二 哦 今天给大家带来的是 如何快速一次成功地将Micropython和自己喜欢的模块编译进自己的Esp32固件中哦 事前准备 Python python的环
  • MFC 中的 libmodbus

    我正在尝试将 libmodbus 提供的 modbus 库集成到 Visual Studio 2010 中的自定义 MFC 项目中 到目前为止我所遵循的步骤如下 1 我在 Visual Studio 2010 中创建了项目 如下面的快照所示
  • ADXL345 与 ESP32 I2C 垃圾值问题

    我已根据以下教程使用 I2C 接口将 ESP32 与 ADXL345 连接起来Tutorial http www esp32learning com code esp32 and adxl345 sensor example php 但是
  • 有没有办法在 python/opencv 中从单摄像头视频生成实时深度图?

    我试图将单个图像转换为其深度图 但我找不到任何有用的教程或文档 我想使用 opencv 但是如果您知道使用张量流等获取深度图的方法 我很高兴听到它 有很多关于立体视觉的教程 但我想让它更便宜 因为它是一个帮助盲人的项目 我目前正在使用 es
  • Google iot MQTT - ESP32 首次连接,仅在 30m 后重新连接

    我正在使用 ESP32 与谷歌物联网云合作 我发送假值只是为了使用 MQTT 数据 PUB SUB 进行测试 显然我成功发布了值 有时 我无法重新连接到谷歌物联网 我不知道为什么它不断检查 wifi publishing 并且不检查 JWT
  • ESP32 上的 Web 服务器:如何自动更新和显示来自服务器的传感器值?

    我在 ESP32 上有一个网络服务器 在该服务器上有一个主页 我想每隔 x 秒自动更新主页上的传感器值 无需用户输入 我无法访问文件系统 该传感器直接连接到 ESP32 传感器值位于我的 C 程序中 存储在变量中并定期更新 变量是全局的 以

随机推荐