x 過去ログを見よ!!
x Arduino IDEの新規タブの意味のわかる人
x 非営利、研究開発目的でM5Stack社さまのプログラムを引用
結果
プログラム
//button_Grover_button_M5StampS3_1
/**
@file button.ino
@author SeanKwok (shaoxiang@m5stack.com)
@brief
@version 0.1
@date 2024-03-19
@Hardwares: M5NanoC6
@Platform Version: Arduino ESP32 Board Manager v3.0.0-alpha3
@Dependent Library:
M5NanoC6: https://github.com/m5stack/M5NanoC6
*/
//#include <M5NanoC6.h>
#include <Arduino.h>
#include "Button_Class.hpp"
using namespace m5;
Button_Class BtnS;
void setup() {
//NanoC6.begin();
//シリアルの初期化処理
Serial.begin(9600);
Serial.println();
Serial.println("START");
Serial.println();
pinMode(15, INPUT); //Grover GPIO1
//GPIOの初期化 WS2812B
pinMode(21, OUTPUT);
}
void loop() {
//NanoC6.update();
uint32_t ms = millis();
BtnS.setRawState(ms, digitalRead(15)); //Grover GPIO15
if (BtnS.wasPressed()) {
Serial.println("Button A was pressed");
neopixelWrite(21, 0, 64, 0);
}
if (BtnS.wasHold()) {
Serial.println("Button A was hold");
neopixelWrite(21, 0, 64, 0);
}
if (BtnS.wasReleased()) {
Serial.println("Button A was released");
neopixelWrite(21, 0, 0, 0);
}
}
Button_Class.hpp
// Copyright (c) M5Stack. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
#ifndef __M5_BUTTON_CLASS_H__
#define __M5_BUTTON_CLASS_H__
#include <cstdint>
namespace m5 {
class Button_Class {
public:
enum button_state_t : std::uint8_t { state_nochange, state_clicked, state_hold, state_decide_click_count };
/// Returns true when the button is pressed briefly and released.
bool wasClicked(void) const {
return _currentState == state_clicked;
}
/// Returns true when the button has been held pressed for a while.
bool wasHold(void) const {
return _currentState == state_hold;
}
/// Returns true when some time has passed since the button was single
/// clicked.
bool wasSingleClicked(void) const {
return _currentState == state_decide_click_count && _clickCount == 1;
}
/// Returns true when some time has passed since the button was double
/// clicked.
bool wasDoubleClicked(void) const {
return _currentState == state_decide_click_count && _clickCount == 2;
}
/// Returns true when some time has passed since the button was multiple
/// clicked.
bool wasDecideClickCount(void) const {
return _currentState == state_decide_click_count;
}
[[deprecated("use wasDecideClickCount()")]] bool wasDeciedClickCount(void) const {
return wasDecideClickCount();
}
std::uint8_t getClickCount(void) const {
return _clickCount;
}
/// Returns true if the button is currently held pressed.
bool isHolding(void) const {
return _press == 2;
}
bool wasChangePressed(void) const {
return ((bool)_press) != ((bool)_oldPress);
}
bool isPressed(void) const {
return _press;
}
bool isReleased(void) const {
return !_press;
}
bool wasPressed(void) const {
return !_oldPress && _press;
}
bool wasReleased(void) const {
return _oldPress && !_press;
}
bool wasReleasedAfterHold(void) const {
return !_press && _oldPress == 2;
}
bool wasReleaseFor(std::uint32_t ms) const {
return _oldPress && !_press && _lastHoldPeriod >= ms;
}
[[deprecated("use wasReleaseFor()")]] bool wasReleasefor(std::uint32_t ms) const {
return wasReleaseFor(ms);
}
bool pressedFor(std::uint32_t ms) const {
return (_press && _lastMsec - _lastChange >= ms);
}
bool releasedFor(std::uint32_t ms) const {
return (!_press && _lastMsec - _lastChange >= ms);
}
void setDebounceThresh(std::uint32_t msec) {
_msecDebounce = msec;
}
void setHoldThresh(std::uint32_t msec) {
_msecHold = msec;
}
void setRawState(std::uint32_t msec, bool press);
void setState(std::uint32_t msec, button_state_t state);
button_state_t getState(void) const {
return _currentState;
}
std::uint32_t lastChange(void) const {
return _lastChange;
}
std::uint32_t getDebounceThresh(void) const {
return _msecDebounce;
}
std::uint32_t getHoldThresh(void) const {
return _msecHold;
}
std::uint32_t getUpdateMsec(void) const {
return _lastMsec;
}
private:
std::uint32_t _lastMsec = 0;
std::uint32_t _lastChange = 0;
std::uint32_t _lastRawChange = 0;
std::uint32_t _lastClicked = 0;
std::uint16_t _msecDebounce = 10;
std::uint16_t _msecHold = 500;
std::uint16_t _lastHoldPeriod = 0;
button_state_t _currentState = state_nochange; // 0:nochange 1:click 2:hold
bool _raw_press = false;
std::uint8_t _press = 0; // 0:release 1:click 2:holding
std::uint8_t _oldPress = 0;
std::uint8_t _clickCount = 0;
};
} // namespace m5
#endif
Button_Class.cpp
// Copyright (c) M5Stack. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
#include "Button_Class.hpp"
namespace m5 {
void Button_Class::setState(std::uint32_t msec, button_state_t state) {
if (_currentState == state_decide_click_count) {
_clickCount = 0;
}
_lastMsec = msec;
bool flg_timeout = (msec - _lastClicked > _msecHold);
switch (state) {
case state_nochange:
if (flg_timeout && !_press && _clickCount) {
if (_oldPress == 0 && _currentState == state_nochange) {
state = state_decide_click_count;
} else {
_clickCount = 0;
}
}
break;
case state_clicked:
++_clickCount;
_lastClicked = msec;
break;
default:
break;
}
_currentState = state;
}
void Button_Class::setRawState(std::uint32_t msec, bool press) {
button_state_t state = button_state_t::state_nochange;
bool disable_db = (msec - _lastMsec) > _msecDebounce;
auto oldPress = _press;
_oldPress = oldPress;
if (_raw_press != press) {
_raw_press = press;
_lastRawChange = msec;
}
if (disable_db || msec - _lastRawChange >= _msecDebounce) {
if (press != (0 != oldPress)) {
_lastChange = msec;
}
if (press) {
std::uint32_t holdPeriod = msec - _lastChange;
_lastHoldPeriod = holdPeriod;
if (!oldPress) {
_press = 1;
} else if (oldPress == 1 && (holdPeriod >= _msecHold)) {
_press = 2;
state = button_state_t::state_hold;
}
} else {
_press = 0;
if (oldPress == 1) {
state = button_state_t::state_clicked;
}
}
}
setState(msec, state);
}
} // namespace m5