Android StudioとKotlinを使って, Androidアプリを作ってみた。

初めてのAndroidアプリ作り

M5Stackの方は放置でいいので他のソフトウェアを書く気分になったから初めてAndroidアプリを作ってみることにする。

それそのままの名前のリポジトリをここにおいておく。
ほしい人は持っていって。

https://github.com/ak1211/MyFirstApplication

動機

Androidアプリの作り方を学ぶのが目的だから, お題そのものがむつかしいモノは避けて以前に作ったことのある赤外線リモコン信号を記録して送信できるものを作ってみる。

自分のAndroidスマホには赤外線入出力機能がないので, 外部にハードウエアを用意してソフトとハードで互いに協調動作させるとしよう。

赤外線リモコン信号送受信用ハードウエア

ダイキンエアコンのリモコン信号を解析する」と 「M5Stack Core2とVSCode + PlatformIOとでM5Stackプログラミングを始めてみた。」 との時に使った

また登場してもらう。

ブレッドボードを出してくるのが面倒だったので Seeeduino XIAO Groveシールド を使うことにする。

接続はこうした。 image01

Android Studio + Kotlin

最近はKotlin推しがつよいので何もしなくてもインストールしてすぐにKotlinでアプリを作れる。

https://developer.android.com/kotlin

Kotlin で Android アプリを開発する

Kotlin では、より質の高い Android アプリをより速く記述できます。Kotlin は最新の静的型付けのプログラミング言語で、プロフェッショナルな Android デベロッパーの 60% 以上に使用されており、生産性、デベロッパーの満足度、コードの安全性の向上に貢献しています。

Androidアプリのお手本

最初はお手本をマネするのが定石なので Android Views and Widgets Samples Repository リポジトリの中からそれっぽいのを探した結果,
Android RecyclerView Sample (Kotlin) をマネする。

スマホを開発者モードにして(連続してタップするやつ)
開発者向けオプションからワイヤレスデバッグをONにして Android Studioのターミナルから

$ adb pair 192.168.1.21:45351

ペア設定コードを入力

$ adb connect 192.168.1.21:45351

こんな感じでワイヤレスデバッグする。
お手本が動いたから, さわりながら休憩。

AndroidでUSBシリアル通信

AndroidスマホからSeeeduino XIAOの間はお互いのUSB-C端子をUSBケーブルでつないでいる。

Android OSとusb-serial-for-androidライブラリの支援を受けて, USB接続の上でお互いに「メッセージ」を通す。

https://developer.android.com/guide/topics/connectivity/usb?hl=ja

USB ホストとアクセサリの概要

Android は、さまざまな USB 周辺機器と Android USB アクセサリ(Android アクセサリ プロトコルを実装したハードウェア)を、USB アクセサリと USB ホストの 2 つのモードでサポートしています。USB アクセサリ モードでは、外部 USB ハードウェアが USB ホストとして動作します。アクセサリの例としては、ロボット コントローラ、ドッキング ステーション、診断機器や楽器、キオスク、カードリーダーなどがあります。これにより、ホスト機能を持たない Android 搭載デバイスが USB ハードウェアと情報をやり取りできるようになります。Android USB アクセサリは、Android 搭載デバイスと連携するように設計されている必要があり、また Android アクセサリ通信プロトコルに準拠している必要があります。USB ホストモードでは、Android デバイスがホストとして動作します。デバイスの例としては、デジタルカメラ、キーボード、マウス、ゲーム コントローラなどがあります。幅広い用途や環境向けに設計された USB デバイスが、そうしたデバイスと正しく通信できる Android アプリと情報をやり取りすることが可能です。

図 1 は 2 つのモードの違いを示しています。Android 搭載デバイスをホストモードにすると、Android デバイスは USB ホストとして動作し、バスに電源を供給します。Android 搭載デバイスを USB アクセサリ モードにすると、接続された USB ハードウェア(この場合は Android USB アクセサリ)がホストとして動作し、バスに電源を供給します。

AndroidスマホからSeeeduino XIAOに電源を供給するんで 「ホストモード」になる。

https://developer.android.com/guide/topics/connectivity/usb/host?hl=ja

