LILYGO TTGO T-Watch-2020が届いたので開発環境を作って動かしてみた


LILYGO TTGOからT-Watch-2020が登場。

販売ページ「LILYGO® TTGO T-Watch-2020 ESP32 Main Chip 1.54 Inch Touch Display Programmable Wearable Environmental Interaction
資料「https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library

発売直後に注文入れたのですが、発送される前に値下がりしてたり、中継地点のシンガポールにつくまで1ヶ月以上音沙汰がなかったりと、約2ヶ月かかるとは思いませんでした。

画像
画像

中身は本体とmicroUSBケーブルだけでした。

初代T-WatchはType-Cコネクタでしたが、microUSBだとは・・・

画像

横についているボタンを押しても電源が入らなかったので、microUSBで電源供給してみたところテストプログラムが実行されました。

画像

とりあえずは問題ないようです。

では、開発環境を作って書き換えましょう。

ドキュメントとして「https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library」と「T-Watch Document」が書かれていますが、後者の記述は微妙なので無視ですね。

初期設定

(1) Arduino IDEをインストール

Arduino IDEをダウンロードしてインストール。うちの環境はWindows10なので Microsoft Storeからインストールしました。

(2) TTGO_TWatch_Library ライブラリをインストール

https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library の「Clone or download」から「Download Zip」を選択してzipファイルをダウンロード。

Arduino IDEの[スケッチ]-[ライブラリをインクルード]-[ZIP形式のライブラリをインストール]にてダウンロードしたzipファイルを指定してインストール。

追加が成功すると画面下部に以下が表示されます。

また「ドキュメント\Arduino\libraries」に「TTGO_TWatch_Library-master」が作成されます。

(3) Arduino IDE Boards Managerにespressif社のURLを登録

Arduino IDEの[ファイル]-[環境設定]の「追加ボードマネージャのURL」に「https://dl.espressif.com/dl/package_esp32_index.json」を追加する。

(3) T-Watchを選択する

Arduino IDEの[ツール]-[ボード]-[ESP32 Arduino]-[TTGO T-Watch]を選択する。(下の方に登録されている)

(4) スケッチ例からSimple Watchを呼び出す

Arduino IDEの[ファイル]-[スケッチ例]-[TTGO T-Watch]-[lvgl]-[Simple Watch]を選択する。

(5-1) Simple WatchをT-Watch-2020用に書き換える(2020/06/28以降のTWatch_Libraryの場合)

2020/06/28以降のlvgl 7.0.0対応のTWatch_Libraryの場合、SimpleWatchを選択した場合にタブで表示される「config.h」にて使用するT-Watchのバージョンを選択するようになった。
T-Watch-2020を使用する場合は、下記の様に「//define LILYGO_WATCH_2020_V1」のコメントを削除する。

// => Hardware select
// #define LILYGO_WATCH_2019_WITH_TOUCH     // To use T-Watch2019 with touchscreen, please uncomment this line
// #define LILYGO_WATCH_2019_NO_TOUCH          // To use T-Watch2019 Not touchscreen , please uncomment this line
#define LILYGO_WATCH_2020_V1             //To use T-Watch2020, please uncomment this line


// => Function select
#define LILYGO_WATCH_LVGL                   //To use LVGL, you need to enable the macro LVGL

#include <LilyGoWatch.h>

(5-2) Simple WatchをT-Watch-2020用に書き換える(2020/06/28より前のTWatch_Libraryの場合)

2020/06/28より前のTWatch_Libraryの場合、「SimpleWatch」のファイル冒頭に「// #define LILYGO_TWATCH_2020_V1 // If you are using T-Watch-2020 version, please open this macro definition」とあるように、T-Watch-2020を使う場合はここのコメントを外す必要がある。

/*
Copyright (c) 2019 lewis he
This is just a demonstration. Most of the functions are not implemented.
The main implementation is low-power standby. 
The off-screen standby (not deep sleep) current is about 4mA.
Select standard motherboard and standard backplane for testing.
Created by Lewis he on October 10, 2019.
*/

#define LILYGO_TWATCH_2020_V1        // If you are using T-Watch-2020 version, please open this macro definition

