また、つまらぬ物を買ってしまった…。 ...嘘です、面白かったです!
はじめに
- 昨日、ダイヤル型入力装置(エンコーダ)と帯状のLED(stripLED)を買ったので、組み合わせて動かしてみた。
動作
- stripLEDの連続した7つを「白、赤、緑、青、黄色、水色、紫色」で光らせて、スクロールさせた。
- エンコーダも活躍させるため、ダイヤルをひねるとスクロール速度を変化させ、ボタンを押している間、スクロール方向を反転させることとした。
書いたコード(arduinoIDE)
#include <M5Unified.h>
#include <Unit_MiniEncoderC.h>
#include <Adafruit_NeoPixel.h>
#define SIGPIN 32 // 信号ピン
#define LEDNUM 15 // stripLEDのLED数
UNIT_MINIENCODERC encoder;
static M5Canvas cv1(&M5.Lcd);//エンコーダのボタン状態、エンコード値表示用
static M5Canvas cv2(&M5.Lcd);//エンコーダ値の増減表示用
static M5Canvas cv3(&M5.Lcd);//stripLEDのループ周期と方向表示用
uint8_t i2c_address = 0; //エンコーダのアドレス
int32_t last_value = 0; //最後に取得したエンコード値
uint8_t strip_loop_time = 0; //stripLEDのループ周期(msec)
bool strip_direction = true; //stripLEDのループ方向
uint16_t cnt = 0;
uint8_t brt = 30; //stripLEDの明るさ(0-255)
Adafruit_NeoPixel strip(LEDNUM, SIGPIN, NEO_GRB);
void page_get_encoder(void) {
int32_t encoder_value = encoder.getEncoderValue(); //1ノッチで、2増減する。ノッチ間で回転を止めると奇数も可。1回転で60。
bool btn_status = encoder.getButtonStatus(); //通常1,押された状態で0
Serial.println(encoder_value);
//増減でエンコーダ裏面のLED色変化
if (last_value != encoder_value) {
if (last_value > encoder_value) {
encoder.setLEDColor(1, 0x000011); //増加:赤
} else {
encoder.setLEDColor(2, 0x110000); //減少:青
}
last_value = encoder_value;
}
//エンコーダのボタンでエンコーダ裏面のLED変化
if (!btn_status) {
encoder.setLEDColor(0, 0x001100); //ボタン押下:緑
}
cv1.fillScreen(BLACK);
cv1.setTextColor(WHITE);
cv1.drawString("ボタン状態:" + String(btn_status), 10, 10);
cv1.drawString("エンコーダ値:", 10, 40);
cv1.setCursor(10, 65);
cv1.setTextColor(GREEN);
cv1.printf("%d", encoder_value);
cv1.pushSprite(0, 0);
//上下限設定
if (encoder_value < -126) {
encoder.setEncoderValue(-126);
encoder_value = -126;
} else if (encoder_value > 126) {
encoder.setEncoderValue(126);
encoder_value = 126;
}
//stripLED用の設定
strip_loop_time = 128 + encoder_value; //128msを中心に増減
strip_direction = btn_status; //順方向1,逆方向0
//stripLED用の設定表示
cv3.fillScreen(BLACK);
cv3.setTextColor(WHITE);
cv3.drawString("loop方向:" + String(btn_status ? "順" : "逆"), 10, 10);
cv3.drawString("loop時間(msec):", 10, 40);
cv3.setCursor(10, 65);
cv3.setTextColor(GREEN);
cv3.printf("%d", strip_loop_time);
cv3.setTextColor(WHITE);
cv3.pushSprite(0, 140);
}
//7色表示
void stripShow(uint16_t cnt) {
strip.clear(); //消灯
strip.setPixelColor((LEDNUM + cnt - 0) % LEDNUM, strip.Color(80, 80, 80)); //白(R+G+B)
strip.setPixelColor((LEDNUM + cnt - 1) % LEDNUM, strip.Color(240, 0, 0)); //赤(R)
strip.setPixelColor((LEDNUM + cnt - 2) % LEDNUM, strip.Color(0, 240, 0)); //緑(G)
strip.setPixelColor((LEDNUM + cnt - 3) % LEDNUM, strip.Color(0, 0, 240)); //青(B)
strip.setPixelColor((LEDNUM + cnt - 4) % LEDNUM, strip.Color(120, 120, 0)); //黄(R+G)
strip.setPixelColor((LEDNUM + cnt - 5) % LEDNUM, strip.Color(0, 120, 120)); //水(G+B)
strip.setPixelColor((LEDNUM + cnt - 6) % LEDNUM, strip.Color(120, 0, 120)); //紫(R+B)
strip.setPixelColor((LEDNUM + cnt - 7) % LEDNUM, strip.Color(0, 0, 0)); //黒
strip.setPixelColor((LEDNUM + cnt + 1) % LEDNUM, strip.Color(0, 0, 0)); //黒(逆方向で色を消すのに必要)
strip.show(); //点灯
}
void setup() {
M5.begin();
cv1.createSprite(135, 100); //エンコーダのボタン状態、エンコード値表示用
cv2.createSprite(135, 40); //エンコーダ値の増減表示用
cv3.createSprite(135, 100); //stripLEDのループ周期と方向表示用
cv1.setFont(&lgfxJapanMincho_16);
cv2.setFont(&lgfxJapanMincho_16);
cv3.setFont(&lgfxJapanMincho_16);
encoder.begin(&Wire, MINIENCODERC_ADDR, 0, 26, 100000UL);
i2c_address = encoder.getI2CAddress();
strip.begin(); //pixelLED初期化
strip.setBrightness(brt); //明るさ(0-255)
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) { //前回ボタンAを押した時点からの増減値を取得
cv2.fillScreen(BLACK);
cv2.setTextColor(WHITE);
cv2.drawString("増減:", 10, 10);
cv2.setTextColor(CYAN);
cv2.setCursor(50, 10);
cv2.print(encoder.getIncrementValue()); //前回取得時との差異
cv2.pushSprite(0, 100);
} else if (M5.BtnB.wasPressed()) { //ボタンBを押すとエンコーダ値リセット
encoder.resetCounter();
cv2.fillScreen(BLACK);
cv2.drawString("リセット!", 10, 10);
cv2.pushSprite(0, 100);
}
page_get_encoder();
stripShow(cnt);
cnt = cnt + (strip_direction ? 1 : -1); //ボタンを押している間、逆方向にスクロール
delay(strip_loop_time);
}
コードの内容
- 動作に書いたこと以外を書くと、M5stickCPlus2のボタンBを押すと、エンコード値がリセット(0)となり、ボタンAを押すと、前回ボタンAを押したときからのエンコード値の増減を画面に表示する。
- stripLEDのスクロールはloopによるものだが、loop周期(msec)は128を中心とし、エンコード値を加えたものとした。
コードの解説
- エンコーダのライブラリとstripLEDのライブラリを利用したので、お手軽に実装できた。
- エンコーダの初期設定は、
encoder.begin(&Wire, MINIENCODERC_ADDR, 0, 26, 100000UL);
- 0はSDA、26はSCLに割り当てたM5stickCPlus2のピン番号。
- 最後の100000ULはspeedのようだが、深く考えず、sampleのスケッチを使い回した。
- 使用したエンコーダのメソッドは、
-
getI2CAddress()
I2Cアドレス取得 -
getEncoderValue()
エンコーダ値取得 -
setEncoderValue(int32_t value)
エンコーダ値設定 -
resetCounter()
エンコーダ値リセット -
getIncrementValue()
前回の増減取得時からの増減を取得
-
- ダイヤルを一周回すとエンコード値は60増減する(時計回りで増加)。
- 回すとノッチ感があり、1ノッチで2増減する。
- stripLEDの初期設定は、
Adafruit_NeoPixel strip(LEDNUM, SIGPIN, NEO_GRB);
- 最後のNEO_GRBはledの色指定時の並びを定義している模様。
- 使用したstripLEDのメソッドは、
-
clear()
消灯 -
show()
点灯 -
setPixelColor(uint16_t n, uint32_t c)
n番目のledの色指定
-
終わりに
- 今日は、サイクルモード東京2024にチャリで行くか、昨日買ったものを動かすプログラムを書くか、迷った末に、プログラムを書くことにした。
- 気がつけば、富士ヒルクライムのエントリー期限も過ぎてたし、このまま運動をサボっているとBMIがK点超えするのも時間の問題。
- そろそろ、プログラムを書くのも控えた方がいいかも。