USB ホストの概要

Android 搭載デバイスを USB ホストモードにすると、Android 搭載デバイスは USB ホストとして動作し、バスに電源を供給して、接続されている USB デバイスを列挙します。USB ホストモードは Android 3.1 以降でサポートされています。

usb-serial-for-androidライブラリ

Android用USBシリアル通信ライブラリを使わせてもらう。

https://github.com/mik3y/usb-serial-for-android

READMEの指示通り

にSeeeduino XIAO(vendor-id: 0x2886, product-id: 0x002f)を追加する。

USBView

Vendor ID/Device ID が突然出て来たけど, WindowsにあるUSBViewというアプリケーションで得たもの。

https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/usbview

ユニバーサル シリアル バス ビューアー (USBView) または USBView.exe は、ご使用のコンピューター上のすべての USB コントローラーと接続されている USB デバイスを参照するために使用できる Windows グラフィカル UI アプリです。 USBView は、すべてのバージョンの Windows で動作します。

USBViewを使って (Circuit Pythonが動作している)Seeeduino XIAO を参照するとこんな情報を得られる。

[Port3]  :  USB Composite Device


Is Port User Connectable:         yes
Is Port Debug Capable:            no
Companion Port Number:            7
Companion Hub Symbolic Link Name: USB#ROOT_HUB30#5&1b0850fa&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
Protocols Supported:
 USB 1.1:                         yes
 USB 2.0:                         yes
 USB 3.0:                         no

Device Power State:               PowerDeviceD0

       ---===>Device Information<===---
English product name: "Seeeduino XIAO"

ConnectionStatus:                  
Current Config Value:              0x01  -> Device Bus Speed: Full (is not SuperSpeed or higher capable)
Device Address:                    0x05
Open Pipes:                           9

          ===>Device Descriptor<===
bLength:                           0x12
bDescriptorType:                   0x01
bcdUSB:                          0x0200
bDeviceClass:                      0x00
*!*ERROR: device class should be Multi-interface Function 0xEF
          When IAD descriptor is used
bDeviceSubClass:                   0x00
*!*ERROR: device SubClass should be USB Common Sub Class 2
          When IAD descriptor is used
bDeviceProtocol:                   0x00
*!*ERROR: device Protocol should be USB IAD Protocol 1
          When IAD descriptor is used
bMaxPacketSize0:                   0x40 = (64) Bytes
idVendor:                        0x2886 = Seeed Technology Co., Ltd.
idProduct:                       0x002F
bcdDevice:                       0x0100
iManufacturer:                     0x02
     English (United States)  "Seeed"
iProduct:                          0x03
     English (United States)  "Seeeduino XIAO"
iSerialNumber:                     0x01
     English (United States)  "E502920D45B435050213E233A22280FF"
bNumConfigurations:                0x01

          ---===>Open Pipes<===---

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x10

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x84  -> Direction: IN - EndpointID: 4
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x08

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x04  -> Direction: OUT - EndpointID: 4
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x08

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x82  -> Direction: IN - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x83  -> Direction: IN - EndpointID: 3
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x03  -> Direction: OUT - EndpointID: 3
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x05  -> Direction: OUT - EndpointID: 5
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x85  -> Direction: IN - EndpointID: 5
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

       ---===>Full Configuration Descriptor<===---

          ===>Configuration Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x02
wTotalLength:                    0x00DA  -> Validated
bNumInterfaces:                    0x06
bConfigurationValue:               0x01
iConfiguration:                    0x00
bmAttributes:                      0x80  -> Bus Powered
MaxPower:                          0x32 = 100 mA

          ===>IAD Descriptor<===
bLength:                           0x08
bDescriptorType:                   0x0B
bFirstInterface:                   0x00
bInterfaceCount:                   0x02
bFunctionClass:                    0x02  -> This is Communications (CDC Control) USB Device Interface Class
bFunctionSubClass:                 0x02
bFunctionProtocol:                 0x00
iFunction:                         0x00

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x00
bAlternateSetting:                 0x00
bNumEndpoints:                     0x01
bInterfaceClass:                   0x02  -> This is Communications (CDC Control) USB Device Interface Class
bInterfaceSubClass:                0x02
bInterfaceProtocol:                0x00
iInterface:                        0x04
     English (United States)  "CircuitPython CDC control"
  -> This is a Communications (CDC Control) USB Device Interface Class

          ===>Descriptor Hex Dump<===