#include <TTGO.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
<以下略>

こんな感じに書き換える。

(6) Simple Watchを日本時間対応にする

SimpleWatchの「gui.cpp」というタブ内で、時刻表示が「CST-8」と設定されているので、それを「JST-9」に書き換えます。

<略>
#include "FS.h"
#include "SD.h"

#define RTC_TIME_ZONE   "JST-9"


LV_FONT_DECLARE(Geometr);
<略>

こんな感じです。

また、「gui.cpp」ではNTPサーバの接続先も設定されています。標準は「pool.ntp.org」ですが、日本国内の「ntp.jst.mfeed.ad.jp」(INTERNET MULTIFEED運営)や「ntp.nict.jp」(NICT運営)に書き換えてください。

(7) T-Watch-2020をパソコンにつなげます

microUSBケーブルを使ってT-Watch-2020をつなげます。

USBシリアルCP2104用のドライバがインストールされていない場合は https://t-watch-document-en.readthedocs.io/en/latest/download/index.htmlCP2104の公式ページなどからSilicon Labs Virtual COM Port (VCP) Universal Driverを入手してインストールします。

(8) T-Watch-2020が接続されたCOMポートを指定します。

Arduino IDEの[ツール]-[シリアルポート]にてCOMポートを指定します。

Arduino IDEの[ツール]-[Upload Speed]は「1152000」と指定しています。この速度はT-Watchのサンプルコードのシリアル入出力で見かける速度指定なので使っています。

それ以外の項目は特に変えていません。

ちなみに「PortPop」というアプリをインストールしておくと、デバイスをつなぎWindows上でCOMポートとして認識した時点で、何番として認識されたのかを教えてくれるので便利です。

(9) コンパイルと書き込み

Arduino IDEの[スケッチ]-[マイコンボードに書き込み]を選択して、コンパイルと書き込みを実行します。

(10) 完成

WiFiをスキャンしてSSID一覧を作り、そこから接続先を選択し、キーを入力することで、ネットワークに接続し、NTPサーバから時刻同期を行う、ということが可能となりました。

画像
画像
画像

Simple Watchの操作は「画面タッチ」です。横の丸ボタンは画面ON/OFFのみのようです。

また、WiFi以外に「Settings」「SDcard」「Camera」などのメニューがありますが、現状未実装です。押しても何も発生しません。

次に作るものは、と製品紹介ページに載っている下記画像を実現できるソースコードを探してみたところ・・・

画像

LilyGoGui」でした。

画像

が・・・時間が変わらないのでおかしいな、とソースを見てみると、画面表示のサンプルなだけで、全てが固定表示だったという・・・

そっか・・・時計実装は自前でやらなきゃならないのか・・・

CentOS7でrshが使えない


古い環境から移行するために、CentOS7環境でのテストを実施中。

該当環境ではrshを使っていたので、CentOS7にrshパッケージを追加して、コマンドを実行してみると・・・

# rsh 192.168.100.101 hostname
poll: protocol failure in circuit setup
#
# firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client amqp amqps apcupsd audit bacula bacula-client bgp bitcoin bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector ctdb dhcp dhcpv6 dhcpv6-client distcc dns docker-registry docker-swarm dropbox-lansync elasticsearch etcd-client etcd-server finger freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client ganglia-master git gre high-availability http https imap imaps ipp ipp-client ipsec irc ircs iscsi-target isns jenkins kadmin kerberos kibana klogin kpasswd kprop kshell ldap ldaps libvirt libvirt-tls lightning-network llmnr managesieve matrix mdns minidlna mongodb mosh mountd mqtt mqtt-tls ms-wbt mssql murmur mysql nfs nfs3 nmea-0183 nrpe ntp nut openvpn ovirt-imageio ovirt-storageconsole ovirt-vmconsole plex pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster quassel radius redis rpc-bind rsh rsyncd rtsp salt-master samba samba-client samba-dc sane sip sips slp smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh steam-streaming svdrp svn syncthing syncthing-gui synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client upnp-client vdsm vnc-server wbem-http wbem-https wsman wsmans xdmcp xmpp-bosh xmpp-client xmpp-local xmpp-server zabbix-agent zabbix-server
#

