Compare commits
22 Commits
main
...
1955b8cb39
| Author | SHA1 | Date | |
|---|---|---|---|
| 1955b8cb39 | |||
| 208f5f7534 | |||
| 7fd4a284af | |||
| 8f701ce81a | |||
| 4b97e6535d | |||
| f274970d63 | |||
| 3d2d44c0bb | |||
| 01db0e543f | |||
| 4acce987de | |||
| b54c0e5018 | |||
| 17f5a1dfe5 | |||
| 7a7d677bfe | |||
| 9530aab1c1 | |||
| 19197aa022 | |||
| 79e5760d19 | |||
| dcbe637ccc | |||
| b5de72a6d1 | |||
| adb15962c6 | |||
| 83a63c1241 | |||
| 2a33316ba8 | |||
| 12ab46f826 | |||
| 7ea491905f |
+1
-1
@@ -91,7 +91,7 @@ dkms.conf
|
|||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
#!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/*.code-snippets
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
|||||||
Vendored
-44
@@ -1,44 +0,0 @@
|
|||||||
// AUTOMATICALLY GENERATED FILE. PLEASE DO NOT MODIFY IT MANUALLY
|
|
||||||
//
|
|
||||||
// PlatformIO Debugging Solution
|
|
||||||
//
|
|
||||||
// Documentation: https://docs.platformio.org/en/latest/plus/debugging.html
|
|
||||||
// Configuration: https://docs.platformio.org/en/latest/projectconf/sections/env/options/debug/index.html
|
|
||||||
|
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "platformio-debug",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "PIO Debug",
|
|
||||||
"executable": "C:/Users/ematr/Documents/VScode/ETcontroller_PRO/.pio/build/esp32-s3-waveshare8/firmware.elf",
|
|
||||||
"projectEnvName": "esp32-s3-waveshare8",
|
|
||||||
"toolchainBinDir": "C:/Users/ematr/.platformio/packages/toolchain-xtensa-esp-elf/bin",
|
|
||||||
"internalConsoleOptions": "openOnSessionStart",
|
|
||||||
"preLaunchTask": {
|
|
||||||
"type": "PlatformIO",
|
|
||||||
"task": "Pre-Debug"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "platformio-debug",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "PIO Debug (skip Pre-Debug)",
|
|
||||||
"executable": "C:/Users/ematr/Documents/VScode/ETcontroller_PRO/.pio/build/esp32-s3-waveshare8/firmware.elf",
|
|
||||||
"projectEnvName": "esp32-s3-waveshare8",
|
|
||||||
"toolchainBinDir": "C:/Users/ematr/.platformio/packages/toolchain-xtensa-esp-elf/bin",
|
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "platformio-debug",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "PIO Debug (without uploading)",
|
|
||||||
"executable": "C:/Users/ematr/Documents/VScode/ETcontroller_PRO/.pio/build/esp32-s3-waveshare8/firmware.elf",
|
|
||||||
"projectEnvName": "esp32-s3-waveshare8",
|
|
||||||
"toolchainBinDir": "C:/Users/ematr/.platformio/packages/toolchain-xtensa-esp-elf/bin",
|
|
||||||
"internalConsoleOptions": "openOnSessionStart",
|
|
||||||
"loadMode": "manual"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,72 @@
|
|||||||
|
#include "ETH_Driver.h"
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
Ethernet::Ethernet(const std::string hostname) : m_hostname(hostname), m_connected(false), m_localIP(IPAddress()), m_udp(NetworkUDP()), m_timeClient(m_udp)
|
||||||
|
{
|
||||||
|
SPI.begin(ETH_SPI_SCK, ETH_SPI_MISO, ETH_SPI_MOSI);
|
||||||
|
ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI);
|
||||||
|
|
||||||
|
m_timeClient = std::move(NTPClient(m_udp, "pool.ntp.org", 0, 3600)); // NTP server, time offset in seconds, update interval
|
||||||
|
m_timeClient.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ethernet::~Ethernet()
|
||||||
|
{
|
||||||
|
m_timeClient.end();
|
||||||
|
ETH.end();
|
||||||
|
SPI.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool Ethernet::getNtpTime(time_t &time)
|
||||||
|
{
|
||||||
|
if (m_connected && m_timeClient.update())
|
||||||
|
{
|
||||||
|
time = m_timeClient.getEpochTime();
|
||||||
|
LOG_DEBUG("Epoch Time:", (long)time);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool Ethernet::isConnected()
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ethernet::onEvent(arduino_event_id_t event, arduino_event_info_t info)
|
||||||
|
{
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case ARDUINO_EVENT_ETH_START:
|
||||||
|
ETH.setHostname("waveshare-esp32s3");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||||
|
LOG_INFO("ETH Connected");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
|
m_localIP = ETH.localIP();
|
||||||
|
LOG_INFO("ETH ", esp_netif_get_desc(info.got_ip.esp_netif), " Got IP:", m_localIP.toString().c_str());
|
||||||
|
LOG_INFO("ETH ", esp_netif_get_desc(info.got_ip.esp_netif), " Gateway:", ETH.gatewayIP().toString().c_str());
|
||||||
|
LOG_INFO("ETH ", esp_netif_get_desc(info.got_ip.esp_netif), " Netmask:", ETH.subnetMask().toString().c_str());
|
||||||
|
m_connected = true;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_LOST_IP:
|
||||||
|
LOG_INFO("ETH Lost IP");
|
||||||
|
m_connected = false;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
|
LOG_INFO("ETH Disconnected");
|
||||||
|
m_connected = false;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_STOP:
|
||||||
|
LOG_INFO("ETH Stopped");
|
||||||
|
m_connected = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Network.h>
|
||||||
|
#include <NTPClient.h>
|
||||||
|
#include <ETH.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
// PHY defines hardware related
|
||||||
|
#ifndef ETH_PHY_TYPE
|
||||||
|
#define ETH_PHY_TYPE ETH_PHY_W5500
|
||||||
|
#define ETH_PHY_ADDR 1
|
||||||
|
#define ETH_PHY_CS 16
|
||||||
|
#define ETH_PHY_IRQ 12
|
||||||
|
#define ETH_PHY_RST 39
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
#define ETH_SPI_SCK 15
|
||||||
|
#define ETH_SPI_MISO 14
|
||||||
|
#define ETH_SPI_MOSI 13
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
class Ethernet
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Ethernet(const std::string hostname);
|
||||||
|
~Ethernet();
|
||||||
|
|
||||||
|
void onEvent(arduino_event_id_t event, arduino_event_info_t info);
|
||||||
|
const bool isConnected();
|
||||||
|
const bool getNtpTime(time_t &time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string m_hostname;
|
||||||
|
bool m_connected;
|
||||||
|
NetworkUDP m_udp;
|
||||||
|
IPAddress m_localIP;
|
||||||
|
NTPClient m_timeClient;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ static bool eth_connected_Old = false;
|
|||||||
IPAddress ETH_ip;
|
IPAddress ETH_ip;
|
||||||
// NTP setup
|
// NTP setup
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
NTPClient timeClient(udp, "pool.ntp.org", timezone*3600, 60000); // NTP server, time offset in seconds, update interval
|
NTPClient timeClient(udp, "pool.ntp.org", TZ*3600, 60000); // NTP server, time offset in seconds, update interval
|
||||||
|
|
||||||
void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
|
void onEvent(arduino_event_id_t event, arduino_event_info_t info) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
@@ -84,7 +84,7 @@ void EthernetTask(void *parameter) {
|
|||||||
while(1){
|
while(1){
|
||||||
if (eth_connected && !eth_connected_Old) {
|
if (eth_connected && !eth_connected_Old) {
|
||||||
eth_connected_Old = eth_connected;
|
eth_connected_Old = eth_connected;
|
||||||
RGB_Open_Time(0, 60, 0,1000, 0);
|
//RGB_Open_Time(0, 60, 0,1000, 0);
|
||||||
printf("Network port connected!\r\n");
|
printf("Network port connected!\r\n");
|
||||||
Acquisition_time();
|
Acquisition_time();
|
||||||
}
|
}
|
||||||
@@ -108,13 +108,13 @@ void Acquisition_time(void) { // Get the netwo
|
|||||||
printf("ETH - Online clock error!!!\r\n");
|
printf("ETH - Online clock error!!!\r\n");
|
||||||
}
|
}
|
||||||
struct tm *localTime = localtime(¤tTime);
|
struct tm *localTime = localtime(¤tTime);
|
||||||
static datetime_t PCF85063_Time = {0};
|
//static datetime_t PCF85063_Time = {0};
|
||||||
PCF85063_Time.year = localTime->tm_year + 1900;
|
//PCF85063_Time.year = localTime->tm_year + 1900;
|
||||||
PCF85063_Time.month = localTime->tm_mon + 1;
|
//PCF85063_Time.month = localTime->tm_mon + 1;
|
||||||
PCF85063_Time.day = localTime->tm_mday;
|
//PCF85063_Time.day = localTime->tm_mday;
|
||||||
PCF85063_Time.dotw = localTime->tm_wday;
|
//PCF85063_Time.dotw = localTime->tm_wday;
|
||||||
PCF85063_Time.hour = localTime->tm_hour;
|
//PCF85063_Time.hour = localTime->tm_hour;
|
||||||
PCF85063_Time.minute = localTime->tm_min;
|
//PCF85063_Time.minute = localTime->tm_min;
|
||||||
PCF85063_Time.second = localTime->tm_sec;
|
//PCF85063_Time.second = localTime->tm_sec;
|
||||||
PCF85063_Set_All(PCF85063_Time);
|
//PCF85063_Set_All(PCF85063_Time);
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,6 @@
|
|||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
#include "WS_PCF85063.h"
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_RTC.h"
|
|
||||||
|
|
||||||
// Set this to 1 to enable dual Ethernet support
|
// Set this to 1 to enable dual Ethernet support
|
||||||
#define USE_TWO_ETH_PORTS 0
|
#define USE_TWO_ETH_PORTS 0
|
||||||
|
|
||||||
@@ -35,7 +31,7 @@
|
|||||||
ETHClass ETH1(1);
|
ETHClass ETH1(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define timezone 8 // china
|
#define TZ 1 // rome
|
||||||
|
|
||||||
void ETH_Init(void);
|
void ETH_Init(void);
|
||||||
void ETH_Loop(void);
|
void ETH_Loop(void);
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#include "TCA9554PWR_Driver.h"
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
TCA9554PWR::TCA9554PWR(I2C &i2c, const uint8_t address) : m_i2c(i2c), m_address(address)
|
||||||
|
{
|
||||||
|
writeRegister(TCA9554_OUTPUT_REG, Low); // set all pins to Low state
|
||||||
|
writeRegister(TCA9554_CONFIG_REG, TCA9554_OUT_MODE); // set all pins as output (relay mode for this board)
|
||||||
|
}
|
||||||
|
|
||||||
|
TCA9554PWR::~TCA9554PWR() {
|
||||||
|
writeRegister(TCA9554_OUTPUT_REG, Low); // set all pins to Low state
|
||||||
|
writeRegister(TCA9554_CONFIG_REG, TCA9554_OUT_MODE); // set all pins as output (relay mode for this board)
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool TCA9554PWR::writeRegister(const uint8_t reg, const uint8_t val)
|
||||||
|
{
|
||||||
|
if (m_i2c.write(m_address, reg, {val}))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("Unable to write register: reg[%d], val[%d] ", reg, val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool TCA9554PWR::readRegister(const uint8_t reg, uint8_t &val)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
if (m_i2c.read(m_address, reg, 1, data))
|
||||||
|
{
|
||||||
|
val = data.back();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_ERROR("Unable to read register: reg[%d]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool TCA9554PWR::setOut(const uint8_t ch, const bool state)
|
||||||
|
{
|
||||||
|
uint8_t currState(0);
|
||||||
|
uint8_t newState(0);
|
||||||
|
|
||||||
|
if (ch < OUT_PIN1 || ch > OUT_PIN8)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Invalid write to output channel: [%d]", ch);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!readPort(currState))
|
||||||
|
return false;
|
||||||
|
if (state)
|
||||||
|
newState = (High << ch) | currState;
|
||||||
|
else
|
||||||
|
newState = (~(High << ch)) & currState;
|
||||||
|
return setPort(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool TCA9554PWR::setPort(const uint8_t state)
|
||||||
|
{
|
||||||
|
if (writeRegister(TCA9554_OUTPUT_REG, state))
|
||||||
|
return true;
|
||||||
|
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 < OUT_PIN1 || ch > OUT_PIN8)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Invalid read to output channel: [%d]", ch);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!readPort(currState))
|
||||||
|
return false;
|
||||||
|
return (currState && (High >> ch));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool TCA9554PWR::readPort(uint8_t &state)
|
||||||
|
{
|
||||||
|
if (readRegister(TCA9554_INPUT_REG, state))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("Unable to read IO port: state[%02x]", state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "I2C_Driver.h"
|
||||||
|
|
||||||
|
/****************************************************** The macro defines the TCA9554PWR information ******************************************************/
|
||||||
|
|
||||||
|
#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address
|
||||||
|
#define TCA9554_INPUT_REG 0x00 // Input register, input level
|
||||||
|
#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output
|
||||||
|
#define TCA9554_POLARITY_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register.
|
||||||
|
#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration
|
||||||
|
|
||||||
|
#define TCA9554_OUT_MODE 0x00 // Configuration register value, output mode
|
||||||
|
#define TCA9554_IN_MODE 0xff // Configuration register value, input mode
|
||||||
|
|
||||||
|
#define Low 0x00
|
||||||
|
#define High 0x01
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
class TCA9554PWR
|
||||||
|
{
|
||||||
|
|
||||||
|
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);
|
||||||
|
~TCA9554PWR();
|
||||||
|
|
||||||
|
const bool setOut(const uint8_t channel, const bool state);
|
||||||
|
const bool setPort(const uint8_t state);
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#include "I2C_Driver.h"
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
I2C::I2C()
|
||||||
|
{
|
||||||
|
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
I2C::~I2C()
|
||||||
|
{
|
||||||
|
Wire.end();
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool I2C::read(const uint8_t deviceAddr, const uint8_t deviceReg, const uint8_t len, std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
//busy.try_lock();
|
||||||
|
Wire.beginTransmission(deviceAddr);
|
||||||
|
Wire.write(deviceReg);
|
||||||
|
switch (Wire.endTransmission(true))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break; // no error, break switch
|
||||||
|
case 1:
|
||||||
|
LOG_ERROR("Data to long to fit in buffer: [%d]", len);
|
||||||
|
case 2:
|
||||||
|
LOG_ERROR("Received NAK on address transmit");
|
||||||
|
case 3:
|
||||||
|
LOG_ERROR("Received NAK on data transmit");
|
||||||
|
case 4:
|
||||||
|
LOG_ERROR("Unknown Error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uint8_t nBytes = Wire.requestFrom(deviceAddr, len);
|
||||||
|
if (nBytes < len)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
for (auto i = 0; i < nBytes; i++)
|
||||||
|
{
|
||||||
|
data[i] = static_cast<uint8_t>(Wire.read());
|
||||||
|
}
|
||||||
|
//busy.unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool I2C::write(const uint8_t deviceAddr, const uint8_t deviceReg, const std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
//busy.lock();
|
||||||
|
Wire.beginTransmission(deviceAddr);
|
||||||
|
Wire.write(deviceReg);
|
||||||
|
for (auto d : data)
|
||||||
|
{
|
||||||
|
Wire.write(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Wire.endTransmission(true))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break; // no error, break switch
|
||||||
|
case 1:
|
||||||
|
LOG_ERROR("Data to long to fit in buffer: [%d]", data.size());
|
||||||
|
case 2:
|
||||||
|
LOG_ERROR("Received NAK on address transmit");
|
||||||
|
case 3:
|
||||||
|
LOG_ERROR("Received NAK on data transmit");
|
||||||
|
case 4:
|
||||||
|
LOG_ERROR("Unknown Error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//busy.unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace drivers
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#define I2C_SCL_PIN 41
|
||||||
|
#define I2C_SDA_PIN 42
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
class I2C
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool isInitialized = false;
|
||||||
|
//std::mutex busy;
|
||||||
|
|
||||||
|
public:
|
||||||
|
I2C(void);
|
||||||
|
~I2C(void);
|
||||||
|
|
||||||
|
const bool read(const uint8_t deviceAddr, const uint8_t deviceReg, const uint8_t len, std::vector<uint8_t> &data);
|
||||||
|
const bool write(const uint8_t deviceAddr, const uint8_t deviceReg, const std::vector<uint8_t> &data);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,413 @@
|
|||||||
|
#include "RS485_driver.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
//#define DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//////////// RS485 ////////////
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
RS485::RS485(const uint32_t baud, const SerialConfig conf) : m_serial(Serial1)
|
||||||
|
{
|
||||||
|
LOG_INFO("Init serial port 1");
|
||||||
|
// RS485 is hardwired to serial port 1
|
||||||
|
m_serial.begin(baud, conf, 18, 17);
|
||||||
|
m_serial.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool RS485::write(const std::vector<uint8_t> data)
|
||||||
|
{
|
||||||
|
return data.size() == m_serial.write(data.data(), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool RS485::readAll(std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
const uint32_t avail(m_serial.available());
|
||||||
|
if (avail == 0)
|
||||||
|
return true;
|
||||||
|
data.resize(avail);
|
||||||
|
return data.size() == m_serial.readBytes(data.data(), avail);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool RS485::readN(const uint16_t nBytes, std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
buf.resize(nBytes);
|
||||||
|
if (m_serial.readBytes(buf.data(), nBytes) == nBytes)
|
||||||
|
{
|
||||||
|
data = std::move(buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool RS485::readUntil(const uint8_t ch, std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
const uint32_t avail(m_serial.available());
|
||||||
|
data.resize(avail);
|
||||||
|
m_serial.readBytesUntil(ch, data.data(), avail);
|
||||||
|
data.shrink_to_fit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//////////// MODBUS ////////////
|
||||||
|
////////////////////////////////
|
||||||
|
MODBUS::MODBUS(const uint32_t baud, const SerialConfig conf) : RS485::RS485(baud, conf)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> garbage;
|
||||||
|
readAll(garbage);
|
||||||
|
LOG_INFO("Init MODBUS Master Mode");
|
||||||
|
m_crc.reset(CRC16_MODBUS_POLYNOME, CRC16_MODBUS_INITIAL, CRC16_MODBUS_XOR_OUT, CRC16_MODBUS_REV_IN, CRC16_MAXIM_REV_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x01
|
||||||
|
const bool MODBUS::readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector<bool> &coils)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x01;
|
||||||
|
LOG_DEBUG("Read coils: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||||
|
return readBinary(device, func, reg, num, coils);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x02
|
||||||
|
const bool MODBUS::readInputs(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<bool> &inputs)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x02;
|
||||||
|
LOG_DEBUG("Read multi inputs: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||||
|
return readBinary(device, func, reg, num, inputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x03
|
||||||
|
const bool MODBUS::readHoldingRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x03;
|
||||||
|
LOG_DEBUG("Read multi holding registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||||
|
return readInteger(device, func, reg, num, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x04
|
||||||
|
const bool MODBUS::readInputRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x04;
|
||||||
|
LOG_DEBUG("Read multi input registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||||
|
return readInteger(device, func, reg, num, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x05
|
||||||
|
const bool MODBUS::writeCoil(const uint8_t device, const uint16_t coil, const bool value)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x05;
|
||||||
|
LOG_DEBUG("Write single coil: dev[", device, "], coil[", coil, "], value[", value ? "true" : "false", "]");
|
||||||
|
return writeBinary(device, func, coil, {value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x06
|
||||||
|
const bool MODBUS::writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x06;
|
||||||
|
LOG_DEBUG("Write single register: dev[", device, "], reg[", reg, "], value[", value, "]");
|
||||||
|
return writeInteger(device, func, reg, {value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x0F
|
||||||
|
const bool MODBUS::writeCoils(const uint8_t device, const uint16_t coils, const std::vector<bool> &values)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x0F;
|
||||||
|
LOG_DEBUG("Write multi coils: dev[", device, "], start[", coils, "], num[", values.size(), "]");
|
||||||
|
return writeBinary(device, func, coils, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Func 0x10
|
||||||
|
const bool MODBUS::writeRegisters(const uint8_t device, const uint16_t reg, const std::vector<uint16_t> &values)
|
||||||
|
{
|
||||||
|
constexpr uint8_t func = 0x10;
|
||||||
|
LOG_DEBUG("Write multi registers: dev[", device, "], start[", reg, "], num[", values.size(), "]");
|
||||||
|
return writeInteger(device, func, reg, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////// Utility Functions ///////////////////////
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const bool MODBUS::readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector<bool> &out)
|
||||||
|
{
|
||||||
|
if (!write(singleRequest(device, func, reg, bits)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send readBinary command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uint16_t nRespDataBytes = (uint16_t)ceil(bits / 8.0f); // 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<uint8_t> response;
|
||||||
|
if (!readN(expectedRespLen, response))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive readBinary response, expected[", expectedRespLen, "], received[", response.size(), "]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// element 2 of response has the response data bytes expected
|
||||||
|
const uint8_t actualRespLen(response.at(2));
|
||||||
|
if (actualRespLen != nRespDataBytes)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive, data to short: actual[", actualRespLen, "], expected[", nRespDataBytes, "]");
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("readBinary Response", response);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute crc of current message
|
||||||
|
if (!verifyCrc(response))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// extract coils data from data portion of response
|
||||||
|
out.clear();
|
||||||
|
out.reserve(bits);
|
||||||
|
uint16_t bitNum(0);
|
||||||
|
|
||||||
|
// get response data bytes excluding header and crc
|
||||||
|
const std::vector<uint8_t> respData(response.begin() + RESP_HEADER_SIZE, response.end() - sizeof(crc_t));
|
||||||
|
for (auto it = respData.begin(); it < respData.end(); it++)
|
||||||
|
{
|
||||||
|
for (uint8_t j(0); j < 8 && bitNum < bits; j++)
|
||||||
|
{
|
||||||
|
const bool cv((0x01 << j) & *it);
|
||||||
|
out.push_back(cv);
|
||||||
|
bitNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MODBUS::readInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t num, std::vector<uint16_t> &out)
|
||||||
|
{
|
||||||
|
if (!write(singleRequest(device, func, reg, num)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send readInteger command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uint16_t nRespDataBytes = num * sizeof(uint16_t);
|
||||||
|
const uint16_t expectedRespLen = (RESP_HEADER_SIZE + sizeof(crc_t)) + nRespDataBytes; // device + function + nbytes + data[] + crc(16b)
|
||||||
|
std::vector<uint8_t> response;
|
||||||
|
if (!readN(expectedRespLen, response))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive readInteger response, expected[", expectedRespLen, "], received[", response.size(), "]");
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("readInteger Response", response);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// element 2 of response has the response data bytes expected
|
||||||
|
const uint8_t actualRespLen(response.at(2));
|
||||||
|
if (actualRespLen != nRespDataBytes)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive, data to short: actual[", actualRespLen, "], expected[", nRespDataBytes, "]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute crc of current message
|
||||||
|
if (!verifyCrc(response))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// extract coils data from data portion of response
|
||||||
|
out.clear();
|
||||||
|
out.reserve(nRespDataBytes / sizeof(uint16_t));
|
||||||
|
// get response data bytes excluding header and crc
|
||||||
|
const std::vector<uint8_t> respData(response.begin() + RESP_HEADER_SIZE, response.end() - RESP_CRC_SIZE);
|
||||||
|
for (auto it = respData.begin(); it < respData.end(); it++)
|
||||||
|
{
|
||||||
|
const uint8_t lo(*it++);
|
||||||
|
const uint8_t hi(*it);
|
||||||
|
const uint16_t val(0xFFFF & ((hi << 8) | lo));
|
||||||
|
out.push_back(be16toh(val));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MODBUS::writeBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<bool> &in)
|
||||||
|
{
|
||||||
|
const uint16_t bits(in.size());
|
||||||
|
std::vector<uint8_t> bitsOut;
|
||||||
|
if (bits == 1) // if single coil value must be 0x00FF[00] for on[off]
|
||||||
|
{
|
||||||
|
if (!write(singleRequest(device, func, reg, in.front() ? 0xFF00 : 0x0000)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send writeSingleBinary command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // if multiple coils value is 0x01 shifted for the number of coil intended
|
||||||
|
{
|
||||||
|
const uint16_t numBytes((uint16_t)ceil(bits / 8.0f));
|
||||||
|
bitsOut.resize(numBytes, 0x00);
|
||||||
|
for (uint16_t i(0); i < in.size(); i++)
|
||||||
|
{
|
||||||
|
if (!in[i]) // if value is false skip
|
||||||
|
continue;
|
||||||
|
bitsOut[i / 8] |= 0x01 << i % 8;
|
||||||
|
}
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
LOG_DEBUG("\nnumBytes", numBytes);
|
||||||
|
printBool("bitsOut", in);
|
||||||
|
printBytes("bitsOut", bitsOut);
|
||||||
|
#endif
|
||||||
|
if (!write(multiRequest(device, func, reg, bits, bitsOut)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send writeMultiBinary command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t expectedRespLen(sizeof(resp_t) + sizeof(crc_t));
|
||||||
|
std::vector<uint8_t> response;
|
||||||
|
if (!readN(expectedRespLen, response))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive writeBinary response, expected[", expectedRespLen, "], received[", response.size(), "]");
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("writeBinary Response", response);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute crc of current message
|
||||||
|
if (!verifyCrc(response))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MODBUS::writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<uint16_t> &in)
|
||||||
|
{
|
||||||
|
const uint16_t num(in.size());
|
||||||
|
if (num == 1)
|
||||||
|
{
|
||||||
|
if (!write(singleRequest(device, func, reg, in[0])))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send writeSingleInteger command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// build data vector for request, inverting bytes if necessary
|
||||||
|
std::vector<uint8_t> requestData;
|
||||||
|
requestData.resize(in.size() * sizeof(uint16_t));
|
||||||
|
auto it=requestData.begin();
|
||||||
|
std::for_each(in.begin(), in.end(), [requestData, &it](auto inV) {
|
||||||
|
const uint16_t beV(htobe16(inV));
|
||||||
|
*it=highByte(beV);
|
||||||
|
*(++it)=lowByte(beV);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!write(multiRequest(device, func, reg, num, requestData)))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed send writeMultiInteger command");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t expectedRespLen(sizeof(resp_t) + sizeof(crc_t));
|
||||||
|
std::vector<uint8_t> response;
|
||||||
|
if (!readN(expectedRespLen, response))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed receive writeInteger response, expected[", expectedRespLen, "], received[", response.size(), "]");
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("writeInteger Response", response);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute crc of current message
|
||||||
|
if (!verifyCrc(response))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t> MODBUS::singleRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t data)
|
||||||
|
{
|
||||||
|
req_t header;
|
||||||
|
header.device = device;
|
||||||
|
header.func = func;
|
||||||
|
header.reg = htobe16(reg);
|
||||||
|
header.data = htobe16(data);
|
||||||
|
|
||||||
|
const uint8_t headerBytes(sizeof(req_t));
|
||||||
|
const uint8_t crcBytes(sizeof(crc_t));
|
||||||
|
|
||||||
|
// compute crc for header + data
|
||||||
|
m_crc.restart();
|
||||||
|
m_crc.add((uint8_t *)&header, headerBytes); // exclude last two bytes of crc
|
||||||
|
const uint16_t crc(htole16(m_crc.calc()));
|
||||||
|
|
||||||
|
std::vector<uint8_t> dataOut(headerBytes + crcBytes, 0);
|
||||||
|
std::memcpy(dataOut.data(), &header, headerBytes);
|
||||||
|
std::memcpy(dataOut.data() + headerBytes, &crc, crcBytes);
|
||||||
|
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("singleRequest", dataOut);
|
||||||
|
#endif
|
||||||
|
return dataOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t> MODBUS::multiRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t qty, const std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
req_multi_t header;
|
||||||
|
header.device = device;
|
||||||
|
header.func = func;
|
||||||
|
header.reg = htobe16(reg);
|
||||||
|
header.qty = htobe16(qty);
|
||||||
|
header.bytes = data.size(); // 8 bit value
|
||||||
|
|
||||||
|
//const uint8_t headerBytes(sizeof(req_multi_t)); // sizeof not working because of memory padding
|
||||||
|
const uint8_t headerBytes(7);
|
||||||
|
const uint8_t dataBytes(data.size());
|
||||||
|
const uint8_t crcBytes(sizeof(crc_t));
|
||||||
|
|
||||||
|
// compute crc for header + data
|
||||||
|
m_crc.restart();
|
||||||
|
m_crc.add((uint8_t *)&header, headerBytes); // add the request excluding the CRC code
|
||||||
|
m_crc.add((uint8_t *)data.data(), dataBytes);
|
||||||
|
const uint16_t crc(htole16(m_crc.calc()));
|
||||||
|
|
||||||
|
std::vector<uint8_t> dataOut;
|
||||||
|
dataOut.resize(headerBytes + dataBytes + crcBytes); // header message + data values + crc code
|
||||||
|
std::memcpy(dataOut.data(), &header, headerBytes); // copy message
|
||||||
|
std::memcpy(dataOut.data() + headerBytes, data.data(), dataBytes); // copy data
|
||||||
|
std::memcpy(dataOut.data() + headerBytes + dataBytes, &crc, crcBytes); // copy crc
|
||||||
|
|
||||||
|
#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE
|
||||||
|
printBytes("multiRequest", dataOut);
|
||||||
|
#endif
|
||||||
|
return dataOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MODBUS::verifyCrc(const std::vector<uint8_t> &data)
|
||||||
|
{
|
||||||
|
// compute crc of current message
|
||||||
|
m_crc.restart();
|
||||||
|
m_crc.add(data.data(), data.size() - sizeof(crc_t));
|
||||||
|
const uint16_t computedCrc(m_crc.calc());
|
||||||
|
// extract crc from response
|
||||||
|
const uint16_t size(data.size());
|
||||||
|
const uint8_t crcLo(data.at(size - 2));
|
||||||
|
const uint8_t crcHi(data.at(size - 1));
|
||||||
|
const uint16_t receivedCrc(0xFFFF & ((crcHi << 8) | crcLo));
|
||||||
|
|
||||||
|
// verify crc code
|
||||||
|
if (highByte(computedCrc) != crcHi || lowByte(computedCrc) != crcLo)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed verify CRC code: comp[", computedCrc, "], rec[", receivedCrc, "]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
||||||
|
#include <CRC16.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#define Extension_CH1 1 // Expansion Channel 1
|
||||||
|
#define Extension_CH2 2 // Expansion Channel 2
|
||||||
|
#define Extension_CH3 3 // Expansion Channel 3
|
||||||
|
#define Extension_CH4 4 // Expansion Channel 4
|
||||||
|
#define Extension_CH5 5 // Expansion Channel 5
|
||||||
|
#define Extension_CH6 6 // Expansion Channel 6
|
||||||
|
#define Extension_CH7 7 // Expansion Channel 7
|
||||||
|
#define Extension_CH8 8 // Expansion Channel 8
|
||||||
|
#define Extension_ALL_ON 9 // Expansion ALL ON
|
||||||
|
#define Extension_ALL_OFF 10 // Expansion ALL OFF
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
class RS485
|
||||||
|
{
|
||||||
|
static const uint8_t PORT = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RS485(const uint32_t baud, const SerialConfig conf);
|
||||||
|
const bool write(const std::vector<uint8_t> data);
|
||||||
|
const bool readAll(std::vector<uint8_t> &data);
|
||||||
|
const bool readN(const uint16_t nBytes, std::vector<uint8_t> &data);
|
||||||
|
const bool readUntil(const uint8_t ch, std::vector<uint8_t> &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HardwareSerial &m_serial;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MODBUS : public RS485
|
||||||
|
{
|
||||||
|
|
||||||
|
static const uint8_t RESP_HEADER_SIZE = 3;
|
||||||
|
static const uint8_t RESP_CRC_SIZE = 2;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t device;
|
||||||
|
uint8_t func;
|
||||||
|
uint16_t reg;
|
||||||
|
uint16_t data;
|
||||||
|
} req_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t device;
|
||||||
|
uint8_t func;
|
||||||
|
uint16_t reg;
|
||||||
|
uint16_t qty;
|
||||||
|
uint8_t bytes;
|
||||||
|
} req_multi_t;
|
||||||
|
|
||||||
|
typedef req_t resp_t;
|
||||||
|
typedef uint16_t crc_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MODBUS(const uint32_t baud, const SerialConfig conf);
|
||||||
|
|
||||||
|
// Func 0x01
|
||||||
|
const bool readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector<bool> &coils);
|
||||||
|
|
||||||
|
// Func 0x02
|
||||||
|
const bool readInputs(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<bool> &inputs);
|
||||||
|
|
||||||
|
// Func 0x03
|
||||||
|
const bool readHoldingRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values);
|
||||||
|
|
||||||
|
// Func 0x04
|
||||||
|
const bool readInputRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values);
|
||||||
|
|
||||||
|
// Func 0x05
|
||||||
|
const bool writeCoil(const uint8_t device, const uint16_t coil, const bool value);
|
||||||
|
|
||||||
|
// Func 0x06
|
||||||
|
const bool writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value);
|
||||||
|
|
||||||
|
// Func 0x0F
|
||||||
|
const bool writeCoils(const uint8_t device, const uint16_t coils, const std::vector<bool> &values);
|
||||||
|
|
||||||
|
// Func 0x10
|
||||||
|
const bool writeRegisters(const uint8_t device, const uint16_t reg, const std::vector<uint16_t> &values);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CRC16 m_crc;
|
||||||
|
const std::vector<uint8_t> singleRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t data);
|
||||||
|
const std::vector<uint8_t> multiRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t qty, const std::vector<uint8_t> &data);
|
||||||
|
const bool readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector<bool> &out);
|
||||||
|
const bool readInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t num, std::vector<uint16_t> &out);
|
||||||
|
const bool writeBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<bool> &in);
|
||||||
|
const bool writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<uint16_t> &in);
|
||||||
|
const bool verifyCrc(const std::vector<uint8_t> &data);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
#include "PCF85063_Driver.h"
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
PCF85063::PCF85063(I2C &i2c, const uint8_t address, const uint8_t ctrl1, const uint8_t ctrl2) : m_i2c(i2c), m_address(address)
|
||||||
|
{
|
||||||
|
bool success(true);
|
||||||
|
if (ctrl1 == RTC_CTRL_1_DEFAULT)
|
||||||
|
{
|
||||||
|
const uint8_t def_conf1 = RTC_CTRL_1_DEFAULT | RTC_CTRL_1_CAP_SEL; // 12.5pF cap and 24h format
|
||||||
|
success &= m_i2c.write(m_address, RTC_CTRL_1_ADDR, {def_conf1});
|
||||||
|
}
|
||||||
|
if (ctrl2 == RTC_CTRL_2_DEFAULT)
|
||||||
|
{
|
||||||
|
const uint8_t def_conf2 = RTC_CTRL_2_DEFAULT | RTC_CTRL_2_MI; // enable 1 minute interrupt
|
||||||
|
success &= m_i2c.write(m_address, RTC_CTRL_2_ADDR, {def_conf2});
|
||||||
|
}
|
||||||
|
if (!success)
|
||||||
|
LOG_ERROR("RTC Init Failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::reset(void)
|
||||||
|
{
|
||||||
|
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_ERROR("RTC Reset Failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::setTime(const datetime_t time)
|
||||||
|
{
|
||||||
|
const std::vector<uint8_t> buf = {
|
||||||
|
decToBcd(time.second),
|
||||||
|
decToBcd(time.minute),
|
||||||
|
decToBcd(time.hour)};
|
||||||
|
if (m_i2c.write(m_address, RTC_SECOND_ADDR, buf))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("RTC setTime failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::setDate(const datetime_t date)
|
||||||
|
{
|
||||||
|
const std::vector<uint8_t> buf = {
|
||||||
|
decToBcd(date.day),
|
||||||
|
decToBcd(date.dotw),
|
||||||
|
decToBcd(date.month),
|
||||||
|
decToBcd(date.year - YEAR_OFFSET)};
|
||||||
|
if (m_i2c.write(m_address, RTC_DAY_ADDR, buf))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("RTC setDate failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::setDatetime(const datetime_t datetime)
|
||||||
|
{
|
||||||
|
return setDate(datetime) && setTime(datetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::readDate(datetime_t &datetime)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
if (m_i2c.read(m_address, RTC_DAY_ADDR, 4, buf))
|
||||||
|
{
|
||||||
|
datetime.day = bcdToDec(buf[0] & 0x3F);
|
||||||
|
datetime.dotw = bcdToDec(buf[1] & 0x07);
|
||||||
|
datetime.month = bcdToDec(buf[2] & 0x1F);
|
||||||
|
datetime.year = bcdToDec(buf[3]) + YEAR_OFFSET;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_ERROR("RTC readDate Failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::readTime(datetime_t &datetime)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
if (m_i2c.read(m_address, RTC_SECOND_ADDR, 3, buf))
|
||||||
|
{
|
||||||
|
datetime.second = bcdToDec(buf[0] & 0x7F);
|
||||||
|
datetime.minute = bcdToDec(buf[1] & 0x7F);
|
||||||
|
datetime.hour = bcdToDec(buf[2] & 0x3F);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_ERROR("RTC readTime Failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::readDatetime(datetime_t &datetime)
|
||||||
|
{
|
||||||
|
return readTime(datetime) && readDate(datetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::enableAlarm(const bool enable)
|
||||||
|
{
|
||||||
|
bool success(true);
|
||||||
|
std::vector<uint8_t> currStatus(1, RTC_CTRL_2_DEFAULT);
|
||||||
|
|
||||||
|
success &= m_i2c.read(m_address, RTC_CTRL_2_ADDR, 1, currStatus);
|
||||||
|
currStatus.at(0) &= ~RTC_CTRL_2_AF; // clear alarm flag
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
currStatus.at(0) |= RTC_CTRL_2_AIE; // enable alarm
|
||||||
|
else
|
||||||
|
currStatus.at(0) &= ~RTC_CTRL_2_AIE; // disable alarm
|
||||||
|
|
||||||
|
if (m_i2c.write(m_address, RTC_CTRL_2_ADDR, currStatus))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("RTC enableAlarm failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::setAlarm(datetime_t time)
|
||||||
|
{
|
||||||
|
const std::vector<uint8_t> buf = {
|
||||||
|
(uint8_t)(decToBcd(time.second) & (~RTC_ALARM)),
|
||||||
|
(uint8_t)(decToBcd(time.minute) & (~RTC_ALARM)),
|
||||||
|
(uint8_t)(decToBcd(time.hour) & (~RTC_ALARM)),
|
||||||
|
(uint8_t)(RTC_ALARM), // disalbe day
|
||||||
|
(uint8_t)(RTC_ALARM) // disalbe weekday
|
||||||
|
};
|
||||||
|
if (m_i2c.write(m_address, RTC_SECOND_ALARM, buf))
|
||||||
|
return true;
|
||||||
|
LOG_ERROR("RTC setAlarm failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::readAlarm(datetime_t &time)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
if (m_i2c.read(m_address, RTC_SECOND_ALARM, 5, buf))
|
||||||
|
{
|
||||||
|
time.second = (uint8_t)bcdToDec(buf[0] & 0x7F);
|
||||||
|
time.minute = (uint8_t)bcdToDec(buf[1] & 0x7F);
|
||||||
|
time.hour = (uint8_t)bcdToDec(buf[2] & 0x3F);
|
||||||
|
time.day = (uint8_t)bcdToDec(buf[3] & 0x3F);
|
||||||
|
time.dotw = (uint8_t)bcdToDec(buf[4] & 0x07);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_ERROR("RTC readAlarm failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool PCF85063::getAlarmFlag(uint8_t &flags)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
if (m_i2c.read(m_address, RTC_CTRL_2_ADDR, 1, buf))
|
||||||
|
{
|
||||||
|
flags = buf.at(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_ERROR("RTC readAlarmFlags failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string PCF85063::getTimeStr()
|
||||||
|
{
|
||||||
|
datetime_t dt;
|
||||||
|
readDatetime(dt);
|
||||||
|
return datetime2str(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
PCF85063::datetime_t PCF85063::fromEpoch(time_t currentTime)
|
||||||
|
{
|
||||||
|
PCF85063::datetime_t tm;
|
||||||
|
struct tm *localTime = std::localtime(¤tTime);
|
||||||
|
tm.year = localTime->tm_year + 1900;
|
||||||
|
tm.month = localTime->tm_mon + 1;
|
||||||
|
tm.day = localTime->tm_mday;
|
||||||
|
tm.dotw = localTime->tm_wday;
|
||||||
|
tm.hour = localTime->tm_hour;
|
||||||
|
tm.minute = localTime->tm_min;
|
||||||
|
tm.second = localTime->tm_sec;
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string PCF85063::datetime2str(datetime_t &datetime)
|
||||||
|
{
|
||||||
|
tm dtime;
|
||||||
|
dtime.tm_sec = datetime.second;
|
||||||
|
dtime.tm_min = datetime.minute;
|
||||||
|
dtime.tm_hour = datetime.hour;
|
||||||
|
dtime.tm_wday = datetime.dotw;
|
||||||
|
dtime.tm_mday = datetime.day;
|
||||||
|
dtime.tm_mon = datetime.month - 1;
|
||||||
|
dtime.tm_year = datetime.year - 1900; // time offset in structure according cpp reference
|
||||||
|
return std::string(std::asctime(&dtime));
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t PCF85063::decToBcd(const int val)
|
||||||
|
{
|
||||||
|
return (uint8_t)((val / 10 * 16) + (val % 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int PCF85063::bcdToDec(uint8_t val)
|
||||||
|
{
|
||||||
|
return (const int)((val / 16 * 10) + (val % 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "I2C_Driver.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// PCF85063_ADDRESS
|
||||||
|
#define PCF85063_ADDRESS (0x51)
|
||||||
|
|
||||||
|
#define YEAR_OFFSET (1970)
|
||||||
|
// registar overview - crtl & status reg
|
||||||
|
#define RTC_CTRL_1_ADDR (0x00)
|
||||||
|
#define RTC_CTRL_2_ADDR (0x01)
|
||||||
|
#define RTC_OFFSET_ADDR (0x02)
|
||||||
|
#define RTC_RAM_by_ADDR (0x03)
|
||||||
|
// registar overview - time & data reg
|
||||||
|
#define RTC_SECOND_ADDR (0x04)
|
||||||
|
#define RTC_MINUTE_ADDR (0x05)
|
||||||
|
#define RTC_HOUR_ADDR (0x06)
|
||||||
|
#define RTC_DAY_ADDR (0x07)
|
||||||
|
#define RTC_WDAY_ADDR (0x08)
|
||||||
|
#define RTC_MONTH_ADDR (0x09)
|
||||||
|
#define RTC_YEAR_ADDR (0x0A) // years 0-99; calculate real year = 1970 + RCC reg year
|
||||||
|
// registar overview - alarm reg
|
||||||
|
#define RTC_SECOND_ALARM (0x0B)
|
||||||
|
#define RTC_MINUTE_ALARM (0x0C)
|
||||||
|
#define RTC_HOUR_ALARM (0x0D)
|
||||||
|
#define RTC_DAY_ALARM (0x0E)
|
||||||
|
#define RTC_WDAY_ALARM (0x0F)
|
||||||
|
// registar overview - timer reg
|
||||||
|
#define RTC_TIMER_VAL (0x10)
|
||||||
|
#define RTC_TIMER_MODE (0x11)
|
||||||
|
|
||||||
|
// RTC_CTRL_1 registar
|
||||||
|
#define RTC_CTRL_1_EXT_TEST (0x80)
|
||||||
|
#define RTC_CTRL_1_STOP (0x20) // 0-RTC clock runs 1- RTC clock is stopped
|
||||||
|
#define RTC_CTRL_1_SR (0X10) // 0-no software reset 1-initiate software rese
|
||||||
|
#define RTC_CTRL_1_CIE (0X04) // 0-no correction interrupt generated 1-interrupt pulses are generated at every correction cycle
|
||||||
|
#define RTC_CTRL_1_12_24 (0X02) // 0-24H 1-12H
|
||||||
|
#define RTC_CTRL_1_CAP_SEL (0X01) // 0-7PF 1-12.5PF
|
||||||
|
|
||||||
|
// RTC_CTRL_2 registar
|
||||||
|
#define RTC_CTRL_2_AIE (0X80) // alarm interrupt 0-disalbe 1-enable
|
||||||
|
#define RTC_CTRL_2_AF (0X40) // alarm flag 0-inactive/cleared 1-active/unchanged
|
||||||
|
#define RTC_CTRL_2_MI (0X20) // minute interrupt 0-disalbe 1-enable
|
||||||
|
#define RTC_CTRL_2_HMI (0X10) // half minute interrupt
|
||||||
|
#define RTC_CTRL_2_TF (0X08)
|
||||||
|
|
||||||
|
//
|
||||||
|
#define RTC_OFFSET_MODE (0X80)
|
||||||
|
|
||||||
|
//
|
||||||
|
#define RTC_TIMER_MODE_TE (0X04) // timer enable 0-disalbe 1-enable
|
||||||
|
#define RTC_TIMER_MODE_TIE (0X02) // timer interrupt enable 0-disalbe 1-enable
|
||||||
|
#define RTC_TIMER_MODE_TI_TP (0X01) // timer interrupt mode 0-interrupt follows timer flag 1-interrupt generates a pulse
|
||||||
|
|
||||||
|
// format
|
||||||
|
#define RTC_ALARM (0x80) // set AEN_x registers
|
||||||
|
#define RTC_CTRL_1_DEFAULT (0x00)
|
||||||
|
#define RTC_CTRL_2_DEFAULT (0x00)
|
||||||
|
|
||||||
|
#define RTC_TIMER_FLAG (0x08)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t month;
|
||||||
|
uint8_t day;
|
||||||
|
uint8_t dotw;
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t minute;
|
||||||
|
uint8_t second;
|
||||||
|
} datetime_t;
|
||||||
|
|
||||||
|
const unsigned char MonthStr[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
const unsigned char Week[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||||
|
|
||||||
|
extern datetime_t datetime;
|
||||||
|
void PCF85063_Init(void);
|
||||||
|
void PCF85063_Reset(void);
|
||||||
|
void PCF85063Task(void *parameter);
|
||||||
|
|
||||||
|
void PCF85063_Set_Time(datetime_t time);
|
||||||
|
void PCF85063_Set_Date(datetime_t date);
|
||||||
|
void PCF85063_Set_All(datetime_t time);
|
||||||
|
|
||||||
|
void PCF85063_Read_Time(datetime_t *time);
|
||||||
|
|
||||||
|
void PCF85063_Enable_Alarm(void);
|
||||||
|
uint8_t PCF85063_Get_Alarm_Flag(void);
|
||||||
|
void PCF85063_Set_Alarm(datetime_t time);
|
||||||
|
void PCF85063_Read_Alarm(datetime_t *time);
|
||||||
|
|
||||||
|
void datetime_to_str(char *datetime_str, datetime_t time);
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
class PCF85063
|
||||||
|
{
|
||||||
|
I2C &m_i2c;
|
||||||
|
uint8_t m_address;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t month;
|
||||||
|
uint8_t day;
|
||||||
|
uint8_t dotw;
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t minute;
|
||||||
|
uint8_t second;
|
||||||
|
} datetime_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PCF85063(I2C &i2c, const uint8_t address, const uint8_t ctrl1 = RTC_CTRL_1_DEFAULT, const uint8_t ctrl2 = RTC_CTRL_2_DEFAULT);
|
||||||
|
|
||||||
|
const bool reset(void);
|
||||||
|
|
||||||
|
const bool setTime(const datetime_t time);
|
||||||
|
const bool setDate(const datetime_t date);
|
||||||
|
const bool setDatetime(const datetime_t datetime);
|
||||||
|
|
||||||
|
const bool readDate(datetime_t &datetime);
|
||||||
|
const bool readTime(datetime_t &datetime);
|
||||||
|
const bool readDatetime(datetime_t &datetime);
|
||||||
|
|
||||||
|
const bool enableAlarm(const bool enable);
|
||||||
|
const bool setAlarm(const datetime_t time);
|
||||||
|
const bool readAlarm(datetime_t &time);
|
||||||
|
const bool getAlarmFlag(uint8_t &flags);
|
||||||
|
|
||||||
|
const std::string datetime2str(datetime_t &datetime);
|
||||||
|
const std::string getTimeStr();
|
||||||
|
|
||||||
|
static PCF85063::datetime_t fromEpoch(time_t currentTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t decToBcd(const int val);
|
||||||
|
const int bcdToDec(const uint8_t val);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void printBytes(const char title[], const std::vector<uint8_t> &b)
|
||||||
|
{
|
||||||
|
Serial0.flush();
|
||||||
|
printf("%s: ", title);
|
||||||
|
for (auto v : b)
|
||||||
|
{
|
||||||
|
printf("0x%02x ", v);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
Serial0.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBytes(const char title[], const std::vector<uint16_t> &b)
|
||||||
|
{
|
||||||
|
Serial0.flush();
|
||||||
|
printf("%s: ", title);
|
||||||
|
for (auto v : b)
|
||||||
|
{
|
||||||
|
printf("0x%04x ", v);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
Serial0.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBool(const char title[], const std::vector<bool> &vals)
|
||||||
|
{
|
||||||
|
Serial0.flush();
|
||||||
|
printf("%s: ", title);
|
||||||
|
for (auto j(0); j < vals.size(); j++)
|
||||||
|
{
|
||||||
|
printf("%s ", vals.at(j) ? "True" : "False");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
Serial0.flush();
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
///////////// UTIL Functions /////////////////
|
||||||
|
|
||||||
|
void printBytes(const char title[], const std::vector<uint8_t> &b);
|
||||||
|
|
||||||
|
void printBytes(const char title[], const std::vector<uint16_t> &b);
|
||||||
|
|
||||||
|
void printBool(const char title[], const std::vector<bool> &vals);
|
||||||
@@ -16,3 +16,25 @@ lib_deps =
|
|||||||
bblanchon/ArduinoJson@^7.4.2
|
bblanchon/ArduinoJson@^7.4.2
|
||||||
arduino-libraries/NTPClient@^3.2.1
|
arduino-libraries/NTPClient@^3.2.1
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
|
robtillaart/CRC@^1.0.3
|
||||||
|
hideakitai/DebugLog@^0.8.4
|
||||||
|
|
||||||
|
[env:esp32-s3-waveshare8-debug]
|
||||||
|
platform = ${env:esp32-s3-waveshare8.platform}
|
||||||
|
board = ${env:esp32-s3-waveshare8.board}
|
||||||
|
framework = ${env:esp32-s3-waveshare8.framework}
|
||||||
|
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
|
||||||
|
build_type = debug
|
||||||
|
build_flags =
|
||||||
|
-O0
|
||||||
|
-g3
|
||||||
|
-ggdb
|
||||||
|
-fno-inline
|
||||||
|
-fno-ipa-sra
|
||||||
|
-fno-tree-sra
|
||||||
|
-fno-builtin
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#include "I2C_Driver.h"
|
|
||||||
|
|
||||||
|
|
||||||
void I2C_Init(void) {
|
|
||||||
Wire.begin( I2C_SDA_PIN, I2C_SCL_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length)
|
|
||||||
{
|
|
||||||
Wire.beginTransmission(Driver_addr);
|
|
||||||
Wire.write(Reg_addr);
|
|
||||||
if ( Wire.endTransmission(true)){
|
|
||||||
printf("The I2C transmission fails. - I2C Read\r\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Wire.requestFrom(Driver_addr, Length);
|
|
||||||
for (int i = 0; i < Length; i++) {
|
|
||||||
*Reg_data++ = Wire.read();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length)
|
|
||||||
{
|
|
||||||
Wire.beginTransmission(Driver_addr);
|
|
||||||
Wire.write(Reg_addr);
|
|
||||||
for (int i = 0; i < Length; i++) {
|
|
||||||
Wire.write(*Reg_data++);
|
|
||||||
}
|
|
||||||
if ( Wire.endTransmission(true))
|
|
||||||
{
|
|
||||||
printf("The I2C transmission fails. - I2C Write\r\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
#define I2C_SCL_PIN 41
|
|
||||||
#define I2C_SDA_PIN 42
|
|
||||||
|
|
||||||
void I2C_Init(void);
|
|
||||||
|
|
||||||
bool I2C_Read(uint8_t Driver_addr, uint8_t Reg_addr, uint8_t *Reg_data, uint32_t Length);
|
|
||||||
bool I2C_Write(uint8_t Driver_addr, uint8_t Reg_addr, const uint8_t *Reg_data, uint32_t Length);
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#include <Arduino.h>
|
|
||||||
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
|
||||||
#include "WS_MQTT.h"
|
|
||||||
#include "WS_Bluetooth.h"
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_Serial.h"
|
|
||||||
#include "WS_RTC.h"
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_DIN.h"
|
|
||||||
#include "WS_SD.h"
|
|
||||||
#include "WS_ETH.h"
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t Simulated_time=0; // Analog time counting
|
|
||||||
|
|
||||||
/******************************************************** Initializing ********************************************************/
|
|
||||||
void setup() {
|
|
||||||
Flash_test();
|
|
||||||
GPIO_Init(); // RGB . Buzzer GPIO
|
|
||||||
I2C_Init();
|
|
||||||
RTC_Init();// RTC
|
|
||||||
SD_Init();
|
|
||||||
Serial_Init(); // UART(RS485/CAN)
|
|
||||||
MQTT_Init();// MQTT
|
|
||||||
Bluetooth_Init();// Bluetooth
|
|
||||||
ETH_Init();
|
|
||||||
|
|
||||||
DIN_Init(); // If you don't want to control the relay through DIN, change Relay_Immediate_Default to 0 in WS_DIN.h and re-burn the program
|
|
||||||
Relay_Init();
|
|
||||||
|
|
||||||
printf("Connect to the WIFI network named \"ESP32-S3-POE-ETH-8DI-8RO\" and access the Internet using the connected IP address!!!\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************** While **********************************************************/
|
|
||||||
void loop() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
#include "WS_Bluetooth.h"
|
|
||||||
|
|
||||||
BLEServer* pServer; // Used to represent a BLE server
|
|
||||||
BLECharacteristic* pTxCharacteristic;
|
|
||||||
BLECharacteristic* pRxCharacteristic;
|
|
||||||
|
|
||||||
/********************************************************** Bluetooth *********************************************************/
|
|
||||||
|
|
||||||
class MyServerCallbacks : public BLEServerCallbacks { //By overriding the onConnect() and onDisconnect() functions
|
|
||||||
void onConnect(BLEServer* pServer) { // When the Device is connected, "Device connected" is printed.
|
|
||||||
Serial.println("Device connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
void onDisconnect(BLEServer* pServer) { // "Device disconnected" will be printed when the device is disconnected
|
|
||||||
Serial.println("Device disconnected");
|
|
||||||
|
|
||||||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); // Re-broadcast so that the device can query
|
|
||||||
pAdvertising->addServiceUUID(SERVICE_UUID); // Re-broadcast so that the device can query
|
|
||||||
pAdvertising->setScanResponse(true); // Re-broadcast so that the device can query
|
|
||||||
pAdvertising->setMinPreferred(0x06); // Re-broadcast so that the device can query
|
|
||||||
pAdvertising->setMinPreferred(0x12); // Re-broadcast so that the device can query
|
|
||||||
BLEDevice::startAdvertising(); // Re-broadcast so that the device can query
|
|
||||||
pRxCharacteristic->notify(); // Re-broadcast so that the device can query
|
|
||||||
pAdvertising->start(); // Re-broadcast so that the device can query
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class MyRXCallback : public BLECharacteristicCallbacks {
|
|
||||||
void onWrite(BLECharacteristic* pCharacteristic) { // The onWrite function is called when the remote device sends data to your feature
|
|
||||||
String rxValue = String(pCharacteristic->getValue().c_str());
|
|
||||||
if (!rxValue.isEmpty()) {
|
|
||||||
// The received data rxValue is processed here
|
|
||||||
if(rxValue.length() == 1)
|
|
||||||
{
|
|
||||||
printf("%s\n", rxValue.c_str()); // Print output through the serial port
|
|
||||||
uint8_t* valueBytes = reinterpret_cast<uint8_t*>(const_cast<char*>(rxValue.c_str())); // Convert value to uint8 t*
|
|
||||||
Relay_Analysis(valueBytes,Bluetooth_Mode); // pilot relay
|
|
||||||
}
|
|
||||||
else if(rxValue.length() == 2)
|
|
||||||
{
|
|
||||||
if(Extension_Enable)
|
|
||||||
{
|
|
||||||
printf("%s\n", rxValue.c_str()); // Print output through the serial port
|
|
||||||
uint8_t* valueBytes = reinterpret_cast<uint8_t*>(const_cast<char*>(rxValue.c_str())); // Convert value to uint8 t*
|
|
||||||
if(valueBytes[0] == 0x06) // Instruction check correct
|
|
||||||
RS485_Analysis(valueBytes); // Control external relay
|
|
||||||
else
|
|
||||||
printf("Note : Non-instruction data was received - Bluetooth !\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("Note : Non-instruction data was received or external relays are not enabled - Bluetooth !\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(rxValue.length() == 14)
|
|
||||||
{
|
|
||||||
if(RTC_Event_Enable)
|
|
||||||
{
|
|
||||||
// printf("%s\n", rxValue.c_str()); // Print output through the serial port
|
|
||||||
uint8_t* valueBytes = reinterpret_cast<uint8_t*>(const_cast<char*>(rxValue.c_str()));
|
|
||||||
BLE_Set_RTC_Event(valueBytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
printf("Note : Non-instruction data was received or RTC events were not enabled - Bluetooth !\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Note : Non-instruction data was received - Bluetooth !\r\n");
|
|
||||||
}
|
|
||||||
pRxCharacteristic->setValue(""); // After data is read, set it to blank for next read
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void BLE_Set_RTC_Event(uint8_t* valueBytes){
|
|
||||||
if(valueBytes[0] == 0xA1 && valueBytes[6] == 0xAA && valueBytes[13] == 0xFF ){
|
|
||||||
datetime_t Event_Time={0};
|
|
||||||
Event_Time.year = (valueBytes[1]/16*10 + valueBytes[1] % 16) *100 + valueBytes[2]/16*10 + valueBytes[2] % 16;
|
|
||||||
Event_Time.month = valueBytes[3]/16*10 + valueBytes[3] % 16;
|
|
||||||
Event_Time.day = valueBytes[4]/16*10 + valueBytes[4] % 16;
|
|
||||||
Event_Time.dotw = valueBytes[5]/16*10 + valueBytes[5] % 16;
|
|
||||||
// valueBytes[6] == 0xAA; // check
|
|
||||||
Event_Time.hour = valueBytes[7]/16*10 + valueBytes[7] % 16;
|
|
||||||
Event_Time.minute = valueBytes[8]/16*10 + valueBytes[8] % 16;
|
|
||||||
Event_Time.second = valueBytes[9]/16*10 + valueBytes[9] % 16;
|
|
||||||
Repetition_event Repetition = (Repetition_event)valueBytes[12]; // cyclical indicators
|
|
||||||
if(valueBytes[11]){ // Whether to control all relays 1:Control all relays 0:Control a relay
|
|
||||||
uint8_t CHxs = valueBytes[10]; // relay control
|
|
||||||
TimerEvent_CHxs_Set(Event_Time, CHxs, Repetition);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint8_t CHx = valueBytes[10]/16;
|
|
||||||
bool State = (valueBytes[10] % 16);
|
|
||||||
TimerEvent_CHx_Set(Event_Time,CHx, State, Repetition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Bluetooth_SendData(char* Data) { // Send data using Bluetooth
|
|
||||||
if (Data != nullptr && strlen(Data) > 0) {
|
|
||||||
if (pServer->getConnectedCount() > 0) {
|
|
||||||
String SendValue = String(Data); // Convert char* to String
|
|
||||||
pTxCharacteristic->setValue(SendValue.c_str()); // Set SendValue to the eigenvalue (String type)
|
|
||||||
pTxCharacteristic->notify(); // Sends a notification to all connected devices
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Bluetooth_Init()
|
|
||||||
{
|
|
||||||
/*************************************************************************
|
|
||||||
Bluetooth
|
|
||||||
*************************************************************************/
|
|
||||||
BLEDevice::init("ESP32-S3-POE-ETH-8DI-8RO"); // Initialize Bluetooth and start broadcasting
|
|
||||||
pServer = BLEDevice::createServer();
|
|
||||||
pServer->setCallbacks(new MyServerCallbacks());
|
|
||||||
BLEService* pService = pServer->createService(SERVICE_UUID);
|
|
||||||
pTxCharacteristic = pService->createCharacteristic(
|
|
||||||
TX_CHARACTERISTIC_UUID,
|
|
||||||
BLECharacteristic:: PROPERTY_READ); // The eigenvalues are readable and can be read by remote devices
|
|
||||||
pRxCharacteristic = pService->createCharacteristic(
|
|
||||||
RX_CHARACTERISTIC_UUID,
|
|
||||||
BLECharacteristic::PROPERTY_WRITE); // The eigenvalues are writable and can be written to by remote devices
|
|
||||||
pRxCharacteristic->setCallbacks(new MyRXCallback());
|
|
||||||
|
|
||||||
pRxCharacteristic->setValue("Successfully Connect To ESP32-S3-POE-ETH-8DI-8RO");
|
|
||||||
pService->start();
|
|
||||||
|
|
||||||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
|
||||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
|
||||||
pAdvertising->setScanResponse(true);
|
|
||||||
pAdvertising->setMinPreferred(0x06);
|
|
||||||
pAdvertising->setMinPreferred(0x12);
|
|
||||||
BLEDevice::startAdvertising();
|
|
||||||
pRxCharacteristic->notify();
|
|
||||||
pAdvertising->start();
|
|
||||||
RGB_Open_Time(0, 0, 60,1000, 0);
|
|
||||||
printf("Now you can read it in your phone!\r\n");
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
BLETask,
|
|
||||||
"BLETask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
2,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLETask(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
Bluetooth_SendData(ipStr);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
|
||||||
#include <BLEDevice.h>
|
|
||||||
#include <BLEUtils.h>
|
|
||||||
#include <BLEServer.h>
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_Serial.h"
|
|
||||||
#include "WS_Information.h"
|
|
||||||
#include "WS_Relay.h"
|
|
||||||
#include "WS_MQTT.h"
|
|
||||||
#include "WS_RTC.h"
|
|
||||||
|
|
||||||
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" // UUID of the server
|
|
||||||
#define RX_CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" // UUID of the characteristic Tx
|
|
||||||
#define TX_CHARACTERISTIC_UUID "beb5484a-36e1-4688-b7f5-ea07361b26a8" // UUID of the characteristic Rx
|
|
||||||
|
|
||||||
#define Bluetooth_Mode 2
|
|
||||||
|
|
||||||
|
|
||||||
void Bluetooth_SendData(char * Data);
|
|
||||||
void Bluetooth_Init();
|
|
||||||
void BLETask(void *parameter);
|
|
||||||
void BLE_Set_RTC_Event(uint8_t* valueBytes);
|
|
||||||
-219
@@ -1,219 +0,0 @@
|
|||||||
#include "WS_CAN.h"
|
|
||||||
|
|
||||||
static bool driver_installed = false;
|
|
||||||
|
|
||||||
void CAN_Init(void)
|
|
||||||
{ // Initializing serial port
|
|
||||||
// Initialize configuration structures using macro initializers
|
|
||||||
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t)TXD1, (gpio_num_t)RXD1, TWAI_MODE_NORMAL);
|
|
||||||
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS(); //Look in the api-reference for other speed sets.
|
|
||||||
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
|
|
||||||
|
|
||||||
// Install TWAI driver
|
|
||||||
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
|
|
||||||
printf("Driver installed\r\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to install driver\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start TWAI driver
|
|
||||||
if (twai_start() == ESP_OK) {
|
|
||||||
printf("Driver started\r\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to start driver\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconfigure alerts to detect TX alerts and Bus-Off errors
|
|
||||||
uint32_t alerts_to_enable = TWAI_ALERT_RX_DATA | TWAI_ALERT_ERR_PASS | TWAI_ALERT_BUS_ERROR | TWAI_ALERT_RX_QUEUE_FULL | TWAI_ALERT_TX_IDLE | TWAI_ALERT_TX_SUCCESS | TWAI_ALERT_TX_FAILED;
|
|
||||||
if (twai_reconfigure_alerts(alerts_to_enable, NULL) == ESP_OK) {
|
|
||||||
printf("CAN Alerts reconfigured\r\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to reconfigure alerts\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TWAI driver is now successfully installed and started
|
|
||||||
driver_installed = true;
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
CANTask,
|
|
||||||
"CANTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_message_Test(void) {
|
|
||||||
// Send message
|
|
||||||
// Configure message to transmit
|
|
||||||
twai_message_t message;
|
|
||||||
message.identifier = 0x0F6;
|
|
||||||
message.data_length_code = 4;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
message.data[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Queue message for transmission
|
|
||||||
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
|
|
||||||
printf("Message queued for transmission\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to queue message for transmission\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Standard frames ID: 0x000 to 0x7FF
|
|
||||||
// Extended frames ID: 0x00000000 to 0x1FFFFFFF
|
|
||||||
// Frame_type : 1:Extended frames 0:Standard frames
|
|
||||||
void send_message(uint32_t CAN_ID, uint8_t* Data, uint8_t Data_length, bool Frame_type) {
|
|
||||||
// Send message
|
|
||||||
// Configure message to transmit
|
|
||||||
twai_message_t message;
|
|
||||||
message.identifier = CAN_ID;
|
|
||||||
message.rtr = 0; // Disable remote frame
|
|
||||||
if(CAN_ID > 0x7FF){
|
|
||||||
if(!Frame_type)
|
|
||||||
printf("The frame type is set incorrectly and data will eventually be sent as an extended frame!!!!\r\n");
|
|
||||||
message.extd = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
message.extd = Frame_type;
|
|
||||||
if(Data_length > 8){
|
|
||||||
uint16_t Frame_count = (Data_length / 8);
|
|
||||||
for (int i = 0; i < Frame_count; i++) {
|
|
||||||
message.data_length_code = 8;
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
message.data[j] = Data[j + (i * 8)];
|
|
||||||
}
|
|
||||||
// Queue message for transmission
|
|
||||||
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
|
|
||||||
printf("Message queued for transmission\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to queue message for transmission\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(Data_length % 8){
|
|
||||||
uint8_t Data_length_Now = Data_length % 8;
|
|
||||||
message.data_length_code = Data_length_Now;
|
|
||||||
for (int k = 0; k < Data_length_Now; k++) {
|
|
||||||
message.data[k] = Data[k + (Data_length - Data_length_Now)];
|
|
||||||
}
|
|
||||||
// Queue message for transmission
|
|
||||||
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
|
|
||||||
printf("Message queued for transmission\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to queue message for transmission\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
message.data_length_code = Data_length;
|
|
||||||
for (int i = 0; i < Data_length; i++) {
|
|
||||||
message.data[i] = Data[i];
|
|
||||||
}
|
|
||||||
// Queue message for transmission
|
|
||||||
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
|
|
||||||
printf("Message queued for transmission\n");
|
|
||||||
} else {
|
|
||||||
printf("Failed to queue message for transmission\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void handle_rx_message(twai_message_t &message) {
|
|
||||||
// Process received message
|
|
||||||
if (message.extd) {
|
|
||||||
printf("Message is in Extended Format\r\n");
|
|
||||||
} else {
|
|
||||||
printf("Message is in Standard Format\r\n");
|
|
||||||
}
|
|
||||||
printf("ID: %lx\nByte:", message.identifier);
|
|
||||||
if (!(message.rtr)) {
|
|
||||||
if (message.data_length_code > 0) {
|
|
||||||
printf(" Data: ");
|
|
||||||
for (int i = 0; i < message.data_length_code; i++) {
|
|
||||||
printf("%02x ", message.data[i]);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
// printf("Send back the received data!\r\n");
|
|
||||||
// send_message(message.identifier, message.data, message.data_length_code, message.extd);
|
|
||||||
} else {
|
|
||||||
printf(" No data available\r\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("This is a Remote Transmission Request (RTR) frame.\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long previousMillis = 0; // will store last time a message was send
|
|
||||||
#if Communication_failure_Enable
|
|
||||||
static unsigned long previous_bus_error_time = 0; // To store the last time a BUS_ERROR was printed
|
|
||||||
#endif
|
|
||||||
void CAN_Loop(void)
|
|
||||||
{
|
|
||||||
if(driver_installed){
|
|
||||||
// Check if an alert happened
|
|
||||||
uint32_t alerts_triggered;
|
|
||||||
twai_read_alerts(&alerts_triggered, pdMS_TO_TICKS(POLLING_RATE_MS));
|
|
||||||
twai_status_info_t twaistatus;
|
|
||||||
twai_get_status_info(&twaistatus);
|
|
||||||
|
|
||||||
// Handle alerts
|
|
||||||
if (alerts_triggered & TWAI_ALERT_ERR_PASS) {
|
|
||||||
printf("Alert: TWAI controller has become error passive.\r\n");
|
|
||||||
}
|
|
||||||
if (alerts_triggered & TWAI_ALERT_BUS_ERROR) {
|
|
||||||
// printf("Alert: A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus.\r\n");
|
|
||||||
// printf("Bus error count: %ld\n", twaistatus.bus_error_count);
|
|
||||||
#if Communication_failure_Enable
|
|
||||||
unsigned long currentMillis = millis();
|
|
||||||
// Only print the message if more than 2 seconds have passed since the last time it was printed
|
|
||||||
if (currentMillis - previous_bus_error_time >= BUS_ERROR_INTERVAL_MS) {
|
|
||||||
printf("Note if there are other devices on the CAN bus (other devices must be present) and that the rate of the device is the same as set in this program\r\n");
|
|
||||||
previous_bus_error_time = currentMillis; // Update the last print time
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (alerts_triggered & TWAI_ALERT_RX_QUEUE_FULL) {
|
|
||||||
printf("Alert: The RX queue is full causing a received frame to be lost.\r\n");
|
|
||||||
printf("RX buffered: %ld\t", twaistatus.msgs_to_rx);
|
|
||||||
printf("RX missed: %ld\t", twaistatus.rx_missed_count);
|
|
||||||
printf("RX overrun %ld\n", twaistatus.rx_overrun_count);
|
|
||||||
}
|
|
||||||
if (alerts_triggered & TWAI_ALERT_TX_FAILED) {
|
|
||||||
printf("Alert: The Transmission failed.\r\n");
|
|
||||||
printf("TX buffered: %ld\t", twaistatus.msgs_to_tx);
|
|
||||||
printf("TX error: %ld\t", twaistatus.tx_error_counter);
|
|
||||||
printf("TX failed: %ld\n", twaistatus.tx_failed_count);
|
|
||||||
}
|
|
||||||
if (alerts_triggered & TWAI_ALERT_TX_SUCCESS) {
|
|
||||||
printf("Alert: The Transmission was successful.\r\n");
|
|
||||||
printf("TX buffered: %ld\t \r\n", twaistatus.msgs_to_tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Receive messages if any are available
|
|
||||||
if (alerts_triggered & TWAI_ALERT_RX_DATA) {
|
|
||||||
// One or more messages received. Handle all.
|
|
||||||
twai_message_t message; // This is the structure used to store the received CAN message.
|
|
||||||
while (twai_receive(&message, 0) == ESP_OK) {
|
|
||||||
handle_rx_message(message); // This function will process the received message.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CANTask(void *parameter) {
|
|
||||||
// send_message_Test();
|
|
||||||
// uint8_t Data[27]={0x80, 0x2A, 0xC3, 0x58, 0x17, 0x11, 0x4D, 0x3F, 0x3B, 0xCE, 0x0F, 0xFF, 0x79, 0x20, 0xB4, 0x40, 0x5D, 0x29, 0x05, 0x49, 0xE6, 0x12, 0x57, 0x0E, 0x6D, 0xC9, 0xAE};
|
|
||||||
// send_message(0x079,Data,27);
|
|
||||||
while(1){
|
|
||||||
CAN_Loop();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "driver/twai.h"
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
|
|
||||||
// Interval:
|
|
||||||
#define TRANSMIT_RATE_MS 1000
|
|
||||||
// Interval:
|
|
||||||
#define POLLING_RATE_MS 1000
|
|
||||||
|
|
||||||
#define Communication_failure_Enable 0 // If the CAN bus is faulty for a long time, determine whether to forcibly exit
|
|
||||||
|
|
||||||
#if Communication_failure_Enable
|
|
||||||
#define BUS_ERROR_INTERVAL_MS 5000 // Send a message every 2 seconds (2000 ms)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void CAN_Init(void);
|
|
||||||
void CAN_Loop(void);
|
|
||||||
void CANTask(void *parameter);
|
|
||||||
|
|
||||||
void send_message(uint32_t CAN_ID, uint8_t* Data, uint8_t Data_length);
|
|
||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
#include "WS_DIN.h"
|
|
||||||
|
|
||||||
bool DIN_Flag[8] = {0}; // DIN current status flag
|
|
||||||
uint8_t DIN_Data = 0;
|
|
||||||
bool Relay_Immediate_Enable = Relay_Immediate_Default;
|
|
||||||
|
|
||||||
bool DIN_Read_CH1(void){
|
|
||||||
DIN_Flag[0] = digitalRead(DIN_PIN_CH1);
|
|
||||||
if(DIN_Flag[0]){
|
|
||||||
DIN_Data |= (1 << 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 0));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH2(void){
|
|
||||||
DIN_Flag[1] = digitalRead(DIN_PIN_CH2);
|
|
||||||
if(DIN_Flag[1]){
|
|
||||||
DIN_Data |= (1 << 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 1));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH3(void){
|
|
||||||
DIN_Flag[2] = digitalRead(DIN_PIN_CH3);
|
|
||||||
if(DIN_Flag[2]){
|
|
||||||
DIN_Data |= (1 << 2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 2));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH4(void){
|
|
||||||
DIN_Flag[3] = digitalRead(DIN_PIN_CH4);
|
|
||||||
if(DIN_Flag[3]){
|
|
||||||
DIN_Data |= (1 << 3);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 3));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH5(void){
|
|
||||||
DIN_Flag[4] = digitalRead(DIN_PIN_CH5);
|
|
||||||
if(DIN_Flag[4]){
|
|
||||||
DIN_Data |= (1 << 4);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 4));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH6(void){
|
|
||||||
DIN_Flag[5] = digitalRead(DIN_PIN_CH6);
|
|
||||||
if(DIN_Flag[5]){
|
|
||||||
DIN_Data |= (1 << 5);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 5));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH7(void){
|
|
||||||
DIN_Flag[6] = digitalRead(DIN_PIN_CH7);
|
|
||||||
if(DIN_Flag[6]){
|
|
||||||
DIN_Data |= (1 << 6);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 6));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool DIN_Read_CH8(void){
|
|
||||||
DIN_Flag[7] = digitalRead(DIN_PIN_CH8);
|
|
||||||
if(DIN_Flag[7]){
|
|
||||||
DIN_Data |= (1 << 7);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DIN_Data &= (~(1 << 7));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint8_t DIN_Read_CHxs(){
|
|
||||||
DIN_Read_CH1();
|
|
||||||
DIN_Read_CH2();
|
|
||||||
DIN_Read_CH3();
|
|
||||||
DIN_Read_CH4();
|
|
||||||
DIN_Read_CH5();
|
|
||||||
DIN_Read_CH6();
|
|
||||||
DIN_Read_CH7();
|
|
||||||
DIN_Read_CH8();
|
|
||||||
return DIN_Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t DIN_Data_Old = 0;
|
|
||||||
void DINTask(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
if(Relay_Immediate_Enable){
|
|
||||||
DIN_Read_CHxs();
|
|
||||||
if(DIN_Data_Old != DIN_Data){
|
|
||||||
if(DIN_Inverse_Enable)
|
|
||||||
Relay_Immediate_CHxs(~DIN_Data , DIN_Mode);
|
|
||||||
else
|
|
||||||
Relay_Immediate_CHxs(DIN_Data , DIN_Mode);
|
|
||||||
DIN_Data_Old = DIN_Data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(20));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DIN_Init(void)
|
|
||||||
{
|
|
||||||
pinMode(DIN_PIN_CH1, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH2, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH3, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH4, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH5, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH6, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH7, INPUT_PULLUP);
|
|
||||||
pinMode(DIN_PIN_CH8, INPUT_PULLUP);
|
|
||||||
|
|
||||||
DIN_Read_CHxs();
|
|
||||||
if(DIN_Inverse_Enable)
|
|
||||||
DIN_Data_Old = 0xFF;
|
|
||||||
else
|
|
||||||
DIN_Data_Old = 0x00;
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
DINTask,
|
|
||||||
"DINTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
4,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_Relay.h"
|
|
||||||
/************************************************************* I/O *************************************************************/
|
|
||||||
#define DIN_PIN_CH1 4 // DIN CH1 GPIO
|
|
||||||
#define DIN_PIN_CH2 5 // DIN CH2 GPIO
|
|
||||||
#define DIN_PIN_CH3 6 // DIN CH3 GPIO
|
|
||||||
#define DIN_PIN_CH4 7 // DIN CH4 GPIO
|
|
||||||
#define DIN_PIN_CH5 8 // DIN CH5 GPIO
|
|
||||||
#define DIN_PIN_CH6 9 // DIN CH6 GPIO
|
|
||||||
#define DIN_PIN_CH7 10 // DIN CH7 GPIO
|
|
||||||
#define DIN_PIN_CH8 11 // DIN CH8 GPIO
|
|
||||||
|
|
||||||
#define Relay_Immediate_Default 1 // Enable the input control relay
|
|
||||||
#define DIN_Inverse_Enable 1 // Input is reversed from control
|
|
||||||
|
|
||||||
void DIN_Init(void);
|
|
||||||
-166
@@ -1,166 +0,0 @@
|
|||||||
#include "WS_GPIO.h"
|
|
||||||
|
|
||||||
/************************************************************* I/O Init *************************************************************/
|
|
||||||
void GPIO_Init() {
|
|
||||||
pinMode(GPIO_PIN_RGB, OUTPUT); // Initialize the control GPIO of RGB
|
|
||||||
pinMode(GPIO_PIN_Buzzer, OUTPUT); // Initialize the control GPIO of Buzzer
|
|
||||||
|
|
||||||
// TODO: Re enable this
|
|
||||||
//ledcAttach(GPIO_PIN_Buzzer, Frequency, Resolution);
|
|
||||||
Set_Dutyfactor(0); //0~100
|
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
RGBTask,
|
|
||||||
"RelayFailTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
2,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
BuzzerTask,
|
|
||||||
"RelayFailTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
2,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************* RGB *************************************************************/
|
|
||||||
void RGB_Light(uint8_t red_val, uint8_t green_val, uint8_t blue_val) {
|
|
||||||
rgbLedWrite(GPIO_PIN_RGB, green_val, red_val, blue_val); // RGB color adjustment
|
|
||||||
}
|
|
||||||
RGB_Indicate RGB_indicate[RGB_Indicate_Number];
|
|
||||||
static uint8_t RGB_indicate_Num = 0;
|
|
||||||
void RGB_Open_Time(uint8_t red_val, uint8_t green_val, uint8_t blue_val, uint16_t Time, uint16_t flicker_time) {
|
|
||||||
|
|
||||||
if(RGB_indicate_Num + 1 >= RGB_Indicate_Number)
|
|
||||||
{
|
|
||||||
printf("Note : The RGB indicates that the cache is full and has been ignored\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
RGB_indicate[RGB_indicate_Num].Red = red_val;
|
|
||||||
RGB_indicate[RGB_indicate_Num].Green = green_val;
|
|
||||||
RGB_indicate[RGB_indicate_Num].Blue = blue_val;
|
|
||||||
RGB_indicate[RGB_indicate_Num].RGB_Time = Time;
|
|
||||||
if(flicker_time<51)
|
|
||||||
flicker_time = 0; // If the blinking interval is less than 50ms, the blinking is ignored
|
|
||||||
RGB_indicate[RGB_indicate_Num].RGB_Flicker = flicker_time;
|
|
||||||
RGB_indicate_Num ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void RGBTask(void *parameter) {
|
|
||||||
bool RGB_Flag = 0;
|
|
||||||
while(1){
|
|
||||||
if(RGB_indicate[0].RGB_Time)
|
|
||||||
{
|
|
||||||
RGB_Flag = 1;
|
|
||||||
RGB_Light(RGB_indicate[0].Red, RGB_indicate[0].Green, RGB_indicate[0].Blue);
|
|
||||||
if(RGB_indicate[0].RGB_Flicker){
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(RGB_indicate[0].RGB_Flicker));
|
|
||||||
RGB_Light(0, 0, 0);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(RGB_indicate[0].RGB_Flicker));
|
|
||||||
}
|
|
||||||
if(RGB_indicate[0].RGB_Time > (RGB_indicate[0].RGB_Flicker * 2 +50))
|
|
||||||
RGB_indicate[0].RGB_Time = RGB_indicate[0].RGB_Time -(RGB_indicate[0].RGB_Flicker * 2 +50);
|
|
||||||
else
|
|
||||||
RGB_indicate[0].RGB_Time = 0;
|
|
||||||
}
|
|
||||||
else if(RGB_Flag && !RGB_indicate[0].RGB_Time){
|
|
||||||
RGB_Light(0, 0, 0);
|
|
||||||
RGB_Flag = 0;
|
|
||||||
RGB_indicate[0].Red = 0;
|
|
||||||
RGB_indicate[0].Green = 0;
|
|
||||||
RGB_indicate[0].Blue = 0;
|
|
||||||
RGB_indicate[0].RGB_Time = 0;
|
|
||||||
RGB_indicate[0].RGB_Flicker = 0;
|
|
||||||
if(RGB_indicate_Num > 0){
|
|
||||||
for (int i = 1; i < RGB_Indicate_Number; i++) {
|
|
||||||
RGB_indicate[i-1] = RGB_indicate[i];
|
|
||||||
}
|
|
||||||
RGB_indicate[RGB_Indicate_Number -1].Red = 0;
|
|
||||||
RGB_indicate[RGB_Indicate_Number -1].Green = 0;
|
|
||||||
RGB_indicate[RGB_Indicate_Number -1].Blue = 0;
|
|
||||||
RGB_indicate[RGB_Indicate_Number -1].RGB_Time = 0;
|
|
||||||
RGB_indicate[RGB_Indicate_Number -1].RGB_Flicker = 0;
|
|
||||||
RGB_indicate_Num --;
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(RGB_Indicating_interval));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************* Buzzer *************************************************************/
|
|
||||||
void Set_Dutyfactor(uint16_t dutyfactor)
|
|
||||||
{
|
|
||||||
if(dutyfactor > Dutyfactor_MAX || dutyfactor < 0)
|
|
||||||
printf("Set Backlight parameters in the range of 0 to %d \r\n",Dutyfactor_MAX);
|
|
||||||
else{
|
|
||||||
ledcWrite(GPIO_PIN_Buzzer, dutyfactor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Buzzer_Open(void)
|
|
||||||
{
|
|
||||||
Set_Dutyfactor(Dutyfactor);
|
|
||||||
}
|
|
||||||
void Buzzer_Closs(void)
|
|
||||||
{
|
|
||||||
Set_Dutyfactor(0);
|
|
||||||
}
|
|
||||||
Buzzer_Indicate Buzzer_indicate[Buzzer_Indicate_Number];
|
|
||||||
static uint8_t Buzzer_indicate_Num = 0;
|
|
||||||
void Buzzer_Open_Time(uint16_t Time, uint16_t flicker_time)
|
|
||||||
{
|
|
||||||
if(Buzzer_indicate_Num + 1 >= Buzzer_Indicate_Number)
|
|
||||||
{
|
|
||||||
printf("Note : The buzzer indicates that the cache is full and has been ignored\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Buzzer_indicate[Buzzer_indicate_Num].Buzzer_Time = Time;
|
|
||||||
if(flicker_time<51)
|
|
||||||
flicker_time = 0; // If the blinking interval is less than 50ms, the blinking is ignored
|
|
||||||
Buzzer_indicate[Buzzer_indicate_Num].Buzzer_Flicker = flicker_time;
|
|
||||||
Buzzer_indicate_Num ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void BuzzerTask(void *parameter) {
|
|
||||||
bool Buzzer_Flag = 0;
|
|
||||||
while(1){
|
|
||||||
if(Buzzer_indicate[0].Buzzer_Time)
|
|
||||||
{
|
|
||||||
Buzzer_Flag = 1;
|
|
||||||
Buzzer_Open();
|
|
||||||
if(Buzzer_indicate[0].Buzzer_Flicker){
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(Buzzer_indicate[0].Buzzer_Flicker));
|
|
||||||
Buzzer_Closs();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(Buzzer_indicate[0].Buzzer_Flicker));
|
|
||||||
}
|
|
||||||
if(Buzzer_indicate[0].Buzzer_Time > (Buzzer_indicate[0].Buzzer_Flicker * 2 +50))
|
|
||||||
Buzzer_indicate[0].Buzzer_Time = Buzzer_indicate[0].Buzzer_Time -(Buzzer_indicate[0].Buzzer_Flicker * 2 +50);
|
|
||||||
else
|
|
||||||
Buzzer_indicate[0].Buzzer_Time = 0;
|
|
||||||
}
|
|
||||||
else if(Buzzer_Flag && !Buzzer_indicate[0].Buzzer_Time){
|
|
||||||
Buzzer_Closs();
|
|
||||||
Buzzer_Flag = 0;
|
|
||||||
Buzzer_indicate[0].Buzzer_Time = 0;
|
|
||||||
Buzzer_indicate[0].Buzzer_Flicker = 0;
|
|
||||||
if(Buzzer_indicate_Num > 0){
|
|
||||||
for (int i = 1; i < Buzzer_indicate_Num; i++) {
|
|
||||||
Buzzer_indicate[i-1] = Buzzer_indicate[i];
|
|
||||||
}
|
|
||||||
Buzzer_indicate[Buzzer_indicate_Num - 1].Buzzer_Time = 0;
|
|
||||||
Buzzer_indicate[Buzzer_indicate_Num - 1].Buzzer_Flicker = 0;
|
|
||||||
Buzzer_indicate_Num --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
|
||||||
|
|
||||||
/************************************************************* I/O *************************************************************/
|
|
||||||
#define TXD1 17 //The TXD of UART1 corresponds to GPIO RS485/CAN
|
|
||||||
#define RXD1 18 //The RXD of UART1 corresponds to GPIO RS485/CAN
|
|
||||||
#define GPIO_PIN_RGB 38 // RGB Control GPIO
|
|
||||||
|
|
||||||
/*********************************************************** Buzzer ***********************************************************/
|
|
||||||
#define GPIO_PIN_Buzzer 46 // Buzzer Control GPIO
|
|
||||||
#define PWM_Channel 1 // PWM Channel
|
|
||||||
#define Frequency 1000 // PWM frequencyconst
|
|
||||||
#define Resolution 8 // PWM resolution ratio
|
|
||||||
#define Dutyfactor 200 // PWM Dutyfactor
|
|
||||||
#define Dutyfactor_MAX 255
|
|
||||||
|
|
||||||
|
|
||||||
#define RGB_Indicate_Number 10 // Number of saved RGB indicator signals
|
|
||||||
#define RGB_Indicating_interval 500 // Time interval of each indication signal(unit: ms)
|
|
||||||
typedef struct {
|
|
||||||
uint8_t Red = 0;
|
|
||||||
uint8_t Green = 0;
|
|
||||||
uint8_t Blue = 0;
|
|
||||||
uint16_t RGB_Time = 0; // RGB lighting duration
|
|
||||||
uint16_t RGB_Flicker = 0; // RGB flicker interval
|
|
||||||
} RGB_Indicate;
|
|
||||||
|
|
||||||
#define Buzzer_Indicate_Number 10 // Number of saved RGB indicator signals
|
|
||||||
typedef struct {
|
|
||||||
uint16_t Buzzer_Time = 0; // Buzzer duration
|
|
||||||
uint16_t Buzzer_Flicker = 0; // Buzzer interval duration
|
|
||||||
} Buzzer_Indicate;
|
|
||||||
/************************************************************* I/O *************************************************************/
|
|
||||||
void GPIO_Init();
|
|
||||||
void RGB_Light(uint8_t red_val, uint8_t green_val, uint8_t blue_val);
|
|
||||||
void RGB_Open_Time(uint8_t red_val, uint8_t green_val, uint8_t blue_val, uint16_t Time, uint16_t flicker_time);
|
|
||||||
void RGBTask(void *parameter);
|
|
||||||
|
|
||||||
void Set_Dutyfactor(uint16_t dutyfactor);
|
|
||||||
void Buzzer_Open(void);
|
|
||||||
void Buzzer_Closs(void);
|
|
||||||
void Buzzer_Open_Time(uint16_t Time, uint16_t flicker_time);
|
|
||||||
void BuzzerTask(void *parameter);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define Extension_Enable 1 // Whether to extend the connection to external devices 1:Expansion device Modbus RTU Relay 0:No extend
|
|
||||||
#define RS485_CAN_Enable 1 // This item is configured according to product selection 1:Select RS485 0:Select CAN
|
|
||||||
#define RTC_Event_Enable 1 // Whether to enable RTC events (Bluetooth) 1:Enable 0:Disable
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Name and password of the WiFi access point
|
|
||||||
#define STASSID "JSBPI"
|
|
||||||
#define STAPSK "waveshare0755"
|
|
||||||
|
|
||||||
// Details about devices on the Waveshare cloud
|
|
||||||
#define MQTT_Server "mqtt.waveshare.cloud"
|
|
||||||
#define MQTT_Port 1883
|
|
||||||
#define MQTT_ID "fc2d8db5"
|
|
||||||
#define MQTT_Pub "Pub/59/54/fc2d8db5"
|
|
||||||
#define MQTT_Sub "Sub/59/54/fc2d8db5"
|
|
||||||
-248
@@ -1,248 +0,0 @@
|
|||||||
#include "WS_MQTT.h"
|
|
||||||
|
|
||||||
// The name and password of the WiFi access point
|
|
||||||
const char* ssid = STASSID;
|
|
||||||
const char* password = STAPSK;
|
|
||||||
// Details about devices on the Waveshare cloud
|
|
||||||
const char* mqtt_server = MQTT_Server;
|
|
||||||
int PORT = MQTT_Port;
|
|
||||||
const char* ID = MQTT_ID; // Defining device ID
|
|
||||||
char pub[] = MQTT_Pub; // MQTT release topic
|
|
||||||
char sub[] = MQTT_Sub; // MQTT subscribe to topics
|
|
||||||
|
|
||||||
|
|
||||||
WiFiClient espClient; //MQTT initializes the contents
|
|
||||||
PubSubClient client(espClient);
|
|
||||||
|
|
||||||
JsonDocument sendJson;
|
|
||||||
JsonDocument readJson;
|
|
||||||
unsigned long lastUpdateTime = 0;
|
|
||||||
char msg[MSG_BUFFER_SIZE];
|
|
||||||
bool WIFI_Connection = 0;
|
|
||||||
bool WIFI_Connection_Old = 0;
|
|
||||||
char ipStr[16];
|
|
||||||
|
|
||||||
const unsigned long updateInterval = 5000;
|
|
||||||
|
|
||||||
void WIFI_Init(void)
|
|
||||||
{
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
WifiStaTask,
|
|
||||||
"WifiStaTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void WifiStaTask(void *parameter) {
|
|
||||||
uint8_t Count = 0;
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
WiFi.setSleep(true);
|
|
||||||
WiFi.begin(ssid, password); // Connect to the specified Wi-Fi network
|
|
||||||
while(1){
|
|
||||||
if(WiFi.status() != WL_CONNECTED)
|
|
||||||
{
|
|
||||||
WIFI_Connection = 0;
|
|
||||||
printf(".\n");
|
|
||||||
RGB_Open_Time(50, 0, 0, 500, 0);
|
|
||||||
Count++;
|
|
||||||
if(Count >= 10){
|
|
||||||
Count = 0;
|
|
||||||
printf("\r\n");
|
|
||||||
WiFi.disconnect();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
WiFi.mode(WIFI_OFF);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
WiFi.mode(WIFI_STA);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
WiFi.begin(ssid, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
WIFI_Connection = 1;
|
|
||||||
IPAddress myIP = WiFi.localIP();
|
|
||||||
printf("IP Address: ");
|
|
||||||
sprintf(ipStr, "%d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]);
|
|
||||||
printf("%s\r\n", ipStr);
|
|
||||||
RGB_Open_Time(0, 50, 0, 1000, 0);
|
|
||||||
|
|
||||||
printf("WIFI connection is successful, relay control can be performed via Waveshare cloud.\r\n");
|
|
||||||
|
|
||||||
while (WiFi.status() == WL_CONNECTED){
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// MQTT subscribes to callback functions for processing received messages
|
|
||||||
void callback(char* topic, byte* payload, unsigned int length) {
|
|
||||||
uint8_t CH_Flag = 0;
|
|
||||||
String inputString;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
inputString += (char)payload[i];
|
|
||||||
}
|
|
||||||
printf("%s\r\n",inputString.c_str()); // Format of data sent back by the server {"data":{"CH1":1}}
|
|
||||||
int dataBegin = inputString.indexOf("\"data\""); // Finds if "data" is present in the string (quotes also)
|
|
||||||
if (dataBegin == -1) {
|
|
||||||
printf("Missing 'data' field in JSON. - MQTT\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int CH_Begin = -1;
|
|
||||||
if (inputString.indexOf("\"CH1\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 1;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH1\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH2\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 2;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH2\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH3\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 3;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH3\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH4\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 4;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH4\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH5\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 5;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH5\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH6\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 6;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH6\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH7\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 7;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH7\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"CH8\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 8;
|
|
||||||
CH_Begin = inputString.indexOf("\"CH8\"", dataBegin);
|
|
||||||
}
|
|
||||||
else if (inputString.indexOf("\"ALL\"", dataBegin) != -1){
|
|
||||||
CH_Flag = 9;
|
|
||||||
CH_Begin = inputString.indexOf("\"ALL\"", dataBegin);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("Note : Non-instruction data was received - MQTT!\r\n");
|
|
||||||
CH_Flag = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int valueBegin = inputString.indexOf(':', CH_Begin);
|
|
||||||
int valueEnd = inputString.indexOf('}', valueBegin);
|
|
||||||
if (valueBegin != -1 && valueEnd != -1) {
|
|
||||||
if(CH_Flag != 0)
|
|
||||||
{
|
|
||||||
String ValueStr = inputString.substring(valueBegin + 1, valueEnd);
|
|
||||||
int Value = ValueStr.toInt();
|
|
||||||
if(CH_Flag < 9){
|
|
||||||
if(Value == 1 && Relay_Flag[CH_Flag - 1] == 0){
|
|
||||||
uint8_t Data[1]={CH_Flag+48};
|
|
||||||
Relay_Analysis(Data,MQTT_Mode);
|
|
||||||
}
|
|
||||||
else if(Value == 0 && Relay_Flag[CH_Flag - 1] == 1){
|
|
||||||
uint8_t Data[1]={CH_Flag+48};
|
|
||||||
Relay_Analysis(Data,MQTT_Mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(CH_Flag == 9){
|
|
||||||
if(Value == 1 && ((Relay_Flag[0] & Relay_Flag[1] & Relay_Flag[2] & Relay_Flag[3] & Relay_Flag[4] & Relay_Flag[5] & Relay_Flag[6] & Relay_Flag[7]) == 0)){
|
|
||||||
uint8_t Data[1]={9+48};
|
|
||||||
Relay_Analysis(Data,MQTT_Mode);
|
|
||||||
}
|
|
||||||
else if(Value == 0 && ((Relay_Flag[0] | Relay_Flag[1] | Relay_Flag[2] | Relay_Flag[3] | Relay_Flag[4] | Relay_Flag[5] | Relay_Flag[6] | Relay_Flag[7] )== 1)){
|
|
||||||
uint8_t Data[1]={0+48};
|
|
||||||
Relay_Analysis(Data,MQTT_Mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Reconnect to the MQTT server
|
|
||||||
void reconnect(void) {
|
|
||||||
uint8_t Count = 0;
|
|
||||||
while (!client.connected()) {
|
|
||||||
Count++;
|
|
||||||
if (client.connect(ID)) {
|
|
||||||
client.subscribe(sub);
|
|
||||||
printf("Waveshare Cloud connection is successful and now you can use all features.\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
delay(500);
|
|
||||||
if(Count % 2 == 0 && Count != 0){
|
|
||||||
printf("%d\r\n", client.state());
|
|
||||||
RGB_Open_Time(50, 0, 50, 1000, 0);
|
|
||||||
}
|
|
||||||
if(Count % 10 == 0){ // 10 attempts failed to connect, cancel the connection, try again
|
|
||||||
client.disconnect();
|
|
||||||
delay(100);
|
|
||||||
client.setServer(mqtt_server, PORT);
|
|
||||||
delay(100);
|
|
||||||
client.setCallback(callback);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
if(Count > 32){ // connection fail
|
|
||||||
Count = 0;
|
|
||||||
printf("warning: Waveshare cloud connection fails. Currently, only Bluetooth control is available !!!\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send data in JSON format to MQTT server
|
|
||||||
void sendJsonData(void) {
|
|
||||||
sendJson["ID"] = ID;
|
|
||||||
String pubres;
|
|
||||||
serializeJson(sendJson, pubres);
|
|
||||||
int str_len = pubres.length() + 1;
|
|
||||||
char char_array[str_len];
|
|
||||||
pubres.toCharArray(char_array, str_len);
|
|
||||||
client.publish(pub, char_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MQTTTask(void *parameter) {
|
|
||||||
bool WIFI_Connection_Old;
|
|
||||||
while(1){
|
|
||||||
if(WIFI_Connection == 1)
|
|
||||||
{
|
|
||||||
if(!WIFI_Connection_Old){
|
|
||||||
WIFI_Connection_Old = 1;
|
|
||||||
client.setServer(mqtt_server, PORT);
|
|
||||||
client.setCallback(callback);
|
|
||||||
}
|
|
||||||
if (!client.connected()) {
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
client.loop();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
WIFI_Connection_Old = 0;
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
void MQTT_Init(void)
|
|
||||||
{
|
|
||||||
WIFI_Init();
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
MQTTTask,
|
|
||||||
"MQTTTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#ifndef _WS_MQTT_H_
|
|
||||||
#define _WS_MQTT_H_
|
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <PubSubClient.h>
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <WiFiClientSecure.h>
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_Information.h"
|
|
||||||
#include "WS_Relay.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MSG_BUFFER_SIZE (50)
|
|
||||||
|
|
||||||
extern char ipStr[16];
|
|
||||||
|
|
||||||
void WIFI_Init(void);
|
|
||||||
void WifiStaTask(void *parameter);
|
|
||||||
void callback(char* topic, byte* payload, unsigned int length); // MQTT subscribes to callback functions for processing received messages
|
|
||||||
void reconnect(void); // Reconnect to the MQTT server
|
|
||||||
void sendJsonData(void); // Send data in JSON format to MQTT server
|
|
||||||
void MQTT_Init(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
#include "WS_PCF85063.h"
|
|
||||||
|
|
||||||
datetime_t datetime= {0};
|
|
||||||
datetime_t Update_datetime= {0};
|
|
||||||
static uint8_t decToBcd(int val);
|
|
||||||
static int bcdToDec(uint8_t val);
|
|
||||||
|
|
||||||
|
|
||||||
void Time_printf(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,datetime);
|
|
||||||
printf("Time:%s\r\n",datetime_str);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
void PCF85063_Init(void) // PCF85063 initialized
|
|
||||||
{
|
|
||||||
uint8_t Value = RTC_CTRL_1_DEFAULT|RTC_CTRL_1_CAP_SEL;
|
|
||||||
|
|
||||||
I2C_Write(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
|
|
||||||
I2C_Read(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
|
|
||||||
if(Value & RTC_CTRL_1_STOP)
|
|
||||||
printf("PCF85063 failed to be initialized.state :%d\r\n",Value);
|
|
||||||
else
|
|
||||||
printf("PCF85063 is running,state :%d\r\n",Value);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Update_datetime.year = 2024;
|
|
||||||
// Update_datetime.month = 9;
|
|
||||||
// Update_datetime.day = 20;
|
|
||||||
// Update_datetime.dotw = 5;
|
|
||||||
// Update_datetime.hour = 9;
|
|
||||||
// Update_datetime.minute = 50;
|
|
||||||
// Update_datetime.second = 0;
|
|
||||||
// PCF85063_Set_All(Update_datetime);
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
PCF85063Task,
|
|
||||||
"PCF85063Task",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
// xTaskCreatePinnedToCore(
|
|
||||||
// Time_printf,
|
|
||||||
// "Time_printf",
|
|
||||||
// 4096,
|
|
||||||
// NULL,
|
|
||||||
// 3,
|
|
||||||
// NULL,
|
|
||||||
// 0
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063Task(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
PCF85063_Read_Time(&datetime);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Reset() // Reset PCF85063
|
|
||||||
{
|
|
||||||
uint8_t Value = RTC_CTRL_1_DEFAULT|RTC_CTRL_1_CAP_SEL|RTC_CTRL_1_SR;
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_CTRL_1_ADDR, &Value, 1);
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Reset failure\r\n");
|
|
||||||
}
|
|
||||||
void PCF85063_Set_Time(datetime_t time) // Set Time
|
|
||||||
{
|
|
||||||
uint8_t buf[3] = {decToBcd(time.second),
|
|
||||||
decToBcd(time.minute),
|
|
||||||
decToBcd(time.hour)};
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Time setting failure\r\n");
|
|
||||||
}
|
|
||||||
void PCF85063_Set_Date(datetime_t date) // Set Date
|
|
||||||
{
|
|
||||||
uint8_t buf[4] = {decToBcd(date.day),
|
|
||||||
decToBcd(date.dotw),
|
|
||||||
decToBcd(date.month),
|
|
||||||
decToBcd(date.year - YEAR_OFFSET)};
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_DAY_ADDR, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Date setting failed\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Set_All(datetime_t time) // Set Time And Date
|
|
||||||
{
|
|
||||||
uint8_t buf[7] = {decToBcd(time.second),
|
|
||||||
decToBcd(time.minute),
|
|
||||||
decToBcd(time.hour),
|
|
||||||
decToBcd(time.day),
|
|
||||||
decToBcd(time.dotw),
|
|
||||||
decToBcd(time.month),
|
|
||||||
decToBcd(time.year - YEAR_OFFSET)};
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Failed to set the date and time\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Read_Time(datetime_t *time) // Read Time And Date
|
|
||||||
{
|
|
||||||
uint8_t buf[7] = {0};
|
|
||||||
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_SECOND_ADDR, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Time read failure\r\n");
|
|
||||||
else{
|
|
||||||
time->second = bcdToDec(buf[0] & 0x7F);
|
|
||||||
time->minute = bcdToDec(buf[1] & 0x7F);
|
|
||||||
time->hour = bcdToDec(buf[2] & 0x3F);
|
|
||||||
time->day = bcdToDec(buf[3] & 0x3F);
|
|
||||||
time->dotw = bcdToDec(buf[4] & 0x07);
|
|
||||||
time->month = bcdToDec(buf[5] & 0x1F);
|
|
||||||
time->year = bcdToDec(buf[6]) + YEAR_OFFSET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Enable_Alarm() // Enable Alarm and Clear Alarm flag
|
|
||||||
{
|
|
||||||
uint8_t Value = RTC_CTRL_2_DEFAULT | RTC_CTRL_2_AIE;
|
|
||||||
Value &= ~RTC_CTRL_2_AF;
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_CTRL_2_ADDR, &Value, 1);
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Failed to enable Alarm Flag and Clear Alarm Flag \r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t PCF85063_Get_Alarm_Flag() // Get Alarm flag
|
|
||||||
{
|
|
||||||
uint8_t Value = 0;
|
|
||||||
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_CTRL_2_ADDR, &Value, 1);
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Failed to obtain a warning flag.\r\n");
|
|
||||||
else
|
|
||||||
Value &= RTC_CTRL_2_AF | RTC_CTRL_2_AIE;
|
|
||||||
//printf("Value = 0x%x",Value);
|
|
||||||
return Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Set_Alarm(datetime_t time) // Set Alarm
|
|
||||||
{
|
|
||||||
|
|
||||||
uint8_t buf[5] ={
|
|
||||||
decToBcd(time.second)&(~RTC_ALARM),
|
|
||||||
decToBcd(time.minute)&(~RTC_ALARM),
|
|
||||||
decToBcd(time.hour)&(~RTC_ALARM),
|
|
||||||
//decToBcd(time.day)&(~RTC_ALARM),
|
|
||||||
//decToBcd(time.dotw)&(~RTC_ALARM)
|
|
||||||
RTC_ALARM, //disalbe day
|
|
||||||
RTC_ALARM //disalbe weekday
|
|
||||||
};
|
|
||||||
esp_err_t ret = I2C_Write(PCF85063_ADDRESS, RTC_SECOND_ALARM, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Failed to set alarm flag\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PCF85063_Read_Alarm(datetime_t *time) // Read Alarm
|
|
||||||
{
|
|
||||||
uint8_t buf[5] = {0};
|
|
||||||
esp_err_t ret = I2C_Read(PCF85063_ADDRESS, RTC_SECOND_ALARM, buf, sizeof(buf));
|
|
||||||
if(ret != ESP_OK)
|
|
||||||
printf("PCF85063 : Failed to read the alarm sign\r\n");
|
|
||||||
else{
|
|
||||||
time->second = bcdToDec(buf[0] & 0x7F);
|
|
||||||
time->minute = bcdToDec(buf[1] & 0x7F);
|
|
||||||
time->hour = bcdToDec(buf[2] & 0x3F);
|
|
||||||
time->day = bcdToDec(buf[3] & 0x3F);
|
|
||||||
time->dotw = bcdToDec(buf[4] & 0x07);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t decToBcd(int val) // Convert normal decimal numbers to binary coded decimal
|
|
||||||
{
|
|
||||||
return (uint8_t)((val / 10 * 16) + (val % 10));
|
|
||||||
}
|
|
||||||
static int bcdToDec(uint8_t val) // Convert binary coded decimal to normal decimal numbers
|
|
||||||
{
|
|
||||||
return (int)((val / 16 * 10) + (val % 16));
|
|
||||||
}
|
|
||||||
void datetime_to_str(char *datetime_str,datetime_t time)
|
|
||||||
{
|
|
||||||
sprintf(datetime_str, " %d.%d.%d %d:%d:%d %s", time.year, time.month,
|
|
||||||
time.day, time.hour, time.minute, time.second, Week[time.dotw]);
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "I2C_Driver.h"
|
|
||||||
|
|
||||||
//PCF85063_ADDRESS
|
|
||||||
#define PCF85063_ADDRESS (0x51)
|
|
||||||
//
|
|
||||||
#define YEAR_OFFSET (1970)
|
|
||||||
// registar overview - crtl & status reg
|
|
||||||
#define RTC_CTRL_1_ADDR (0x00)
|
|
||||||
#define RTC_CTRL_2_ADDR (0x01)
|
|
||||||
#define RTC_OFFSET_ADDR (0x02)
|
|
||||||
#define RTC_RAM_by_ADDR (0x03)
|
|
||||||
// registar overview - time & data reg
|
|
||||||
#define RTC_SECOND_ADDR (0x04)
|
|
||||||
#define RTC_MINUTE_ADDR (0x05)
|
|
||||||
#define RTC_HOUR_ADDR (0x06)
|
|
||||||
#define RTC_DAY_ADDR (0x07)
|
|
||||||
#define RTC_WDAY_ADDR (0x08)
|
|
||||||
#define RTC_MONTH_ADDR (0x09)
|
|
||||||
#define RTC_YEAR_ADDR (0x0A) // years 0-99; calculate real year = 1970 + RCC reg year
|
|
||||||
// registar overview - alarm reg
|
|
||||||
#define RTC_SECOND_ALARM (0x0B)
|
|
||||||
#define RTC_MINUTE_ALARM (0x0C)
|
|
||||||
#define RTC_HOUR_ALARM (0x0D)
|
|
||||||
#define RTC_DAY_ALARM (0x0E)
|
|
||||||
#define RTC_WDAY_ALARM (0x0F)
|
|
||||||
// registar overview - timer reg
|
|
||||||
#define RTC_TIMER_VAL (0x10)
|
|
||||||
#define RTC_TIMER_MODE (0x11)
|
|
||||||
|
|
||||||
//RTC_CTRL_1 registar
|
|
||||||
#define RTC_CTRL_1_EXT_TEST (0x80)
|
|
||||||
#define RTC_CTRL_1_STOP (0x20) //0-RTC clock runs 1- RTC clock is stopped
|
|
||||||
#define RTC_CTRL_1_SR (0X10) //0-no software reset 1-initiate software rese
|
|
||||||
#define RTC_CTRL_1_CIE (0X04) //0-no correction interrupt generated 1-interrupt pulses are generated at every correction cycle
|
|
||||||
#define RTC_CTRL_1_12_24 (0X02) //0-24H 1-12H
|
|
||||||
#define RTC_CTRL_1_CAP_SEL (0X01) //0-7PF 1-12.5PF
|
|
||||||
|
|
||||||
//RTC_CTRL_2 registar
|
|
||||||
#define RTC_CTRL_2_AIE (0X80) //alarm interrupt 0-disalbe 1-enable
|
|
||||||
#define RTC_CTRL_2_AF (0X40) //alarm flag 0-inactive/cleared 1-active/unchanged
|
|
||||||
#define RTC_CTRL_2_MI (0X20) //minute interrupt 0-disalbe 1-enable
|
|
||||||
#define RTC_CTRL_2_HMI (0X10) //half minute interrupt
|
|
||||||
#define RTC_CTRL_2_TF (0X08)
|
|
||||||
|
|
||||||
//
|
|
||||||
#define RTC_OFFSET_MODE (0X80)
|
|
||||||
|
|
||||||
//
|
|
||||||
#define RTC_TIMER_MODE_TE (0X04) //timer enable 0-disalbe 1-enable
|
|
||||||
#define RTC_TIMER_MODE_TIE (0X02) //timer interrupt enable 0-disalbe 1-enable
|
|
||||||
#define RTC_TIMER_MODE_TI_TP (0X01) //timer interrupt mode 0-interrupt follows timer flag 1-interrupt generates a pulse
|
|
||||||
|
|
||||||
// format
|
|
||||||
#define RTC_ALARM (0x80) // set AEN_x registers
|
|
||||||
#define RTC_CTRL_1_DEFAULT (0x00)
|
|
||||||
#define RTC_CTRL_2_DEFAULT (0x00)
|
|
||||||
|
|
||||||
#define RTC_TIMER_FLAG (0x08)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t year;
|
|
||||||
uint8_t month;
|
|
||||||
uint8_t day;
|
|
||||||
uint8_t dotw;
|
|
||||||
uint8_t hour;
|
|
||||||
uint8_t minute;
|
|
||||||
uint8_t second;
|
|
||||||
}datetime_t;
|
|
||||||
|
|
||||||
|
|
||||||
const unsigned char MonthStr[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
|
|
||||||
const unsigned char Week[7][5] = {"SUN","Mon","Tues","Wed","Thur","Fri","Sat"};
|
|
||||||
|
|
||||||
extern datetime_t datetime;
|
|
||||||
void PCF85063_Init(void);
|
|
||||||
void PCF85063_Reset(void);
|
|
||||||
void PCF85063Task(void *parameter);
|
|
||||||
|
|
||||||
void PCF85063_Set_Time(datetime_t time);
|
|
||||||
void PCF85063_Set_Date(datetime_t date);
|
|
||||||
void PCF85063_Set_All(datetime_t time);
|
|
||||||
|
|
||||||
void PCF85063_Read_Time(datetime_t *time);
|
|
||||||
|
|
||||||
|
|
||||||
void PCF85063_Enable_Alarm(void);
|
|
||||||
uint8_t PCF85063_Get_Alarm_Flag();
|
|
||||||
void PCF85063_Set_Alarm(datetime_t time);
|
|
||||||
void PCF85063_Read_Alarm(datetime_t *time);
|
|
||||||
|
|
||||||
void datetime_to_str(char *datetime_str,datetime_t time);
|
|
||||||
|
|
||||||
|
|
||||||
// weekday format
|
|
||||||
// 0 - sunday
|
|
||||||
// 1 - monday
|
|
||||||
// 2 - tuesday
|
|
||||||
// 3 - wednesday
|
|
||||||
// 4 - thursday
|
|
||||||
// 5 - friday
|
|
||||||
// 6 - saturday
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
#include "WS_RS485.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
HardwareSerial lidarSerial(1); // Using serial port 1
|
|
||||||
uint8_t data[][8] = { // ESP32-S3-POE-ETH-8DI-8RO Control Command (RS485 receiving data)
|
|
||||||
{ 0x06, 0x05, 0x00, 0x01, 0x55, 0x00, 0xA2, 0xED }, // ESP32-S3-POE-ETH-8DI-8RO CH1 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x02, 0x55, 0x00, 0x52, 0xED }, // ESP32-S3-POE-ETH-8DI-8RO CH2 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x03, 0x55, 0x00, 0x03, 0x2D }, // ESP32-S3-POE-ETH-8DI-8RO CH3 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x04, 0x55, 0x00, 0xB2, 0xEC }, // ESP32-S3-POE-ETH-8DI-8RO CH4 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x05, 0x55, 0x00, 0xE3, 0x2C }, // ESP32-S3-POE-ETH-8DI-8RO CH5 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x06, 0x55, 0x00, 0x13, 0x2C }, // ESP32-S3-POE-ETH-8DI-8RO CH6 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x07, 0x55, 0x00, 0x42, 0xEC }, // ESP32-S3-POE-ETH-8DI-8RO CH7 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0x08, 0x55, 0x00, 0x72, 0xEF }, // ESP32-S3-POE-ETH-8DI-8RO CH8 Toggle
|
|
||||||
{ 0x06, 0x05, 0x00, 0xFF, 0xFF, 0x00, 0xBD, 0xBD }, // ESP32-S3-POE-ETH-8DI-8RO ALL ON
|
|
||||||
{ 0x06, 0x05, 0x00, 0xFF, 0x00, 0x00, 0xFC, 0x4D }, // ESP32-S3-POE-ETH-8DI-8RO ALL OFF
|
|
||||||
};
|
|
||||||
uint8_t Send_Data[][8] = { // Modbus RTU Relay Control Command (RS485 send data)
|
|
||||||
{ 0x01, 0x05, 0x00, 0x00, 0x55, 0x00, 0xF2, 0x9A }, // Modbus RTU Relay CH1 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x01, 0x55, 0x00, 0xA3, 0x5A }, // Modbus RTU Relay CH2 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x02, 0x55, 0x00, 0x53, 0x5A }, // Modbus RTU Relay CH3 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x03, 0x55, 0x00, 0x02, 0x9A }, // Modbus RTU Relay CH4 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x04, 0x55, 0x00, 0xB3, 0x5B }, // Modbus RTU Relay CH5 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x05, 0x55, 0x00, 0xE2, 0x9B }, // Modbus RTU Relay CH6 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x06, 0x55, 0x00, 0x12, 0x9B }, // Modbus RTU Relay CH7 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0x07, 0x55, 0x00, 0x43, 0x5B }, // Modbus RTU Relay CH8 Toggle
|
|
||||||
{ 0x01, 0x05, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x4A }, // Modbus RTU Relay ALL ON
|
|
||||||
{ 0x01, 0x05, 0x00, 0xFF, 0x00, 0x00, 0xFD, 0xFA }, // Modbus RTU Relay ALL OFF
|
|
||||||
};
|
|
||||||
uint8_t buf[20] = {0}; // Data storage area
|
|
||||||
int numRows = sizeof(data) / sizeof(data[0]);
|
|
||||||
|
|
||||||
void SetData(uint8_t* data, size_t length) {
|
|
||||||
lidarSerial.write(data, length); // Send data from the RS485
|
|
||||||
}
|
|
||||||
void ReadData(uint8_t* buf, uint8_t length) {
|
|
||||||
uint8_t Receive_Flag = 0;
|
|
||||||
Receive_Flag = lidarSerial.available();
|
|
||||||
if (Receive_Flag >= length) {
|
|
||||||
lidarSerial.readBytes(buf, length);
|
|
||||||
char printBuf[length * 3 + 1];
|
|
||||||
sprintf(printBuf, "Received data: ");
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
sprintf(printBuf + strlen(printBuf), "%02X ", buf[i]);
|
|
||||||
}
|
|
||||||
printf(printBuf);
|
|
||||||
/*************************
|
|
||||||
Add a receiving data handler
|
|
||||||
*************************/
|
|
||||||
Receive_Flag = 0;
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void RS485_Analysis(uint8_t *buf)
|
|
||||||
{
|
|
||||||
switch(buf[1])
|
|
||||||
{
|
|
||||||
case Extension_CH1:
|
|
||||||
SetData(Send_Data[0],sizeof(Send_Data[0]));
|
|
||||||
printf("|*** Toggle expansion channel 1 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH2:
|
|
||||||
SetData(Send_Data[1],sizeof(Send_Data[1]));
|
|
||||||
printf("|*** Toggle expansion channel 2 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH3:
|
|
||||||
SetData(Send_Data[2],sizeof(Send_Data[2]));
|
|
||||||
printf("|*** Toggle expansion channel 3 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH4:
|
|
||||||
SetData(Send_Data[3],sizeof(Send_Data[3]));
|
|
||||||
printf("|*** Toggle expansion channel 4 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH5:
|
|
||||||
SetData(Send_Data[4],sizeof(Send_Data[4]));
|
|
||||||
printf("|*** Toggle expansion channel 5 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH6:
|
|
||||||
SetData(Send_Data[5],sizeof(Send_Data[5]));
|
|
||||||
printf("|*** Toggle expansion channel 6 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH7:
|
|
||||||
SetData(Send_Data[6],sizeof(Send_Data[6]));
|
|
||||||
printf("|*** Toggle expansion channel 7 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_CH8:
|
|
||||||
SetData(Send_Data[7],sizeof(Send_Data[7]));
|
|
||||||
printf("|*** Toggle expansion channel 8 ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_ALL_ON:
|
|
||||||
SetData(Send_Data[8],sizeof(Send_Data[8]));
|
|
||||||
printf("|*** Enable all extension channels ***|\r\n");
|
|
||||||
break;
|
|
||||||
case Extension_ALL_OFF:
|
|
||||||
SetData(Send_Data[9],sizeof(Send_Data[9]));
|
|
||||||
printf("|*** Close all expansion channels ***|\r\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Note : Non-control external device instructions !\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t Baudrate = 0;
|
|
||||||
double transmission_time = 0;
|
|
||||||
double RS485_cmd_Time = 0;
|
|
||||||
void RS485_Init() // Initializing serial port
|
|
||||||
{
|
|
||||||
Baudrate = 9600; // Set the baud rate of the serial port
|
|
||||||
lidarSerial.begin(Baudrate, SERIAL_8N1, RXD1, TXD1); // Initializing serial port
|
|
||||||
transmission_time = 10.0 / Baudrate * 1000 ;
|
|
||||||
RS485_cmd_Time = transmission_time*8; // 8:data length
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
RS485Task,
|
|
||||||
"RS485Task",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RS485Task(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
RS485_Loop();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RS485_Loop()
|
|
||||||
{
|
|
||||||
uint8_t Receive_Flag = 0; // Receiving mark
|
|
||||||
Receive_Flag = lidarSerial.available();
|
|
||||||
|
|
||||||
if (Receive_Flag > 0) {
|
|
||||||
if(RS485_cmd_Time > 1) // Time greater than 1 millisecond
|
|
||||||
delay((uint16_t)RS485_cmd_Time);
|
|
||||||
else // Time is less than 1 millisecond
|
|
||||||
delay(1);
|
|
||||||
Receive_Flag = lidarSerial.available();
|
|
||||||
lidarSerial.readBytes(buf, Receive_Flag); // The Receive_Flag length is read
|
|
||||||
if(Receive_Flag == 8){
|
|
||||||
uint8_t i=0;
|
|
||||||
for(i=0;i<numRows;i++){
|
|
||||||
bool result = std::equal(std::begin(buf), std::begin(buf) + 8, std::begin(data[i])); // Compare two arrays
|
|
||||||
if(result){
|
|
||||||
if(i < numRows-1)
|
|
||||||
buf[0] = i+1+48;
|
|
||||||
else if(i == numRows-1)
|
|
||||||
buf[0] = 48;
|
|
||||||
Relay_Analysis(buf,RS485_Mode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(i > numRows-1)
|
|
||||||
printf("Note : Non-instruction data was received - RS485 !\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("Note : Non-instruction data was received .Number of bytes: %d - RS485 !\r\n",Receive_Flag);
|
|
||||||
}
|
|
||||||
Receive_Flag=0;
|
|
||||||
memset(buf,0, sizeof(buf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
#include "WS_Relay.h"
|
|
||||||
|
|
||||||
#define Extension_CH1 1 // Expansion Channel 1
|
|
||||||
#define Extension_CH2 2 // Expansion Channel 2
|
|
||||||
#define Extension_CH3 3 // Expansion Channel 3
|
|
||||||
#define Extension_CH4 4 // Expansion Channel 4
|
|
||||||
#define Extension_CH5 5 // Expansion Channel 5
|
|
||||||
#define Extension_CH6 6 // Expansion Channel 6
|
|
||||||
#define Extension_CH7 7 // Expansion Channel 7
|
|
||||||
#define Extension_CH8 8 // Expansion Channel 8
|
|
||||||
#define Extension_ALL_ON 9 // Expansion ALL ON
|
|
||||||
#define Extension_ALL_OFF 10 // Expansion ALL OFF
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SetData(uint8_t* data, size_t length); // Send data from the RS485
|
|
||||||
void ReadData(uint8_t* buf, uint8_t length); // Data is received over RS485
|
|
||||||
|
|
||||||
void RS485_Analysis(uint8_t *buf); // External relay control
|
|
||||||
void RS485_Init(); // Example Initialize the system serial port and RS485
|
|
||||||
void RS485_Loop(); // Read RS485 data, parse and control relays
|
|
||||||
void RS485Task(void *parameter);
|
|
||||||
-350
@@ -1,350 +0,0 @@
|
|||||||
#include "WS_RTC.h"
|
|
||||||
|
|
||||||
Timing_RTC CHx_State[Timing_events_Number_MAX]; // Set a maximum of Timing_events_Number_MAX timers
|
|
||||||
char Event_str[Timing_events_Number_MAX][1000];
|
|
||||||
static Timing_RTC CHx_State_Default; // Event initial state
|
|
||||||
const unsigned char Event_cycle[4][13] = {"Aperiodicity","everyday","Weekly","monthly"};
|
|
||||||
|
|
||||||
void RTC_Init(void){
|
|
||||||
PCF85063_Init();
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
RTCTask,
|
|
||||||
"RTCTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
uint8_t Timing_events_Num = 0;
|
|
||||||
void RTCTask(void *parameter)
|
|
||||||
{
|
|
||||||
static uint8_t Time_Old = 0;
|
|
||||||
while(1){
|
|
||||||
if(Timing_events_Num){
|
|
||||||
for (int i = 0; i < Timing_events_Number_MAX; i++){
|
|
||||||
if(CHx_State[i].Enable_Flag){
|
|
||||||
if(CHx_State[i].Time.hour == datetime.hour && CHx_State[i].Time.minute == datetime.minute && CHx_State[i].Time.second == datetime.second && datetime.second != Time_Old){ // The event time is consistent with the current time
|
|
||||||
switch(CHx_State[i].repetition_State){
|
|
||||||
case Repetition_NONE:
|
|
||||||
if(CHx_State[i].Time.year == datetime.year && CHx_State[i].Time.month == datetime.month && CHx_State[i].Time.day == datetime.day){ // Executes at the defined date and time
|
|
||||||
TimerEvent_handling(CHx_State[i]);
|
|
||||||
TimerEvent_Del(CHx_State[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Repetition_everyday:
|
|
||||||
TimerEvent_handling(CHx_State[i]);
|
|
||||||
break;
|
|
||||||
case Repetition_Weekly:
|
|
||||||
if(CHx_State[i].Time.dotw == datetime.dotw){
|
|
||||||
TimerEvent_handling(CHx_State[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Repetition_monthly:
|
|
||||||
if(CHx_State[i].Time.day == datetime.day){
|
|
||||||
TimerEvent_handling(CHx_State[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Event error!!!!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Time_Old = datetime.second;
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerEvent_handling(Timing_RTC event){
|
|
||||||
uint8_t Retain_channels = 0;
|
|
||||||
printf("Event %d : \r\n", event.Event_Number);
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,event.Time);
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if(*(&(event.Relay_CH1)+i) == STATE_Retain) // Find the modified channel
|
|
||||||
Retain_channels ++; // Number of unmodified channels
|
|
||||||
}
|
|
||||||
if(Retain_channels < Relay_Number_MAX - 1){
|
|
||||||
printf("%s\r\n", datetime_str);
|
|
||||||
printf("CHx Open : ");
|
|
||||||
int j = 0;
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(*(&(event.Relay_CH1)+j) == STATE_Open)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
printf("\r\nCHx Closs : ");
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(*(&(event.Relay_CH1)+j) == STATE_Closs)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
if(Retain_channels){
|
|
||||||
printf("\r\nCHx Retain : ");
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(*(&(event.Relay_CH1)+j) == STATE_Retain)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
Relay_Immediate_CHxn(&(event.Relay_CH1), RTC_Mode);
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
else if(Retain_channels == Relay_Number_MAX - 1){ // Modified a channel (use TimerEvent_CHx_Set())
|
|
||||||
printf("%s\r\n", datetime_str);
|
|
||||||
for (int x = 0; x < Relay_Number_MAX; x++) {
|
|
||||||
if(*(&(event.Relay_CH1)+x) != STATE_Retain){ // Find the modified channel
|
|
||||||
if(*(&(event.Relay_CH1)+x)){
|
|
||||||
printf("CH%d Open\r\n", x);
|
|
||||||
Relay_Immediate(x, true, RTC_Mode);
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("CH%d Closs\r\n", x);
|
|
||||||
Relay_Immediate(x, false, RTC_Mode);
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("Event error or no relay control!!!\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerEvent_CHx_Set(datetime_t time,uint8_t CHx, bool State, Repetition_event Repetition)
|
|
||||||
{
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,datetime);
|
|
||||||
printf("Now Time: %s!!!!\r\n", datetime_str);
|
|
||||||
if(CHx > Relay_Number_MAX){
|
|
||||||
printf("Timing_CHx_Set(function): Error passing parameter CHx!!!!\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(Timing_events_Num + 1 >= Timing_events_Number_MAX)
|
|
||||||
{
|
|
||||||
printf("Note : The number of scheduled events is full.\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
RGB_Open_Time(50, 36, 0, 1000, 0);
|
|
||||||
CHx_State[Timing_events_Num].Enable_Flag = true;
|
|
||||||
CHx_State[Timing_events_Num].Event_Number = Timing_events_Num + 1;
|
|
||||||
*(&(CHx_State[Timing_events_Num].Relay_CH1)+CHx) = (Status_adjustment)State;
|
|
||||||
CHx_State[Timing_events_Num].Time = time;
|
|
||||||
CHx_State[Timing_events_Num].repetition_State = Repetition;
|
|
||||||
Timing_events_Num ++;
|
|
||||||
datetime_to_str(datetime_str,time);
|
|
||||||
if(State){
|
|
||||||
printf("New timing event%d :\r\n %s set CH%d Open ----- %s\r\n\r\n", Timing_events_Num, datetime_str, CHx, Event_cycle[Repetition]);
|
|
||||||
sprintf(Event_str[Timing_events_Num-1], "Event %d : %s set CH%d Open ----- %s\\n\\n", Timing_events_Num, datetime_str, CHx, Event_cycle[Repetition]);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("New timing event%d :\r\n %s set CH%d Closs ----- %s\r\n\r\n", Timing_events_Num, datetime_str, CHx, Event_cycle[Repetition]);
|
|
||||||
sprintf(Event_str[Timing_events_Num-1], "Event %d : %s set CH%d Closs ----- %s\\n\\n", Timing_events_Num, datetime_str, CHx, Event_cycle[Repetition]);
|
|
||||||
}
|
|
||||||
Buzzer_Open_Time(700, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerEvent_CHxs_Set(datetime_t time,uint8_t PinState, Repetition_event Repetition)
|
|
||||||
{
|
|
||||||
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,datetime);
|
|
||||||
printf("Now Time: %s!!!!\r\n", datetime_str);
|
|
||||||
if(Timing_events_Num + 1 >= Timing_events_Number_MAX)
|
|
||||||
{
|
|
||||||
printf("Note : The number of scheduled events is full.\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
RGB_Open_Time(50, 36, 0, 1000, 0);
|
|
||||||
CHx_State[Timing_events_Num].Enable_Flag = true;
|
|
||||||
CHx_State[Timing_events_Num].Event_Number = Timing_events_Num + 1;
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
*(&(CHx_State[Timing_events_Num].Relay_CH1)+i) = (Status_adjustment)((PinState >> i) & 0x01);
|
|
||||||
}
|
|
||||||
CHx_State[Timing_events_Num].Time = time;
|
|
||||||
CHx_State[Timing_events_Num].repetition_State = Repetition;
|
|
||||||
Timing_events_Num ++;
|
|
||||||
datetime_to_str(datetime_str,time);
|
|
||||||
printf("New timing event%d :\r\n %s \r\n",Timing_events_Num, datetime_str);
|
|
||||||
printf(" CHx :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++)
|
|
||||||
printf("CH%d ", i+1);
|
|
||||||
printf("\r\n State :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if((PinState >> i) & 0x01)
|
|
||||||
printf("Open ");
|
|
||||||
else
|
|
||||||
printf("Closs ");
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
printf(" ----- %s\r\n\r\n", Event_cycle[Repetition]);
|
|
||||||
printf("\r\n");
|
|
||||||
Buzzer_Open_Time(700, 0);
|
|
||||||
|
|
||||||
int len = 0;
|
|
||||||
char Event_content[1000];
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, " CHx :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "CH%d ", i + 1);
|
|
||||||
}
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "\\n State :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if ((PinState >> i) & 0x01)
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "Open ");
|
|
||||||
else
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "Closs ");
|
|
||||||
}
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "\\n ----- %s\\n\\n", Event_cycle[Repetition]);
|
|
||||||
// printf("%s\r\n", Event_content);
|
|
||||||
sprintf(Event_str[Timing_events_Num-1], "Event %d : %s \\n%s", Timing_events_Num, datetime_str,Event_content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void TimerEvent_CHxn_Set(datetime_t time,Status_adjustment *Relay_n, Repetition_event Repetition)
|
|
||||||
{
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,datetime);
|
|
||||||
printf("Now Time: %s!!!!\r\n", datetime_str);
|
|
||||||
if(Timing_events_Num + 1 >= Timing_events_Number_MAX)
|
|
||||||
{
|
|
||||||
printf("Note : The number of scheduled events is full.\r\n");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
RGB_Open_Time(50, 36, 0, 1000, 0);
|
|
||||||
CHx_State[Timing_events_Num].Enable_Flag = true;
|
|
||||||
CHx_State[Timing_events_Num].Event_Number = Timing_events_Num + 1;
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
*(&(CHx_State[Timing_events_Num].Relay_CH1)+i) = Relay_n[i];
|
|
||||||
}
|
|
||||||
CHx_State[Timing_events_Num].Time = time;
|
|
||||||
CHx_State[Timing_events_Num].repetition_State = Repetition;
|
|
||||||
Timing_events_Num ++;
|
|
||||||
datetime_to_str(datetime_str,time);
|
|
||||||
printf("New timing event%d :\r\n %s \r\n",Timing_events_Num, datetime_str);
|
|
||||||
printf(" CHx :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++)
|
|
||||||
printf("CH%d ", i+1);
|
|
||||||
printf("\r\n State :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if(Relay_n[i] == STATE_Open)
|
|
||||||
printf("Open ");
|
|
||||||
else if(Relay_n[i] == STATE_Closs)
|
|
||||||
printf("Closs ");
|
|
||||||
else if(Relay_n[i] == STATE_Retain)
|
|
||||||
printf("Retain ");
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
printf(" ----- %s\r\n\r\n", Event_cycle[Repetition]);
|
|
||||||
printf("\r\n");
|
|
||||||
Buzzer_Open_Time(700, 0);
|
|
||||||
|
|
||||||
int len = 0;
|
|
||||||
char Event_content[1000];
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, " CHx :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "CH%d ", i + 1);
|
|
||||||
}
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "\\n State :");
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if (Relay_n[i] == STATE_Open)
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "Open ");
|
|
||||||
else if(Relay_n[i] == STATE_Closs)
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "Closs ");
|
|
||||||
else if(Relay_n[i] == STATE_Retain)
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "Retain ");
|
|
||||||
}
|
|
||||||
len += snprintf(Event_content + len, sizeof(Event_content) - len, "\\n ----- %s\\n\\n", Event_cycle[Repetition]);
|
|
||||||
// printf("%s\r\n", Event_content);
|
|
||||||
sprintf(Event_str[Timing_events_Num-1], "Event %d : %s \\n%s", Timing_events_Num, datetime_str,Event_content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerEvent_printf(Timing_RTC event){
|
|
||||||
uint8_t Retain_channels = 0;
|
|
||||||
uint8_t open[8]={0};
|
|
||||||
printf("Event %d : \r\n", event.Event_Number);
|
|
||||||
char datetime_str[50];
|
|
||||||
datetime_to_str(datetime_str,event.Time);
|
|
||||||
for (int i = 0; i < Relay_Number_MAX; i++) {
|
|
||||||
if(*(&(event.Relay_CH1)+i) == STATE_Retain) // Find the modified channel
|
|
||||||
Retain_channels ++; // Number of unmodified channels
|
|
||||||
else
|
|
||||||
open[i] = *(&(event.Relay_CH1)+i);
|
|
||||||
}
|
|
||||||
if(Retain_channels == 0){ // All channels have been modified (use TimerEvent_CHxs_Set())
|
|
||||||
printf("%s\r\n", datetime_str);
|
|
||||||
printf(" CHx Open : ");
|
|
||||||
for (int j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(open[j])
|
|
||||||
printf("CH%d ", j);
|
|
||||||
}
|
|
||||||
printf("\r\n CHx Closs : ");
|
|
||||||
for (int k = 0; k < Relay_Number_MAX; k++) {
|
|
||||||
if(!open[k])
|
|
||||||
printf("CH%d ", k);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
else if(Retain_channels == Relay_Number_MAX - 1){ // Modified a channel (use TimerEvent_CHx_Set())
|
|
||||||
printf("%s ,", datetime_str);
|
|
||||||
for (int x = 0; x < Relay_Number_MAX; x++) {
|
|
||||||
if(*(&(event.Relay_CH1)+x) != STATE_Retain){ // Find the modified channel
|
|
||||||
if(*(&(event.Relay_CH1)+x))
|
|
||||||
printf("CH%d Open\r\n", x);
|
|
||||||
else
|
|
||||||
printf("CH%d Closs\r\n", x);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("%s\r\n", datetime_str);
|
|
||||||
printf("CHx Open : ");
|
|
||||||
int j = 0;
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(open[j] == STATE_Open)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
printf("\r\nCHx Closs : ");
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(open[j] == STATE_Closs)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
printf("\r\nCHx Retain : ");
|
|
||||||
for (j = 0; j < Relay_Number_MAX; j++) {
|
|
||||||
if(open[j] == STATE_Retain)
|
|
||||||
printf("CH%d ", j+1);
|
|
||||||
}
|
|
||||||
printf("\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerEvent_printf_ALL(void)
|
|
||||||
{
|
|
||||||
printf("/******************* Current RTC event *******************/ \r\n");
|
|
||||||
for (int i = 0; i < Timing_events_Number_MAX; i++) {
|
|
||||||
if(CHx_State[i].Enable_Flag)
|
|
||||||
TimerEvent_printf(CHx_State[i]);
|
|
||||||
}
|
|
||||||
printf("/******************* Current RTC event *******************/\r\n\r\n ");
|
|
||||||
}
|
|
||||||
void TimerEvent_Del(Timing_RTC event){
|
|
||||||
RGB_Open_Time(20, 0, 50, 1000, 0);
|
|
||||||
printf("Example Delete an RTC event%d\r\n\r\n",event.Event_Number);
|
|
||||||
for (int i = event.Event_Number; i < Timing_events_Number_MAX; i++) {
|
|
||||||
CHx_State[i].Event_Number = CHx_State[i].Event_Number -1;
|
|
||||||
CHx_State[i-1] = CHx_State[i];
|
|
||||||
}
|
|
||||||
CHx_State[Timing_events_Number_MAX - 1] = CHx_State_Default;
|
|
||||||
memset(Event_str[Timing_events_Number_MAX - 1], 0, sizeof(Event_str[Timing_events_Number_MAX - 1]));
|
|
||||||
Timing_events_Num --;
|
|
||||||
}
|
|
||||||
void TimerEvent_Del_Number(uint8_t Event_Number){
|
|
||||||
TimerEvent_Del(CHx_State[Event_Number - 1]);
|
|
||||||
Buzzer_Open_Time(700, 300);
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WS_PCF85063.h"
|
|
||||||
#include "WS_Relay.h"
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
|
|
||||||
#define Timing_events_Number_MAX 10 // Indicates the number of timers that can be set
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Repetition_NONE = 0, // aperiodicity
|
|
||||||
Repetition_everyday = 1, // The event is repeated at this time every day
|
|
||||||
Repetition_Weekly = 2, // This event is repeated every week at this time
|
|
||||||
Repetition_monthly = 3, // This event is repeated every month at this time
|
|
||||||
} Repetition_event;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool Enable_Flag = false; // The timer event enabled flag.
|
|
||||||
uint8_t Event_Number = 0; // Current event sequence number
|
|
||||||
Status_adjustment Relay_CH1 = STATE_Retain; // The CH1 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH2 = STATE_Retain; // The CH2 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH3 = STATE_Retain; // The CH3 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH4 = STATE_Retain; // The CH4 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH5 = STATE_Retain; // The CH5 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH6 = STATE_Retain; // The CH6 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH7 = STATE_Retain; // The CH7 status is changed periodically
|
|
||||||
Status_adjustment Relay_CH8 = STATE_Retain; // The CH8 status is changed periodically
|
|
||||||
datetime_t Time;
|
|
||||||
Repetition_event repetition_State = Repetition_NONE; // Periodic execution
|
|
||||||
}Timing_RTC;
|
|
||||||
|
|
||||||
extern uint8_t Timing_events_Num;
|
|
||||||
extern Timing_RTC CHx_State[Timing_events_Number_MAX];
|
|
||||||
extern char Event_str[Timing_events_Number_MAX][1000];
|
|
||||||
|
|
||||||
void RTCTask(void *parameter);
|
|
||||||
void TimerEvent_handling(Timing_RTC event);
|
|
||||||
void TimerEvent_printf(Timing_RTC event);
|
|
||||||
void TimerEvent_Del(Timing_RTC event);
|
|
||||||
|
|
||||||
void RTC_Init(void);
|
|
||||||
void TimerEvent_CHx_Set(datetime_t time,uint8_t CHx, bool State, Repetition_event Repetition);
|
|
||||||
void TimerEvent_CHxs_Set(datetime_t time,uint8_t PinState, Repetition_event Repetition);
|
|
||||||
void TimerEvent_CHxn_Set(datetime_t time,Status_adjustment *Relay_n, Repetition_event Repetition);
|
|
||||||
void TimerEvent_printf_ALL(void);
|
|
||||||
void TimerEvent_Del_Number(uint8_t Event_Number);
|
|
||||||
@@ -1,273 +0,0 @@
|
|||||||
#include "WS_Relay.h"
|
|
||||||
|
|
||||||
bool Failure_Flag = 0;
|
|
||||||
/************************************************************* Relay I/O *************************************************************/
|
|
||||||
bool Relay_Open(uint8_t CHx)
|
|
||||||
{
|
|
||||||
if(!Set_EXIO(CHx, true)){
|
|
||||||
printf("Failed to Open CH%d!!!\r\n", CHx);
|
|
||||||
Failure_Flag = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
bool Relay_Closs(uint8_t CHx)
|
|
||||||
{
|
|
||||||
if(!Set_EXIO(CHx, false)){
|
|
||||||
printf("Failed to Closs CH%d!!!\r\n", CHx);
|
|
||||||
Failure_Flag = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
bool Relay_CHx_Toggle(uint8_t CHx)
|
|
||||||
{
|
|
||||||
if(!Set_Toggle(CHx)){
|
|
||||||
printf("Failed to Toggle CH%d!!!\r\n", CHx);
|
|
||||||
Failure_Flag = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
bool Relay_CHx(uint8_t CHx, bool State)
|
|
||||||
{
|
|
||||||
bool result = 0;
|
|
||||||
if(State)
|
|
||||||
result = Relay_Open(CHx);
|
|
||||||
else
|
|
||||||
result = Relay_Closs(CHx);
|
|
||||||
if(!result)
|
|
||||||
Failure_Flag = 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
bool Relay_CHxs_PinState(uint8_t PinState)
|
|
||||||
{
|
|
||||||
if(!Set_EXIOS(PinState)){
|
|
||||||
printf("Failed to set the relay status!!!\r\n");
|
|
||||||
Failure_Flag = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RelayFailTask(void *parameter) {
|
|
||||||
while(1){
|
|
||||||
if(Failure_Flag)
|
|
||||||
{
|
|
||||||
Failure_Flag = 0;
|
|
||||||
printf("Error: Relay control failed!!!\r\n");
|
|
||||||
RGB_Open_Time(60,0,0,5000,500);
|
|
||||||
Buzzer_Open_Time(5000, 500);
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
|
||||||
}
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
void Relay_Init(void)
|
|
||||||
{
|
|
||||||
TCA9554PWR_Init(0x00);
|
|
||||||
xTaskCreatePinnedToCore(
|
|
||||||
RelayFailTask,
|
|
||||||
"RelayFailTask",
|
|
||||||
4096,
|
|
||||||
NULL,
|
|
||||||
3,
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************** Data Analysis ********************************************************/
|
|
||||||
bool Relay_Flag[8] = {0}; // Relay current status flag
|
|
||||||
void Relay_Analysis(uint8_t *buf,uint8_t Mode_Flag)
|
|
||||||
{
|
|
||||||
uint8_t ret = 0;
|
|
||||||
if(Mode_Flag == Bluetooth_Mode)
|
|
||||||
printf("Bluetooth Data :\r\n");
|
|
||||||
else if(Mode_Flag == WIFI_Mode)
|
|
||||||
printf("WIFI Data :\r\n");
|
|
||||||
else if(Mode_Flag == MQTT_Mode)
|
|
||||||
printf("MQTT Data :\r\n");
|
|
||||||
else if(Mode_Flag == RS485_Mode)
|
|
||||||
printf("RS485 Data :\r\n");
|
|
||||||
switch(buf[0])
|
|
||||||
{
|
|
||||||
case CH1:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH1); //Toggle the level status of the GPIO_PIN_CH1 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[0] =! Relay_Flag[0];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[0])
|
|
||||||
printf("|*** Relay CH1 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH1 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH2:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH2); //Toggle the level status of the GPIO_PIN_CH2 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[1] =! Relay_Flag[1];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[1])
|
|
||||||
printf("|*** Relay CH2 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH2 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH3:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH3); //Toggle the level status of the GPIO_PIN_CH3 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[2] =! Relay_Flag[2];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[2])
|
|
||||||
printf("|*** Relay CH3 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH3 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH4:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH4); //Toggle the level status of the GPIO_PIN_CH4 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[3] =! Relay_Flag[3];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[3])
|
|
||||||
printf("|*** Relay CH4 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH4 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH5:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH5); //Toggle the level status of the GPIO_PIN_CH5 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[4] =! Relay_Flag[4];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[4])
|
|
||||||
printf("|*** Relay CH5 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH5 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH6:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH6); //Toggle the level status of the GPIO_PIN_CH6 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[5] =! Relay_Flag[5];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[5])
|
|
||||||
printf("|*** Relay CH6 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH6 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH7:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH7); //Toggle the level status of the GPIO_PIN_CH6 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[6] =! Relay_Flag[6];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[6])
|
|
||||||
printf("|*** Relay CH7 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH7 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CH8:
|
|
||||||
ret = Relay_CHx_Toggle(GPIO_PIN_CH8); //Toggle the level status of the GPIO_PIN_CH6 pin
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[7] =! Relay_Flag[7];
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[7])
|
|
||||||
printf("|*** Relay CH8 on ***|\r\n");
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH8 off ***|\r\n");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ALL_ON:
|
|
||||||
ret = Relay_CHxs_PinState(0xFF); // Turn on all relay
|
|
||||||
if(ret){
|
|
||||||
memset(Relay_Flag,1, sizeof(Relay_Flag));
|
|
||||||
printf("|*** Relay ALL on ***|\r\n");
|
|
||||||
Buzzer_Open_Time(500, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ALL_OFF:
|
|
||||||
ret = Relay_CHxs_PinState(0x00); // Turn off all relay
|
|
||||||
if(ret){
|
|
||||||
memset(Relay_Flag,0, sizeof(Relay_Flag));
|
|
||||||
printf("|*** Relay ALL off ***|\r\n");
|
|
||||||
Buzzer_Open_Time(500, 150);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("Note : Non-instruction data was received ! - %c\r\n", buf[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relay_Immediate(uint8_t CHx, bool State, uint8_t Mode_Flag)
|
|
||||||
{
|
|
||||||
if(!CHx || CHx > 8){
|
|
||||||
printf("Relay_Immediate(function): Incoming parameter error!!!!\r\n");
|
|
||||||
Failure_Flag = 1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
uint8_t ret = 0;
|
|
||||||
if(Mode_Flag == DIN_Mode)
|
|
||||||
printf("DIN Data :\r\n");
|
|
||||||
else if(Mode_Flag == RTC_Mode)
|
|
||||||
printf("RTC Data :\r\n");
|
|
||||||
ret = Relay_CHx(CHx,State);
|
|
||||||
if(ret){
|
|
||||||
Relay_Flag[CHx-1] = State;
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
if(Relay_Flag[0])
|
|
||||||
printf("|*** Relay CH%d on ***|\r\n",CHx);
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH%d off ***|\r\n",CHx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Relay_Immediate_CHxn(Status_adjustment * Relay_n, uint8_t Mode_Flag)
|
|
||||||
{
|
|
||||||
uint8_t ret = 0;
|
|
||||||
if(Mode_Flag == DIN_Mode)
|
|
||||||
printf("DIN Data :\r\n");
|
|
||||||
else if(Mode_Flag == RTC_Mode)
|
|
||||||
printf("RTC Data :\r\n");
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
if(Relay_n[i] == STATE_Open || Relay_n[i] == STATE_Closs){
|
|
||||||
Relay_Flag[i] = (bool)Relay_n[i];
|
|
||||||
ret = Relay_CHx(i+1,Relay_n[i]);
|
|
||||||
if(Relay_n[i] == STATE_Open)
|
|
||||||
printf("|*** Relay CH%d on ***|\r\n",i+1);
|
|
||||||
else if(Relay_n[i] == STATE_Closs)
|
|
||||||
printf("|*** Relay CH%d off ***|\r\n",i+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Relay_Immediate_CHxs(uint8_t PinState, uint8_t Mode_Flag)
|
|
||||||
{
|
|
||||||
uint8_t ret = 0;
|
|
||||||
if(Mode_Flag == DIN_Mode)
|
|
||||||
printf("DIN Data :\r\n");
|
|
||||||
else if(Mode_Flag == RTC_Mode)
|
|
||||||
printf("RTC Data :\r\n");
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
Relay_Flag[i] = (PinState >> i) & 0x01; // 提取每一位并赋值
|
|
||||||
}
|
|
||||||
ret = Relay_CHxs_PinState(PinState);
|
|
||||||
if(ret){
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
if(Relay_Flag[j])
|
|
||||||
printf("|*** Relay CH%d on ***|\r\n",j+1);
|
|
||||||
else
|
|
||||||
printf("|*** Relay CH%d off ***|\r\n",j+1);
|
|
||||||
}
|
|
||||||
Buzzer_Open_Time(200, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Relay_Immediate_CHxs(function): Relay control failure!!!!\r\n");
|
|
||||||
Failure_Flag = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WS_TCA9554PWR.h"
|
|
||||||
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
|
|
||||||
#include "WS_GPIO.h"
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************* I/O *************************************************************/
|
|
||||||
#define Relay_Number_MAX 8
|
|
||||||
#define GPIO_PIN_CH1 EXIO_PIN1 // CH1 Control GPIO
|
|
||||||
#define GPIO_PIN_CH2 EXIO_PIN2 // CH2 Control GPIO
|
|
||||||
#define GPIO_PIN_CH3 EXIO_PIN3 // CH3 Control GPIO
|
|
||||||
#define GPIO_PIN_CH4 EXIO_PIN4 // CH4 Control GPIO
|
|
||||||
#define GPIO_PIN_CH5 EXIO_PIN5 // CH5 Control GPIO
|
|
||||||
#define GPIO_PIN_CH6 EXIO_PIN6 // CH6 Control GPIO
|
|
||||||
#define GPIO_PIN_CH7 EXIO_PIN7 // CH7 Control GPIO
|
|
||||||
#define GPIO_PIN_CH8 EXIO_PIN8 // CH8 Control GPIO
|
|
||||||
|
|
||||||
|
|
||||||
#define CH1 '1' // CH1 Enabled Instruction Hex : 0x31
|
|
||||||
#define CH2 '2' // CH2 Enabled Instruction Hex : 0x32
|
|
||||||
#define CH3 '3' // CH3 Enabled Instruction Hex : 0x33
|
|
||||||
#define CH4 '4' // CH4 Enabled Instruction Hex : 0x34
|
|
||||||
#define CH5 '5' // CH5 Enabled Instruction Hex : 0x35
|
|
||||||
#define CH6 '6' // CH6 Enabled Instruction Hex : 0x36
|
|
||||||
#define CH7 '7' // CH5 Enabled Instruction Hex : 0x37
|
|
||||||
#define CH8 '8' // CH6 Enabled Instruction Hex : 0x38
|
|
||||||
#define ALL_ON '9' // Start all channel instructions Hex : 0x39
|
|
||||||
#define ALL_OFF '0' // Disable all channel instructions Hex : 0x30
|
|
||||||
|
|
||||||
#define DIN_Mode 1
|
|
||||||
#define RS485_Mode 2 // Used to distinguish data sources
|
|
||||||
#define Bluetooth_Mode 3
|
|
||||||
#define WIFI_Mode 4
|
|
||||||
#define MQTT_Mode 5
|
|
||||||
#define RTC_Mode 6
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
STATE_Closs = 0, // Closs Relay
|
|
||||||
STATE_Open = 1, // Open Relay
|
|
||||||
STATE_Retain = 2, // Stay in place
|
|
||||||
} Status_adjustment;
|
|
||||||
|
|
||||||
extern bool Relay_Flag[8]; // Relay current status flag
|
|
||||||
|
|
||||||
void Relay_Init(void);
|
|
||||||
bool Relay_Closs(uint8_t CHx);
|
|
||||||
bool Relay_Open(uint8_t CHx);
|
|
||||||
bool Relay_CHx_Toggle(uint8_t CHx);
|
|
||||||
bool Relay_CHx(uint8_t CHx, bool State);
|
|
||||||
bool Relay_CHxs_PinState(uint8_t PinState);
|
|
||||||
|
|
||||||
void Relay_Analysis(uint8_t *buf,uint8_t Mode_Flag);
|
|
||||||
void Relay_Immediate(uint8_t CHx, bool State, uint8_t Mode_Flag);
|
|
||||||
void Relay_Immediate_CHxs(uint8_t PinState, uint8_t Mode_Flag);
|
|
||||||
void Relay_Immediate_CHxn(Status_adjustment * Relay_n, uint8_t Mode_Flag);
|
|
||||||
-113
@@ -1,113 +0,0 @@
|
|||||||
#include "WS_SD.h"
|
|
||||||
|
|
||||||
bool SDCard_Flag = 0;
|
|
||||||
bool SDCard_Finish = 0;
|
|
||||||
|
|
||||||
uint16_t SDCard_Size = 0;
|
|
||||||
uint16_t Flash_Size = 0;
|
|
||||||
|
|
||||||
void SD_Init() {
|
|
||||||
// SD MMC
|
|
||||||
if(!SD_MMC.setPins(SD_CLK_PIN, SD_CMD_PIN, SD_D0_PIN,-1,-1,-1)){
|
|
||||||
printf("SD MMC: Pin change failed!\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (SD_MMC.begin("/sdcard", true, true)) { // "/sdcard", true, true or "/sdcard", true, false
|
|
||||||
printf("SD card initialization successful!\r\n");
|
|
||||||
} else {
|
|
||||||
printf("SD card initialization failed!\r\n");
|
|
||||||
}
|
|
||||||
uint8_t cardType = SD_MMC.cardType();
|
|
||||||
if(cardType == CARD_NONE){
|
|
||||||
printf("No SD card attached\r\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
printf("SD Card Type: ");
|
|
||||||
if(cardType == CARD_MMC){
|
|
||||||
printf("MMC\r\n");
|
|
||||||
} else if(cardType == CARD_SD){
|
|
||||||
printf("SDSC\r\n");
|
|
||||||
} else if(cardType == CARD_SDHC){
|
|
||||||
printf("SDHC\r\n");
|
|
||||||
} else {
|
|
||||||
printf("UNKNOWN\r\n");
|
|
||||||
}
|
|
||||||
uint64_t totalBytes = SD_MMC.totalBytes();
|
|
||||||
uint64_t usedBytes = SD_MMC.usedBytes();
|
|
||||||
SDCard_Size = totalBytes/(1024*1024);
|
|
||||||
printf("Total space: %llu\n", totalBytes);
|
|
||||||
printf("Used space: %llu\n", usedBytes);
|
|
||||||
printf("Free space: %llu\n", totalBytes - usedBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool File_Search(const char* directory, const char* fileName)
|
|
||||||
{
|
|
||||||
File Path = SD_MMC.open(directory);
|
|
||||||
if (!Path) {
|
|
||||||
printf("Path: <%s> does not exist\r\n",directory);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
File file = Path.openNextFile();
|
|
||||||
while (file) {
|
|
||||||
if (strcmp(file.name(), fileName) == 0) {
|
|
||||||
if (strcmp(directory, "/") == 0)
|
|
||||||
printf("File '%s%s' found in root directory.\r\n",directory,fileName);
|
|
||||||
else
|
|
||||||
printf("File '%s/%s' found in root directory.\r\n",directory,fileName);
|
|
||||||
Path.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
file = Path.openNextFile();
|
|
||||||
}
|
|
||||||
if (strcmp(directory, "/") == 0)
|
|
||||||
printf("File '%s%s' not found in root directory.\r\n",directory,fileName);
|
|
||||||
else
|
|
||||||
printf("File '%s/%s' not found in root directory.\r\n",directory,fileName);
|
|
||||||
Path.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint16_t Folder_retrieval(const char* directory, const char* fileExtension, char File_Name[][100],uint16_t maxFiles)
|
|
||||||
{
|
|
||||||
File Path = SD_MMC.open(directory);
|
|
||||||
if (!Path) {
|
|
||||||
printf("Path: <%s> does not exist\r\n",directory);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t fileCount = 0;
|
|
||||||
char filePath[100];
|
|
||||||
File file = Path.openNextFile();
|
|
||||||
while (file && fileCount < maxFiles) {
|
|
||||||
if (!file.isDirectory() && strstr(file.name(), fileExtension)) {
|
|
||||||
strncpy(File_Name[fileCount], file.name(), sizeof(File_Name[fileCount]));
|
|
||||||
if (strcmp(directory, "/") == 0) {
|
|
||||||
snprintf(filePath, 100, "%s%s", directory, file.name());
|
|
||||||
} else {
|
|
||||||
snprintf(filePath, 100, "%s/%s", directory, file.name());
|
|
||||||
}
|
|
||||||
printf("File found: %s\r\n", filePath);
|
|
||||||
fileCount++;
|
|
||||||
}
|
|
||||||
file = Path.openNextFile();
|
|
||||||
}
|
|
||||||
Path.close();
|
|
||||||
if (fileCount > 0) {
|
|
||||||
printf("Retrieved %d mp3 files\r\n",fileCount);
|
|
||||||
return fileCount;
|
|
||||||
} else {
|
|
||||||
printf("No files with extension '%s' found in directory: %s\r\n", fileExtension, directory);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Flash_test()
|
|
||||||
{
|
|
||||||
printf("/********** RAM Test**********/\r\n");
|
|
||||||
// Get Flash size
|
|
||||||
uint32_t flashSize = ESP.getFlashChipSize();
|
|
||||||
Flash_Size = flashSize/1024/1024;
|
|
||||||
printf("Flash size: %d MB \r\n", flashSize/1024/1024);
|
|
||||||
|
|
||||||
printf("/******* RAM Test Over********/\r\n\r\n");
|
|
||||||
}
|
|
||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include <cstring>
|
|
||||||
#include "FS.h"
|
|
||||||
#include "SD_MMC.h"
|
|
||||||
|
|
||||||
#define SD_CLK_PIN 48
|
|
||||||
#define SD_CMD_PIN 47
|
|
||||||
#define SD_D0_PIN 45
|
|
||||||
|
|
||||||
extern uint16_t SDCard_Size;
|
|
||||||
extern uint16_t Flash_Size;
|
|
||||||
|
|
||||||
void SD_Init();
|
|
||||||
void Flash_test();
|
|
||||||
|
|
||||||
bool File_Search(const char* directory, const char* fileName);
|
|
||||||
uint16_t Folder_retrieval(const char* directory, const char* fileExtension, char File_Name[][100],uint16_t maxFiles);
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#include "WS_Serial.h"
|
|
||||||
void Serial_Init()
|
|
||||||
{
|
|
||||||
if(RS485_CAN_Enable)
|
|
||||||
RS485_Init();
|
|
||||||
else
|
|
||||||
CAN_Init();
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WS_Information.h"
|
|
||||||
#include "WS_RS485.h"
|
|
||||||
#include "WS_CAN.h"
|
|
||||||
|
|
||||||
void Serial_Init(); // Example Initialize the system serial port and RS485
|
|
||||||
void Serial_Loop(); // Read RS485 data, parse and control relays
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#include "WS_TCA9554PWR.h"
|
|
||||||
|
|
||||||
/***************************************************** Operation register REG ****************************************************/
|
|
||||||
uint8_t Read_REG(uint8_t REG) // Read the value of the TCA9554PWR register REG
|
|
||||||
{
|
|
||||||
Wire.beginTransmission(TCA9554_ADDRESS);
|
|
||||||
Wire.write(REG);
|
|
||||||
uint8_t result = Wire.endTransmission();
|
|
||||||
if (result != 0) {
|
|
||||||
printf("Data Transfer Failure !!!\r\n");
|
|
||||||
}
|
|
||||||
Wire.requestFrom(TCA9554_ADDRESS, 1);
|
|
||||||
uint8_t bitsStatus = Wire.read();
|
|
||||||
return bitsStatus;
|
|
||||||
}
|
|
||||||
uint8_t Write_REG(uint8_t REG,uint8_t Data) // Write Data to the REG register of the TCA9554PWR
|
|
||||||
{
|
|
||||||
Wire.beginTransmission(TCA9554_ADDRESS);
|
|
||||||
Wire.write(REG);
|
|
||||||
Wire.write(Data);
|
|
||||||
uint8_t result = Wire.endTransmission();
|
|
||||||
if (result != 0) {
|
|
||||||
printf("Data write failure!!!\r\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/********************************************************** Set EXIO mode **********************************************************/
|
|
||||||
void Mode_EXIO(uint8_t Pin,uint8_t State) // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
|
|
||||||
{
|
|
||||||
uint8_t bitsStatus = Read_REG(TCA9554_CONFIG_REG);
|
|
||||||
uint8_t Data = (0x01 << (Pin-1)) | bitsStatus;
|
|
||||||
uint8_t result = Write_REG(TCA9554_CONFIG_REG,Data);
|
|
||||||
if (result != 0) {
|
|
||||||
printf("I/O Configuration Failure !!!\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Mode_EXIOS(uint8_t PinState) // Set the mode of the 7 pins from the TCA9554PWR with PinState
|
|
||||||
{
|
|
||||||
uint8_t result = Write_REG(TCA9554_CONFIG_REG,PinState);
|
|
||||||
if (result != 0) {
|
|
||||||
printf("I/O Configuration Failure !!!\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/********************************************************** Read EXIO status **********************************************************/
|
|
||||||
uint8_t Read_EXIO(uint8_t Pin) // Read the level of the TCA9554PWR Pin
|
|
||||||
{
|
|
||||||
uint8_t inputBits = Read_REG(TCA9554_INPUT_REG);
|
|
||||||
uint8_t bitStatus = (inputBits >> (Pin-1)) & 0x01;
|
|
||||||
return bitStatus;
|
|
||||||
}
|
|
||||||
uint8_t Read_EXIOS(uint8_t REG = TCA9554_INPUT_REG) // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
|
|
||||||
{
|
|
||||||
uint8_t inputBits = Read_REG(REG);
|
|
||||||
return inputBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************** Set the EXIO output status **********************************************************/
|
|
||||||
bool Set_EXIO(uint8_t Pin,uint8_t State) // Sets the level state of the Pin without affecting the other pins
|
|
||||||
{
|
|
||||||
uint8_t Data;
|
|
||||||
if(State < 2 && Pin < 9 && Pin > 0){
|
|
||||||
uint8_t bitsStatus = Read_EXIOS(TCA9554_OUTPUT_REG);
|
|
||||||
if(State == 1)
|
|
||||||
Data = (0x01 << (Pin-1)) | bitsStatus;
|
|
||||||
else if(State == 0)
|
|
||||||
Data = (~(0x01 << (Pin-1))) & bitsStatus;
|
|
||||||
uint8_t result = Write_REG(TCA9554_OUTPUT_REG,Data);
|
|
||||||
if (result != 0) {
|
|
||||||
printf("Failed to set GPIO!!!\r\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Parameter error, please enter the correct parameter!\r\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool Set_EXIOS(uint8_t PinState) // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
|
|
||||||
{
|
|
||||||
uint8_t result = Write_REG(TCA9554_OUTPUT_REG,PinState);
|
|
||||||
if (result != 0) {
|
|
||||||
printf("Failed to set GPIO!!!\r\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/********************************************************** Flip EXIO state **********************************************************/
|
|
||||||
bool Set_Toggle(uint8_t Pin) // Flip the level of the TCA9554PWR Pin
|
|
||||||
{
|
|
||||||
uint8_t bitsStatus = Read_EXIO(Pin);
|
|
||||||
uint8_t result = Set_EXIO(Pin,(bool)!bitsStatus);
|
|
||||||
if (!result) {
|
|
||||||
printf("Failed to Toggle GPIO!!!\r\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
|
|
||||||
void TCA9554PWR_Init(uint8_t PinMode, uint8_t PinState) // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
|
|
||||||
{
|
|
||||||
Set_EXIOS(PinState);
|
|
||||||
Mode_EXIOS(PinMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "I2C_Driver.h"
|
|
||||||
|
|
||||||
/****************************************************** The macro defines the TCA9554PWR information ******************************************************/
|
|
||||||
|
|
||||||
#define TCA9554_ADDRESS 0x20 // TCA9554PWR I2C address
|
|
||||||
#define TCA9554_INPUT_REG 0x00 // Input register,input level
|
|
||||||
#define TCA9554_OUTPUT_REG 0x01 // Output register, high and low level output
|
|
||||||
#define TCA9554_Polarity_REG 0x02 // The Polarity Inversion register (register 2) allows polarity inversion of pins defined as inputs by the Configuration register.
|
|
||||||
#define TCA9554_CONFIG_REG 0x03 // Configuration register, mode configuration
|
|
||||||
|
|
||||||
|
|
||||||
#define Low 0
|
|
||||||
#define High 1
|
|
||||||
#define EXIO_PIN1 1
|
|
||||||
#define EXIO_PIN2 2
|
|
||||||
#define EXIO_PIN3 3
|
|
||||||
#define EXIO_PIN4 4
|
|
||||||
#define EXIO_PIN5 5
|
|
||||||
#define EXIO_PIN6 6
|
|
||||||
#define EXIO_PIN7 7
|
|
||||||
#define EXIO_PIN8 8
|
|
||||||
|
|
||||||
/***************************************************** Operation register REG ****************************************************/
|
|
||||||
uint8_t Read_REG(uint8_t REG); // Read the value of the TCA9554PWR register REG
|
|
||||||
uint8_t Write_REG(uint8_t REG,uint8_t Data); // Write Data to the REG register of the TCA9554PWR
|
|
||||||
/********************************************************** Set EXIO mode **********************************************************/
|
|
||||||
void Mode_EXIO(uint8_t Pin,uint8_t State); // Set the mode of the TCA9554PWR Pin. The default is Output mode (output mode or input mode). State: 0= Output mode 1= input mode
|
|
||||||
void Mode_EXIOS(uint8_t PinState); // Set the mode of the 7 pins from the TCA9554PWR with PinState
|
|
||||||
/********************************************************** Read EXIO status **********************************************************/
|
|
||||||
uint8_t Read_EXIO(uint8_t Pin); // Read the level of the TCA9554PWR Pin
|
|
||||||
uint8_t Read_EXIOS(uint8_t REG); // Read the level of all pins of TCA9554PWR, the default read input level state, want to get the current IO output state, pass the parameter TCA9554_OUTPUT_REG, such as Read_EXIOS(TCA9554_OUTPUT_REG);
|
|
||||||
/********************************************************** Set the EXIO output status **********************************************************/
|
|
||||||
bool Set_EXIO(uint8_t Pin,uint8_t State); // Sets the level state of the Pin without affecting the other pins
|
|
||||||
bool Set_EXIOS(uint8_t PinState); // Set 7 pins to the PinState state such as :PinState=0x23, 0010 0011 state (the highest bit is not used)
|
|
||||||
/********************************************************** Flip EXIO state **********************************************************/
|
|
||||||
bool Set_Toggle(uint8_t Pin); // Flip the level of the TCA9554PWR Pin
|
|
||||||
/********************************************************* TCA9554PWR Initializes the device ***********************************************************/
|
|
||||||
void TCA9554PWR_Init(uint8_t PinMode = 0x00, uint8_t PinState = 0x00); // Set the seven pins to PinState state, for example :PinState=0x23, 0010 0011 State (the highest bit is not used) (Output mode or input mode) 0= Output mode 1= Input mode. The default value is output mode
|
|
||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
#define DEBUGLOG_DEFAULT_LOG_LEVEL_INFO
|
||||||
|
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <DebugLogEnable.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
#include <RS485_Driver.h>
|
||||||
|
#include <TCA9554PWR_Driver.h>
|
||||||
|
#include <PCF85063_Driver.h>
|
||||||
|
#include <ETH_Driver.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void callback(char *topic, uint8_t *payload, unsigned int length)
|
||||||
|
{
|
||||||
|
std::string pl;
|
||||||
|
pl.resize(length);
|
||||||
|
std::snprintf(pl.data(), length, "%s", payload);
|
||||||
|
LOG_INFO("Message: Topic [", topic, "], Payload [", pl.c_str(), "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
void myTask(void *mqtt)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
((PubSubClient *)(mqtt))->loop();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////// GLOBALS ///////////////
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
LOG_ATTACH_SERIAL(Serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
const uint8_t tempBoardAddr(0xAA);
|
||||||
|
const uint8_t relayBoardAddr(0x01);
|
||||||
|
const uint8_t baseRegister(0x00);
|
||||||
|
uint16_t k(0);
|
||||||
|
|
||||||
|
//////////////// DEVICES ////////////////
|
||||||
|
// Declared here to keep devices local to the main loop otherwise the kernel crashes //
|
||||||
|
auto i2c = drivers::I2C();
|
||||||
|
auto relays = drivers::TCA9554PWR(i2c, TCA9554_ADDRESS);
|
||||||
|
auto bus = drivers::MODBUS(9600, SERIAL_8N1);
|
||||||
|
auto rtc = drivers::PCF85063(i2c, PCF85063_ADDRESS);
|
||||||
|
auto eth = drivers::Ethernet("waveshare-test");
|
||||||
|
|
||||||
|
Network.onEvent([ð](arduino_event_id_t event, arduino_event_info_t info)
|
||||||
|
{ eth.onEvent(event, info); });
|
||||||
|
|
||||||
|
while (!eth.isConnected())
|
||||||
|
{
|
||||||
|
LOG_WARN("Waiting for Ethernet");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set RTC time at startup
|
||||||
|
time_t ntpTime;
|
||||||
|
drivers::PCF85063::datetime_t dt;
|
||||||
|
eth.getNtpTime(ntpTime);
|
||||||
|
rtc.setDatetime(drivers::PCF85063::fromEpoch(ntpTime));
|
||||||
|
|
||||||
|
// MQTT Test
|
||||||
|
NetworkClient tcp;
|
||||||
|
PubSubClient mqtt(tcp);
|
||||||
|
|
||||||
|
mqtt.setServer("10.0.2.249", 1883);
|
||||||
|
mqtt.setCallback(callback);
|
||||||
|
mqtt.connect("esp32-client");
|
||||||
|
mqtt.subscribe("test/esp32-in");
|
||||||
|
xTaskCreatePinnedToCore(myTask, "mqttLoop", 4096, &mqtt, 2, NULL, 1);
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
///////// MAIN LOOP INSIDE LOOP ////////
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
LOG_INFO("[", k++, "] Loop");
|
||||||
|
std::vector<uint16_t> results;
|
||||||
|
std::vector<bool> values;
|
||||||
|
|
||||||
|
eth.getNtpTime(ntpTime);
|
||||||
|
dt = drivers::PCF85063::fromEpoch(ntpTime);
|
||||||
|
LOG_INFO("Netwrok Datetime", rtc.datetime2str(dt).c_str());
|
||||||
|
LOG_INFO("Current Datetime", rtc.getTimeStr().c_str());
|
||||||
|
mqtt.publish("test/esp32-out", ("[" + std::to_string(k) + "] -> " + rtc.getTimeStr()).c_str());
|
||||||
|
|
||||||
|
if (bus.readHoldingRegisters(tempBoardAddr, baseRegister, 1, results))
|
||||||
|
{
|
||||||
|
for (auto i(0); i < results.size(); i++)
|
||||||
|
{
|
||||||
|
LOG_INFO("[", i, "]Temperature: ", results.at(i) / 10.0f);
|
||||||
|
}
|
||||||
|
results.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
LOG_INFO("====>Read Inputs");
|
||||||
|
bus.readInputs(relayBoardAddr, 0x00, 8, values);
|
||||||
|
printBool("====>Inputs", values);
|
||||||
|
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
///////// MAIN LOOP INSIDE LOOP ////////
|
||||||
|
////////////////////////////////////////
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user