bLength:                           0x05
bDescriptorType:                   0x24
05 24 00 10 01 
  -> This is a Communications (CDC Control) USB Device Interface Class

          ===>Descriptor Hex Dump<===
bLength:                           0x05
bDescriptorType:                   0x24
05 24 01 01 01 
  -> This is a Communications (CDC Control) USB Device Interface Class

          ===>Descriptor Hex Dump<===
bLength:                           0x04
bDescriptorType:                   0x24
04 24 02 02 
  -> This is a Communications (CDC Control) USB Device Interface Class

          ===>Descriptor Hex Dump<===
bLength:                           0x05
bDescriptorType:                   0x24
05 24 06 00 01 

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x10

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x01
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0x0A  -> This is a CDC Data USB Device Interface Class
bInterfaceSubClass:                0x00
bInterfaceProtocol:                0x00
iInterface:                        0x05
     English (United States)  "CircuitPython CDC data"

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x82  -> Direction: IN - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x02
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0x08  -> This is a Mass Storage USB Device Interface Class
bInterfaceSubClass:                0x06
bInterfaceProtocol:                0x50
iInterface:                        0x06
     English (United States)  "CircuitPython Mass Storage"

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x83  -> Direction: IN - EndpointID: 3
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x03  -> Direction: OUT - EndpointID: 3
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x03
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0x03  -> HID Interface Class
bInterfaceSubClass:                0x00
bInterfaceProtocol:                0x00
iInterface:                        0x07
     English (United States)  "CircuitPython HID"

          ===>HID Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x21
bcdHID:                          0x0111
bCountryCode:                      0x00
bNumDescriptors:                   0x01
bDescriptorType:                   0x22 (Report Descriptor)
wDescriptorLength:               0x00C3

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x84  -> Direction: IN - EndpointID: 4
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x08

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x04  -> Direction: OUT - EndpointID: 4
bmAttributes:                      0x03  -> Interrupt Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x08

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x04
bAlternateSetting:                 0x00
bNumEndpoints:                     0x00
bInterfaceClass:                   0x01  -> Audio Interface Class
bInterfaceSubClass:                0x01  -> Audio Control Interface SubClass
bInterfaceProtocol:                0x00
iInterface:                        0x0B
     English (United States)  "CircuitPython Audio"

          ===>Audio Control Interface Header Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x24 (CS_INTERFACE)
bDescriptorSubtype:                0x01 (HEADER)
bcdADC:                          0x0100
wTotalLength:                    0x0009
bInCollection:                     0x01
baInterfaceNr[1]:                  0x05

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x05
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0x01  -> Audio Interface Class
bInterfaceSubClass:                0x03  -> MIDI Streaming Interface SubClass
bInterfaceProtocol:                0x00
iInterface:                        0x0A
     English (United States)  "CircuitPython MIDI"

          ===>Descriptor Hex Dump<===
bLength:                           0x07
bDescriptorType:                   0x24
07 24 01 00 01 25 00 

          ===>Descriptor Hex Dump<===
bLength:                           0x06
bDescriptorType:                   0x24
06 24 02 01 01 08 

          ===>Descriptor Hex Dump<===
bLength:                           0x06
bDescriptorType:                   0x24
06 24 02 02 02 00 

          ===>Descriptor Hex Dump<===
bLength:                           0x09
bDescriptorType:                   0x24
09 24 03 01 03 01 02 01 09 

          ===>Descriptor Hex Dump<===
bLength:                           0x09
bDescriptorType:                   0x24
09 24 03 02 04 01 01 01 00 

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x05  -> Direction: OUT - EndpointID: 5
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Descriptor Hex Dump<===
bLength:                           0x05
bDescriptorType:                   0x25
05 25 01 01 01 

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x85  -> Direction: IN - EndpointID: 5
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0040 = 0x40 bytes
bInterval:                         0x00

          ===>Descriptor Hex Dump<===