「rsh」というのがあるが、これはサーバ側としての設定で、実際に設定しても状況は変わらない。

# firewall-cmd --permanent --zone=public --add-service=rsh
success
# firewall-cmd --reload
success
# rsh 192.168.100.101 hostname
poll: protocol failure in circuit setup
#

じゃぁ、ポートの何番を開けたらいいのかというあたりについて調べるとRedHat KB「rsh 接続が使用するポート数を確認する」が見つかる。

詳細はログインしないと見れないが、ログインしなくてもみれる部分に「しかし、ファイアウォールでその他のポート (512~1023) も許可しないと、接続が成功しません。」と書いてある。

基本的には1023番から順に使われていないポートを探していく、という設定になっている。

このため通常の実用上は1020~1023の4ポートをあけておけばなんとかなるようである。

なので、firewalldに対する設定としては「firewall-cmd –permanent –zone=public –add-port=1020-1023/tcp」で行うこととする。

# firewall-cmd --permanent --zone=public --add-port=1020-1023/tcp
success
# firewall-cmd --reload
success
# rsh 192.168.100.101 hostname
testserver
#

問題無く動作した。

TTGO T-Watch用開発環境の作り方2020年3月版


最初に入手したときと作成手法が変わっていたのでメモ書き

(1) Arduino IDEをインストール

Windowsの場合、Microsoft StoreからArduino IDEをインストールする。

(2)githubのTTGO_TWatch_LibraryをArduino IDEに組み込む

githubの https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library にて「Download ZIP」を行い、T-Wach用ライブラリzipをダウンロード。

