1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

M5StampS3でGROVE- Button(ボタンクラス)で遊ぶ。(M5Stack社さまのButtonClassを導入)

Last updated at Posted at 2024-10-25

x 過去ログを見よ!!
x Arduino IDEの新規タブの意味のわかる人
x 非営利、研究開発目的でM5Stack社さまのプログラムを引用

結果

o_coq565.jpg

o_coq566.jpg

プログラム




//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


1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?