bLength:                           0x05
bDescriptorType:                   0x25
05 25 01 01 03 

これこれ

          ===>Device Descriptor<===
idVendor:                        0x2886 = Seeed Technology Co., Ltd.
idProduct:                       0x002F

参考
USB-シリアル変換器のデバイスファイル名を固定する

Communications Device Class

ライブラリにまかせる領域でも一応確認しておく。

[Port3]  :  USB Composite Device

(Circuit Pythonが動作している) Seeeduino XIAOはOSからUSB複合デバイスとして見えている。そのうちのこれ。

This is a Communications (CDC Control) USB Device Interface Class

Communications Device Class (CDCクラス)インターフェースと接続する。

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x00
bAlternateSetting:                 0x00
bNumEndpoints:                     0x01
bInterfaceClass:                   0x02  -> This is Communications (CDC Control) USB Device Interface Class
bInterfaceSubClass:                0x02
bInterfaceProtocol:                0x00
iInterface:                        0x04
     English (United States)  "CircuitPython CDC control"
  -> This is a Communications (CDC Control) USB Device Interface Class
          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x01
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0x0A  -> This is a CDC Data USB Device Interface Class
bInterfaceSubClass:                0x00
bInterfaceProtocol:                0x00
iInterface:                        0x05
     English (United States)  "CircuitPython CDC data"

確認のためusb.orgから資料をダウンロードしてきた。

usbcdc

page20

page21

bInterfaceClass: 0x02bInterfaceSubClass: 0x02 であるため
Communications Interface Class のサブクラスであるAbstract Control Modelサブクラスの存在を確認できる。

bInterfaceClass: 0x0A であるので Data Interface Class の存在も確認できる。

参考
USB CDCについて

このUSB接続は PSTN Device Model のサブクラスである ACMプロトコルを通じてアプリケーションからは(アナログ)モデムとして見えている。

つまり仮想COMポート。 モデムを接続してホストコンピュータに電話をかけて通信する端末みたいなもん。

以前にWindowsのRLoginと Seeeduino XIAO上のCurcuit Pythonとの間ですでに疎通確認をすましているので, あとはAndroidスマホ側を実装すれば通信できる。

リモコン信号解析器

赤外線リモコン信号の解析アプリケーション
で作った解析器をPureScriptからkotlinに持ってくる。

Maybe(Optional), Either, map, fold, foldMap, traverse … が必要なので ライブラリを探したらあったので使わしてもらいました。

なぜかREADME通りに入れられなかったので, こんなふうに1.0.0-SNAPSHOTを入れた。
https://github.com/ak1211/MyFirstApplication/blob/main/build.gradle

Kotlinで書く

もともとはこうで
https://github.com/ak1211/pi_hvac/blob/master/frontend/src/InfraredRemoteCode/Internal.purs

Kotlinではこんな風になった。
https://github.com/ak1211/MyFirstApplication/blob/main/infraredremote/src/main/java/com/example/infraredremote/InfraredRemote.kt

ついでにテストも付けておいた。
https://github.com/ak1211/MyFirstApplication/blob/main/infraredremote/src/test/java/DecodeTest.kt

赤外線リモコンコードは

なので, ありがたく頂戴した。

Curcuit Python プログラム

Androidアプリケーションの都合でちょっと改造してmain.pyをこうした。

