ELEGOO:Lesson 11~12

Lesson 11 Membrane Switch Module

メンブレンスイッチによるキーボードです。

Wikipedia:メンブレンキーボード
https://ja.wikipedia.org/wiki/メンブレンキーボード

内部構造は、単なるスイッチ。配線は8本です。多い。

列ごと、行ごとのON / OFF を検出するので、列用に4つ、行用に4つでピン8つ使います。

サンプルプログラムにキーパッド用のライブラリが付属しているので、それを使います。

内容は、こちらのライブラリでした。

Arduino Library List:KeyPad
https://www.arduinolibraries.info/libraries/keypad

初期値として、キーの配列、使用する縦横のピン番号を設定。

const byte ROWS = 4; //four rows
 const byte COLS = 4; //four columns
 //define the cymbols on the buttons of the keypads
 char hexaKeys[ROWS][COLS] = {
 {'1','2','3','A'},
 {'4','5','6','B'},
 {'7','8','9','C'},
 {'*','0','#','D'}
 };
 byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
 byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
//initialize an instance of class NewKeypad
 Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

キー状態を取得して、入力があればコンソールに表示。

char customKey = customKeypad.getKey();
if (customKey){
    Serial.println(customKey);
|

起動して、キーボードのボタンを押すと…

押したキーの文字が出ましたー。


今回も、実際の処理はライブラリの中の実装です。見てみましょう。

今回使っているのは getKey()関数。

char Keypad::getKey() {
    single_key = true;
    if (getKeys() && key[0].stateChanged && (key[0].kstate==PRESSED))
       return key[0].kchar;
    single_key = false;
    return NO_KEY;
}

getKeys() でキー全体の状態を更新。
複数キー対応の場合は key 配列に順次複数キー押下状態が入るみたいですね。
今回はシングルキーのみ対応なので、key[0]の状態をチェック。状態が変化していて、かつ押下状態であれば、key[0].kchar が押されたキーのキャラクターとなるようです。

getKeys() の中まで追っていくと、かなり深いとこにはまりそうなので、今回はここまでとします…。キーボード制御は keyUp / keyDown の処理や、複数同時押下、チャタリング対策など、いろいろと考えないといけないので、かなり複雑です。

ピン8本の接続が必要になるので、今回のパーツは、M5Stackとの接続はナシでーす。(接続できたとしても、処理が複雑すぎて簡単には作れない気がする…。)


Lesson 12 DHT11 Temperature and Humidity Sensor

温度&湿度計、DHT11です!

部品からピンが4本出てますけど、実際は3本しか使わないです。あと、抵抗の接続が必要とのこと。

キット付属のパーツは、抵抗実装済みで、使うピンだけの3本ピン状態になっています。

SimpleDHTというライブラリを使って計測。

SimpleDHT
https://github.com/winlinvip/SimpleDHT

実行!

あれれ?うまくいかない…。

SimpleDHTに新しいバージョンが出てるみたいなのアップデートしてみる。もう一度実行!

うーん、結果は出るようになったけど、2回に1回、失敗になってますね。

あっ、DHT11の説明で、
Remark: For DHT11, no more than 1 Hz sampling rate (once every second).
ってあるので、
待ち時間 delay(1000); だと微妙な個体差でギリギリアウトになってるのかも。
ちょっと長めの delay(1100); にしたところ…

うまくいったー。

Sample DHT11...
Sample RAW Bits: 0011 1011 0000 0000 0001 1101 0000 0011 0101 1011
Sample OK: 29 *C, 59 %

コンソールへの出力は、RAW Bits で取得したそのままのデータを出して、その後、それを変換した温度と湿度を出しています。

データは、上から、湿度整数部8ビット、湿度小数部8ビット、温度整数部8ビット、温度小数部8ビット、パリティ8ビットになっています。
パリティは8ビット区切りを上から足したものです。
0011 1011 + 0000 0000 + 0001 1101 + 0000 0011 = 0101 1011 ですね。

DHT11の解像度的に、小数部は基本的には 0000 になるはず。だけど温度が微妙に変。誤差かな…。

整数部を10進数にすると、
湿度: 0011 1011 = 0x3B = 59 (%)
温度: 0001 1101 = 0x1D = 29 (℃)
で、表示通りの値となりました。


今回も実際の処理はライブラリの中。どうやって値を取得しているか見てみます。こういう手順でした。

1.センサーへの計測開始を指示する:

LOWを20ms。その後、HIGHを 20~40 uS にする。これが計測開始の指示。

2.センサーが反応しているのを確認する:

ピンをINPUTに変更して、ピンの状態を確認。
ピンの状態が LOW 80uS、その後 HIGH 80uS になったら、DHT11側も計測開始したということ。

3.データの受信:

計測開始になったら5バイト(湿度2バイト、温度2バイト、パリティ1バイト)のデータが1ビットずつ連続して送られてくる。
データの送り方は、最初に LOW状態が 50uS 続き、その後 26~28uS がHIGHならデータ値は「0」。70uSが HIGHなら「1」。以降繰り返し。

LOW/HIGH だけの信号でバイト列送信するのもなかなか大変だ。
というか、こんなふうに逐次的に反応をする仕掛けが小さくて安価な DHT11 の中に入ってるってのもすごいよね。


DHT11の電源は3.3~5.5Vなので、M5Stack の Grove 端子からの電源でも動作可能です。
ということで、M5Stack Grove端子からの接続。

MicroPytho用のDHT11ライブラリは無かったので、今回は、Arduino で Adafruit の DHT ライブラリを使って動作しています。


M5Stackのチャージングベース(新型)には、DHT12 が付属しています。DHT12は、DHT11よりも細かくデータが取得でき(0.1度単位)、誤差も少なく、I2Cによる2本ピン接続で、より安定した動作が可能になっているとのことです。良いですねー。

知的好奇心 for IoT:WiFi温度・湿度計をDHT11からDHT12にアップグレードした
http://intellectualcuriosity.hatenablog.com/entry/2017/09/25/193739

DHT12は、MicroPython用ライブラリあったので MicroPythonでの動作です。

M5Stackと合体させて使うと、M5Stack本体の発熱を受けてしまうのが難点である…。