Skip to content

Commit

Permalink
Allow dynamic pin mapping for CMT module
Browse files Browse the repository at this point in the history
  • Loading branch information
tbnobody committed Apr 15, 2023
1 parent 3c0d89f commit 4588254
Show file tree
Hide file tree
Showing 19 changed files with 173 additions and 89 deletions.
5 changes: 5 additions & 0 deletions docs/DeviceProfiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ The json file can contain multiple profiles. Each profile requires a name and di
| nrf24.irq | number | Interrupt Pin |
| nrf24.en | number | Enable Pin |
| nrf24.cs | number | Chip Select Pin |
| cmt.sdio | number | SDIO Pin |
| cmt.clk | number | CLK Pin |
| cmt.cs | number | CS Pin |
| cmt.fcs | number | FCS Pin |
| cmt.gpio3 | number | GPIO3 Pin |
| eth.enabled | boolean | Enable/Disable the ethernet stack |
| eth.phy_addr | number | Unique PHY addr |
| eth.power | number | Power Pin (if available). Use -1 for not assigned pins. |
Expand Down
8 changes: 8 additions & 0 deletions include/PinMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ struct PinMapping_t {
int8_t nrf24_irq;
int8_t nrf24_en;
int8_t nrf24_cs;

int8_t cmt_clk;
int8_t cmt_cs;
int8_t cmt_fcs;
int8_t cmt_gpio3;
int8_t cmt_sdio;

int8_t eth_phy_addr;
bool eth_enabled;
int eth_power;
Expand All @@ -40,6 +47,7 @@ class PinMappingClass {
PinMapping_t& get();

bool isValidNrf24Config();
bool isValidCmt2300Config();
bool isValidEthConfig();

private:
Expand Down
4 changes: 2 additions & 2 deletions lib/CMT2300a/cmt2300a_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
* @name CMT2300A_InitSpi
* @desc Initializes the CMT2300A SPI interface.
* *********************************************************/
void CMT2300A_InitSpi(void)
void CMT2300A_InitSpi(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs)
{
cmt_spi3_init();
cmt_spi3_init(pin_sdio, pin_clk, pin_cs, pin_fcs);
}

/*! ********************************************************
Expand Down
2 changes: 1 addition & 1 deletion lib/CMT2300a/cmt2300a_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extern "C" {
#define CMT2300A_GetTickCount() millis()
/* ************************************************************************ */

void CMT2300A_InitSpi(void);
void CMT2300A_InitSpi(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs);

uint8_t CMT2300A_ReadReg(uint8_t addr);
void CMT2300A_WriteReg(uint8_t addr, uint8_t dat);
Expand Down
12 changes: 6 additions & 6 deletions lib/CMT2300a/cmt_spi3.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

spi_device_handle_t spi_reg, spi_fifo;

void cmt_spi3_init(void)
void cmt_spi3_init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs)
{
spi_bus_config_t buscfg = {
.mosi_io_num = CMT_PIN_SDIO,
.mosi_io_num = pin_sdio,
.miso_io_num = -1, // single wire MOSI/MISO
.sclk_io_num = CMT_PIN_CLK,
.sclk_io_num = pin_clk,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 32,
Expand All @@ -23,7 +23,7 @@ void cmt_spi3_init(void)
.dummy_bits = 0,
.mode = 0, // SPI mode 0
.clock_speed_hz = CMT_SPI_CLK,
.spics_io_num = CMT_PIN_CS,
.spics_io_num = pin_cs,
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
.queue_size = 1,
.pre_cb = NULL,
Expand All @@ -42,15 +42,15 @@ void cmt_spi3_init(void)
.cs_ena_pretrans = 2,
.cs_ena_posttrans = (uint8_t)(1 / (CMT_SPI_CLK * 10e6 * 2) + 2), // >2 us
.clock_speed_hz = CMT_SPI_CLK,
.spics_io_num = CMT_PIN_FCS,
.spics_io_num = pin_fcs,
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
.queue_size = 1,
.pre_cb = NULL,
.post_cb = NULL,
};
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg2, &spi_fifo));

esp_rom_gpio_connect_out_signal(CMT_PIN_SDIO, spi_periph_signal[SPI2_HOST].spid_out, true, false);
esp_rom_gpio_connect_out_signal(pin_sdio, spi_periph_signal[SPI2_HOST].spid_out, true, false);
delay(100);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/CMT2300a/cmt_spi3.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <stdint.h>

void cmt_spi3_init(void);
void cmt_spi3_init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs);

