diff --git a/lib/GPIO/TCA9554PWR_Driver.cpp b/lib/GPIO/TCA9554PWR_Driver.cpp index 1ec881a..67511fe 100644 --- a/lib/GPIO/TCA9554PWR_Driver.cpp +++ b/lib/GPIO/TCA9554PWR_Driver.cpp @@ -13,7 +13,7 @@ namespace drivers { if (m_i2c.write(m_address, reg, {val})) return true; - log_e("Unable to write register: reg[%d], val[%d] ", reg, val); + LOG_ERROR("Unable to write register: reg[%d], val[%d] ", reg, val); return false; } @@ -25,7 +25,7 @@ namespace drivers val = data.back(); return true; } - log_e("Unable to read register: reg[%d]"); + LOG_ERROR("Unable to read register: reg[%d]"); return false; } @@ -34,9 +34,9 @@ namespace drivers uint8_t currState(0); uint8_t newState(0); - if (ch < EXIO_PIN1 || ch > EXIO_PIN8) + if (ch < OUT_PIN1 || ch > OUT_PIN8) { - log_e("Invalid write to output channel: [%d]", ch); + LOG_ERROR("Invalid write to output channel: [%d]", ch); return false; } if (!readPort(currState)) @@ -52,16 +52,16 @@ namespace drivers { if (writeRegister(TCA9554_OUTPUT_REG, state)) return true; - log_e("Unable to write IO port: state[%02x]", state); + LOG_ERROR("Unable to write IO port: state[%02x]", state); return false; } const bool TCA9554PWR::readOut(const uint8_t ch) { uint8_t currState(0); - if (ch < EXIO_PIN1 || ch > EXIO_PIN8) + if (ch < OUT_PIN1 || ch > OUT_PIN8) { - log_e("Invalid read to output channel: [%d]", ch); + LOG_ERROR("Invalid read to output channel: [%d]", ch); return false; } if (!readPort(currState)) @@ -73,7 +73,7 @@ namespace drivers { if (readRegister(TCA9554_INPUT_REG, state)) return true; - log_e("Unable to read IO port: state[%02x]", state); + LOG_ERROR("Unable to read IO port: state[%02x]", state); return false; } diff --git a/lib/GPIO/TCA9554PWR_Driver.h b/lib/GPIO/TCA9554PWR_Driver.h index 1e311b7..356cc60 100644 --- a/lib/GPIO/TCA9554PWR_Driver.h +++ b/lib/GPIO/TCA9554PWR_Driver.h @@ -15,27 +15,25 @@ #define Low 0x00 #define High 0x01 -#define EXIO_PIN1 0 -#define EXIO_PIN2 1 -#define EXIO_PIN3 2 -#define EXIO_PIN4 3 -#define EXIO_PIN5 4 -#define EXIO_PIN6 5 -#define EXIO_PIN7 6 -#define EXIO_PIN8 7 - namespace drivers { class TCA9554PWR { - I2C &m_i2c; - uint8_t m_address; - - private: - const bool writeRegister(const uint8_t reg, const uint8_t val); - const bool readRegister(const uint8_t reg, uint8_t &val); public: + enum + { + OUT_PIN1, + OUT_PIN2, + OUT_PIN3, + OUT_PIN4, + OUT_PIN5, + OUT_PIN6, + OUT_PIN7, + OUT_PIN8, + OUT_PIN_MAX + }; + TCA9554PWR(I2C &i2c, const uint8_t address); const bool setOut(const uint8_t channel, const bool state); @@ -43,5 +41,11 @@ namespace drivers const bool readOut(const uint8_t channel); const bool readPort(uint8_t &state); + + private: + I2C &m_i2c; + uint8_t m_address; + const bool writeRegister(const uint8_t reg, const uint8_t val); + const bool readRegister(const uint8_t reg, uint8_t &val); }; } \ No newline at end of file diff --git a/lib/I2C/I2C_Driver.cpp b/lib/I2C/I2C_Driver.cpp index f4e16b5..3d76956 100644 --- a/lib/I2C/I2C_Driver.cpp +++ b/lib/I2C/I2C_Driver.cpp @@ -17,7 +17,7 @@ namespace drivers const bool I2C::read(const uint8_t deviceAddr, const uint8_t deviceReg, const uint8_t len, std::vector &data) { - busy.try_lock(); + //busy.try_lock(); Wire.beginTransmission(deviceAddr); Wire.write(deviceReg); switch (Wire.endTransmission(true)) @@ -25,19 +25,19 @@ namespace drivers case 0: break; // no error, break switch case 1: - log_e("Data to long to fit in buffer: [%d]", len); + LOG_ERROR("Data to long to fit in buffer: [%d]", len); case 2: - log_e("Received NAK on address transmit"); + LOG_ERROR("Received NAK on address transmit"); case 3: - log_e("Received NAK on data transmit"); + LOG_ERROR("Received NAK on data transmit"); case 4: - log_e("Unknown Error"); + LOG_ERROR("Unknown Error"); return false; } const uint8_t nBytes = Wire.requestFrom(deviceAddr, len); if (nBytes < len) { - log_w("Received data is less than expected: len[%d], nBytes[%d]", len, nBytes); + LOG_ERROR("Received data is less than expected: len[%d], nBytes[%d]", len, nBytes); } data.clear(); data.resize(nBytes); // resize out buffer to received data len, no check if data len is correct @@ -45,13 +45,13 @@ namespace drivers { data[i] = static_cast(Wire.read()); } - busy.unlock(); + //busy.unlock(); return true; } const bool I2C::write(const uint8_t deviceAddr, const uint8_t deviceReg, const std::vector &data) { - busy.lock(); + //busy.lock(); Wire.beginTransmission(deviceAddr); Wire.write(deviceReg); for (auto d : data) @@ -64,16 +64,16 @@ namespace drivers case 0: break; // no error, break switch case 1: - log_e("Data to long to fit in buffer: [%d]", data.size()); + LOG_ERROR("Data to long to fit in buffer: [%d]", data.size()); case 2: - log_e("Received NAK on address transmit"); + LOG_ERROR("Received NAK on address transmit"); case 3: - log_e("Received NAK on data transmit"); + LOG_ERROR("Received NAK on data transmit"); case 4: - log_e("Unknown Error"); + LOG_ERROR("Unknown Error"); return false; } - busy.unlock(); + //busy.unlock(); return true; } diff --git a/lib/I2C/I2C_Driver.h b/lib/I2C/I2C_Driver.h index cb53f3c..ba2db68 100644 --- a/lib/I2C/I2C_Driver.h +++ b/lib/I2C/I2C_Driver.h @@ -1,4 +1,7 @@ #pragma once + +#include +#include #include #include #include @@ -13,7 +16,7 @@ namespace drivers { private: bool isInitialized = false; - std::mutex busy; + //std::mutex busy; public: I2C(void); diff --git a/lib/RS485/RS485_Driver.cpp b/lib/RS485/RS485_Driver.cpp index 96e6889..96e071e 100644 --- a/lib/RS485/RS485_Driver.cpp +++ b/lib/RS485/RS485_Driver.cpp @@ -1,7 +1,14 @@ #include "RS485_driver.h" #include #include +#include +#ifdef ESP32 #include +#else +#define be16toh(x) __bswap16(x) +#define htobe16(x) __bswap16(x) +#define htole16(x) x +#endif uint8_t data[][8] = { // ESP32-S3-POE-ETH-8DI-8RO Control Command (RS485 receiving data) @@ -37,14 +44,23 @@ namespace drivers //////////// RS485 //////////// //////////////////////////////// +#ifdef ESP32 RS485::RS485(const uint32_t baud, const SerialConfig conf) { - log_i("Init serial port 1"); + LOG_INFO("Init serial port 1"); m_serial = std::make_unique(PORT); // RS485 is hardwired to serial port 1 m_serial->begin(baud, conf); m_serial->setMode(UART_MODE_RS485_HALF_DUPLEX); } +#else + RS485::RS485(const uint32_t baud) + { + LOG_INFO("Init serial port 1"); + m_serial = std::make_unique(PORT); // RS485 is hardwired to serial port 1 + m_serial->begin(baud); + } +#endif const bool RS485::write(const std::vector data) { return data.size() == m_serial->write(data.data(), data.size()); @@ -75,17 +91,22 @@ namespace drivers //////////////////////////////// //////////// MODBUS //////////// //////////////////////////////// - +#ifdef ESP32 MODBUS::MODBUS(const uint32_t baud, const SerialConfig conf) : RS485::RS485(baud, conf) { - log_i("Init MODBUS Master Mode"); + LOG_INFO("Init MODBUS Master Mode"); } - +#else + MODBUS::MODBUS(const uint32_t baud) : RS485::RS485(baud) + { + LOG_INFO("Init MODBUS Master Mode"); + } +#endif // Func 0x01 const bool MODBUS::readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector &coils) { constexpr uint8_t func = 0x01; - log_d("Read coils: dev[%02x], reg[%04x], num[%d]", device, reg, num); + LOG_DEBUG("Read coils: dev[%02x], reg[%04x], num[%d]", device, reg, num); return readBinary(func, device, reg, num, coils); } @@ -93,7 +114,7 @@ namespace drivers const bool MODBUS::readInputs(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector &inputs) { constexpr uint8_t func = 0x01; - log_d("Read multi inputs: dev[%02x], reg[%04x], num[%d]", device, reg, num); + LOG_DEBUG("Read multi inputs: dev[%02x], reg[%04x], num[%d]", device, reg, num); return readBinary(func, device, reg, num, inputs); } @@ -101,7 +122,7 @@ namespace drivers const bool MODBUS::readHoldingRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector &values) { constexpr uint8_t func = 0x03; - log_d("Read multi holding registers: dev[%02x], reg[%04x], num[%d]", device, reg, num); + LOG_DEBUG("Read multi holding registers: dev[%02x], reg[%04x], num[%d]", device, reg, num); return readInteger(func, device, reg, num, values); } @@ -109,7 +130,7 @@ namespace drivers const bool MODBUS::readInputRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector &values) { constexpr uint8_t func = 0x04; - log_d("Read multi input registers: dev[%02x], reg[%04x], num[%d]", device, reg, num); + LOG_DEBUG("Read multi input registers: dev[%02x], reg[%04x], num[%d]", device, reg, num); return readInteger(func, device, reg, num, values); } @@ -117,7 +138,7 @@ namespace drivers const bool MODBUS::writeCoil(const uint8_t device, const uint16_t coil, const bool value) { constexpr uint8_t func = 0x05; - log_d("Write single coil: dev[%02x], reg[%04x], val[...]", device, reg); + LOG_DEBUG("Write single coil: dev[%02x], reg[%04x], val[...]", device, coil); return writeBinary(device, func, coil, 1, {value}); } @@ -125,7 +146,7 @@ namespace drivers const bool MODBUS::writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value) { constexpr uint8_t func = 0x06; - log_d("Write single register: dev[%02x], reg[%04x], val[%04x]", device, reg, value); + LOG_DEBUG("Write single register: dev[%02x], reg[%04x], val[%04x]", device, reg, value); return writeInteger(device, func, reg, 1, {value}); } @@ -133,7 +154,7 @@ namespace drivers const bool MODBUS::writeCoils(const uint8_t device, const uint16_t coils, const std::vector &values) { constexpr uint8_t func = 0x0F; - log_d("Write multi coils: dev[%02x], reg[%04x], val[...]", device, reg); + LOG_DEBUG("Write multi coils: dev[%02x], reg[%04x], val[...]", device, coils); return writeBinary(device, func, coils, values.size(), values); } @@ -141,7 +162,7 @@ namespace drivers const bool MODBUS::writeRegisters(const uint8_t device, const uint16_t reg, const std::vector &values) { constexpr uint8_t func = 0x10; - log_d("Write multi registers: dev[%02x], reg[%04x], val[...]", device, reg); + LOG_DEBUG("Write multi registers: dev[%02x], reg[%04x], val[...]", device, reg); return writeInteger(device, func, reg, values.size(), values); } @@ -153,22 +174,22 @@ namespace drivers { if (!write(singleRequest(device, func, reg, bits))) { - log_e("Failed send readBinary command"); + LOG_ERROR("Failed send readBinary command"); return false; } - const uint16_t nRespDataBytes = 1 + (uint16_t)(bits / 8); // 1 bit for every coil, if not 8 mutiple padded with zeroes + const uint16_t nRespDataBytes = 1 + (uint16_t)(bits / 8); // 1 bit for every coil, if not 8 mutiple padded with zeroes const uint16_t expectedRespLen = (RESP_HEADER_SIZE + RESP_CRC_SIZE) + nRespDataBytes; // device + function + nbytes + data[] + crc(16b) std::vector response; if (!readN(expectedRespLen, response)) { - log_e("Failed receive readBinary response"); + LOG_ERROR("Failed receive readBinary response"); return false; } // element 2 of response has the response data bytes expected if (response.at(2) != nRespDataBytes) { - log_e("Failed receive, data to short: bytes[%d], expected[%d]", response.at(2), nRespDataBytes); + LOG_ERROR("Failed receive, data to short: bytes[%d], expected[%d]", response.at(2), nRespDataBytes); return false; } @@ -200,7 +221,7 @@ namespace drivers { if (!write(singleRequest(device, func, reg, num))) { - log_e("Failed send readInteger command"); + LOG_ERROR("Failed send readInteger command"); return false; } const uint16_t nRespDataBytes = num * sizeof(uint16_t); @@ -208,14 +229,14 @@ namespace drivers std::vector response; if (!readN(expectedRespLen, response)) { - log_e("Failed receive readInteger response"); + LOG_ERROR("Failed receive readInteger response"); return false; } // element 2 of response has the response data bytes expected if (response.at(2) != nRespDataBytes) { - log_e("Failed receive, data to short: bytes[%d], expected[%d]", response.at(2), nRespDataBytes); + LOG_ERROR("Failed receive, data to short: bytes[%d], expected[%d]", response.at(2), nRespDataBytes); return false; } @@ -260,7 +281,7 @@ namespace drivers if (!write(multiRequest(device, func, reg, bits, bitsOut))) { - log_e("Failed send writeBinary command"); + LOG_ERROR("Failed send writeBinary command"); return false; } @@ -268,7 +289,7 @@ namespace drivers std::vector response; if (!readN(expectedRespLen, response)) { - log_e("Failed receive writeBinary response"); + LOG_ERROR("Failed receive writeBinary response"); return false; } @@ -283,7 +304,7 @@ namespace drivers { if (!write(multiRequest(device, func, reg, num, in))) { - log_e("Failed send writeInteger command"); + LOG_ERROR("Failed send writeInteger command"); return false; } @@ -291,7 +312,7 @@ namespace drivers std::vector response; if (!readN(expectedRespLen, response)) { - log_e("Failed receive writeInteger response"); + LOG_ERROR("Failed receive writeInteger response"); return false; } @@ -371,7 +392,7 @@ namespace drivers // verify crc code if (highByte(computedCrc) != crcHi || lowByte(computedCrc) != crcLo) { - log_e("Failed verify CRC code: comp[%04x], rec[%04x]", computedCrc, 0xFFFF & ((crcHi << 8) | crcLo)); + LOG_ERROR("Failed verify CRC code: comp[%04x], rec[%04x]", computedCrc, 0xFFFF & ((crcHi << 8) | crcLo)); return false; } return true; diff --git a/lib/RS485/RS485_Driver.h b/lib/RS485/RS485_Driver.h index 1535bbc..93a2c20 100644 --- a/lib/RS485/RS485_Driver.h +++ b/lib/RS485/RS485_Driver.h @@ -1,7 +1,8 @@ #pragma once -#include // Reference the ESP32 built-in serial port library +#include #include +#include // Reference the ESP32 built-in serial port library #include #include @@ -23,8 +24,11 @@ namespace drivers static const uint8_t PORT = 1; public: +#ifdef ESP32 RS485(const uint32_t baud, const SerialConfig conf); - +#else + RS485(const uint32_t baud); +#endif const bool write(const std::vector data); const bool readAll(std::vector &data); const bool readN(const uint16_t nBytes, std::vector &data); @@ -61,7 +65,11 @@ namespace drivers typedef uint16_t crc_t; public: +#ifdef ESP32 MODBUS(const uint32_t baud, const SerialConfig conf); +#else + MODBUS(const uint32_t baud); +#endif // Func 0x01 const bool readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector &coils); diff --git a/lib/RTC/PCF85063_Driver.cpp b/lib/RTC/PCF85063_Driver.cpp index f7a5eae..8d9e90e 100644 --- a/lib/RTC/PCF85063_Driver.cpp +++ b/lib/RTC/PCF85063_Driver.cpp @@ -18,16 +18,16 @@ namespace drivers success &= m_i2c.write(m_address, RTC_CTRL_2_ADDR, {def_conf2}); } if (!success) - log_e("RTC Init Failure"); + LOG_ERROR("RTC Init Failure"); } const bool PCF85063::reset(void) { - log_i("RTC Reset Initiated"); + LOG_INFO("RTC Reset Initiated"); const uint8_t cfg = RTC_CTRL_1_DEFAULT | RTC_CTRL_1_CAP_SEL | RTC_CTRL_1_SR; if (m_i2c.write(m_address, RTC_CTRL_1_ADDR, {cfg})) return true; - log_e("RTC Reset Failure"); + LOG_ERROR("RTC Reset Failure"); return false; } @@ -39,7 +39,7 @@ namespace drivers decToBcd(time.hour)}; if (m_i2c.write(m_address, RTC_SECOND_ADDR, buf)) return true; - log_e("RTC setTime failure"); + LOG_ERROR("RTC setTime failure"); return false; } @@ -52,7 +52,7 @@ namespace drivers decToBcd(date.year - YEAR_OFFSET)}; if (m_i2c.write(m_address, RTC_DAY_ADDR, buf)) return true; - log_e("RTC setDate failure"); + LOG_ERROR("RTC setDate failure"); return false; } @@ -72,7 +72,7 @@ namespace drivers datetime.year = bcdToDec(buf[3]) + YEAR_OFFSET; return true; } - log_e("RTC readDate Failure"); + LOG_ERROR("RTC readDate Failure"); return false; } @@ -86,7 +86,7 @@ namespace drivers datetime.hour = bcdToDec(buf[2] & 0x3F); return true; } - log_e("RTC readTime Failure"); + LOG_ERROR("RTC readTime Failure"); return false; } @@ -110,7 +110,7 @@ namespace drivers if (m_i2c.write(m_address, RTC_CTRL_2_ADDR, currStatus)) return true; - log_e("RTC enableAlarm failure"); + LOG_ERROR("RTC enableAlarm failure"); return false; } @@ -125,7 +125,7 @@ namespace drivers }; if (m_i2c.write(m_address, RTC_SECOND_ALARM, buf)) return true; - log_e("RTC setAlarm failure"); + LOG_ERROR("RTC setAlarm failure"); return false; } @@ -141,7 +141,7 @@ namespace drivers time.dotw = (uint8_t)bcdToDec(buf[4] & 0x07); return true; } - log_e("RTC readAlarm failure"); + LOG_ERROR("RTC readAlarm failure"); return false; } @@ -153,7 +153,7 @@ namespace drivers flags = buf.at(0); return true; } - log_e("RTC readAlarmFlags failure"); + LOG_ERROR("RTC readAlarmFlags failure"); return false; } diff --git a/platformio.ini b/platformio.ini index 193f5f4..21123a2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,15 @@ lib_deps = arduino-libraries/NTPClient@^3.2.1 knolleary/PubSubClient@^2.8 robtillaart/CRC@^1.0.3 + hideakitai/DebugLog@^0.8.4 -[env:native] -platform = native -test_framework = doctest +[env:nucleo_f401re] +platform = ststm32 +board = nucleo_f401re +framework = arduino +lib_deps = + bblanchon/ArduinoJson@^7.4.2 + arduino-libraries/NTPClient@^3.2.1 + knolleary/PubSubClient@^2.8 + robtillaart/CRC@^1.0.3 + hideakitai/DebugLog@^0.8.4 diff --git a/src/main.cpp b/src/main.cpp index 87f36b8..e0f35ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,38 +1,71 @@ +#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG + +#include #include #include +#include -void setup() { +void setup() +{ bool success = true; + LOG_INFO("Create i2c driver"); + auto i2c = drivers::I2C(); + LOG_INFO("Create relay driver"); + auto relays = drivers::TCA9554PWR(i2c, TCA9554_ADDRESS); + + for (auto i(0); i < drivers::TCA9554PWR::OUT_PIN_MAX; i++) + { + LOG_INFO("Toggle relay [%d]=ON", i); + success &= relays.setOut(i, true); + delay(1000); + LOG_INFO("Toggle relay [%d]=OFF", i); + success &= relays.setOut(i, false); + delay(1000); + } + + LOG_INFO("Toggle port [0x55]"); + success &= relays.setPort(0x55); + delay(2000); + LOG_INFO("Toggle port [0xAA]"); + success &= relays.setPort(0xAA); + delay(2000); + + LOG_INFO("Create modbus driver"); +#ifdef ESP32 auto bus = drivers::MODBUS(9600, SERIAL_8N1); +#else + auto bus = drivers::MODBUS(9600); +#endif const uint8_t devAddress(0x01); const uint8_t baseRegister(0x02); - log_i("Write single coil"); + LOG_INFO("Write single coil"); success &= bus.writeCoil(devAddress, baseRegister, true); - success &=bus.writeCoil(devAddress, baseRegister, false); + success &= bus.writeCoil(devAddress, baseRegister, false); - log_i("Write multiple coils"); + LOG_INFO("Write multiple coils"); const uint16_t coilsNum(32); std::vector coilsValues(coilsNum, false); - bool v=true; - for (auto i(0); i < coilsNum; i++) { + bool v = true; + for (auto i(0); i < coilsNum; i++) + { coilsValues[i] = v; - v=~v; + v = ~v; } - success &=bus.writeCoils(devAddress, baseRegister, coilsValues); + success &= bus.writeCoils(devAddress, baseRegister, coilsValues); - log_i("Write single register"); - success &=bus.writeRegister(devAddress, baseRegister, 0xAA); - - log_i("Write multiple registers"); + LOG_INFO("Write single register"); + success &= bus.writeRegister(devAddress, baseRegister, 0xAA); + + LOG_INFO("Write multiple registers"); const uint16_t regNum(16); std::vector regValues(regNum, 0); - for (uint16_t i(0); i < regNum; i++) { - regValues[i] = i*2; + for (uint16_t i(0); i < regNum; i++) + { + regValues[i] = i * 2; } - } -void loop() { - +void loop() +{ } \ No newline at end of file