Newer
Older
m5stickcplus / week1.rst
@Motoki Miura Motoki Miura on 4 Mar 2021 17 KB sprite
1週目
========================

.. note:: 以下の項目について、全員がすべてを試す必要はありません。役割分担をして、確認と理解をすすめてください。

電源の切り方・入れ方
----------------------------------------

- 電源を切るには、電源ボタン(M5と書かれたAボタンの左側面)を、6秒間長押しします。
- 電源を入れるには、電源ボタンを、2秒間長押しします。
- `M5StickCガイド <https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/M5StickC_Guide_Japanese.pdf>`_ の、4ページ目、ハードウェアの概要が参考になります。 


プログラムの書き込み方
--------------------------------------

:ref:`writetom5` を参照してください。


コードを書くときのヒントと注意
-------------------------------------------------------

- 以下のソースコード例は、右上のボタンを押すと、クリップボードに簡単にコピーできます。
- ソースコードのインデントは、CTRL+T (Macの場合はCommand+T)キーで、自動整形できます。
- ``#include <M5StickC.h>``  は、M5StickC用のコードです。 **M5StickCPlus** では、``#include <M5StickCPlus.h>`` に変更しないと、表示がおかしくなることがあります。
- 大文字と小文字は厳密に区別されます。
- 画面をつかうプログラムを書き込んだあと、画面を使わないプログラムを書き込むと、前のプログラムの画面が残ることがあります。

Serial通信
---------------------------------------

:numref:`serial01` は、シリアルモニタへ文字列を出力するシンプルな例です。グローバル変数 num を 0 に設定したうえで、setup()関数が1回実行されます。その後、loop()関数が繰り返し実行されます。
プログラムの出力をみるには、Arduino IDEで「シリアルモニタ」をひらいてください。コードエディタ右上の虫眼鏡アイコンボタンをおします。
Serialクラスには、print()関数、println()関数、 printf()関数があります。Serial通信を用いると、デバイス側の変数の値や状況を、PC側で確認するプログラムを書くことができます。

.. literalinclude:: src/serial01.ino
  :caption: 
  :name: serial01
  :language: arduino
  :emphasize-lines: 2
  :linenos:

シリアルモニタは、デバイスからの出力を確認するだけではなく、デバイスに文字を送信することもできます。:numref:`serial02` は、シリアルモニタを介して、PCからデバイスに文字を送信する例です。シリアルモニタ上部のテキストエリアから 0 を送信すると、カウンタ num をリセットします。10〜14行目で、PCから送信された文字を、1文字ずつ ``Serial.read()`` で読み取って、配列 ``buf`` に格納しています。PCから複数の文字を1回で送信すると、 ``Serial.available()`` は連続して 1 (=true) を返しますので、1回に送信された文字をすべて ``buf`` に格納することができます。ちなみに、シリアルモニタで送信された文字列の最後は、改行コード(10)が付与されます。

.. literalinclude:: src/serial02.ino
  :caption: 
  :name: serial02
  :language: arduino
  :emphasize-lines: 10-14
  :linenos:

.. note:: 16行目の処理を忘れると、どうなるでしょうか? また、buf が溢れると、なにが起きるでしょうか?プログラムを書くときは、常に例外的な事象がおきる可能性を考えておきましょう。ただし、全ての例外的な事象に対処するのは困難な場合が多いです。


本体の液晶ディスプレイ(LCD)
-------------------------------------------

- M5StickCのDisplay周り解析 <https://lang-ship.com/blog/work/m5stickc-display> が詳しいです。
- :numref:`lcd01` のサンプルでは、外側から内側に向かって、10ピクセルずつ余白を残しながら、色を変えて塗りつぶしています。その後、8,16,26ピクセルフォント(それぞれ1,2,4番)をsetCursor()関数で指定して、print()関数で文字列を描画しています。
- M5StickCPlusの機能である液晶ディスプレイ(LCD)を使用するため、 ``#include <M5StickCPlus.h>`` を指定し、``M5.begin()`` を呼び出しています。

