LoginSignup
1
1

More than 3 years have passed since last update.

Arduinoでクイズボタンを作る

Last updated at Posted at 2020-01-22

Arduino Leonardo (Pro micro)を使ってクイズボタンを作ります。
ボタンを押すとキー入力が行われます(押し下し続けてもリピートせず一回のみ押されます)。
ボタン(ピン)は設定したピンとGNDにつないで使用します。
pose_button_osu_s.png

不公平のないよう、各ボタンのループ中にはdelay()を入れず、
ボタンの数や割当てピン、割り当てキーを指定できるようにしています。
公平な早押しを実現したい場合は、
・loop()内で->isPressed()をチェック
・複数ボタンが同時に押されたら(->isPressed()がtrueになったら)そのうちの1つをランダムで取得
・取得したもの以外の->loop(deltaMillis)をやめる(キーが押されたのをキャンセル)
で実現できます。

#include <Arduino.h>
#include <Keyboard.h>

class TmButtonKey{
  public:
  TmButtonKey(uint8_t _pin, uint8_t _key, long _wait=100){
    mPin = _pin;
    mKey = _key;
    mWait = _wait;
    mTimer=0;
    mIsPressed=false;
    mIsOn=mPreOn=false;
    pinMode(_pin,INPUT_PULLUP);
  }
  bool isPressed(){ return mIsPressed;}
  bool loop(unsigned int _deltaMillis){
    bool ret = false;
    if(!mIsPressed){
      mIsOn = !digitalRead(mPin);
      if(mIsOn & !mPreOn){
        push();
      }
      mPreOn = mIsOn;
    }else{ // mIsPressed
      mTimer += _deltaMillis;
      if(mTimer>=mWait){
        ret = true;
        mIsPressed = false;
        Keyboard.release(mKey);
      }
    }
    return ret;
  }
  private:
  uint8_t mPin;
  uint8_t mKey;
  long mWait;
  long mTimer;
  bool mIsPressed;
  bool mIsOn,mPreOn;

  bool push(){
    bool ret = false;
    if(!mIsPressed){
      ret = true;
      mIsPressed=true;
      mTimer = 0;
      Keyboard.press(mKey);
    }
    return ret;
  }
};

#define BTN1PL (PIN2)
#define BTN1PR (PIN3)
#define BTN1PU (PIN4)
#define BTN2PL (PIN5)
#define BTN2PR (PIN6)
#define BTN2PU (PIN7)
#define LED1PL (8)
#define LED1PR (9)
#define LED1PU (10)
#define LED2PL (14)
#define LED2PR (15)
#define LED2PU (16)
TmButtonKey* pKey1R;
TmButtonKey* pKey1L;
TmButtonKey* pKey1U;
TmButtonKey* pKey2R;
TmButtonKey* pKey2L;
TmButtonKey* pKey2U;
unsigned long mymillis;

void setup() {
  // put your setup code here, to run once:
  Keyboard.begin();
  pKey1L = new TmButtonKey(BTN1PL,KEY_LEFT_ARROW);
  pKey1R = new TmButtonKey(BTN1PR,KEY_RIGHT_ARROW);
  pKey1U = new TmButtonKey(BTN1PU,KEY_UP_ARROW);
  pKey2L = new TmButtonKey(BTN2PL,'a');
  pKey2R = new TmButtonKey(BTN2PR,'s');
  pKey2U = new TmButtonKey(BTN2PU,'w');
  pinMode(LED1PL,OUTPUT);
  pinMode(LED1PR,OUTPUT);
  pinMode(LED1PU,OUTPUT);
  pinMode(LED2PL,OUTPUT);
  pinMode(LED2PR,OUTPUT);
  pinMode(LED2PU,OUTPUT);
  mymillis = millis();
}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long nowMillis = millis();
  unsigned long deltaMillis = nowMillis - mymillis;
  mymillis = nowMillis;
  pKey1L->loop(deltaMillis);
  pKey1R->loop(deltaMillis);
  pKey1U->loop(deltaMillis);
  pKey2L->loop(deltaMillis);
  pKey2R->loop(deltaMillis);
  pKey2U->loop(deltaMillis);

  digitalWrite(LED1PL,pKey1L->isPressed()?HIGH:LOW);
  digitalWrite(LED1PR,pKey1R->isPressed()?HIGH:LOW);
  digitalWrite(LED1PU,pKey1U->isPressed()?HIGH:LOW);
  digitalWrite(LED2PL,pKey2L->isPressed()?HIGH:LOW);
  digitalWrite(LED2PR,pKey2R->isPressed()?HIGH:LOW);
  digitalWrite(LED2PU,pKey2U->isPressed()?HIGH:LOW);
  delay(5);
}

