0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

I2Cキーボード(FreeRTOS理解:番外編1)

Posted at

I2Cキーボードを試す

スイッチサイエンスなどで入手できるI2Cキーボードを試した。M5Stack用、、と記載されているが、I2C制御できるものであれば、どんなものにでも接続できる。

今回は、Arduinoに接続した。

ハードウェア

ATmega328p U-THにより制御されている。

ピン配置は異なるが、Arduino搭載のマイコンと基本的には同じ。

参考ソースコード

Arduino IDE上で利用できるソースコードは、ここに見つかる。

テスト用ソースコード

FreeRTOSを使って、キーボード入力を行うタスクを設け、改行コードが入力されたら、それまでに入力された内容を別タスクに伝えることとした。

定義

# include <Arduino_FreeRTOS.h>
# include <queue.h>
# include <Wire.h>

# define CARDKB_ADDR   0x5F    // I2C slave address
# define KBD_BUF_SIZE  32
# define NL            0x0d
# define BS            0x08

TaskHandle_t xKbd, xRecv;
QueueHandle_t qMsg;
  • ArduinoでFreeRTOSの利用
  • FreeRTOSでのQueueの利用
  • I2Cアドレス
  • キーボードバッファサイズおよび特殊コード(改行およびバックスペース)
  • タスクハンドラ及びキューの定義

キーボード入力タスク(行入力)

void TaskOneLine(void *arg) {
  char      key[KBD_BUF_SIZE];
  uint16_t  i = 0;
  for (;;) {  
    Wire.requestFrom(CARDKB_ADDR, 1);
    while (Wire.available()) {
      char c = Wire.read();   // receive a byte
      if (c != 0) {
        if (c == BS) {        // Back space
          if (i != 0) {
            i--;
          }          
        } else {              // Store input data in buffer
          key[i++] = c;       // Not consider KBD_BUF_SIZE for input
          if (c == NL) {      // Read until new line and Send data to queue
            key[i] = 0;
            xQueueSend(qMsg, key, portMAX_DELAY);
            i = 0;
          }
        }
      }
    }
    vTaskDelay(1);
  }  
}
  • 1バイト入力およびキーボードバッファへの格納
  • バックスペース入力時にはキーボードバッファで1バイト分戻る
  • 改行入力時にはQueueにキーボードバッファをつむ

キーボードバッファを受けるタスク

ここでは、数値を受信することを想定して、数値分、LEDの点灯を繰り返すこととした。なお、数値以外のコード入力時のエラー処理は考慮していない。

void TaskDataRecv(void *arg) {
  char      buf[KBD_BUF_SIZE];
  
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  for (;;) {
    if (xQueueReceive(qMsg, buf, portMAX_DELAY) == pdPASS) {
      //Serial.println(buf);
      uint16_t n = atoi(buf);
      for (int i=0; i<n; i++) {
        digitalWrite(LED_BUILTIN, HIGH);
        delay(300);
        digitalWrite(LED_BUILTIN, LOW);
        delay(300);
      }
    }  
    vTaskDelay(1);
  }
}

実用では、バッファ受信側で、自由なコードを作ればよい。

Arduinoお決まり部分

void setup() {
  Serial.begin(9600);
  Wire.begin();
  qMsg = xQueueCreate(1, KBD_BUF_SIZE);
  xTaskCreate(TaskOneLine, "TaskOneLine", 128, NULL, 1, &xKbd);
  xTaskCreate(TaskDataRecv, "TaskDataRecv", 128, NULL, 1, &xRecv);
  vTaskStartScheduler();
}

void loop() {
  // Nothing in Arduino
}
  • I2C初期化
  • キュー初期化
  • タスク生成
  • タスクスケジューリング

最後に

執筆時点で1111円。自明であるが、キーボードはマイコン制御に便利である。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?