.. literalinclude:: src/lcd01.ino
  :caption: 
  :name: lcd01
  :language: arduino
  :linenos:
..  :emphasize-lines: 10-14

画面の向きは、setRotation() 関数で、設定します。0〜3までの整数で、指定します。

.. figure:: images/setRotation.gif
   :scale: 100%

.. note:: フォントの種類を設定するときは、setTextFont() や、setCursor()の第3引数をつかいます。setTextSize()は、指定したフォントを何倍に引き伸ばして表示するか?なので、基本は1を指定することが多いです。倍率を増やすと、ギザギザが目立ちます。


本体のボタン
------------------------------------------

本体には、3つのボタンがあります。
(参考:`M5StickCガイド <https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/M5StickC_Guide_Japanese.pdf>`_ の、4ページ目、ハードウェアの概要)

:numref:`button01` に、ボタンをおしたらシリアルモニタに表示する例を示します。ボタンも、M5StickC/CPlusの機能なので、 ``#include <M5StickCPlus.h>`` を指定し、``M5.begin()`` を呼び出しておく必要があります。また、ボタンの状態を読み出して、ボタンオブジェクト(BtnA,BtnB)に設定するために、 ``M5.update()`` を、ループのなかに入れておく必要があります( `update()の定義 <https://github.com/m5stack/M5StickC-Plus/blob/master/src/M5StickCPlus.cpp>`_ )。長押しと普通押しを区別したい場合は、ifで確認する順番(長押しを先に判定する)が重要です。

.. literalinclude:: src/button01.ino
  :caption: 
  :name: button01
  :language: arduino
  :linenos:
..  :emphasize-lines: 10-14

.. note:: `非公式リファレンスの「ボタン管理(Button)」 <https://lang-ship.com/reference/unofficial/M5StickC/Class/Button>`_ も参考になります。


文字列の扱い、16進数や10進数の変換
-------------------------------------------------------------

:numref:`str01` に、文字列から整数に変換したり、16進数表現の文字列を10進数に変換する例を示します。
Stringクラスを用いると、char配列 / byte配列 / 小文字変換や、空白改行の削除(ただし文字列の前後のみ)、部分文字列の取得などができます。
元のデータが保持されるメソッドと、破壊されるメソッドがあることに注意しましょう。
M5系デバイスのLCDでは、色を16ビット値(赤5bit/緑6bit/青5bit)で表現しています。 ``M5.Lcd.color565()`` という関数もありますが、ここではビット演算の理解を深めるため、関数を定義しています。
C言語のポインタや、シフト演算などを理解していると、このような処理を円滑に記述できるようになります。

.. literalinclude:: src/str01.ino
  :caption: 
  :name: str01
  :language: arduino
  :linenos:
..  :emphasize-lines: 10-14

.. note:: 参考:https://qiita.com/nnn112358/items/ea6b5e81623ba690343c


ブザー(Beep)
-------------------------------------

:numref:`sound01` は、内蔵Beepを鳴らすサンプルです。音の周波数は、最初の1オクターブ (f[0]〜f[6]) のみを配列宣言時に指定し、残りの3オクターブはsetup()内で、倍数を計算して配列に設定しています。

``setBeep()`` と ``beep()`` を使うと、同じビープ音を使い回すときは記述が短くて便利ですが、通常は ``tone()`` のほうが簡潔です。
どちらの記法でも、命令実行のあと、音の停止を待たずに、すぐに次の処理に移行します(ノンブロッキング)。
継続ミリ秒数(ms)は、 ``M5.Beep.update()`` が周期的に呼び出せるときに指定し、それ以外は省略するとよいでしょう。(結局、 ``delay()`` と ``mute()`` が必要になるため) 

.. literalinclude:: src/sound01.ino
  :caption: 
  :name: sound01
  :language: arduino
  :linenos:
..  :emphasize-lines: 10-14


内蔵LED(赤・赤外) 
----------------------------------------

M5StickCPlusには、2つのLEDランプが内蔵されています。GPIO(General Purpose I/O)10 には、赤色LED、GPIO9 には、赤外LEDが接続されています。
場所は、USBケーブルを挿す面の反対側の面にある、小さな穴2つの内側です。

