Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions examples/Modules/StamPLC_AC/Relay/Relay.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#include <Arduino.h>
#include <M5StamPLC.h>

M5StamPLC_AC stamplc_ac;

void setup()
{
/* Init M5StamPLC */
M5StamPLC.begin();

/* Init M5StamPLC-AC */
while (!stamplc_ac.begin()) {
printf("M5StamPLC-AC init failed, retry in 1s...\n");
delay(1000);
}
}

void loop()
{
static bool relay_state = false;

/* Toggle M5StamPLC-AC relay state */
relay_state = !relay_state;
stamplc_ac.writeRelay(relay_state);
printf("Write M5StamPLC-AC Relay to %s\n", stamplc_ac.readRelay() ? "ON" : "OFF");

delay(1000);
}
49 changes: 49 additions & 0 deletions examples/Modules/StamPLC_AC/StatusLight/StatusLight.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#include <Arduino.h>
#include <M5StamPLC.h>

M5StamPLC_AC stamplc_ac;

void setup()
{
/* Init M5StamPLC */
M5StamPLC.begin();

/* Init M5StamPLC-AC */
while (!stamplc_ac.begin()) {
printf("M5StamPLC-AC init failed, retry in 1s...\n");
delay(1000);
}
}

void loop()
{
/* Set status light to red */
stamplc_ac.setStatusLight(1, 0, 0);
printf("Set M5StamPLC-AC status light to red\n");
delay(1000);

/* Set status light to green */
stamplc_ac.setStatusLight(0, 1, 0);
printf("Set M5StamPLC-AC status light to green\n");
delay(1000);

/* Set status light to blue */
stamplc_ac.setStatusLight(0, 0, 1);
printf("Set M5StamPLC-AC status light to blue\n");
delay(1000);

/* Set status light to white */
stamplc_ac.setStatusLight(1, 1, 1);
printf("Set M5StamPLC-AC status light to white\n");
delay(1000);

/* Set status light to black */
stamplc_ac.setStatusLight(0, 0, 0);
printf("Set M5StamPLC-AC status light to black\n");
delay(1000);
}
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"M5Unified": "*",
"M5GFX": "*"
},
"version": "1.1.0",
"version": "1.2.0",
"frameworks": "arduino",
"platforms": "espressif32"
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=M5StamPLC
version=1.1.0
version=1.2.0
author=M5Stack
maintainer=M5Stack
sentence=M5StamPLC is a library for M5StamPLC
Expand Down
1 change: 1 addition & 0 deletions src/M5StamPLC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "utils/aw9523/aw9523.h"
#include "utils/lm75b/lm75b.h"
#include "utils/rx8130/rx8130.h"
#include "modules/M5StamPLC_AC.h"
#include <M5GFX.h>
#include <M5Unified.hpp>
#include <driver/twai.h>
Expand Down
98 changes: 98 additions & 0 deletions src/modules/M5StamPLC_AC.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#include "M5StamPLC_AC.h"
#include "utils/make_unique_compat.h"
#include <esp_log.h>
#include <memory>

static const char* _tag = "M5StamPLC_AC";

static const uint8_t _ioe_address = 0x44;
static const uint8_t _pin_relay = 2;
static const uint8_t _pin_status_light_r = 5;
static const uint8_t _pin_status_light_g = 6;
static const uint8_t _pin_status_light_b = 7;

bool M5StamPLC_AC::begin()
{
if (_ioe) {
ESP_LOGW(_tag, "IOExpander already initialized");
return true;
}

_ioe = std::make_unique<m5::PI4IOE5V6408_Class>(_ioe_address, 400000, &m5::In_I2C);
if (!_ioe->begin()) {
_ioe.reset();
ESP_LOGE(_tag, "IOExpander initialization failed");
return false;
}

// AC relay
_ioe->setDirection(_pin_relay, true);
_ioe->setPullMode(_pin_relay, false);
_ioe->setHighImpedance(_pin_relay, false);

// Status light
auto setup_status_light_pin = [](m5::PI4IOE5V6408_Class* ioe, uint8_t pin) {
ioe->setDirection(pin, true);
ioe->setPullMode(pin, true);
ioe->setHighImpedance(pin, false);
ioe->digitalWrite(pin, true);
};

setup_status_light_pin(_ioe.get(), _pin_status_light_r);
setup_status_light_pin(_ioe.get(), _pin_status_light_g);
setup_status_light_pin(_ioe.get(), _pin_status_light_b);

return true;
}

bool M5StamPLC_AC::readRelay()
{
if (!is_ioe_valid()) {
return false;
}

return _ioe->getWriteValue(_pin_relay);
}

void M5StamPLC_AC::writeRelay(const bool& state)
{
if (!is_ioe_valid()) {
return;
}

_ioe->digitalWrite(_pin_relay, state);
}

void M5StamPLC_AC::setStatusLight(const uint8_t& r, const uint8_t& g, const uint8_t& b)
{
if (!is_ioe_valid()) {
return;
}

auto set_channel = [](m5::PI4IOE5V6408_Class* ioe, uint8_t pin, uint8_t value) {
if (value == 0) {
ioe->setHighImpedance(pin, true);
} else {
ioe->setHighImpedance(pin, false);
ioe->digitalWrite(pin, false);
}
};

set_channel(_ioe.get(), _pin_status_light_r, r);
set_channel(_ioe.get(), _pin_status_light_g, g);
set_channel(_ioe.get(), _pin_status_light_b, b);
}

bool M5StamPLC_AC::is_ioe_valid()
{
if (!_ioe) {
ESP_LOGE(_tag, "IOExpander not initialized");
return false;
}
return true;
}
49 changes: 49 additions & 0 deletions src/modules/M5StamPLC_AC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <M5GFX.h>
#include <M5Unified.hpp>
#include <utility/PI4IOE5V6408_Class.hpp>
#include <memory>

class M5StamPLC_AC {
public:
/**
* @brief Initialize M5StamPLC-AC
*
* @return true
* @return false
*/
bool begin();

/**
* @brief Read Relay state
*
* @return true if ON, false if OFF
*/
bool readRelay();

/**
* @brief Write AC Relay state
*
* @param state true if ON, false if OFF
*/
void writeRelay(const bool& state);

/**
* @brief Set Status Light
*
* @param r
* @param g
* @param b
*/
void setStatusLight(const uint8_t& r, const uint8_t& g, const uint8_t& b);

protected:
std::unique_ptr<m5::PI4IOE5V6408_Class> _ioe;

bool is_ioe_valid();
};
33 changes: 33 additions & 0 deletions src/utils/make_unique_compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <memory>
#include <utility>
#include <type_traits>
#include <cstddef>

#if __cplusplus < 201402L
namespace std {

template <class T, class... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <class T>
typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, std::unique_ptr<T>>::type make_unique(
std::size_t n)
{
using U = typename std::remove_extent<T>::type;
return std::unique_ptr<T>(new U[n]());
}

template <class T, class... Args>
typename std::enable_if<(std::extent<T>::value != 0), void>::type make_unique(Args&&...) = delete;

} // namespace std
#endif
Loading
Loading