mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-20 09:55:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/protocols/modbus/serial/mb_example_common)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(modbus_slave)
|
||||
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := modbus_slave
|
||||
|
||||
EXTRA_COMPONENT_DIRS := $(IDF_PATH)/examples/protocols/modbus/serial/mb_example_common
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# Modbus Slave Example
|
||||
|
||||
This example demonstrates using of FreeModbus stack port implementation for ESP32. The external Modbus host is able to read/write device parameters using Modbus protocol transport. The parameters accessible thorough Modbus are located in deviceparams.h/c files and can be updated by user.
|
||||
These are represented in structures holding_reg_params, input_reg_params, coil_reg_params, discrete_reg_params for holding registers, input parameters, coils and discrete inputs accordingly. The app_main application demonstrates how to setup Modbus stack and use notifications about parameters change from host system.
|
||||
The FreeModbus stack located in components\freemodbus\ folder and contain \port folder inside which contains FreeModbus stack port for ESP32. There are some parameters that can be configured in KConfig file to start stack correctly (See description below for more information).
|
||||
|
||||
The slave example uses shared parameter structures defined in examples\protocols\modbus\serial\common_components folder.
|
||||
|
||||
## Hardware required :
|
||||
Option 1:
|
||||
PC + USB Serial adapter connected to USB port + RS485 line drivers + ESP32 WROVER-KIT board.
|
||||
The MAX485 line driver is used as an example below but other similar chips can be used as well.
|
||||
|
||||
Option 2:
|
||||
The modbus_master example application configured as described in its README.md file and flashed into ESP32 WROVER-KIT board.
|
||||
Note: The ```Example Data (Object) Dictionary``` in the modbus_master example can be edited to address parameters from other slaves connected into Modbus segment.
|
||||
|
||||
RS485 example circuit schematic:
|
||||
```
|
||||
VCC ---------------+ +--------------- VCC
|
||||
| |
|
||||
+-------x-------+ +-------x-------+
|
||||
RXD <------| RO | DIFFERENTIAL | RO|-----> RXD
|
||||
| B|---------------|B |
|
||||
TXD ------>| DI MAX485 | \ / | MAX485 DI|<----- TXD
|
||||
ESP32 WROVER KIT 1 | | RS-485 side | | Modbus master
|
||||
RTS --+--->| DE | / \ | DE|---+
|
||||
| | A|---------------|A | |
|
||||
+----| /RE | PAIR | /RE|---+-- RTS
|
||||
+-------x--------+ +-------x-------+
|
||||
| |
|
||||
--- ---
|
||||
```
|
||||
|
||||
## How to setup and use an example:
|
||||
|
||||
### Configure the application
|
||||
Start the command below to show the configuration menu:
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
Select Modbus Example Configuration menu item.
|
||||
Configure the UART pins used for modbus communication using command and table below.
|
||||
```
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
| ESP32 Interface | #define | Default ESP32 Pin | Default ESP32-S2 Pins | External RS485 Driver Pin |
|
||||
| ----------------------|--------------------|-----------------------|-----------------------|---------------------------|
|
||||
| Transmit Data (TxD) | CONFIG_MB_UART_TXD | GPIO23 | GPIO20 | DI |
|
||||
| Receive Data (RxD) | CONFIG_MB_UART_RXD | GPIO22 | GPIO19 | RO |
|
||||
| Request To Send (RTS) | CONFIG_MB_UART_RTS | GPIO18 | GPIO18 | ~RE/DE |
|
||||
| Ground | n/a | GND | GND | GND |
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
```
|
||||
Note: The GPIO22 - GPIO25 can not be used with ESP32-S2 chip because they are used for flash chip connection. Please refer to UART documentation for selected target.
|
||||
|
||||
Define the ```Modbus communiction mode``` for slave in Kconfig - CONFIG_MB_COMM_MODE (must be the same for master and slave application).
|
||||
Set ```Modbus slave address``` for the example application (by default for example script is set to 1).
|
||||
The communication parameters of freemodbus stack (Component config->Modbus configuration) allow to configure it appropriately but usually it is enough to use default settings.
|
||||
See the help strings of parameters for more information.
|
||||
|
||||
### Setup external Modbus master software
|
||||
Option 1:
|
||||
Configure the external Modbus master software according to port configuration parameters used in application.
|
||||
As an example the Modbus Poll application can be used with this example.
|
||||
Option 2:
|
||||
Setup ESP32 WROVER-KIT board and set modbus_master example configuration as described in its README.md file.
|
||||
Setup one or more slave boards with different slave addresses and connect them into the same Modbus segment (See configuration above).
|
||||
Note: The ```Modbus communiction mode``` parameter must be the same for master and slave example application to be able to communicate with each other.
|
||||
|
||||
### Build and flash software
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
Example output of the application:
|
||||
```
|
||||
I (13941) SLAVE_TEST: INPUT READ (13651163 us), ADDR:1, TYPE:8, INST_ADDR:0x3ffb2fd0, SIZE:2
|
||||
I (13951) SLAVE_TEST: HOLDING READ (13656431 us), ADDR:1, TYPE:2, INST_ADDR:0x3ffb2fe0, SIZE:2
|
||||
I (13961) SLAVE_TEST: INPUT READ (13665877 us), ADDR:3, TYPE:8, INST_ADDR:0x3ffb2fd4, SIZE:2
|
||||
I (13971) SLAVE_TEST: HOLDING READ (13676010 us), ADDR:3, TYPE:2, INST_ADDR:0x3ffb2fe4, SIZE:2
|
||||
I (13981) SLAVE_TEST: INPUT READ (13686130 us), ADDR:5, TYPE:8, INST_ADDR:0x3ffb2fd8, SIZE:2
|
||||
I (13991) SLAVE_TEST: HOLDING READ (13696267 us), ADDR:5, TYPE:2, INST_ADDR:0x3ffb2fe8, SIZE:2
|
||||
I (14001) SLAVE_TEST: COILS READ (13706331 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb2fcc, SIZE:8
|
||||
I (14001) SLAVE_TEST: Modbus controller destroyed.
|
||||
```
|
||||
The output lines describe type of operation, its timestamp, modbus address, access type, storage address in parameter structure and number of registers accordingly.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
set(PROJECT_NAME "modbus_slave")
|
||||
|
||||
idf_component_register(SRCS "slave.c"
|
||||
INCLUDE_DIRS ".")
|
||||
@@ -0,0 +1,75 @@
|
||||
menu "Modbus Example Configuration"
|
||||
|
||||
config MB_UART_PORT_NUM
|
||||
int "UART port number"
|
||||
range 0 2 if IDF_TARGET_ESP32
|
||||
default 2 if IDF_TARGET_ESP32
|
||||
range 0 1 if IDF_TARGET_ESP32S2
|
||||
default 1 if IDF_TARGET_ESP32S2
|
||||
help
|
||||
UART communication port number for Modbus example.
|
||||
|
||||
config MB_UART_BAUD_RATE
|
||||
int "UART communication speed"
|
||||
range 1200 115200
|
||||
default 115200
|
||||
help
|
||||
UART communication speed for Modbus example.
|
||||
|
||||
config MB_UART_RXD
|
||||
int "UART RXD pin number"
|
||||
range 0 34 if IDF_TARGET_ESP32
|
||||
default 22 if IDF_TARGET_ESP32
|
||||
range 0 46 if IDF_TARGET_ESP32S2
|
||||
default 19 if IDF_TARGET_ESP32S2
|
||||
help
|
||||
GPIO number for UART RX pin. See UART documentation for more information
|
||||
about available pin numbers for UART.
|
||||
|
||||
config MB_UART_TXD
|
||||
int "UART TXD pin number"
|
||||
range 0 34 if IDF_TARGET_ESP32
|
||||
default 23 if IDF_TARGET_ESP32
|
||||
range 0 46 if IDF_TARGET_ESP32S2
|
||||
default 20 if IDF_TARGET_ESP32S2
|
||||
help
|
||||
GPIO number for UART TX pin. See UART documentation for more information
|
||||
about available pin numbers for UART.
|
||||
|
||||
config MB_UART_RTS
|
||||
int "UART RTS pin number"
|
||||
range 0 34 if IDF_TARGET_ESP32
|
||||
range 0 46 if IDF_TARGET_ESP32S2
|
||||
default 18
|
||||
help
|
||||
GPIO number for UART RTS pin. This pin is connected to
|
||||
~RE/DE pin of RS485 transceiver to switch direction.
|
||||
See UART documentation for more information about available pin
|
||||
numbers for UART.
|
||||
|
||||
choice MB_COMM_MODE
|
||||
prompt "Modbus communication mode"
|
||||
default MB_COMM_MODE_RTU if CONFIG_FMB_COMM_MODE_RTU_EN
|
||||
help
|
||||
Selection of Modbus communication mode option for Modbus.
|
||||
|
||||
config MB_COMM_MODE_RTU
|
||||
bool "RTU mode"
|
||||
depends on FMB_COMM_MODE_RTU_EN
|
||||
|
||||
config MB_COMM_MODE_ASCII
|
||||
bool "ASCII mode"
|
||||
depends on FMB_COMM_MODE_ASCII_EN
|
||||
|
||||
endchoice
|
||||
|
||||
config MB_SLAVE_ADDR
|
||||
int "Modbus slave address"
|
||||
range 1 127
|
||||
default 1
|
||||
help
|
||||
This is the Modbus slave address in the network.
|
||||
It is used to organize Modbus network with several slaves connected into the same segment.
|
||||
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
@@ -0,0 +1,201 @@
|
||||
/* FreeModbus Slave Example ESP32
|
||||
|
||||
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 <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "mbcontroller.h" // for mbcontroller defines and api
|
||||
#include "modbus_params.h" // for modbus parameters structures
|
||||
#include "esp_log.h" // for log_write
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define MB_PORT_NUM (CONFIG_MB_UART_PORT_NUM) // Number of UART port used for Modbus connection
|
||||
#define MB_SLAVE_ADDR (CONFIG_MB_SLAVE_ADDR) // The address of device in Modbus network
|
||||
#define MB_DEV_SPEED (CONFIG_MB_UART_BAUD_RATE) // The communication speed of the UART
|
||||
|
||||
// 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.
|
||||
|
||||
// Defines below are used to define register start address for each type of Modbus registers
|
||||
#define MB_REG_DISCRETE_INPUT_START (0x0000)
|
||||
#define MB_REG_INPUT_START (0x0000)
|
||||
#define MB_REG_HOLDING_START (0x0000)
|
||||
#define MB_REG_COILS_START (0x0000)
|
||||
|
||||
#define MB_PAR_INFO_GET_TOUT (10) // Timeout for get parameter info
|
||||
#define MB_CHAN_DATA_MAX_VAL (6)
|
||||
#define MB_CHAN_DATA_OFFSET (0.2f)
|
||||
#define MB_READ_MASK (MB_EVENT_INPUT_REG_RD \
|
||||
| MB_EVENT_HOLDING_REG_RD \
|
||||
| MB_EVENT_DISCRETE_RD \
|
||||
| MB_EVENT_COILS_RD)
|
||||
#define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR \
|
||||
| MB_EVENT_COILS_WR)
|
||||
#define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
|
||||
|
||||
static const char *SLAVE_TAG = "SLAVE_TEST";
|
||||
|
||||
static portMUX_TYPE param_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// Set register values into known state
|
||||
static void setup_reg_data(void)
|
||||
{
|
||||
// Define initial state of parameters
|
||||
discrete_reg_params.discrete_input1 = 1;
|
||||
discrete_reg_params.discrete_input3 = 1;
|
||||
discrete_reg_params.discrete_input5 = 1;
|
||||
discrete_reg_params.discrete_input7 = 1;
|
||||
|
||||
holding_reg_params.holding_data0 = 1.34;
|
||||
holding_reg_params.holding_data1 = 2.56;
|
||||
holding_reg_params.holding_data2 = 3.78;
|
||||
holding_reg_params.holding_data3 = 4.90;
|
||||
|
||||
coil_reg_params.coils_port0 = 0x55;
|
||||
coil_reg_params.coils_port1 = 0xAA;
|
||||
|
||||
input_reg_params.input_data0 = 1.12;
|
||||
input_reg_params.input_data1 = 2.34;
|
||||
input_reg_params.input_data2 = 3.56;
|
||||
input_reg_params.input_data3 = 4.78;
|
||||
}
|
||||
|
||||
// An example application of Modbus slave. It is based on freemodbus stack.
|
||||
// See deviceparams.h file for more information about assigned Modbus parameters.
|
||||
// These parameters can be accessed from main application and also can be changed
|
||||
// by external Modbus master host.
|
||||
void app_main(void)
|
||||
{
|
||||
mb_param_info_t reg_info; // keeps the Modbus registers access information
|
||||
mb_communication_info_t comm_info; // Modbus communication parameters
|
||||
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
|
||||
|
||||
// Set UART log level
|
||||
esp_log_level_set(SLAVE_TAG, ESP_LOG_INFO);
|
||||
void* mbc_slave_handler = NULL;
|
||||
|
||||
ESP_ERROR_CHECK(mbc_slave_init(MB_PORT_SERIAL_SLAVE, &mbc_slave_handler)); // Initialization of Modbus controller
|
||||
|
||||
// Setup communication parameters and start stack
|
||||
#if CONFIG_MB_COMM_MODE_ASCII
|
||||
comm_info.mode = MB_MODE_ASCII,
|
||||
#elif CONFIG_MB_COMM_MODE_RTU
|
||||
comm_info.mode = MB_MODE_RTU,
|
||||
#endif
|
||||
comm_info.slave_addr = MB_SLAVE_ADDR;
|
||||
comm_info.port = MB_PORT_NUM;
|
||||
comm_info.baudrate = MB_DEV_SPEED;
|
||||
comm_info.parity = MB_PARITY_NONE;
|
||||
ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info));
|
||||
|
||||
// The code below initializes Modbus register area descriptors
|
||||
// for Modbus Holding Registers, Input Registers, Coils and Discrete Inputs
|
||||
// Initialization should be done for each supported Modbus register area according to register map.
|
||||
// When external master trying to access the register in the area that is not initialized
|
||||
// by mbc_slave_set_descriptor() API call then Modbus stack
|
||||
// will send exception response for this register area.
|
||||
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
|
||||
reg_area.start_offset = MB_REG_HOLDING_START; // Offset of register area in Modbus protocol
|
||||
reg_area.address = (void*)&holding_reg_params; // Set pointer to storage instance
|
||||
reg_area.size = sizeof(holding_reg_params); // Set the size of register storage instance
|
||||
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||
|
||||
// Initialization of Input Registers area
|
||||
reg_area.type = MB_PARAM_INPUT;
|
||||
reg_area.start_offset = MB_REG_INPUT_START;
|
||||
reg_area.address = (void*)&input_reg_params;
|
||||
reg_area.size = sizeof(input_reg_params);
|
||||
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||
|
||||
// Initialization of Coils register area
|
||||
reg_area.type = MB_PARAM_COIL;
|
||||
reg_area.start_offset = MB_REG_COILS_START;
|
||||
reg_area.address = (void*)&coil_reg_params;
|
||||
reg_area.size = sizeof(coil_reg_params);
|
||||
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||
|
||||
// Initialization of Discrete Inputs register area
|
||||
reg_area.type = MB_PARAM_DISCRETE;
|
||||
reg_area.start_offset = MB_REG_DISCRETE_INPUT_START;
|
||||
reg_area.address = (void*)&discrete_reg_params;
|
||||
reg_area.size = sizeof(discrete_reg_params);
|
||||
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
|
||||
|
||||
setup_reg_data(); // Set values into known state
|
||||
|
||||
// Starts of modbus controller and stack
|
||||
ESP_ERROR_CHECK(mbc_slave_start());
|
||||
|
||||
// Set UART pin numbers
|
||||
ESP_ERROR_CHECK(uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD,
|
||||
CONFIG_MB_UART_RXD, CONFIG_MB_UART_RTS,
|
||||
UART_PIN_NO_CHANGE));
|
||||
|
||||
// Set UART driver mode to Half Duplex
|
||||
ESP_ERROR_CHECK(uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX));
|
||||
|
||||
ESP_LOGI(SLAVE_TAG, "Modbus slave stack initialized.");
|
||||
ESP_LOGI(SLAVE_TAG, "Start modbus test...");
|
||||
|
||||
// The cycle below will be terminated when parameter holdingRegParams.dataChan0
|
||||
// incremented each access cycle reaches the CHAN_DATA_MAX_VAL value.
|
||||
for(;holding_reg_params.holding_data0 < MB_CHAN_DATA_MAX_VAL;) {
|
||||
// Check for read/write events of Modbus master for certain events
|
||||
mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK);
|
||||
const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE";
|
||||
// Filter events and process them accordingly
|
||||
if(event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) {
|
||||
// Get parameter information from parameter queue
|
||||
ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT));
|
||||
ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||
rw_str,
|
||||
(uint32_t)reg_info.time_stamp,
|
||||
(uint32_t)reg_info.mb_offset,
|
||||
(uint32_t)reg_info.type,
|
||||
(uint32_t)reg_info.address,
|
||||
(uint32_t)reg_info.size);
|
||||
if (reg_info.address == (uint8_t*)&holding_reg_params.holding_data0)
|
||||
{
|
||||
portENTER_CRITICAL(¶m_lock);
|
||||
holding_reg_params.holding_data0 += MB_CHAN_DATA_OFFSET;
|
||||
if (holding_reg_params.holding_data0 >= (MB_CHAN_DATA_MAX_VAL - MB_CHAN_DATA_OFFSET)) {
|
||||
coil_reg_params.coils_port1 = 0xFF;
|
||||
}
|
||||
portEXIT_CRITICAL(¶m_lock);
|
||||
}
|
||||
} else if (event & MB_EVENT_INPUT_REG_RD) {
|
||||
ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT));
|
||||
ESP_LOGI(SLAVE_TAG, "INPUT READ (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||
(uint32_t)reg_info.time_stamp,
|
||||
(uint32_t)reg_info.mb_offset,
|
||||
(uint32_t)reg_info.type,
|
||||
(uint32_t)reg_info.address,
|
||||
(uint32_t)reg_info.size);
|
||||
} else if (event & MB_EVENT_DISCRETE_RD) {
|
||||
ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT));
|
||||
ESP_LOGI(SLAVE_TAG, "DISCRETE READ (%u us): ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||
(uint32_t)reg_info.time_stamp,
|
||||
(uint32_t)reg_info.mb_offset,
|
||||
(uint32_t)reg_info.type,
|
||||
(uint32_t)reg_info.address,
|
||||
(uint32_t)reg_info.size);
|
||||
} else if (event & (MB_EVENT_COILS_RD | MB_EVENT_COILS_WR)) {
|
||||
ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT));
|
||||
ESP_LOGI(SLAVE_TAG, "COILS %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
|
||||
rw_str,
|
||||
(uint32_t)reg_info.time_stamp,
|
||||
(uint32_t)reg_info.mb_offset,
|
||||
(uint32_t)reg_info.type,
|
||||
(uint32_t)reg_info.address,
|
||||
(uint32_t)reg_info.size);
|
||||
if (coil_reg_params.coils_port1 == 0xFF) break;
|
||||
}
|
||||
}
|
||||
// Destroy of Modbus controller on alarm
|
||||
ESP_LOGI(SLAVE_TAG,"Modbus controller destroyed.");
|
||||
vTaskDelay(100);
|
||||
ESP_ERROR_CHECK(mbc_slave_destroy());
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Modbus configuration
|
||||
#
|
||||
CONFIG_MB_COMM_MODE_ASCII=y
|
||||
CONFIG_MB_SLAVE_ADDR=1
|
||||
CONFIG_MB_UART_BAUD_RATE=115200
|
||||
CONFIG_FMB_TIMER_PORT_ENABLED=y
|
||||
CONFIG_FMB_TIMER_GROUP=0
|
||||
CONFIG_FMB_TIMER_INDEX=0
|
||||
CONFIG_FMB_TIMER_ISR_IN_IRAM=y
|
||||
Reference in New Issue
Block a user