:numref:`led01` は、赤色LEDを点滅させるシンプルなプログラムです。

.. literalinclude:: src/led01.ino
  :caption: 
  :name: led01
  :language: arduino
  :linenos:
..  :emphasize-lines: 10-14


外部のLED等を接続
-----------------------------------------

外部のLED等は、 G0, G25, G26 に接続します。
サンプルプログラムは、:numref:`led01` と同様です。PIN 番号を、0 / 25 / 26 に変更してください。

ブレッドボードに、抵抗とLEDを直列に接続します。
LEDの長い足のほうに、G0 (or G25 or G26) をジャンパワイヤで接続し、反対側(短い足)のほうを、GND (グランド)に接続します。
ポートを「HIGH」にすると、3.3Vの電圧がかかります。

.. figure:: images/SimpleLED_m5s.png
   :scale: 60%

.. warning:: LEDのみで回路を構成しないよう注意!一般に、LEDは抵抗をつないで使用しないと、故障したり、最悪の場合破裂したりして危険です。ただし、抵抗入りLEDであれば問題ありません。

PWM (Pulse Width Modulation)
-------------------------------------------------------------------

パルス幅変調とは、信号の周期Tに対する、パルスの幅を変化させる方法です。
直流モータの速度制御や、サーボモータの制御、LEDの明度調整などに使われます。

:numref:`pwm01` は、赤色LEDを点滅させるシンプルなプログラムです。 ``ledcSetup(チャンネル, 周波数, 分解能)`` で、PWMチャンネル(0〜3)に対する周波数と分解能設定をし、 ``lecAttachPin(ピン番号, チャンネル)`` で、PWMチャンネルを適用する出力ピンを選択します。そのあと、 ``ledcWrite(チャンネル, 値)`` で、分解能で設定したビットで表現できる最大値+1以下の値を指定することで、デューティー比を設定します。:numref:`pwm01` の場合、分解能で8bitを指定したので、0〜256 の値が、デューティー比 0〜1 のパルス生成に対応します。

.. literalinclude:: src/pwm01.ino
  :caption: 
  :name: pwm01
  :language: arduino
  :linenos:
  :emphasize-lines: 6-7, 15,19

.. note:: ソースコードのコメントにも書いていますが、周波数を小さくする(20〜30程度)と、どうなるでしょうか?ぜひやってみてください。

サーボモータ(サーボハット利用)
-------------------------------------------------------------

:numref:`servohat01` は、`サーボハット <https://www.switch-science.com/catalog/6076/>`_ のサーボモータを動かすサンプルです。サーボモータの制御はPWMですので、基本的に、上のPWMとやっていることは同じです。おまけとして、LEDも点灯させました。``map関数`` は、Arduinoで使える関数で、範囲に対応する値を変換するときに使います。ここでは、サーボ制御で用いる5〜33の値を、LED制御の値0〜256に変換しています。

.. literalinclude:: src/servohat01.ino
  :caption: 
  :name: servohat01
  :language: arduino
  :linenos:
..  :emphasize-lines: 6-7, 15,19



外部のセンサを接続 (ADC)
-----------------------------------------

ADCは、Analog to Digital Converter の意味です。
``analogRead(PIN)`` は、PIN番ピンの電圧(0~3.3V)を、0〜4095 の値で返します。一般に、抵抗値が変化するタイプのセンサは、この方法をつかって、読み取ることができます。

.. warning:: `ADC <https://lang-ship.com/reference/unofficial/M5StickC/Peripherals/ADC/>`_ にかいてあるように、G26, G32, G33, G36のみ使えます。G26は、無線利用時には使えません。

:numref:`cds01` はCdSセル(照度センサ) の値を読み取るサンプルです。

.. literalinclude:: src/cds01.ino
  :caption: 
  :name: cds01
  :language: arduino
  :linenos:
..  :emphasize-lines: 6-7, 15,19


圧力センサや、曲げセンサも、同様の方法で利用することができます。