次にArduino IDEを起動して、「スケッチ」-「ライブラリをインクルード」-[.ZIP形式のライブラリをインストール」を選択し、ダウンロードしたT-Watch用ライブラリzipを読み込む。

この結果、「スケッチ」-「ライブラリをインクルード」を開くと下の方にある「提供されたライブラリ」の下に「TTGO T-Watch」が追加される。

(3)Ardbuino IDEのボードマネージャにESP32を追加

Installation instructions using Arduino IDE Boards Manager」に書いてあるとおりだけど、「ファイル」-「環境設定」を開き、「追加のボードマネージャのURL」に「 https://dl.espressif.com/dl/package_esp32_index.json 」を追加します。

なお、既にURLが書かれている場合は「,」で区切ることで複数のURLを記述できます。

追加した後は「ツール」-「ボード」-「ボードマネージャ」を選択し、検索欄に「esp32」と入力すると、「esp32 by Espressif SYstems」というのが登場しますので、それをインストールします。

(4) ボードでTTGO T-Watchを選択する

「ツール」-「ボード」から「TTGO T-Watch」を選択する。

Windowsのシリアルポートの番号確認バッチファイル


WindowsでUSBシリアルを繋いだ場合、そのCOM番号が何になったのかを確認するにはデバイスマネージャーの表示で確認する必要がある。

まぁ、いちいち面倒なので、ポートが認識されるとポップアップ表示をしてくれる「PortPop」とか、GUIで一覧を表示する「ViewComPorts」があったりする。

で、ViewComPortsを試してみようと思ったら、こちらはコンパイル済みバイナリが無い・・・ソースを見てみるとWMIから情報を引っ張っているっぽい。

ということはPowerShellで実装できるのでは?

と試してみたところ成功

バッチファイルの内容は下記3行。

@echo off
powershell -sta -ExecutionPolicy Unrestricted -Command "Get-WmiObject -Class Win32_PnPEntity -Filter \"PNPClass='Ports'\" | select Name,Manufacturer,DeviceID"
pause

なお、最初オンボードのIntel Active Managamentが「Service:Serial」だったので、それでfilterしようとしたら、FDTIのは「Service:FTSER2K」だったので、両方に共通の「PNPClass:Ports」を選択しています。

FDTIのWMI出力サンプル

__GENUS                     : 2
__CLASS                     : Win32_PnPEntity
__SUPERCLASS                : CIM_LogicalDevice
__DYNASTY                   : CIM_ManagedSystemElement
__RELPATH                   : Win32_PnPEntity.DeviceID="FTDIBUS\\VID_0403+PID_6001+FTHG96ISA\\0000"
__PROPERTY_COUNT            : 26
__DERIVATION                : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER                    : WIN10PC
__NAMESPACE                 : root\cimv2
__PATH                      : \\WIN10PC\root\cimv2:Win32_PnPEntity.DeviceID="FTDIBUS\\VID_0403+PID_6001+FTHG96ISA\\0000"
Availability                : 
Caption                     : USB Serial Port (COM4)
ClassGuid                   : {4d36e978-e325-11ce-bfc1-08002be10318}
CompatibleID                : 
ConfigManagerErrorCode      : 0
ConfigManagerUserConfig     : False
CreationClassName           : Win32_PnPEntity
Description                 : USB Serial Port
DeviceID                    : FTDIBUS\VID_0403+PID_6001+FTHG96ISA\0000
ErrorCleared                : 
ErrorDescription            : 
HardwareID                  : {FTDIBUS\COMPORT&VID_0403&PID_6001}
InstallDate                 : 
LastErrorCode               : 
Manufacturer                : FTDI
Name                        : USB Serial Port (COM4)
PNPClass                    : Ports
PNPDeviceID                 : FTDIBUS\VID_0403+PID_6001+FTHG96ISA\0000
PowerManagementCapabilities : 
PowerManagementSupported    : 
Present                     : True
Service                     : FTSER2K
Status                      : OK
StatusInfo                  : 
SystemCreationClassName     : Win32_ComputerSystem
SystemName                  : WIN10PC
PSComputerName              : WIN10PC

Intel Active ManagementのWMI出力サンプル

__GENUS                     : 2
__CLASS                     : Win32_PnPEntity
__SUPERCLASS                : CIM_LogicalDevice
__DYNASTY                   : CIM_ManagedSystemElement
__RELPATH                   : Win32_PnPEntity.DeviceID="PCI\\VEN_8086&DEV_A2BD&SUBSYS_82B4103C&REV_00\\3&11583659&1&B3"
__PROPERTY_COUNT            : 26
__DERIVATION                : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER                    : WIN10PC
__NAMESPACE                 : root\cimv2
__PATH                      : \\WIN10PC\root\cimv2:Win32_PnPEntity.DeviceID="PCI\\VEN_8086&DEV_A2BD&SUBSYS_82B4103C&REV_00\\3&11583659&1&B3"
Availability                : 
Caption                     : Intel(R) Active Management Technology - SOL (COM3)
ClassGuid                   : {4d36e978-e325-11ce-bfc1-08002be10318}
CompatibleID                : {PCI\VEN_8086&DEV_A2BD&REV_00, PCI\VEN_8086&DEV_A2BD, PCI\VEN_8086&CC_070002, PCI\VEN_8086&CC_0700...}
ConfigManagerErrorCode      : 0
ConfigManagerUserConfig     : False
CreationClassName           : Win32_PnPEntity
Description                 : Intel(R) Active Management Technology - SOL
DeviceID                    : PCI\VEN_8086&DEV_A2BD&SUBSYS_82B4103C&REV_00\3&11583659&1&B3
ErrorCleared                : 
ErrorDescription            : 
HardwareID                  : {PCI\VEN_8086&DEV_A2BD&SUBSYS_82B4103C&REV_00, PCI\VEN_8086&DEV_A2BD&SUBSYS_82B4103C, PCI\VEN_8086&DEV_A2BD&CC_070002, PCI\VEN_8086&DEV_A2BD&CC_0700}
InstallDate                 : 
LastErrorCode               : 
Manufacturer                : Intel
Name                        : Intel(R) Active Management Technology - SOL (COM3)
PNPClass                    : Ports
PNPDeviceID                 : PCI\VEN_8086&DEV_A2BD&SUBSYS_82B4103C&REV_00\3&11583659&1&B3
PowerManagementCapabilities : 
PowerManagementSupported    : 
Present                     : True
Service                     : Serial
Status                      : OK
StatusInfo                  : 
SystemCreationClassName     : Win32_ComputerSystem
SystemName                  : WIN10PC
PSComputerName              : WIN10PC

rsyncによるディレクトリ同期を行う際、並列実行により高速化する手法


rsyncを高速化するために、分散して実行することにした。

全部を1つのスクリプトとしてもいいのだが、デバグがしやすいように分割して作業を行えるようにしている。

また、下記の記述はLinuxの/usrをコピーすることを想定している。環境に応じて書き換えること。

まず、/usr/xxx以下にあるファイルまでをコピーするために以下を実行する。

# rsync --archive -v --exclude="*/*/" /usr/ /mnt/vol/voltest

このexcludeオプションをつけている場合、「/usr/xxx/yyy」のファイルとシンボリックリンクはコピーされる。しかし「/usr/xxx/zzz/」のディレクトリはコピーされない。

次に、「/usr/xxx/zzz/」のディレクトリ一覧を取得する。

# find /usr -mindepth 2 -maxdepth 2 -type d -print

このディレクトリ一覧を下記のperlスクリプトに食わせる。(下記スクリプトは” find /usr -mindepth 2 -maxdepth 2 -type d -print > list.txt”で取得したlist.txtを使う想定)

#!/usr/bin/perl

use threads;
use Thread::Queue;

my $LOGDIR="/root/test";
my $MAXSESSION=5;

my $sourcepathbase="/usr";
my $destpathbase="/mnt/vol/voltest";

my $stream = Thread::Queue->new;

open(FILE,"list.txt");
while(my $tmp=<FILE>){
        $stream->enqueue("$tmp");

}
close(FILE);

sub SyncExecute{
        while(my $str = $stream->dequeue){
                # 改行削除
                $str =~ s/\n//ig;
                $str =~ s/\r//ig;
                # ログ出力用ファイル名
                my $filename=$str;
                $filename =~ s/\//-/ig;
                $filename =~ s/\.//ig;
                $filename =~ s/-$//ig;
                $filename =~ s/#//ig;
                $filename =~ s/^-//ig;
                $filename =~ s/ //ig;
                my $logfile="$LOGDIR/test-$filename.log";
                # rsync元と先の処理
                my $tmp,$st,$ed;
                my $sourcepath,$destpath;
                $tmp=substr($str,0,1);
                if($tmp eq "/"){
                        $sourcepath=$sourcepathbase.$str."/";
                        $destpath=$destpathbase.$str;
                }else{
                        $sourcepath=$sourcepathbase."/".$str."/";
                        $destpath=$destpathbase."/".$str;
                }
                `date >> $logfile`;
                print "rsync -v --archive $sourcepath $destpath >> $logfile 2>&1 \n";
                `rsync -v --archive $sourcepath $destpath >> $logfile 2>&1 `;
                `date >> $logfile`;
                #`sleep 5`;
        }
}


my @kids;
foreach(1..$MAXSESSION){
        my $kid = threads->new(\&SyncExecute,$stream);
        push(@kids,$kid);
        $stream->enqueue(undef);
}


print "wait\n";

foreach(@kids){
        my ($return) =$_ -> join;
}

このスクリプトは、rsyncの同時実行数5で、並列にrsyncを実行していくものになっている。

実行したサーバの負荷状況に応じて「my $MAXSESSION=5;」で設定している 同時実行数 を調整する。あまり大きくしすぎるとサーバからの応答が遅くなりすぎるのでほどほどに・・・


2020/03/10追記

上記で実行するrsyncコマンドはハードリンクの処理を行わないものとなっている。

このため、ハードリンクされているファイルがある場合、コピー先のファイルが1つではなく複数別個のものとしてコピーされる。

ハードリンクをそのままコピーしたい場合は「–hard-links」オプションを追加する必要があるのだが、ハードリンク処理の効力範囲は同一プロセス内で処理すること、という条件があるため、今回のような分割処理して高速化する、という場合には不適切となっている。

このため、ハードリンクファイルがある場合は、初回同期は分割処理で行い、2回目はディレクトリ全体を–hard-linksオプションをつけて1プロセスで処理してハードリンク処理を行わせる、という手法をとる必要がある。

なお、ハードリンク処理が完了したあと、分割処理の対象となった場合、すでにファイルが存在しているので再コピーされる、ということは発生しない。