お作法通りやりたい場合は下記のようにファイルを分けます。

TmButtonKey.h
#include <Arduino.h>

class TmButtonKey{
  public:
  TmButtonKey(uint8_t _pin, uint8_t _key, long _wait=100);
  bool isPressed();
  bool loop(unsigned int _deltaMillis);
  private:
  uint8_t mPin;
  uint8_t mKey;
  long mWait;
  long mTimer;
  bool mIsPressed;
  bool mIsOn,mPreOn;
  bool push();
};
TmButtonKey.cpp
#include <Arduino.h>
#include <Keyboard.h>
#include "TmButtonKey.h"

TmButtonKey::TmButtonKey(uint8_t _pin, uint8_t _key, long _wait){
    mPin = _pin;
    mKey = _key;
    mWait = _wait;
    mTimer=0;
    mIsPressed=false;
    mIsOn=mPreOn=false;
    pinMode(_pin,INPUT_PULLUP);
}
bool TmButtonKey::isPressed(){ return mIsPressed;}
bool TmButtonKey::loop(unsigned int _deltaMillis){
    bool ret = false;
    if(!mIsPressed){
        mIsOn = !digitalRead(mPin);
        if(mIsOn & !mPreOn){
            push();
        }
        mPreOn = mIsOn;
    }else{ // mIsPressed
        mTimer += _deltaMillis;
        if(mTimer>=mWait){
            ret = true;
            mIsPressed = false;
            Keyboard.release(mKey);
        }
    }
    return ret;
}
bool TmButtonKey::push(){
    bool ret = false;
    if(!mIsPressed){
        ret = true;
        mIsPressed=true;
        mTimer = 0;
        Keyboard.press(mKey);
    }
    return ret;
}
main.cpp
#include <Arduino.h>
#include <Keyboard.h>
#include "TmButtonKey.h"

#define BTN1PL (PIN2)
#define BTN1PR (PIN3)
#define BTN1PU (PIN4)
#define BTN2PL (PIN5)
#define BTN2PR (PIN6)
#define BTN2PU (PIN7)
#define LED1PL (8)
#define LED1PR (9)
#define LED1PU (10)
#define LED2PL (14)
#define LED2PR (15)
#define LED2PU (16)
TmButtonKey* pKey1R;
TmButtonKey* pKey1L;
TmButtonKey* pKey1U;
TmButtonKey* pKey2R;
TmButtonKey* pKey2L;
TmButtonKey* pKey2U;
unsigned long mymillis;

void setup() {
  // put your setup code here, to run once:
  Keyboard.begin();
  pKey1L = new TmButtonKey(BTN1PL,KEY_LEFT_ARROW);
  pKey1R = new TmButtonKey(BTN1PR,KEY_RIGHT_ARROW);
  pKey1U = new TmButtonKey(BTN1PU,KEY_UP_ARROW);
  pKey2L = new TmButtonKey(BTN2PL,'a');
  pKey2R = new TmButtonKey(BTN2PR,'s');
  pKey2U = new TmButtonKey(BTN2PU,'w');
  pinMode(LED1PL,OUTPUT);
  pinMode(LED1PR,OUTPUT);
  pinMode(LED1PU,OUTPUT);
  pinMode(LED2PL,OUTPUT);
  pinMode(LED2PR,OUTPUT);
  pinMode(LED2PU,OUTPUT);
  mymillis = millis();
}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long nowMillis = millis();
  unsigned long deltaMillis = nowMillis - mymillis;
  mymillis = nowMillis;

  digitalWrite(LED1PL,pKey1L->isPressed()?HIGH:LOW);
  digitalWrite(LED1PR,pKey1R->isPressed()?HIGH:LOW);
  digitalWrite(LED1PU,pKey1U->isPressed()?HIGH:LOW);
  digitalWrite(LED2PL,pKey2L->isPressed()?HIGH:LOW);
  digitalWrite(LED2PR,pKey2R->isPressed()?HIGH:LOW);
  digitalWrite(LED2PU,pKey2U->isPressed()?HIGH:LOW);

  pKey1L->loop(deltaMillis);
  pKey1R->loop(deltaMillis);
  pKey1U->loop(deltaMillis);
  pKey2L->loop(deltaMillis);
  pKey2R->loop(deltaMillis);
  pKey2U->loop(deltaMillis);

  delay(5);
}
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