Arduino Leonardo (Pro micro)を使ってクイズボタンを作ります。
ボタンを押すとキー入力が行われます(押し下し続けてもリピートせず一回のみ押されます)。
ボタン(ピン)は設定したピンとGNDにつないで使用します。
不公平のないよう、各ボタンのループ中には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);
}