void cmt_spi3_write(uint8_t addr, uint8_t dat);
uint8_t cmt_spi3_read(uint8_t addr);
Expand Down
113 changes: 65 additions & 48 deletions lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,86 +3,103 @@
* Copyright (C) 2022 Thomas Basler and others
*/
#include "Hoymiles.h"
#include "inverters/HM_1CH.h"
#include "inverters/HM_2CH.h"
#include "inverters/HM_4CH.h"
#include "inverters/HMS_1CH.h"
#include "inverters/HMS_2CH.h"
#include "inverters/HMS_4CH.h"
#include "inverters/HM_1CH.h"
#include "inverters/HM_2CH.h"
#include "inverters/HM_4CH.h"
#include <Arduino.h>

#define HOY_SEMAPHORE_TAKE() xSemaphoreTake(_xSemaphore, portMAX_DELAY)
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)

HoymilesClass Hoymiles;

void HoymilesClass::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ)
void HoymilesClass::init()
{
_xSemaphore = xSemaphoreCreateMutex();
HOY_SEMAPHORE_GIVE(); // release before first use
HOY_SEMAPHORE_GIVE(); // release before first use

_pollInterval = 0;
_radioNrf.reset(new HoymilesRadio_NRF());
_radioCmt.reset(new HoymilesRadio_CMT());
}

void HoymilesClass::initNRF(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ)
{
_radioNrf->init(initialisedSpiBus, pinCE, pinIRQ);
}

_radioCmt.reset(new HoymilesRadio_CMT());
_radioCmt->init();
void HoymilesClass::initCMT(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio3)
{
_radioCmt->init(pin_sdio, pin_clk, pin_cs, pin_fcs, pin_gpio3);
}

void HoymilesClass::loop()
{
HOY_SEMAPHORE_TAKE();
_radioNrf->loop();
_radioCmt->loop();
if (_radioNrf->isInitialized()) {
_radioNrf->loop();
}

if (_radioCmt->isInitialized()) {
_radioCmt->loop();
}

if (getNumInverters() > 0) {
if (millis() - _lastPoll > (_pollInterval * 1000)) {
static uint8_t inverterPos = 0;

if (_radioNrf->isIdle() && _radioCmt->isIdle()) {
std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos);
if (iv != nullptr) {
_messageOutput->print("Fetch inverter: ");
_messageOutput->println(iv->serial(), HEX);

iv->sendStatsRequest();

// Fetch event log
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
iv->sendAlarmLogRequest(force);

// Fetch limit
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
_messageOutput->println("Request SystemConfigPara");
iv->sendSystemConfigParaRequest();
}

// Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend ActivePowerControl");
iv->resendActivePowerControlRequest();
}

// Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend PowerCommand");
iv->resendPowerControlRequest();
}

// Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) {
_messageOutput->println("Request device info");
iv->sendDevInfoRequest();
}
}
std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos);
if ((iv == nullptr) || ((iv != nullptr) && (!iv->getRadio()->isInitialized()))) {
if (++inverterPos >= getNumInverters()) {
inverterPos = 0;
}
}

_lastPoll = millis();
if (iv != nullptr && iv->getRadio()->isInitialized() && iv->getRadio()->isIdle()) {
_messageOutput->print("Fetch inverter: ");
_messageOutput->println(iv->serial(), HEX);

iv->sendStatsRequest();

// Fetch event log
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
iv->sendAlarmLogRequest(force);

// Fetch limit
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
_messageOutput->println("Request SystemConfigPara");
iv->sendSystemConfigParaRequest();
}

// Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend ActivePowerControl");
iv->resendActivePowerControlRequest();
}

// Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend PowerCommand");
iv->resendPowerControlRequest();
}

// Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) {
_messageOutput->println("Request device info");
iv->sendDevInfoRequest();
}

if (++inverterPos >= getNumInverters()) {
inverterPos = 0;
}

_lastPoll = millis();
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/Hoymiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

class HoymilesClass {
public:
void init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ);
void init();
void initNRF(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pinIRQ);
void initCMT(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio3);
void loop();

void setMessageOutput(Print* output);
Expand Down
10 changes: 10 additions & 0 deletions lib/Hoymiles/src/HoymilesRadio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,14 @@ void HoymilesRadio::dumpBuf(const char* info, uint8_t buf[], uint8_t len)
Hoymiles.getMessageOutput()->printf("%02X ", buf[i]);
}
Hoymiles.getMessageOutput()->println("");
}

bool HoymilesRadio::isInitialized()
{
return _isInitialized;
}

