Skip to content

Commit

Permalink
Introduce flow control pin (Closes: #18) (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
syssi committed Mar 20, 2022
1 parent 7d254a9 commit a900cf2
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 24 deletions.
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,3 @@ repos:
rev: v1.3.5
hooks:
- id: clang-format
- id: clang-tidy
39 changes: 30 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ ESPHome component to monitor a Solax X1 mini via RS485.
## Supported devices

* SolaX X1 Mini
- SolaX X1 Mini X1-0.6-S-D
- SolaX X1 Mini X1-0.6-S-D(L)
* SolaX X1 Mini G2
- SolaX X1 Mini X1-1.5-S-D(L) (master version 1.08, manager version 1.07) (reported by [@beocycris](https://github.com/syssi/esphome-modbus-solax-x1/issues/18#issuecomment-1073188868))
- SolaX X1 Mini X1-2.0-S-D(L) (master version 1.08, manager version 1.07) (reported by [@zcloud-at](https://github.com/syssi/esphome-modbus-solax-x1/issues/15))

## Requirements
Expand All @@ -26,15 +27,34 @@ ESPHome component to monitor a Solax X1 mini via RS485.

## Schematics

#### RS485-TTL module without flow control pin

```
RS485 UART
┌─────────┐ ┌─────────────┐ ┌─────────────────┐
│ │ │ GND│<--------->│GND │
│ Solax │<-----B- ---->│ RS485 RXD│<--------->│RX ESP32/ │
│ X1 Mini │<---- A+ ---->│ to TTL TXD│<--------->│TX ESP8266 │
│ │<--- GND ---->│ module VCC│<--------->│3.3V VCC│<--
│ │ │ │ │ GND│<--
└─────────┘ └─────────────┘ └─────────────────┘
```
RS485 UART
┌─────────┐ ┌──────────┐ ┌─────────┐
│ │ │ │<----- RX ----->│ │
│ Solax │<-----B- ---->│ RS485 │<----- TX ----->│ ESP32/ │
│ X1 Mini │<---- A+ ---->│ to TTL │<----- GND ---->│ ESP8266 │
│ │<--- GND ---->│ module │<-- 3.3 VCC --->│ │<-- VCC
│ │ │ │ │ │<-- GND
└─────────┘ └──────────┘ └─────────┘

#### RS485-TTL module with flow control pin

```
RS485 UART
┌─────────┐ ┌─────────────┐ ┌─────────────────┐
│ │ │ DI│<--------->│TX │
│ Solax │<-----B- ---->│ RS485 DE│<--\ │ ESP32/ │
│ X1 Mini │<---- A+ ---->│ to TTL RE│<---+----->│GPIO0 ESP8266 │
│ │<--- GND ---->│ module RO│<--------->│RX │
│ │ │ │ │ │
│ │ │ VCC│<--------->│3.3V VCC│<--
│ │ │ GND│<--------->│GND GND│<--
└─────────┘ └─────────────┘ └─────────────────┘
```

Please make sure to power the RS485 module with 3.3V because it affects the TTL (transistor-transistor logic) voltage between RS485 module and ESP.
Expand Down Expand Up @@ -126,6 +146,7 @@ solax_x1:
serial_number: "3132333435363737363534333231"
address: 0x0A
update_interval: 1s
# flow_control_pin: GPIO0

text_sensor:
- platform: solax_x1
Expand Down
29 changes: 19 additions & 10 deletions components/modbus_solax/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import uart
from esphome.const import CONF_ADDRESS, CONF_ID
from esphome.core import coroutine
import esphome.config_validation as cv
from esphome.const import CONF_ADDRESS, CONF_FLOW_CONTROL_PIN, CONF_ID
from esphome.cpp_helpers import gpio_pin_expression
from esphome import pins

CODEOWNERS = ["@syssi"]
DEPENDENCIES = ["uart"]
Expand All @@ -15,7 +16,12 @@
CONF_MODBUS_SOLAX_ID = "modbus_solax_id"
CONF_SERIAL_NUMBER = "serial_number"
CONFIG_SCHEMA = (
cv.Schema({cv.GenerateID(): cv.declare_id(ModbusSolax)})
cv.Schema(
{
cv.GenerateID(): cv.declare_id(ModbusSolax),
cv.Optional(CONF_FLOW_CONTROL_PIN): pins.gpio_output_pin_schema,
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(uart.UART_DEVICE_SCHEMA)
)
Expand Down Expand Up @@ -46,12 +52,16 @@ def as_hex_array(value):
return cg.RawExpression(f"(uint8_t*)(const uint8_t[16]){{{','.join(cpp_array)}}}")


def to_code(config):
async def to_code(config):
cg.add_global(modbus_solax_ns.using)
var = cg.new_Pvariable(config[CONF_ID])
yield cg.register_component(var, config)
await cg.register_component(var, config)

await uart.register_uart_device(var, config)

yield uart.register_uart_device(var, config)
if CONF_FLOW_CONTROL_PIN in config:
pin = await gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN])
cg.add(var.set_flow_control_pin(pin))


def modbus_solax_device_schema():
Expand All @@ -63,9 +73,8 @@ def modbus_solax_device_schema():
return cv.Schema(schema)


@coroutine
def register_modbus_solax_device(var, config):
parent = yield cg.get_variable(config[CONF_MODBUS_SOLAX_ID])
async def register_modbus_solax_device(var, config):
parent = await cg.get_variable(config[CONF_MODBUS_SOLAX_ID])
cg.add(var.set_parent(parent))
cg.add(var.set_address(config[CONF_ADDRESS]))
cg.add(var.set_serial_number(as_hex_array(config[CONF_SERIAL_NUMBER])))
Expand Down
17 changes: 16 additions & 1 deletion components/modbus_solax/modbus_solax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ namespace modbus_solax {

static const char *const TAG = "modbus_solax";

void ModbusSolax::setup() {
if (this->flow_control_pin_ != nullptr) {
this->flow_control_pin_->setup();
}
}

void ModbusSolax::loop() {
const uint32_t now = millis();
if (now - this->last_modbus_solax_byte_ > 50) {
Expand Down Expand Up @@ -138,7 +144,10 @@ bool ModbusSolax::parse_modbus_solax_byte_(uint8_t byte) {
return false;
}

void ModbusSolax::dump_config() { ESP_LOGCONFIG(TAG, "ModbusSolax:"); }
void ModbusSolax::dump_config() {
ESP_LOGCONFIG(TAG, "ModbusSolax:");
LOG_PIN(" Flow Control Pin: ", this->flow_control_pin_);
}
float ModbusSolax::get_setup_priority() const {
// After UART bus
return setup_priority::BUS - 1.0f;
Expand Down Expand Up @@ -217,8 +226,14 @@ void ModbusSolax::send(SolaxMessageT *tx_message) {

ESP_LOGVV(TAG, "TX -> %s", format_hex_pretty((const uint8_t *) tx_message, msg_len).c_str());

if (this->flow_control_pin_ != nullptr)
this->flow_control_pin_->digital_write(true);

this->write_array((const uint8_t *) tx_message, msg_len);
this->flush();

if (this->flow_control_pin_ != nullptr)
this->flow_control_pin_->digital_write(false);
}

} // namespace modbus_solax
Expand Down
3 changes: 3 additions & 0 deletions components/modbus_solax/modbus_solax.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ class ModbusSolax : public uart::UARTDevice, public Component {
public:
ModbusSolax() = default;

void setup() override;
void loop() override;

void dump_config() override;

void register_device(ModbusSolaxDevice *device) { this->devices_.push_back(device); }
void set_flow_control_pin(GPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; }

float get_setup_priority() const override;

Expand All @@ -38,6 +40,7 @@ class ModbusSolax : public uart::UARTDevice, public Component {

protected:
bool parse_modbus_solax_byte_(uint8_t byte);
GPIOPin *flow_control_pin_{nullptr};

std::vector<uint8_t> rx_buffer_;
uint32_t last_modbus_solax_byte_{0};
Expand Down
2 changes: 1 addition & 1 deletion components/solax_x1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import modbus_solax
import esphome.config_validation as cv
from esphome.const import CONF_ID

AUTO_LOAD = ["modbus_solax", "sensor", "text_sensor"]
Expand Down
2 changes: 1 addition & 1 deletion components/solax_x1/sensor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_MODE,
CONF_TEMPERATURE,
Expand Down
2 changes: 1 addition & 1 deletion components/solax_x1/text_sensor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import text_sensor
import esphome.config_validation as cv
from esphome.const import CONF_ICON, CONF_ID

from . import CONF_SOLAX_X1_ID, SolaxX1
Expand Down
7 changes: 7 additions & 0 deletions esp32-example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,18 @@ mqtt:
id: mqtt_client

uart:
id: uart0
baud_rate: 9600
tx_pin: GPIO1
rx_pin: GPIO3

modbus_solax:
- id: modbus0
uart_id: uart0
# flow_control_pin: GPIO0

solax_x1:
modbus_solax_id: modbus0
serial_number: "3132333435363737363534333231"
address: 0x0A
update_interval: 1s
Expand Down

0 comments on commit a900cf2

Please sign in to comment.