加速度センサ
-----------------------------------------

:numref:`accgyro01` は、内蔵されている加速度センサ(MPU6886) の値を表示するサンプルです。ちなみに、IMUとは、Inertial Measurement Unit: 慣性計測装置 の略です。
「ツール」→「シリアルプロッタ」をひらくと、値をグラフでみることができます。
ジャイロセンサの値も取得可能です。


.. literalinclude:: src/accgyro.ino
  :caption: 
  :name: accgyro01
  :language: arduino
  :linenos:
..  :emphasize-lines: 6-7, 15,19


赤外(InfraRed)リモコン
------------------------------------------

信号の読み取り
~~~~~~~~~~~~~~~~~~~~~

赤外線リモコン受信モジュールが必要です。ここでは、`GP1UXC41QS <https://akizukidenshi.com/catalog/g/gI-06487/>`_ を前提に、話をすすめます。

また、準備として、ライブラリマネージャにて、IRremoteESP8266 をインストールします。ちなみに、テストしたバージョンは2.7.15でした。

ファイルメニュー → スケッチ例 → IRremoteESP8266 → IRrecvDumpV2 を選択します。

ブレッドボードに、以下の図のように配線します。Pとかいてある面が、受光器が出っ張っている面です。47Ωの抵抗を、5Vとの間に入れます。
赤外線リモコン受信モジュールに接続したピンを ``const uint16_t kRecvPin = 36;`` として設定します。
受光器にリモコンを向けて、ボタンを押すと、シリアルモニタに情報が表示されます。ここでは、Protocol : NEC , Code 0x2FD48B7 (32 Bits) と表示されたとします。

.. figure:: images/ir_sensor_47owm.png
   :scale: 60%


信号の送信
~~~~~~~~~~~~~~~~~~~~~~~~

内蔵の赤外LEDを用いて、信号を送信する例を :numref:`irsend01` に示します。
内蔵の赤外LED光はあまり強くないため、50cm程度まで近づかないと反応しない場合があります。
単体の赤外LEDを接続して用いると、距離を伸ばすことができます。

.. literalinclude:: src/irsend01.ino
  :caption: 
  :name: irsend01
  :language: arduino
  :linenos:
..  :emphasize-lines: 6-7, 15,19




スプライト表示(TFT_eSprite クラス)
-------------------------------------------------------------

M5.Lcd ではじまる画面描画命令は、表示されている画面に対して、直接描画するため、画面のちらつきが生じることがあります。
TFT_eSprite クラスを用いると、画面に表示されていない仮想画面(オフスクリーン)を作成して、そこに対して描画を行っておき、さいごにまとめて仮想画面の内容をメインの画面(Lcd)に描画することができます。
これにより、画面のちらつきが抑制できます(ダブルバッファリング)。
ちらつき防止のほかに、なめらかに画面スクロールする目的で、実画面よりも大きい仮想画面を作成しておき、その一部の領域のみを実画面に描画するといった用途にも使われます。

TFT_eSprite クラスは、Lcdクラスとほぼ同様の描画関数を備えています。:numref:`sprite01` は、スプライトの効果あり/なしを確認できるサンプルプログラムです。

.. literalinclude:: src/sprite01.ino
  :caption: 
  :name: sprite01
  :language: arduino
  :linenos:
..  :emphasize-lines: 6-7, 15,19





Wifi 接続
--------------------------------------


NTPサーバ (Network Time Protocol) と時刻の取得
-----------------------------------------------------------------------------------------------------------------------------------



WebClient
---------------------------------------


WebServer
----------------------------------------


Bluetooth Low Energy
--------------------------------------

アドバータイズ


Bluetooth Serial Protocol Profile (SPP)
--------------------------------------------


Preference
-------------------------------------------


電力制御
-----------------------------------


その他
-------------------------------------
- CO2 (CCS811)
- RCS-620S (Felica)
- JJYClock
- RTC(BM8563)
- OTA

参考リンク
------------------------------------------

- M5StickC非公式日本語リファレンス <https://lang-ship.com/reference/unofficial/M5StickC></https:>