bool HoymilesRadio::isIdle()
{
return !_busyFlag;
}
5 changes: 5 additions & 0 deletions lib/Hoymiles/src/HoymilesRadio.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class HoymilesRadio {
serial_u DtuSerial();
virtual void setDtuSerial(uint64_t serial);

bool isIdle();
bool isInitialized();

template <typename T>
T* enqueCommand()
{
Expand All @@ -29,4 +32,6 @@ class HoymilesRadio {

serial_u _dtuSerial;
std::queue<std::shared_ptr<CommandAbstract>> _commandQueue;
bool _isInitialized = false;
bool _busyFlag = false;
};
16 changes: 6 additions & 10 deletions lib/Hoymiles/src/HoymilesRadio_CMT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ enumCMTresult HoymilesRadio_CMT::cmtProcess(void)
cmtRxTimeoutCnt++;
} else {
uint32_t invSerial = cmtTxBuffer[1] << 24 | cmtTxBuffer[2] << 16 | cmtTxBuffer[3] << 8 | cmtTxBuffer[4]; // read inverter serial from last Tx buffer
cmtSwitchInvAndDtuFreq(invSerial, HOY_BOOT_FREQ / 1000, CMT_WORK_FREQ);
cmtSwitchInvAndDtuFreq(invSerial, HOY_BOOT_FREQ / 1000, HOYMILES_CMT_WORK_FREQ);
}

nRes = CMT_RX_TIMEOUT;
Expand Down Expand Up @@ -315,12 +315,12 @@ enumCMTresult HoymilesRadio_CMT::cmtProcess(void)
return nRes;
}

void HoymilesRadio_CMT::init()
void HoymilesRadio_CMT::init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio3)
{
_dtuSerial.u64 = 0;
uint8_t tmp;

CMT2300A_InitSpi();
CMT2300A_InitSpi(pin_sdio, pin_clk, pin_cs, pin_fcs);
if (!CMT2300A_Init()) {
Hoymiles.getMessageOutput()->println("CMT2300A_Init() failed!");
return;
Expand All @@ -345,11 +345,12 @@ void HoymilesRadio_CMT::init()
return;
}

attachInterrupt(digitalPinToInterrupt(CMT_PIN_GPIO3), std::bind(&HoymilesRadio_CMT::handleIntr, this), RISING);
attachInterrupt(digitalPinToInterrupt(pin_gpio3), std::bind(&HoymilesRadio_CMT::handleIntr, this), RISING);

cmtSwitchDtuFreq(CMT_WORK_FREQ); // start dtu at work freqency, for fast Rx if inverter is already on and frequency switched
cmtSwitchDtuFreq(HOYMILES_CMT_WORK_FREQ); // start dtu at work freqency, for fast Rx if inverter is already on and frequency switched

_ChipConnected = true;
_isInitialized = true;

Hoymiles.getMessageOutput()->println("CMT init successful");
}
Expand Down Expand Up @@ -447,11 +448,6 @@ void HoymilesRadio_CMT::loop()
}
}

bool HoymilesRadio_CMT::isIdle()
{
return !_busyFlag;
}

bool HoymilesRadio_CMT::isConnected()
{
return _ChipConnected;
Expand Down
5 changes: 1 addition & 4 deletions lib/Hoymiles/src/HoymilesRadio_CMT.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ typedef enum {

class HoymilesRadio_CMT : public HoymilesRadio {
public:
void init();
void init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio3);
void loop();

bool isIdle();
bool isConnected();

private:
Expand All @@ -55,8 +54,6 @@ class HoymilesRadio_CMT : public HoymilesRadio {
std::queue<fragment_t> _rxBuffer;
TimeoutHelper _rxTimeout;

bool _busyFlag = false;

bool _ChipConnected = false;

String cmtChToFreq(const uint8_t channel);
Expand Down
6 changes: 1 addition & 5 deletions lib/Hoymiles/src/HoymilesRadio_NRF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void HoymilesRadio_NRF::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t

openReadingPipe();
_radio->startListening();
_isInitialized = true;
}

void HoymilesRadio_NRF::loop()
Expand Down Expand Up @@ -159,11 +160,6 @@ void HoymilesRadio_NRF::setDtuSerial(uint64_t serial)
openReadingPipe();
}

bool HoymilesRadio_NRF::isIdle()
{
return !_busyFlag;
}

bool HoymilesRadio_NRF::isConnected()
{
return _radio->isChipConnected();
Expand Down
Loading

0 comments on commit 4588254

Please sign in to comment.