# https://ak1211.com/7707 (main.py)
# Copyright 2021 Akihiro Yamamoto
# Licensed under the Apache License, Version 2.0
from digitalio import DigitalInOut, Direction
import board
import pulseio
import supervisor
import sys
import time
import array
import gc
# 受け付けるリモコンパルス数の最低長
ACCEPT_MIN_IR_PULSES = 40
# IRM
irm_pulse = pulseio.PulseIn(board.D0, maxlen=2000, idle_state=True)
# PWM
# carrier: 38kHz
# duty cycle: 1/3 = 65536/3 = 21845
pwm = pulseio.PWMOut(board.D1, duty_cycle=21845, frequency=38000, variable_frequency=False)
infrared_led_pulse = pulseio.PulseOut(pwm)
led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT
# LEDを消灯させる
led.value = 1
def output_pulse_to_console():
# LEDを点灯させる
led.value = 0
# パルス読み込み一時停止
irm_pulse.pause()
#
bytes = array.array('B')
bytes.append(ord('['))
for index in range(len(irm_pulse)):
for ch in str(irm_pulse[index]):
bytes.append(ord(ch))
bytes.append(ord(','))
bytes[len(bytes)-1] = ord(']')
# 返答
for ch in bytes:
sys.stdout.write(chr(ch))
sys.stdout.write("\r\n")
# パルス読み込み再開
irm_pulse.resume()
# LEDを消灯させる
led.value = 1
def serial_input_loop():
inputs = ""
for x in range(1*5000/1):
time.sleep(1/5000)
while supervisor.runtime.serial_bytes_available:
inputs += sys.stdin.read(1)
return inputs
while True:
if (len(irm_pulse) > ACCEPT_MIN_IR_PULSES):
output_pulse_to_console()
# 読み込んだパルスを消去する
irm_pulse.clear()
# ここで時間待ちのついでにシリアル入力をしておく
serial_inputs = serial_input_loop()
# 入力文字列を配列にする
start = serial_inputs.find('[')
end = serial_inputs.rfind(']')
if (end-start) > 1:
contents = serial_inputs[1+start:end]
to_output_pulses = array.array( 'H', [int(v.strip()) for v in contents.split(',')] )
if len(to_output_pulses) > ACCEPT_MIN_IR_PULSES:
# LEDを点灯させる
led.value = 0
# パルス読み込み一時停止
irm_pulse.pause()
# 読み込んだパルスを消去する
irm_pulse.clear()
# 赤外線リモコン信号送出
infrared_led_pulse.send(to_output_pulses)
# パルス読み込み再開
irm_pulse.resume()
# 返答
sys.stdout.write("ok")
sys.stdout.write("\r\n")
# LEDを消灯させる
led.value = 1
del to_output_pulses
del contents
#
del end
del start
del serial_inputs
gc.collect()
view raw main.py hosted with ❤ by GitHub

使ってみようAndroidアプリ

ここまでで Androidスマホ から USB-CDC ACMプロトコルで Seeeduino XIAO までつながった。

image03

image04

3144, 1654 (単位はマイクロ秒) これは 8T, 4T なので T=413.5μs (425μs typ.)
AEHAだとわかる。

参考
赤外線リモコンの通信フォーマット

何もしなくてもリモコン信号を受信してリストに追加するし, リストをタップすることで赤外線リモコン信号を送信する。

この動作は要約すると
Androidスマホ <---> Seeeeduino XIAO <---> エアコンとか
この3者で動いているマイクロコントローラとソフトウェアの間でメッセージを通している。

天井照明が反応しないのはパワー不足

天井の照明が赤外線リモコン信号に反応しない。

M5Stack用赤外線送受信ユニット は名前の通りM5Stack用なので。

https://docs.m5stack.com/en/unit/ir

M5GO_Unit_ir m5-ir ir-sch

5V

Seeeduino XIAO Groveシールド

xiao-schematic

3V3 = 3.3V

5Vを100%とすると3.3Vは67%しかないわけで, 赤外線LEDの出力は物足りなくなる。

天井に近づけたら反応するけれども, このページ「文ばっかやな」とおもったからバランスをとるために部品を集めて回路を作りましょうか。

送受信回路

パワーが物足りないのでブレッドボードを出してきた。

赤外線リモコン信号を記録して送信する学習リモコンをラズパイゼロでつくる。」でしたことと被っているけどまあええねん。
こんなん何度やってもいいですからね。

Seeeduino XAIOのMPUであるATSAMD21G18のデータシートより

atsamd21-953 atsamd21-954

各クラスタあたり46mA流せるのでI/Oポートから5mA位引っ張っても余裕かな。

赤外線LEDは同じもの(OSI5FU5111C-40)を4個つかってNPNトランジスタにはUTC製の2SC2655を使います。 2SC2655

これでいいか。 ir-driver