├── .gitignore ├── doc └── modbus_protocol.pdf ├── main ├── CMakeLists.txt ├── component.mk ├── Kconfig.projbuild ├── epever.h ├── main.c └── epever.c ├── Makefile ├── CMakeLists.txt ├── LICENSE ├── partitions.csv └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | sdkconfig 3 | sdkconfig.old 4 | .vscode 5 | .travis.yml 6 | -------------------------------------------------------------------------------- /doc/modbus_protocol.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chakphanu/epever-esp-idf/HEAD/doc/modbus_protocol.pdf -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(PROJECT_NAME "epever-esp-idf") 2 | set(srcs 3 | "epever.c" 4 | "main.c" 5 | ) 6 | 7 | idf_component_register( 8 | SRCS "${srcs}" 9 | INCLUDE_DIRS "." 10 | ) 11 | 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := epever-esp-idf 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | 7 | project(epever-esp-idf) 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Code in this repository is in the Public Domain (or CC0 licensed, at your option.) 2 | 3 | Unless required by applicable law or agreed to in writing, this 4 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 5 | CONDITIONS OF ANY KIND, either express or implied. 6 | -------------------------------------------------------------------------------- /partitions.csv: -------------------------------------------------------------------------------- 1 | # Name, Type, SubType, Offset, Size, Flags 2 | # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap 3 | # increased nvs to 64k 4 | nvs, data, nvs, , 0x10000, 5 | phy_init, data, phy, , 0x1000, 6 | factory, app, factory, , 1M, 7 | -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main component makefile. 3 | # 4 | # This Makefile can be left empty. By default, it will take the sources in the 5 | # src/ directory, compile them and link them into lib(subdirectory_name).a 6 | # in the build directory. This behaviour is entirely configurable, 7 | # please read the ESP-IDF documents if you need to do this. 8 | # 9 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Modbus Example Configuration" 2 | 3 | config MB_UART_PORT_NUM 4 | int "UART port number" 5 | range 0 2 if IDF_TARGET_ESP32 6 | default 2 if IDF_TARGET_ESP32 7 | range 0 1 if IDF_TARGET_ESP32S2 8 | default 1 if IDF_TARGET_ESP32S2 9 | help 10 | UART communication port number for Modbus example. 11 | 12 | config MB_UART_BAUD_RATE 13 | int "UART communication speed" 14 | range 1200 115200 15 | default 115200 16 | help 17 | UART communication speed for Modbus example. 18 | 19 | config MB_UART_RXD 20 | int "UART RXD pin number" 21 | range 0 34 if IDF_TARGET_ESP32 22 | default 22 if IDF_TARGET_ESP32 23 | range 0 46 if IDF_TARGET_ESP32S2 24 | default 19 if IDF_TARGET_ESP32S2 25 | help 26 | GPIO number for UART RX pin. See UART documentation for more information 27 | about available pin numbers for UART. 28 | 29 | config MB_UART_TXD 30 | int "UART TXD pin number" 31 | range 0 34 if IDF_TARGET_ESP32 32 | default 23 if IDF_TARGET_ESP32 33 | range 0 46 if IDF_TARGET_ESP32S2 34 | default 20 if IDF_TARGET_ESP32S2 35 | help 36 | GPIO number for UART TX pin. See UART documentation for more information 37 | about available pin numbers for UART. 38 | 39 | config MB_UART_RTS 40 | int "UART RTS pin number" 41 | range 0 34 if IDF_TARGET_ESP32 42 | range 0 46 if IDF_TARGET_ESP32S2 43 | default 18 44 | help 45 | GPIO number for UART RTS pin. This pin is connected to 46 | ~RE/DE pin of RS485 transceiver to switch direction. 47 | See UART documentation for more information about available pin 48 | numbers for UART. 49 | 50 | choice MB_COMM_MODE 51 | prompt "Modbus communication mode" 52 | default MB_COMM_MODE_RTU if CONFIG_FMB_COMM_MODE_RTU_EN 53 | help 54 | Selection of Modbus communication mode option for Modbus. 55 | 56 | config MB_COMM_MODE_RTU 57 | bool "RTU mode" 58 | depends on FMB_COMM_MODE_RTU_EN 59 | 60 | config MB_COMM_MODE_ASCII 61 | bool "ASCII mode" 62 | depends on FMB_COMM_MODE_ASCII_EN 63 | 64 | endchoice 65 | 66 | endmenu 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2 | 3 | $idf.py build 4 | 5 | 6 | ## Hardware required : 7 | Option 1: 8 | PC (Modbus Slave app) + USB Serial adapter connected to USB port + RS485 line drivers + ESP32 WROVER-KIT board. 9 | 10 | Option 2: 11 | Several ESP32 WROVER-KIT board flashed with modbus_slave example software to represent slave device with specific slave address (See CONFIG_MB_SLAVE_ADDR). The slave addresses for each board have to be configured as defined in "connection schematic" above. 12 | One ESP32 WROVER-KIT board flashed with modbus_master example. All the boards require connection of RS485 line drivers (see below). 13 | 14 | The MAX485 line driver is used as an example below but other similar chips can be used as well. 15 | RS485 example circuit schematic for connection of master and slave devices into segment: 16 | ``` 17 | VCC ---------------+ +--------------- VCC 18 | | | 19 | +-------x-------+ +-------x-------+ 20 | RXD <------| RO | DIFFERENTIAL | RO|-----> RXD 21 | | B|---------------|B | 22 | TXD ------>| DI MAX485 | \ / | MAX485 DI|<----- TXD 23 | ESP32 WROVER KIT 1 | | RS-485 side | | External PC (emulator) with USB to serial or 24 | RTS --+--->| DE | / \ | DE|---+ ESP32 WROVER KIT 2 (slave) 25 | | | A|---------------|A | | 26 | +----| /RE | PAIR | /RE|---+-- RTS 27 | +-------x-------+ +-------x-------+ 28 | | | 29 | --- --- 30 | Modbus Master device Modbus Slave device 31 | 32 | ``` 33 | 34 | ## How to setup and use an example: 35 | 36 | ### Configure the application 37 | Start the command below to setup configuration: 38 | ``` 39 | idf.py menuconfig 40 | ``` 41 | Configure the UART pins used for modbus communication using and table below. 42 | Define the communication mode parameter for master and slave in Kconfig - CONFIG_MB_COMM_MODE (must be the same for master and slave devices in one segment). 43 | Configure the slave address for each slave in the Modbus segment (the CONFIG_MB_SLAVE_ADDR in Kconfig). 44 | ``` 45 | -------------------------------------------------------------------------------------------------------------------------- 46 | | ESP32 Interface | #define | Default ESP32 Pin | Default ESP32-S2 Pins | External RS485 Driver Pin | 47 | | ----------------------|--------------------|-----------------------|-----------------------|---------------------------| 48 | | Transmit Data (TxD) | CONFIG_MB_UART_TXD | GPIO23 | GPIO20 | DI | 49 | | Receive Data (RxD) | CONFIG_MB_UART_RXD | GPIO22 | GPIO19 | RO | 50 | | Request To Send (RTS) | CONFIG_MB_UART_RTS | GPIO18 | GPIO18 | ~RE/DE | 51 | | Ground | n/a | GND | GND | GND | 52 | -------------------------------------------------------------------------------------------------------------------------- 53 | ``` 54 | 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. 55 | 56 | Connect USB to RS485 adapter to computer and connect its D+, D- output lines with the D+, D- lines of RS485 line driver connected to ESP32 (See picture above). 57 | 58 | The communication parameters of Modbus stack allow to configure it appropriately but usually it is enough to use default settings. 59 | See the help string of parameters for more information. -------------------------------------------------------------------------------- /main/epever.h: -------------------------------------------------------------------------------- 1 | #include "mbcontroller.h" 2 | 3 | 4 | typedef struct 5 | { 6 | uint16_t ChargingRatedInputVoltage; 7 | uint16_t ChargingRatedInputCurrent; 8 | uint32_t ChargingRatedInputPower; 9 | 10 | uint16_t ChargingRatedOutputVoltage; 11 | uint16_t ChargingRatedOutputCurrent; 12 | uint32_t ChargingRatedOutputPower; 13 | 14 | uint16_t ChargingMode; 15 | uint16_t OutputRatedLoadCurrent; 16 | 17 | } epever_rated_t; 18 | 19 | typedef struct 20 | { 21 | uint16_t ChargingInputVoltage; 22 | uint16_t ChargingInputCurrent; 23 | uint32_t ChargingInputPower; 24 | 25 | uint16_t ChargingOutputVoltage; 26 | uint16_t ChargingOutputCurrent; 27 | uint32_t ChargingOutputPower; 28 | 29 | uint16_t DischargingOutputVoltage; 30 | uint16_t DischargingOutputCurrent; 31 | uint32_t DischargingOutputPower; 32 | 33 | uint16_t BatteryTemperature; 34 | uint16_t ChargerCaseTemperature; 35 | uint16_t ChargerSiliconTemperature; 36 | 37 | uint16_t BatterySOC; 38 | uint16_t RemoteBatteryTemperature; 39 | uint16_t BatteryRealRatedVoltage; 40 | 41 | uint16_t BatteryStatus; 42 | uint16_t ChargerStatus; 43 | } epever_realtime_t; 44 | 45 | typedef struct 46 | { 47 | uint16_t TodayMaxInputVoltage; 48 | uint16_t TodayMinInputVoltage; 49 | uint16_t TodayMaxBatteryVoltage; 50 | uint16_t TodayMinBatteryVoltage; 51 | 52 | uint32_t TodayConsumedEnergy; 53 | uint32_t ThisMonthConsumedEnergy; 54 | uint32_t ThisYearConsumedEnergy; 55 | uint32_t TotalConsumedEnergy; 56 | 57 | uint32_t TodayGeneratedEnergy; 58 | uint32_t ThisMonthGeneratedEnergy; 59 | uint32_t ThisYearGeneratedEnergy; 60 | uint32_t TotalGeneratedEnergy; 61 | 62 | uint32_t CarbonDioxideReduction; 63 | 64 | uint32_t BatteryCurrent; 65 | 66 | uint16_t BatteryTemperature; 67 | uint16_t AmbientTemperature; 68 | 69 | } epever_statistical_t; 70 | 71 | typedef struct 72 | { 73 | uint16_t BatteryType; 74 | uint16_t BatteryCapacity; 75 | uint16_t TemperatureCompensationCoefficient; 76 | uint16_t HighVoltDisconnect; 77 | uint16_t ChargingLimitVoltage; 78 | uint16_t OverVoltageReconnect; 79 | uint16_t EqualizationVoltage; 80 | uint16_t BoostVoltage; 81 | uint16_t FloatVoltage; 82 | uint16_t BoostReconnectVoltage; 83 | uint16_t LowVoltageReconnect; 84 | uint16_t UnderVoltageRecover; 85 | uint16_t UnderVoltageWarning; 86 | uint16_t LowVoltageDisconnect; 87 | uint16_t DischargingLimitVoltage; 88 | uint16_t RealTimeClock1; 89 | uint16_t RealTimeClock2; 90 | uint16_t RealTimeClock3; 91 | uint16_t EqualizationChargingCycle; 92 | uint16_t BatteryTemperatureWarningUpperLimit; 93 | uint16_t BatteryTemperatureWarningLowerLimit; 94 | uint16_t ControllerInnerTemperatureUpperLimit; 95 | uint16_t ControllerInnerTemperatureUpperLimitRecover; 96 | uint16_t PowerComponentTemperatureUpperLimit; 97 | uint16_t PowerComponentTemperatureUpperLimitRecover; 98 | uint16_t LineImpedance; 99 | uint16_t NightTimeThresholdVolt; 100 | uint16_t LightSignalStartupDelayTime; 101 | uint16_t DayTimeThresholdVolt; 102 | uint16_t LightSignalTurnOffDelayTime; 103 | uint16_t LoadControlingMode; 104 | uint16_t WorkingTimeLength1; 105 | uint16_t WorkingTimeLength2; 106 | uint16_t TurnOnTiming1Second; 107 | uint16_t TurnOnTiming1Minute; 108 | uint16_t TurnOnTiming1Hour; 109 | uint16_t TurnOffTiming1Second; 110 | uint16_t TurnOffTiming1Minute; 111 | uint16_t TurnOffTiming1Hour; 112 | uint16_t TurnOnTiming2Second; 113 | uint16_t TurnOnTiming2Minute; 114 | uint16_t TurnOnTiming2Hour; 115 | uint16_t TurnOffTiming2Second; 116 | uint16_t TurnOffTiming2Minute; 117 | uint16_t TurnOffTiming2Hour; 118 | uint16_t LengthOfNight; 119 | uint16_t BatteryRatedVoltageCode; 120 | uint16_t LoadTimingControlSelection; 121 | uint16_t DefaultLoadOnOffInManualMode; 122 | uint16_t EqualizeDuration; 123 | uint16_t BoostDuration; 124 | uint16_t DischargingPercentage; 125 | uint16_t ChargingPercentage; 126 | uint16_t ManagementModeOfBatteryChargingAndDischarging; 127 | }epever_setting_t; 128 | 129 | typedef struct 130 | { 131 | uint16_t ManualControlTheLoad; 132 | uint16_t EnableLoadTestMode; 133 | uint16_t ForceTheLoadOnOff; 134 | } epever_coil_t; 135 | 136 | typedef struct 137 | { 138 | uint16_t OverTemperatureInsideTheDevice; 139 | uint16_t DayNight; 140 | } epever_discrete_t; 141 | 142 | 143 | esp_err_t master_init(void); 144 | void master_read_rated(epever_rated_t *epever); 145 | void master_read_realtime(epever_realtime_t *epever); 146 | void master_read_statistical(epever_statistical_t *epever); 147 | void master_read_setting(epever_setting_t *epever); 148 | void master_read_coil(epever_coil_t *epever); 149 | void master_read_discrete(epever_discrete_t *epever); 150 | 151 | void master_write_coil_ManualControlTheLoad(bool value); 152 | 153 | 154 | -------------------------------------------------------------------------------- /main/main.c: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "string.h" 16 | #include "esp_log.h" 17 | //#include "sdkconfig.h" 18 | #include "epever.h" 19 | 20 | 21 | void print_rated(epever_rated_t *epever_rated) 22 | { 23 | ESP_LOGI("-------- print_rated ", "--------"); 24 | ESP_LOGI("ChargingRatedInputVoltage", "%d", epever_rated->ChargingRatedInputVoltage); 25 | ESP_LOGI("ChargingRatedInputCurrent", "%d", epever_rated->ChargingRatedInputCurrent); 26 | ESP_LOGI("ChargingRatedOutputPower", "%d", epever_rated->ChargingRatedOutputPower); 27 | 28 | ESP_LOGI("ChargingMode", "%d", epever_rated->ChargingMode); 29 | ESP_LOGI("OutputRatedLoadCurrent", "%d", epever_rated->OutputRatedLoadCurrent); 30 | } 31 | 32 | void print_setting(epever_setting_t *epever_setting) 33 | { 34 | ESP_LOGI("-------- print_setting ", "--------"); 35 | ESP_LOGI("BatteryType", "%d", epever_setting->BatteryType); 36 | ESP_LOGI("BatteryCapacity", "%d", epever_setting->BatteryCapacity); 37 | ESP_LOGI("TemperatureCompensationCoefficient", "%d", epever_setting->TemperatureCompensationCoefficient); 38 | ESP_LOGI("HighVoltDisconnect", "%d", epever_setting->HighVoltDisconnect); 39 | ESP_LOGI("ChargingLimitVoltage", "%d", epever_setting->ChargingLimitVoltage); 40 | ESP_LOGI("OverVoltageReconnect", "%d", epever_setting->OverVoltageReconnect); 41 | ESP_LOGI("EqualizationVoltage", "%d", epever_setting->EqualizationVoltage); 42 | ESP_LOGI("BoostVoltage", "%d", epever_setting->BoostVoltage); 43 | ESP_LOGI("FloatVoltage", "%d", epever_setting->FloatVoltage); 44 | ESP_LOGI("BoostReconnectVoltage", "%d", epever_setting->BoostReconnectVoltage); 45 | ESP_LOGI("LowVoltageReconnect", "%d", epever_setting->LowVoltageReconnect); 46 | ESP_LOGI("UnderVoltageRecover", "%d", epever_setting->UnderVoltageRecover); 47 | ESP_LOGI("UnderVoltageWarning", "%d", epever_setting->UnderVoltageWarning); 48 | ESP_LOGI("LowVoltageDisconnect", "%d", epever_setting->LowVoltageDisconnect); 49 | ESP_LOGI("DischargingLimitVoltage", "%d", epever_setting->DischargingLimitVoltage); 50 | ESP_LOGI("RealTimeClock1", "%d", epever_setting->RealTimeClock1); 51 | ESP_LOGI("RealTimeClock2", "%d", epever_setting->RealTimeClock2); 52 | ESP_LOGI("RealTimeClock3", "%d", epever_setting->RealTimeClock3); 53 | ESP_LOGI("EqualizationChargingCycle", "%d", epever_setting->EqualizationChargingCycle); 54 | ESP_LOGI("BatteryTemperatureWarningUpperLimit", "%d", epever_setting->BatteryTemperatureWarningUpperLimit); 55 | ESP_LOGI("BatteryTemperatureWarningLowerLimit", "%d", epever_setting->BatteryTemperatureWarningLowerLimit); 56 | ESP_LOGI("ControllerInnerTemperatureUpperLimit", "%d", epever_setting->ControllerInnerTemperatureUpperLimit); 57 | ESP_LOGI("ControllerInnerTemperatureUpperLimitRecover", "%d", epever_setting->ControllerInnerTemperatureUpperLimitRecover); 58 | ESP_LOGI("PowerComponentTemperatureUpperLimit", "%d", epever_setting->PowerComponentTemperatureUpperLimit); 59 | ESP_LOGI("PowerComponentTemperatureUpperLimitRecover", "%d", epever_setting->PowerComponentTemperatureUpperLimitRecover); 60 | ESP_LOGI("LineImpedance", "%d", epever_setting->LineImpedance); 61 | ESP_LOGI("NightTimeThresholdVolt", "%d", epever_setting->NightTimeThresholdVolt); 62 | ESP_LOGI("LightSignalStartupDelayTime", "%d", epever_setting->LightSignalStartupDelayTime); 63 | ESP_LOGI("DayTimeThresholdVolt", "%d", epever_setting->DayTimeThresholdVolt); 64 | ESP_LOGI("LightSignalTurnOffDelayTime", "%d", epever_setting->LightSignalTurnOffDelayTime); 65 | ESP_LOGI("LoadControlingMode", "%d", epever_setting->LoadControlingMode); 66 | ESP_LOGI("WorkingTimeLength1", "%d", epever_setting->WorkingTimeLength1); 67 | ESP_LOGI("WorkingTimeLength2", "%d", epever_setting->WorkingTimeLength2); 68 | ESP_LOGI("TurnOnTiming1Second", "%d", epever_setting->TurnOnTiming1Second); 69 | ESP_LOGI("TurnOnTiming1Minute", "%d", epever_setting->TurnOnTiming1Minute); 70 | ESP_LOGI("TurnOnTiming1Hour", "%d", epever_setting->TurnOnTiming1Hour); 71 | ESP_LOGI("TurnOffTiming1Second", "%d", epever_setting->TurnOffTiming1Second); 72 | ESP_LOGI("TurnOffTiming1Minute", "%d", epever_setting->TurnOffTiming1Minute); 73 | ESP_LOGI("TurnOffTiming1Hour", "%d", epever_setting->TurnOffTiming1Hour); 74 | ESP_LOGI("TurnOnTiming2Second", "%d", epever_setting->TurnOnTiming2Second); 75 | ESP_LOGI("TurnOnTiming2Minute", "%d", epever_setting->TurnOnTiming2Minute); 76 | ESP_LOGI("TurnOnTiming2Hour", "%d", epever_setting->TurnOnTiming2Hour); 77 | ESP_LOGI("TurnOffTiming2Second", "%d", epever_setting->TurnOffTiming2Second); 78 | ESP_LOGI("TurnOffTiming2Minute", "%d", epever_setting->TurnOffTiming2Minute); 79 | ESP_LOGI("TurnOffTiming2Hour", "%d", epever_setting->TurnOffTiming2Hour); 80 | ESP_LOGI("LengthOfNight", "%d", epever_setting->LengthOfNight); 81 | ESP_LOGI("BatteryRatedVoltageCode", "%d", epever_setting->BatteryRatedVoltageCode); 82 | ESP_LOGI("LoadTimingControlSelection", "%d", epever_setting->LoadTimingControlSelection); 83 | ESP_LOGI("DefaultLoadOnOffInManualMode", "%d", epever_setting->DefaultLoadOnOffInManualMode); 84 | ESP_LOGI("EqualizeDuration", "%d", epever_setting->EqualizeDuration); 85 | ESP_LOGI("BoostDuration", "%d", epever_setting->BoostDuration); 86 | ESP_LOGI("DischargingPercentage", "%d", epever_setting->DischargingPercentage); 87 | ESP_LOGI("ChargingPercentage", "%d", epever_setting->ChargingPercentage); 88 | ESP_LOGI("ManagementModeOfBatteryChargingAndDischarging", "%d", epever_setting->ManagementModeOfBatteryChargingAndDischarging); 89 | } 90 | 91 | void print_realtime(epever_realtime_t *epever_realtime ) 92 | { 93 | ESP_LOGI("-------- print_realtime ", "--------"); 94 | ESP_LOGI("ChargingInputVoltage", "%d", epever_realtime->ChargingInputVoltage); 95 | ESP_LOGI("ChargingInputCurrent", "%d", epever_realtime->ChargingInputCurrent); 96 | ESP_LOGI("ChargingInputPower", "%d", epever_realtime->ChargingInputPower); 97 | 98 | ESP_LOGI("ChargingOutputVoltage", "%d", epever_realtime->ChargingOutputVoltage); 99 | ESP_LOGI("ChargingOutputCurrent", "%d", epever_realtime->ChargingOutputCurrent); 100 | ESP_LOGI("ChargingOutputPower", "%d", epever_realtime->ChargingOutputPower); 101 | 102 | ESP_LOGI("DischargingOutputVoltage", "%d", epever_realtime->DischargingOutputVoltage); 103 | ESP_LOGI("DischargingOutputCurrent", "%d", epever_realtime->DischargingOutputCurrent); 104 | ESP_LOGI("DischargingOutputPower", "%d", epever_realtime->DischargingOutputPower); 105 | 106 | ESP_LOGI("BatteryTemperature", "%d", epever_realtime->BatteryTemperature); 107 | ESP_LOGI("ChargerCaseTemperature", "%d", epever_realtime->ChargerCaseTemperature); 108 | ESP_LOGI("ChargerSiliconTemperature", "%d", epever_realtime->ChargerSiliconTemperature); 109 | 110 | ESP_LOGI("BatterySOC", "%d", epever_realtime->BatterySOC); 111 | ESP_LOGI("RemoteBatteryTemperature", "%d", epever_realtime->RemoteBatteryTemperature); 112 | ESP_LOGI("BatteryRealRatedVoltage", "%d", epever_realtime->BatteryRealRatedVoltage); 113 | 114 | ESP_LOGI("BatteryStatus", "%d", epever_realtime->BatteryStatus); 115 | ESP_LOGI("ChargerStatus", "%d", epever_realtime->ChargerStatus); 116 | } 117 | 118 | void print_statistical(epever_statistical_t *epever_statistical) 119 | { 120 | ESP_LOGI("-------- print_statistical ", "--------"); 121 | ESP_LOGI("TodayMaxInputVoltage", "%d", epever_statistical->TodayMaxInputVoltage); 122 | ESP_LOGI("TodayMinInputVoltage", "%d", epever_statistical->TodayMinInputVoltage); 123 | ESP_LOGI("TodayMaxBatteryVoltage", "%d", epever_statistical->TodayMaxBatteryVoltage); 124 | ESP_LOGI("TodayMinBatteryVoltage", "%d", epever_statistical->TodayMinBatteryVoltage); 125 | 126 | ESP_LOGI("TodayConsumedEnergy", "%d", epever_statistical->TodayConsumedEnergy); 127 | ESP_LOGI("ThisMonthConsumedEnergy", "%d", epever_statistical->ThisMonthConsumedEnergy); 128 | ESP_LOGI("ThisYearConsumedEnergy", "%d", epever_statistical->ThisYearConsumedEnergy); 129 | ESP_LOGI("TotalConsumedEnergy", "%d", epever_statistical->TotalConsumedEnergy); 130 | 131 | ESP_LOGI("TodayGeneratedEnergy", "%d", epever_statistical->TodayGeneratedEnergy); 132 | ESP_LOGI("ThisMonthGeneratedEnergy", "%d", epever_statistical->ThisMonthGeneratedEnergy); 133 | ESP_LOGI("ThisYearGeneratedEnergy", "%d", epever_statistical->ThisYearGeneratedEnergy); 134 | ESP_LOGI("TotalGeneratedEnergy", "%d", epever_statistical->TotalGeneratedEnergy); 135 | 136 | ESP_LOGI("CarbonDioxideReduction", "%d", epever_statistical->CarbonDioxideReduction); 137 | 138 | ESP_LOGI("BatteryCurrent", "%d", epever_statistical->BatteryCurrent); 139 | 140 | ESP_LOGI("BatteryTemperature", "%d", epever_statistical->BatteryTemperature); 141 | ESP_LOGI("AmbientTemperature", "%d", epever_statistical->AmbientTemperature); 142 | } 143 | 144 | void print_coil(epever_coil_t *epever_coil) 145 | { 146 | ESP_LOGI("-------- print_coil ", "--------"); 147 | ESP_LOGI("ManualControlTheLoad", "%d", epever_coil->ManualControlTheLoad); 148 | ESP_LOGI("EnableLoadTestMode", "%d", epever_coil->EnableLoadTestMode); 149 | ESP_LOGI("ForceTheLoadOnOff", "%d", epever_coil->ForceTheLoadOnOff); 150 | } 151 | 152 | void print_discrete(epever_discrete_t *epever_discrete) 153 | { 154 | ESP_LOGI("-------- print_discrete ", "--------"); 155 | ESP_LOGI("OverTemperatureInsideTheDevice", "%d", epever_discrete->OverTemperatureInsideTheDevice); 156 | ESP_LOGI("DayNight", "%d", epever_discrete->DayNight); 157 | } 158 | 159 | void app_main(void) 160 | { 161 | 162 | // Initialization of device peripheral and objects 163 | ESP_ERROR_CHECK(master_init()); 164 | vTaskDelay(10); 165 | 166 | 167 | epever_rated_t epever_rated = {}; 168 | epever_realtime_t epever_realtime = {}; 169 | epever_statistical_t epever_statistical = {}; 170 | epever_setting_t epever_setting = {}; 171 | 172 | epever_coil_t epever_coil = {}; 173 | epever_discrete_t epever_discrete = {}; 174 | 175 | uint32_t loop = 0; 176 | 177 | master_read_rated(&epever_rated); 178 | master_read_setting(&epever_setting); 179 | 180 | print_rated(&epever_rated); 181 | print_setting(&epever_setting); 182 | 183 | 184 | master_read_coil(&epever_coil); 185 | master_read_discrete(&epever_discrete); 186 | 187 | print_coil(&epever_coil); 188 | print_discrete(&epever_discrete); 189 | 190 | 191 | vTaskDelay(500); 192 | 193 | master_write_coil_ManualControlTheLoad(1); 194 | vTaskDelay(500); 195 | master_write_coil_ManualControlTheLoad(0); 196 | 197 | 198 | while(1) 199 | { 200 | ESP_LOGI("LOOP ", "%d", loop++); 201 | master_read_realtime(&epever_realtime); 202 | print_realtime(&epever_realtime); 203 | 204 | master_read_statistical(&epever_statistical); 205 | print_statistical(&epever_statistical); 206 | 207 | 208 | ESP_LOGI("--------- ","---------"); 209 | 210 | vTaskDelay(1000); 211 | } 212 | } 213 | 214 | -------------------------------------------------------------------------------- /main/epever.c: -------------------------------------------------------------------------------- 1 | #include "esp_log.h" 2 | #include "mbcontroller.h" 3 | #include "epever.h" 4 | 5 | typedef struct 6 | { 7 | uint16_t uint16_value[50]; 8 | } discrete_reg_params_t; 9 | 10 | typedef struct 11 | { 12 | uint16_t uint16_value[50]; 13 | } coil_reg_params_t; 14 | 15 | typedef struct 16 | { 17 | uint16_t uint16_value[50]; 18 | } input_reg_params_t; 19 | 20 | typedef struct 21 | { 22 | uint16_t uint16_value[50]; 23 | } holding_reg_params_t; 24 | 25 | holding_reg_params_t holding_reg_params; 26 | input_reg_params_t input_reg_params; 27 | coil_reg_params_t coil_reg_params; 28 | discrete_reg_params_t discrete_reg_params; 29 | 30 | 31 | 32 | #define MB_PORT_NUM (CONFIG_MB_UART_PORT_NUM) // Number of UART port used for Modbus connection 33 | #define MB_DEV_SPEED (CONFIG_MB_UART_BAUD_RATE) // The communication speed of the UART 34 | 35 | // Note: Some pins on target chip cannot be assigned for UART communication. 36 | // See UART documentation for selected board and target to configure pins using Kconfig. 37 | 38 | // The number of parameters that intended to be used in the particular control process 39 | #define MASTER_MAX_CIDS num_device_parameters 40 | 41 | // Number of reading of parameters from slave 42 | #define MASTER_MAX_RETRY 30 43 | 44 | // Timeout to update cid over Modbus 45 | #define UPDATE_CIDS_TIMEOUT_MS (500) 46 | #define UPDATE_CIDS_TIMEOUT_TICS (UPDATE_CIDS_TIMEOUT_MS / portTICK_RATE_MS) 47 | 48 | // Timeout between polls 49 | #define POLL_TIMEOUT_MS (1) 50 | #define POLL_TIMEOUT_TICS (POLL_TIMEOUT_MS / portTICK_RATE_MS) 51 | 52 | #define MASTER_TAG "MASTER_TEST" 53 | 54 | 55 | #define MASTER_CHECK(a, ret_val, str, ...) \ 56 | if (!(a)) { \ 57 | ESP_LOGE(MASTER_TAG, "%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 58 | return (ret_val); \ 59 | } 60 | 61 | // The macro to get offset for parameter in the appropriate structure 62 | #define HOLD_OFFSET(field) ((uint16_t)(offsetof(holding_reg_params_t, field) + 1)) 63 | #define INPUT_OFFSET(field) ((uint16_t)(offsetof(input_reg_params_t, field) + 1)) 64 | #define COIL_OFFSET(field) ((uint16_t)(offsetof(coil_reg_params_t, field) + 1)) 65 | // Discrete offset macro 66 | #define DISCR_OFFSET(field) ((uint16_t)(offsetof(discrete_reg_params_t, field) + 1)) 67 | 68 | #define STR(fieldname) ((const char*)( fieldname )) 69 | // Options can be used as bit masks or parameter limits 70 | #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val } 71 | 72 | // Enumeration of modbus device addresses accessed by master device 73 | enum { 74 | MB_DEVICE_ADDR1 = 1 // Only one slave device used for the test (add other slave addresses here) 75 | }; 76 | 77 | // Enumeration of all supported CIDs for device (used in parameter definition table) 78 | enum { 79 | ChargingRated1 = 0, 80 | ChargingRated2, 81 | 82 | ChargingRealtime1, 83 | ChargingRealtime2, 84 | ChargingRealtime3, 85 | ChargingRealtime4, 86 | ChargingRealtime5, 87 | 88 | Statistical1, 89 | Statistical2, 90 | 91 | Setting1, 92 | Setting2, 93 | Setting3, 94 | Setting4, 95 | Setting5, 96 | Setting6, 97 | Setting7, 98 | Setting8, 99 | 100 | Coil1, 101 | Coil2, 102 | 103 | Discrete1, 104 | Discrete2, 105 | 106 | }; 107 | 108 | 109 | 110 | 111 | 112 | 113 | const mb_parameter_descriptor_t device_parameters[] = { 114 | // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode} 115 | 116 | {ChargingRated1, STR("ChargingRated1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x3000, 9, 117 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 18, OPTS( 0, 0, 0), PAR_PERMS_READ }, 118 | {ChargingRated2, STR("ChargingRated2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x300e, 1, 119 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 65535, 1), PAR_PERMS_READ }, 120 | 121 | {ChargingRealtime1, STR("ChargingRealtime1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x3100, 8, 122 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 16, OPTS( 0, 0, 0), PAR_PERMS_READ }, 123 | {ChargingRealtime2, STR("ChargingRealtime2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x310c, 7, 124 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 14, OPTS( 0, 0, 0), PAR_PERMS_READ }, 125 | {ChargingRealtime3, STR("ChargingRealtime3"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x311a, 2, 126 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 4, OPTS( 0, 0, 0), PAR_PERMS_READ }, 127 | {ChargingRealtime4, STR("ChargingRealtime4"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x311d, 1, 128 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 129 | {ChargingRealtime5, STR("ChargingRealtime5"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x3200, 2, 130 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 4, OPTS( 0, 0, 0), PAR_PERMS_READ }, 131 | 132 | 133 | {Statistical1, STR("Statistical1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x3300, 22, 134 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 44, OPTS( 0, 0, 0), PAR_PERMS_READ }, 135 | {Statistical2, STR("Statistical2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0x331b, 4, 136 | INPUT_OFFSET(uint16_value), PARAM_TYPE_U16, 8, OPTS( 0, 0, 0), PAR_PERMS_READ }, 137 | 138 | {Setting1, STR("Setting1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9000, 15, 139 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 30, OPTS( 0, 0, 0), PAR_PERMS_READ }, 140 | {Setting2, STR("Setting2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9013, 15, 141 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 30, OPTS( 0, 0, 0), PAR_PERMS_READ }, 142 | {Setting3, STR("Setting3"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x903d, 3, 143 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 6, OPTS( 0, 0, 0), PAR_PERMS_READ }, 144 | {Setting4, STR("Setting4"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9042, 12, 145 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 24, OPTS( 0, 0, 0), PAR_PERMS_READ }, 146 | {Setting5, STR("Setting5"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9065, 1, 147 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 148 | {Setting6, STR("Setting6"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9067, 1, 149 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 150 | {Setting7, STR("Setting7"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9069, 6, 151 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 14, OPTS( 0, 0, 0), PAR_PERMS_READ }, 152 | {Setting8, STR("Setting8"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0x9070, 1, 153 | HOLD_OFFSET(uint16_value), PARAM_TYPE_U16, 14, OPTS( 0, 0, 0), PAR_PERMS_READ }, 154 | 155 | {Coil1, STR("Coil1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0x2, 1, 156 | COIL_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 157 | {Coil2, STR("Coil2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_COIL, 0x5, 2, 158 | COIL_OFFSET(uint16_value), PARAM_TYPE_U16, 4, OPTS( 0, 0, 0), PAR_PERMS_READ }, 159 | 160 | {Discrete1, STR("Discrete1"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_DISCRETE, 0x2000, 1, 161 | DISCR_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 162 | {Discrete2, STR("Discrete2"), STR(""), MB_DEVICE_ADDR1, MB_PARAM_DISCRETE, 0x200c, 1, 163 | DISCR_OFFSET(uint16_value), PARAM_TYPE_U16, 2, OPTS( 0, 0, 0), PAR_PERMS_READ }, 164 | }; 165 | 166 | 167 | // Calculate number of parameters in the table 168 | const uint16_t num_device_parameters = (sizeof(device_parameters)/sizeof(device_parameters[0])); 169 | 170 | // The function to get pointer to parameter storage (instance) according to parameter description table 171 | static void* master_get_param_data(const mb_parameter_descriptor_t* param_descriptor) 172 | { 173 | assert(param_descriptor != NULL); 174 | void* instance_ptr = NULL; 175 | if (param_descriptor->param_offset != 0) { 176 | switch(param_descriptor->mb_param_type) 177 | { 178 | case MB_PARAM_HOLDING: 179 | instance_ptr = ((void*)&holding_reg_params + param_descriptor->param_offset - 1); 180 | break; 181 | case MB_PARAM_INPUT: 182 | instance_ptr = ((void*)&input_reg_params + param_descriptor->param_offset - 1); 183 | break; 184 | case MB_PARAM_COIL: 185 | instance_ptr = ((void*)&coil_reg_params + param_descriptor->param_offset - 1); 186 | break; 187 | case MB_PARAM_DISCRETE: 188 | instance_ptr = ((void*)&discrete_reg_params + param_descriptor->param_offset - 1); 189 | break; 190 | default: 191 | instance_ptr = NULL; 192 | break; 193 | } 194 | } else { 195 | ESP_LOGE(MASTER_TAG, "Wrong parameter offset for CID #%d", param_descriptor->cid); 196 | assert(instance_ptr != NULL); 197 | } 198 | return instance_ptr; 199 | } 200 | 201 | 202 | 203 | // Modbus master initialization 204 | esp_err_t master_init(void) 205 | { 206 | // Initialize and start Modbus controller 207 | mb_communication_info_t comm = { 208 | .port = MB_PORT_NUM, 209 | .mode = MB_MODE_RTU, 210 | .baudrate = MB_DEV_SPEED, 211 | .parity = MB_PARITY_NONE 212 | }; 213 | void* master_handler = NULL; 214 | 215 | esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); 216 | MASTER_CHECK((master_handler != NULL), ESP_ERR_INVALID_STATE, 217 | "mb controller initialization fail."); 218 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 219 | "mb controller initialization fail, returns(0x%x).", 220 | (uint32_t)err); 221 | err = mbc_master_setup((void*)&comm); 222 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 223 | "mb controller setup fail, returns(0x%x).", 224 | (uint32_t)err); 225 | 226 | // Set UART pin numbers 227 | err = uart_set_pin(MB_PORT_NUM, CONFIG_MB_UART_TXD, CONFIG_MB_UART_RXD, 228 | CONFIG_MB_UART_RTS, UART_PIN_NO_CHANGE); 229 | 230 | err = mbc_master_start(); 231 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 232 | "mb controller start fail, returns(0x%x).", 233 | (uint32_t)err); 234 | 235 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 236 | "mb serial set pin failure, uart_set_pin() returned (0x%x).", (uint32_t)err); 237 | // Set driver mode to Half Duplex 238 | err = uart_set_mode(MB_PORT_NUM, UART_MODE_RS485_HALF_DUPLEX); 239 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 240 | "mb serial set mode failure, uart_set_mode() returned (0x%x).", (uint32_t)err); 241 | 242 | vTaskDelay(5); 243 | err = mbc_master_set_descriptor(&device_parameters[0], num_device_parameters); 244 | MASTER_CHECK((err == ESP_OK), ESP_ERR_INVALID_STATE, 245 | "mb controller set descriptor fail, returns(0x%x).", 246 | (uint32_t)err); 247 | ESP_LOGI(MASTER_TAG, "Modbus master stack initialized..."); 248 | return err; 249 | } 250 | 251 | void master_read_rated(epever_rated_t *epever) 252 | { 253 | ESP_LOGI(MASTER_TAG,"Begin reading...."); 254 | esp_err_t err = ESP_OK; 255 | const mb_parameter_descriptor_t* param_descriptor = NULL; 256 | 257 | 258 | ESP_LOGI(MASTER_TAG,"ChargingRated1"); 259 | err = mbc_master_get_cid_info(ChargingRated1, ¶m_descriptor); 260 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 261 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 262 | void* temp_data_ptr = master_get_param_data(param_descriptor); 263 | assert(temp_data_ptr); 264 | uint8_t type = 0; 265 | uint16_t value[9] = { 0 }; 266 | err = mbc_master_get_parameter(ChargingRated1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 267 | if (err == ESP_OK) { 268 | epever->ChargingRatedInputVoltage = *(uint16_t*)&value[0]; 269 | epever->ChargingRatedInputCurrent = *(uint16_t*)&value[1]; 270 | epever->ChargingRatedInputPower = (*(uint16_t*)&value[2]) | (*(uint16_t*)&value[3]) << 16; 271 | 272 | epever->ChargingRatedOutputVoltage = *(uint16_t*)&value[4]; 273 | epever->ChargingRatedOutputCurrent = *(uint16_t*)&value[5]; 274 | epever->ChargingRatedOutputPower = (*(uint16_t*)&value[6]) | (*(uint16_t*)&value[7]) << 16; 275 | 276 | epever->ChargingMode = *(uint16_t*)&value[8]; 277 | } 278 | } 279 | } 280 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 281 | 282 | 283 | ESP_LOGI(MASTER_TAG,"ChargingRated2"); 284 | err = mbc_master_get_cid_info(ChargingRated2, ¶m_descriptor); 285 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 286 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 287 | void* temp_data_ptr = master_get_param_data(param_descriptor); 288 | assert(temp_data_ptr); 289 | uint8_t type = 0; 290 | uint16_t value = 0; 291 | err = mbc_master_get_parameter(ChargingRated2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 292 | if (err == ESP_OK) { 293 | epever->OutputRatedLoadCurrent = *(uint16_t*)&value; 294 | } 295 | } 296 | } 297 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 298 | 299 | 300 | 301 | ESP_LOGI(MASTER_TAG,"End Rated reading."); 302 | } 303 | 304 | 305 | 306 | 307 | void master_read_realtime(epever_realtime_t *epever) 308 | { 309 | ESP_LOGI(MASTER_TAG,"Begin reading Realtime...."); 310 | esp_err_t err = ESP_OK; 311 | const mb_parameter_descriptor_t* param_descriptor = NULL; 312 | 313 | ESP_LOGI(MASTER_TAG,"ChargingRealtime1"); 314 | err = mbc_master_get_cid_info(ChargingRealtime1, ¶m_descriptor); 315 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 316 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 317 | void* temp_data_ptr = master_get_param_data(param_descriptor); 318 | assert(temp_data_ptr); 319 | uint8_t type = 0; 320 | uint16_t value[8] = { 0 }; 321 | err = mbc_master_get_parameter(ChargingRealtime1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 322 | if (err == ESP_OK) { 323 | epever->ChargingInputVoltage= *(uint16_t*)&value[0]; 324 | epever->ChargingInputCurrent = *(uint16_t*)&value[1]; 325 | epever->ChargingInputPower = (*(uint16_t*)&value[2]) | (*(uint16_t*)&value[3]) << 16; 326 | 327 | epever->ChargingOutputVoltage = *(uint16_t*)&value[4]; 328 | epever->ChargingOutputCurrent = *(uint16_t*)&value[5]; 329 | epever->ChargingOutputPower = (*(uint16_t*)&value[6]) | (*(uint16_t*)&value[7]) << 16; 330 | } 331 | } 332 | } 333 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 334 | 335 | ESP_LOGI(MASTER_TAG,"ChargingRealtime2"); 336 | err = mbc_master_get_cid_info(ChargingRealtime2, ¶m_descriptor); 337 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 338 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 339 | void* temp_data_ptr = master_get_param_data(param_descriptor); 340 | assert(temp_data_ptr); 341 | uint8_t type = 0; 342 | uint16_t value[7] = { 0 }; 343 | err = mbc_master_get_parameter(ChargingRealtime2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 344 | if (err == ESP_OK) { 345 | epever->DischargingOutputVoltage= *(uint16_t*)&value[0]; 346 | epever->DischargingOutputCurrent = *(uint16_t*)&value[1]; 347 | epever->DischargingOutputPower = (*(uint16_t*)&value[2]) | (*(uint16_t*)&value[3]) << 16; 348 | 349 | epever->BatteryTemperature = *(uint16_t*)&value[4]; 350 | epever->ChargerCaseTemperature = *(uint16_t*)&value[5]; 351 | epever->ChargerSiliconTemperature = *(uint16_t*)&value[6]; 352 | } 353 | } 354 | } 355 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 356 | 357 | ESP_LOGI(MASTER_TAG,"ChargingRealtime3"); 358 | err = mbc_master_get_cid_info(ChargingRealtime3, ¶m_descriptor); 359 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 360 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 361 | void* temp_data_ptr = master_get_param_data(param_descriptor); 362 | assert(temp_data_ptr); 363 | uint8_t type = 0; 364 | uint16_t value[2] = { 0 }; 365 | err = mbc_master_get_parameter(ChargingRealtime3, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 366 | if (err == ESP_OK) { 367 | epever->BatterySOC= *(uint16_t*)&value[0]; 368 | epever->RemoteBatteryTemperature = *(uint16_t*)&value[1]; 369 | } 370 | } 371 | } 372 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 373 | 374 | 375 | ESP_LOGI(MASTER_TAG,"ChargingRealtime4"); 376 | err = mbc_master_get_cid_info(ChargingRealtime4, ¶m_descriptor); 377 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 378 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 379 | void* temp_data_ptr = master_get_param_data(param_descriptor); 380 | assert(temp_data_ptr); 381 | uint8_t type = 0; 382 | uint16_t value = 0 ; 383 | err = mbc_master_get_parameter(ChargingRealtime4, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 384 | if (err == ESP_OK) { 385 | epever->BatteryRealRatedVoltage= *(uint16_t*)&value; 386 | } 387 | } 388 | } 389 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 390 | 391 | ESP_LOGI(MASTER_TAG,"ChargingRealtime5"); 392 | err = mbc_master_get_cid_info(ChargingRealtime5, ¶m_descriptor); 393 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 394 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 395 | void* temp_data_ptr = master_get_param_data(param_descriptor); 396 | assert(temp_data_ptr); 397 | uint8_t type = 0; 398 | uint16_t value[2] = { 0 }; 399 | err = mbc_master_get_parameter(ChargingRealtime5, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 400 | if (err == ESP_OK) { 401 | epever->BatteryStatus= *(uint16_t*)&value[0]; 402 | epever->ChargerStatus = *(uint16_t*)&value[1]; 403 | } 404 | } 405 | } 406 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 407 | 408 | ESP_LOGI(MASTER_TAG,"End reading Realtime."); 409 | 410 | 411 | } 412 | 413 | 414 | void master_read_statistical(epever_statistical_t *epever) 415 | { 416 | ESP_LOGI(MASTER_TAG,"Begin reading Statistical...."); 417 | esp_err_t err = ESP_OK; 418 | const mb_parameter_descriptor_t* param_descriptor = NULL; 419 | 420 | ESP_LOGI(MASTER_TAG,"Statistical1"); 421 | err = mbc_master_get_cid_info(Statistical1, ¶m_descriptor); 422 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 423 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 424 | void* temp_data_ptr = master_get_param_data(param_descriptor); 425 | assert(temp_data_ptr); 426 | uint8_t type = 0; 427 | uint16_t value[22] = { 0 }; 428 | err = mbc_master_get_parameter(Statistical1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 429 | if (err == ESP_OK) { 430 | epever->TodayMaxInputVoltage = *(uint16_t*)&value[0]; 431 | epever->TodayMinInputVoltage = *(uint16_t*)&value[1]; 432 | epever->TodayMaxBatteryVoltage = *(uint16_t*)&value[2]; 433 | epever->TodayMinBatteryVoltage = *(uint16_t*)&value[3]; 434 | 435 | epever->TodayConsumedEnergy = (*(uint16_t*)&value[4]) | (*(uint16_t*)&value[5]) << 16; 436 | epever->ThisMonthConsumedEnergy = (*(uint16_t*)&value[6]) | (*(uint16_t*)&value[7]) << 16; 437 | epever->ThisYearConsumedEnergy = (*(uint16_t*)&value[8]) | (*(uint16_t*)&value[9]) << 16; 438 | epever->TotalConsumedEnergy = (*(uint16_t*)&value[10]) | (*(uint16_t*)&value[11]) << 16; 439 | 440 | epever->TodayGeneratedEnergy = (*(uint16_t*)&value[12]) | (*(uint16_t*)&value[13]) << 16; 441 | epever->ThisMonthGeneratedEnergy = (*(uint16_t*)&value[14]) | (*(uint16_t*)&value[15]) << 16; 442 | epever->ThisYearGeneratedEnergy = (*(uint16_t*)&value[16]) | (*(uint16_t*)&value[17]) << 16; 443 | epever->TotalGeneratedEnergy = (*(uint16_t*)&value[18]) | (*(uint16_t*)&value[19]) << 16; 444 | 445 | epever->CarbonDioxideReduction = (*(uint16_t*)&value[20]) | (*(uint16_t*)&value[21]) << 16; 446 | } 447 | } 448 | } 449 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 450 | 451 | ESP_LOGI(MASTER_TAG,"Statistical2"); 452 | err = mbc_master_get_cid_info(Statistical2, ¶m_descriptor); 453 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 454 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 455 | void* temp_data_ptr = master_get_param_data(param_descriptor); 456 | assert(temp_data_ptr); 457 | uint8_t type = 0; 458 | uint16_t value[4] = { 0 }; 459 | err = mbc_master_get_parameter(Statistical2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 460 | if (err == ESP_OK) { 461 | epever->BatteryCurrent = (*(int32_t*)&value[0]) | (*(uint16_t*)&value[1]) << 16; 462 | epever->BatteryTemperature = *(uint16_t*)&value[2]; 463 | epever->AmbientTemperature = *(uint16_t*)&value[3]; 464 | } 465 | } 466 | } 467 | vTaskDelay(POLL_TIMEOUT_TICS); // timeout between polls 468 | 469 | ESP_LOGI(MASTER_TAG,"End reading Statistical."); 470 | } 471 | 472 | 473 | 474 | void master_read_setting(epever_setting_t *epever) 475 | { 476 | ESP_LOGI(MASTER_TAG,"Begin reading Setting...."); 477 | esp_err_t err = ESP_OK; 478 | const mb_parameter_descriptor_t* param_descriptor = NULL; 479 | 480 | ESP_LOGI(MASTER_TAG,"Setting1"); 481 | err = mbc_master_get_cid_info(Setting1, ¶m_descriptor); 482 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 483 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 484 | void* temp_data_ptr = master_get_param_data(param_descriptor); 485 | assert(temp_data_ptr); 486 | uint8_t type = 0; 487 | uint16_t value[15] = { 0 }; 488 | err = mbc_master_get_parameter(Setting1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 489 | if (err == ESP_OK) { 490 | epever->BatteryType = *(uint16_t*)&value[0]; 491 | epever->BatteryCapacity = *(uint16_t*)&value[1]; 492 | epever->TemperatureCompensationCoefficient = *(uint16_t*)&value[2]; 493 | epever->HighVoltDisconnect = *(uint16_t*)&value[3]; 494 | epever->ChargingLimitVoltage = *(uint16_t*)&value[4]; 495 | epever->OverVoltageReconnect = *(uint16_t*)&value[5]; 496 | epever->EqualizationVoltage = *(uint16_t*)&value[6]; 497 | epever->BoostVoltage = *(uint16_t*)&value[7]; 498 | epever->FloatVoltage = *(uint16_t*)&value[8]; 499 | epever->BoostReconnectVoltage = *(uint16_t*)&value[9]; 500 | epever->LowVoltageReconnect = *(uint16_t*)&value[10]; 501 | epever->UnderVoltageRecover = *(uint16_t*)&value[11]; 502 | epever->UnderVoltageWarning = *(uint16_t*)&value[12]; 503 | epever->LowVoltageDisconnect = *(uint16_t*)&value[13]; 504 | epever->DischargingLimitVoltage = *(uint16_t*)&value[14]; 505 | } 506 | } 507 | } 508 | vTaskDelay(POLL_TIMEOUT_TICS); 509 | 510 | 511 | ESP_LOGI(MASTER_TAG,"Setting2"); 512 | err = mbc_master_get_cid_info(Setting2, ¶m_descriptor); 513 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 514 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 515 | void* temp_data_ptr = master_get_param_data(param_descriptor); 516 | assert(temp_data_ptr); 517 | uint8_t type = 0; 518 | uint16_t value[15] = { 0 }; 519 | err = mbc_master_get_parameter(Setting2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 520 | if (err == ESP_OK) { 521 | epever->RealTimeClock1 = *(uint16_t*)&value[0]; 522 | epever->RealTimeClock2 = *(uint16_t*)&value[1]; 523 | epever->RealTimeClock3 = *(uint16_t*)&value[2]; 524 | epever->EqualizationChargingCycle = *(uint16_t*)&value[3]; 525 | epever->BatteryTemperatureWarningUpperLimit = *(uint16_t*)&value[4]; 526 | epever->BatteryTemperatureWarningLowerLimit = *(uint16_t*)&value[5]; 527 | epever->ControllerInnerTemperatureUpperLimit = *(uint16_t*)&value[6]; 528 | epever->ControllerInnerTemperatureUpperLimitRecover = *(uint16_t*)&value[7]; 529 | epever->PowerComponentTemperatureUpperLimit = *(uint16_t*)&value[8]; 530 | epever->PowerComponentTemperatureUpperLimitRecover = *(uint16_t*)&value[9]; 531 | epever->LineImpedance = *(uint16_t*)&value[10]; 532 | epever->NightTimeThresholdVolt = *(uint16_t*)&value[11]; 533 | epever->LightSignalStartupDelayTime = *(uint16_t*)&value[12]; 534 | epever->DayTimeThresholdVolt = *(uint16_t*)&value[13]; 535 | epever->LightSignalTurnOffDelayTime = *(uint16_t*)&value[14]; 536 | } 537 | } 538 | } 539 | vTaskDelay(POLL_TIMEOUT_TICS); 540 | 541 | ESP_LOGI(MASTER_TAG,"Setting3"); 542 | err = mbc_master_get_cid_info(Setting3, ¶m_descriptor); 543 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 544 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 545 | void* temp_data_ptr = master_get_param_data(param_descriptor); 546 | assert(temp_data_ptr); 547 | uint8_t type = 0; 548 | uint16_t value[3] = { 0 }; 549 | err = mbc_master_get_parameter(Setting3, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 550 | if (err == ESP_OK) { 551 | epever->LoadControlingMode = *(uint16_t*)&value[0]; 552 | epever->WorkingTimeLength1 = *(uint16_t*)&value[1]; 553 | epever->WorkingTimeLength2 = *(uint16_t*)&value[2]; 554 | } 555 | } 556 | } 557 | vTaskDelay(POLL_TIMEOUT_TICS); 558 | 559 | ESP_LOGI(MASTER_TAG,"Setting4"); 560 | err = mbc_master_get_cid_info(Setting4, ¶m_descriptor); 561 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 562 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 563 | void* temp_data_ptr = master_get_param_data(param_descriptor); 564 | assert(temp_data_ptr); 565 | uint8_t type = 0; 566 | uint16_t value[12] = { 0 }; 567 | err = mbc_master_get_parameter(Setting4, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 568 | if (err == ESP_OK) { 569 | epever->TurnOnTiming1Second = *(uint16_t*)&value[0]; 570 | epever->TurnOnTiming1Minute = *(uint16_t*)&value[1]; 571 | epever->TurnOnTiming1Hour = *(uint16_t*)&value[2]; 572 | epever->TurnOffTiming1Second = *(uint16_t*)&value[3]; 573 | epever->TurnOffTiming1Minute = *(uint16_t*)&value[4]; 574 | epever->TurnOffTiming1Hour = *(uint16_t*)&value[5]; 575 | epever->TurnOnTiming2Second = *(uint16_t*)&value[6]; 576 | epever->TurnOnTiming2Minute = *(uint16_t*)&value[7]; 577 | epever->TurnOnTiming2Hour = *(uint16_t*)&value[8]; 578 | epever->TurnOffTiming2Second = *(uint16_t*)&value[9]; 579 | epever->TurnOffTiming2Minute = *(uint16_t*)&value[10]; 580 | epever->TurnOffTiming2Hour = *(uint16_t*)&value[11]; 581 | } 582 | } 583 | } 584 | vTaskDelay(POLL_TIMEOUT_TICS); 585 | 586 | ESP_LOGI(MASTER_TAG,"Setting5"); 587 | err = mbc_master_get_cid_info(Setting5, ¶m_descriptor); 588 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 589 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 590 | void* temp_data_ptr = master_get_param_data(param_descriptor); 591 | assert(temp_data_ptr); 592 | uint8_t type = 0; 593 | uint16_t value[1] = { 0 } ; 594 | err = mbc_master_get_parameter(Setting5, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 595 | if (err == ESP_OK) { 596 | epever->LengthOfNight = *(uint16_t*)&value[0]; 597 | } 598 | } 599 | } 600 | vTaskDelay(POLL_TIMEOUT_TICS); 601 | 602 | ESP_LOGI(MASTER_TAG,"Setting6"); 603 | err = mbc_master_get_cid_info(Setting6, ¶m_descriptor); 604 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 605 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 606 | void* temp_data_ptr = master_get_param_data(param_descriptor); 607 | assert(temp_data_ptr); 608 | uint8_t type = 0; 609 | uint16_t value[1] = { 0 }; 610 | err = mbc_master_get_parameter(Setting6, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 611 | if (err == ESP_OK) { 612 | epever->BatteryRatedVoltageCode = *(uint16_t*)&value[0]; 613 | } 614 | } 615 | } 616 | vTaskDelay(POLL_TIMEOUT_TICS); 617 | 618 | ESP_LOGI(MASTER_TAG,"Setting7"); 619 | err = mbc_master_get_cid_info(Setting7, ¶m_descriptor); 620 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 621 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 622 | void* temp_data_ptr = master_get_param_data(param_descriptor); 623 | assert(temp_data_ptr); 624 | uint8_t type = 0; 625 | uint16_t value[6] = { 0 }; 626 | err = mbc_master_get_parameter(Setting7, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 627 | if (err == ESP_OK) { 628 | epever->LoadTimingControlSelection = *(uint16_t*)&value[0]; 629 | epever->DefaultLoadOnOffInManualMode = *(uint16_t*)&value[1]; 630 | epever->EqualizeDuration = *(uint16_t*)&value[2]; 631 | epever->BoostDuration = *(uint16_t*)&value[3]; 632 | epever->DischargingPercentage = *(uint16_t*)&value[4]; 633 | epever->ChargingPercentage = *(uint16_t*)&value[5]; 634 | } 635 | } 636 | } 637 | vTaskDelay(POLL_TIMEOUT_TICS); 638 | 639 | ESP_LOGI(MASTER_TAG,"Setting8"); 640 | err = mbc_master_get_cid_info(Setting8, ¶m_descriptor); 641 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 642 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 643 | void* temp_data_ptr = master_get_param_data(param_descriptor); 644 | assert(temp_data_ptr); 645 | uint8_t type = 0; 646 | uint16_t value[1] = { 0 }; 647 | err = mbc_master_get_parameter(Setting8, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 648 | if (err == ESP_OK) { 649 | epever->ManagementModeOfBatteryChargingAndDischarging = *(uint16_t*)&value[0]; 650 | } 651 | } 652 | } 653 | vTaskDelay(POLL_TIMEOUT_TICS); 654 | 655 | ESP_LOGI(MASTER_TAG,"End reading Setting."); 656 | } 657 | 658 | 659 | void master_read_coil(epever_coil_t *epever) 660 | { 661 | ESP_LOGI(MASTER_TAG,"Begin reading coil...."); 662 | esp_err_t err = ESP_OK; 663 | const mb_parameter_descriptor_t* param_descriptor = NULL; 664 | 665 | ESP_LOGI(MASTER_TAG,"Coil1"); 666 | err = mbc_master_get_cid_info(Coil1, ¶m_descriptor); 667 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 668 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 669 | void* temp_data_ptr = master_get_param_data(param_descriptor); 670 | assert(temp_data_ptr); 671 | uint8_t type = 0; 672 | uint16_t value[1] = { 0 }; 673 | err = mbc_master_get_parameter(Coil1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 674 | if (err == ESP_OK) { 675 | epever->ManualControlTheLoad = (*(uint16_t*)&value[0]) > 1; 676 | } 677 | } 678 | } 679 | vTaskDelay(POLL_TIMEOUT_TICS); 680 | 681 | ESP_LOGI(MASTER_TAG,"Coil2"); 682 | err = mbc_master_get_cid_info(Coil2, ¶m_descriptor); 683 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 684 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 685 | void* temp_data_ptr = master_get_param_data(param_descriptor); 686 | assert(temp_data_ptr); 687 | uint8_t type = 0; 688 | uint16_t value[2] = { 0 }; 689 | err = mbc_master_get_parameter(Coil2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 690 | if (err == ESP_OK) { 691 | epever->EnableLoadTestMode = (*(uint16_t*)&value[0]) > 1; 692 | epever->ForceTheLoadOnOff = (*(uint16_t*)&value[1]) > 1; 693 | } 694 | } 695 | } 696 | vTaskDelay(POLL_TIMEOUT_TICS); 697 | 698 | ESP_LOGI(MASTER_TAG,"End reading coil."); 699 | } 700 | 701 | 702 | void master_read_discrete(epever_discrete_t *epever) 703 | { 704 | ESP_LOGI(MASTER_TAG,"Begin reading discrete...."); 705 | esp_err_t err = ESP_OK; 706 | const mb_parameter_descriptor_t* param_descriptor = NULL; 707 | 708 | ESP_LOGI(MASTER_TAG,"Discrete1"); 709 | err = mbc_master_get_cid_info(Discrete1, ¶m_descriptor); 710 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 711 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 712 | void* temp_data_ptr = master_get_param_data(param_descriptor); 713 | assert(temp_data_ptr); 714 | uint8_t type = 0; 715 | uint16_t value[1] = { 0 }; 716 | err = mbc_master_get_parameter(Discrete1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 717 | if (err == ESP_OK) { 718 | epever->OverTemperatureInsideTheDevice = *(uint16_t*)&value[0]; 719 | } 720 | } 721 | } 722 | vTaskDelay(POLL_TIMEOUT_TICS); 723 | 724 | ESP_LOGI(MASTER_TAG,"Discrete2"); 725 | err = mbc_master_get_cid_info(Discrete2, ¶m_descriptor); 726 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 727 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 728 | void* temp_data_ptr = master_get_param_data(param_descriptor); 729 | assert(temp_data_ptr); 730 | uint8_t type = 0; 731 | uint16_t value[1] = { 0 }; 732 | err = mbc_master_get_parameter(Discrete2, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 733 | if (err == ESP_OK) { 734 | epever->DayNight = *(uint16_t*)&value[0]; 735 | } 736 | } 737 | } 738 | vTaskDelay(POLL_TIMEOUT_TICS); 739 | 740 | ESP_LOGI(MASTER_TAG,"End reading discrete."); 741 | } 742 | 743 | 744 | 745 | void master_write_coil_ManualControlTheLoad(bool value) 746 | { 747 | ESP_LOGI(MASTER_TAG,"Begin master_write_coil") ; 748 | esp_err_t err = ESP_OK; 749 | const mb_parameter_descriptor_t* param_descriptor = NULL; 750 | 751 | err = mbc_master_get_cid_info(Coil1, ¶m_descriptor); 752 | uint8_t type = 0; 753 | err = mbc_master_set_parameter(Coil1, (char*)param_descriptor->param_key, (uint8_t*)&value, &type); 754 | if (err == ESP_OK) { 755 | ESP_LOGI(MASTER_TAG,"Write coil ok."); 756 | }else{ 757 | ESP_LOGI(MASTER_TAG,"Write coil fail."); 758 | } 759 | /* 760 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 761 | if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { 762 | //void* temp_data_ptr = master_get_param_data(param_descriptor); 763 | //assert(temp_data_ptr); 764 | 765 | } 766 | }*/ 767 | 768 | 769 | vTaskDelay(POLL_TIMEOUT_TICS); 770 | ESP_LOGI(MASTER_TAG,"End write coil."); 771 | } --------------------------------------------------------------------------------