2021年6月16日 (水)

Headless RaspberryPi(64bits)インストール方法(USB/SSD boot)

2021/6/20
「CPUクロック状況」を追加した。

2021/6/19
「32bits SSD boot」について追加した。

2021/6/16+ 初版

headless RaspberryPi 64bits,USB/SSD boot

headless RaspberryPi 64bits, USB/SSD boot

概要

Headless RaspberryPi(64bits)インストール方法(USB/SSD boot)
表示装置を接続しないでPCを運用することをheadlessというが、ここでは、最初のbootからRaspberryPiをheadlessで使う方法についてまとめた。ここでは、「headless RaspberryPiインストール方法(v2) 」の発展形として、raspberry-pi-4を64bitsモードかつUSB/SSD-bootで動かすこととする。

事前準備(ホストPC側(linux))

以下のdeamonをインストールする:

sudo apt-get update sudo apt-get install avahi-daemon

sshのポートを開くための設定:

sudo ufw allow ssh

Downloading raspbian image

以下から以下の手順で64bitsイメージをダウンロードする。

cd ~/Downloads wget https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2021-05-28/2021-05-07-raspios-buster-arm64.zip

・2021/6時点では、64bitsイメージは、上のベータ版のみである。

書き込みツール(Etcher)の準備

本ツールで使用するライブラリを以下の手順でインストールする。

suso apt update sudo apt install zenity

以下の手順でツール自身をダウンロードする:

cd ~/Downloads wget https://github.com/balena-io/etcher/releases/download/v1.5.120/balena-etcher-electron-1.5.120-linux-x64.zip #ダウンロードしたzipを解凍すると以下のディレクトリができる: $ ls balena-etcher-electron-1.5.120-linux-x64 balenaEtcher-1.5.120-x64.AppImage #このxxxx.AppImageをダブル・クリックすると書き込みツールが起動する

留意:入力ファイルは、.zipのままで良い。

参照:
LinuxにEtcherをインストールする
簡単な 3 ステップで使えるブートUSB 作成ツール!「balenaEtcher」
使用方法については上を参照のこと

M.2-SSDの初期化(PI4-CASE-ARGON-ONE-M.2使用の場合)

M.2-SSDを使用する場合、gpartedなどで、FAT32でフォーマットする必要がある。その後、書き込みツールでイメージを書き込む。

重要な注意:
ARGONのM.2-SSDは、PCで主流になっているNVMeではなく、SATAであるので注意のこと。(パソコン・ショップなどの店頭に出ているのはNVMeが多いようなので注意)

参考:
M.2 SSDの取り付け方
【2019年版】M.2 SSDとは?SATA接続とNVMe接続の違いについてもまとめました

ブートデスク(SD/USB/SSD)作成

上の書き込みツールを使って、ダウンロードしたイメージを、SD,USB/SSDに書き込む。
なお、SDは、ブートコード(rpi-eeprom)書き込み/確認用、USB/SSDは、実際に使用するブートディスクになる。

ただし、現状、書き込みツール(Etcher)で、USB3.0-SSD(M.2-SSDを含む)を書き込んだ場合、ブートデバイスにならないようだ。そのため、USB3.0-SSDをブートデバイスにする場合、SD/USBでブートした後、VNCで接続して以下の手順でブートデバイスを作成する:
(つまり、raspberry-pi自身でブートデバイスを作成する必要がある)

/************************************************************
VNCでログイン後、
(0)ブートデバイスにしたいデバイスをUSB接続し、アンマウントにする
(1)[Raspberry Menue/Accessories/SD Cord Copier]を起動する
(2)Copy From Devide:ブートしたSD/USBのデバイス名を選択する
(3)Copy TO Device:書き込むデバイス(ブートデバイスにしたいデバイス)を選択する
(4)[New Partition UUIDs]にチェックを入れる
(5)[Start]をクリックして書き込みを実行する
************************************************************/

作成したブートディスク(SD,USB/SSD)は以下に述べるようにホストPCに接続して変更を施す:
([SD Card Copier]を使う場合を除く)

boot/rootfsディレクトリのファイル追加/修正

書き込んだSD/USB/SSDをいったん取り外し、再度、挿入する。 すると、boot/rootfsディレクトリが出現する。

(1)ssh有効化
bootにsshという名前のファイルを作成する。(ファイル内容は空で良い)

(2)wireless設定
bootにwpa_supplicant.confという名前で 以下の内容のファイルを作成する:

wpa_supplicant.conf
(複数のSSIDを設定する例)

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=JP network={ ssid="<Name of your WiFi>" psk="<Password for your WiFi>" priority=1 id_str="<ID1(任意)>" } network={ ssid="<Name of your WiFi>" psk="<Password for your WiFi>" priority=2 id_str="<ID2(任意)>" }

接続するssidの方式はWAPかWPA2であること
(WEPでは接続できないようだ)

rootfsディレクトリに対して以下を行なう:
(3)hostnameを変更するために
以下の2つのファイルに記述されているhostnameを 新しいものにエディタで変更(編集)する。
(書き込み権限が必要なので「sudo」を付ける必要がある)

#「raspberrypi」を任意の名前に変更する # USERは自分の環境に合わせる sudo nano /media/USER/rootfs/etc/hostname sudo nano /media/USER/rootfs/etc/hosts

(4)該当SD/USB/SSDを取り出す boot,rootfsをアンマウントする。

(5)該当USB/SSDのext4パーティションのリサイズ
起動後、raspi-configでリサイズ可能だが、遅いという話もあるようなので、gpartedなどで、ext4パーティションをリサイズしておく。(拡張する)

SD-Boot

ここでは、ブートコード(rpi-eeprom)をアップデートするために 書き込んだSDをRaspberryPiのボードに刺し、電源をオンする。(起動する)
ボードのLEDが点滅し始めて、常灯するまで待つ。

SD-Login

ホストPCで接続を確認するために
(名前解決に時間がかかるので)
以下のコマンドを成功するまで繰り返す。
ping raspberrypi.local

出力ログ例:

$ ping raspberrypi.local PING raspberrypi.local (192.168.0.26) 56(84) bytes of data. 64 bytes from 192.168.0.26: icmp_seq=1 ttl=64 time=39.4 ms 64 bytes from 192.168.0.26: icmp_seq=2 ttl=64 time=78.2 ms 64 bytes from 192.168.0.26: icmp_seq=3 ttl=64 time=10.0 ms 64 bytes from 192.168.0.26: icmp_seq=4 ttl=64 time=9.81 ms 64 bytes from 192.168.0.26: icmp_seq=5 ttl=64 time=18.9 ms ^C --- raspberrypi.local ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4005ms rtt min/avg/max/mdev = 9.816/31.306/78.254/25.833 ms

どうしても接続確認ができないようなら「arp -a」を入力して、接続中のPCのIPアドレスを表示させて、RaspberryPiのIPアドレスを推定する。

接続確認が終わったら以下のコマンドを入力してloginする:
(デフォルトのパスワードはraspberry)

ssh pi@raspberrypi.local

SD-login後

以下のコマンドでブートコード(rpi-eeprom)をアップデートする:

sudo apt update sudo apt full-upgrade sudo reboot #ここで、いったんリブートする sudo rpi-eeprom-update sudo vcgencmd bootloader_version #-------------------------------- # 以下、出力例- $ sudo rpi-eeprom-update BOOTLOADER: up to date CURRENT: Thu Apr 29 16:11:25 UTC 2021 (1619712685) LATEST: Thu Apr 29 16:11:25 UTC 2021 (1619712685) RELEASE: stable (/lib/firmware/raspberrypi/bootloader/stable) Use raspi-config to change the release. VL805_FW: Using bootloader EEPROM VL805: up to date CURRENT: 000138a1 LATEST: 000138a1 $ sudo vcgencmd bootloader_version Apr 29 2021 17:11:25 version cf8c388c4ee37ad709ace403467d163e8dd91ce (release) timestamp 1619712685 update-time 1623061523 capabilities 0x0000001f #上の出力の場合、既に最新版になっている #最新版にする場合は以下を実行する sudo rpi-eeprom-update -d -a #-------------------------------- #ブート順序の変更 sudo raspi-config Choose 6 "Advanced Options", then click 'Enter'. Coose A6 "Boot Order", click 'Enter'. Choose B1 "SD Card Boot ..., otherwise boot from USB" or B2 "USB Boot", click 'Enter #「SDがない場合、USBブート」 か 「USBブートのみ」に設定する 

ここまで、設定したら、rpiの電源を落として、SDを取り出してブートUSBを挿して再起動する.
ここの状態でeepromがUSBからブートできる状態になっている。

VNC-serverの設定

headlessといえども、なにかを設定する際、guiのほうが設定しやすいことがあるので、VNC-serverを設定する。(直近の例では「SD Card Copier」を利用するためにVNCが必要となる)
「sudo raspi-config」を実行して 以下の値に設定する:

設定値: ・3 Boot Options B1 Desktop / CLI B4 Desktop Autologin Desktop GUI, automatically logged in as 'pi' user ・5 Interfacing Options P3 VNC ⇒ Enable  ・7 Advanced Options A5 Resolution DMT Mode 85 1280x720 60Hz 16:9    (使用しているモニターのサイズに合わせて7種類から選択する)

設定後、rebootする。 なお、上の設定でなく「Login Desktop GUI」(Autoでない)でも良い。
(raspi-configのメニューはバージョンによって変更になるので注意のこと)

VNC-severについては、以下の記事を参考した:
【解決】Raspberry Pi4 VNC接続で画面が出ない!!

なお、ホストPC側のRealVNC-viewerは以下のurlからダウンロードできる: https://www.realvnc.com/en/connect/download/viewer/linux/

ダウンロードしたファイルは実行形式なので実行属性を与えて実行する。

USB/SSD-boot後

ログインしたら開発ツールとして使用するために以下を実行する:
(既にインストール済みのものもある)

#linuxのバージョンの確認 uname -a #出力 Linux xxxx 5.10.17-v8+ #1414 SMP PREEMPT Fri Apr 30 13:23:25 BST 2021 aarch64 GNU/Linux #aarch64が表示されていれば64bitsである #RAM容量の確認 free -h #出力 total used free shared buff/cache available Mem: 7.6Gi 220Mi 7.1Gi 24Mi 299Mi 7.3Gi Swap: 99Mi 0B 99Mi #Mem:が8GB弱ならば、RAM-8GB版になる #releaseの詳細 cat /etc/os-release #出力 PRETTY_NAME="Debian GNU/Linux 10 (buster)" NAME="Debian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" #まだ、debianのままになっている #ブートコード(rpi-eeprom)の状況 cat /etc/default/rpi-eeprom-update #出力 FIRMWARE_RELEASE_STATUS="stable" #ケースとしてPI4-CASE-ARGON-ONEを使用している場合、以下を実行する: curl https://download.argon40.com/argon1.sh | bash #<------------------------------------------ #出力例: out: *************************** Argon One Setup Completed. *************************** You may need to reboot for changes to take effect Use argonone-config to configure fan Use argonone-uninstall to uninstall #>------------------------------------------ argonone-ir #<------------------------------------------ #出力例: -------------------------------- Argon One IR Configuration Tool -------------------------------- WARNING: This only supports NEC protocol only. Press Y to continue:Y Thank you. Select remote control to configure: 1. Configure Remote ON/OFF Button 2. Cancel Enter Number (1-2):1 Select remote control to configure: 1. Use Argon Remote ON/OFF Button 2. Use Custom Remote ON/OFF Button 3. Cancel Enter Number (1-3):1 Updating Device... Thank you. #>------------------------------------------ sudo apt update sudo apt install net-tools sudo apt install git curl sudo apt install gcc-arm-none-eabi build-essential sudo apt install cmake sudo apt install libusb-dev sudo apt install libusb-1.0-0-dev sudo apt install picocom sudo apt install python3-distutils sudo apt install python3-venv pip3 install pyserial #bt(bootterm)のインストール mkdir ~/tools/bt cd ~/tools/bt git clone https://github.com/wtarreau/bootterm cd bootterm make sudo make install #64bitsのライブラリのインストール sudo dpkg --add-architecture armhf sudo apt install libstdc++6-8-dbg:armhf sudo apt install libstdc++:armhf

platformioのインストール

以下の手順を実行する:

mkdir ~/pio_ws cd ~/pio_ws python3 -m venv pio_env source pio_env/bin/activate pip3 install platformio #インストール後も、このツールを使用する場合 #同じディレクトリで以下を実行する: #source pio_env/bin/activate # 「source」は、「.」でも良い #udev登録 #以下を実行して、udevのrulesを登録する: curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules sudo udevadm control --reload-rules sudo usermod -a -G dialout $USER sudo usermod -a -G plugdev $USER

platformio.iniの変更

基本的には、そのまま使用可能だが、ARM64bitsライブラリの整備状況や実行環境の違いから以下の修正が必要である:

1.ARM系コンパイラを使用する場合、最新のものが用意されていないので platformio.iniに以下を追加する:
(古いバージョンを使用する)

platform_packages = toolchain-gccarmnoneeabi @ 1.50401.1

2.シリアルポートは(rpiの場合、別のシリアルが有効になっているので)明示する必要がある。したがって以下をplatformio.iniに追加する必要がある:

upload_port = /dev/ttyACM0

3.プロジェクト・ディレクトリごと外部から持ってきた場合、以下の手順で、いったん環境を消去する必要がある:

cd proj_dir #環境の消去 rm -r .pio #必要ツールのダウンロード pio run -t clean

ブート後のディスク関連の状況(参考)

ネット情報を見ているとブートできない状況もあるようなので、ブートに成功した状況を以下に挙げる:

M.2-SSD boot時

$ lsusb -t /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 2: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M $ lsusb Bus 002 Device 002: ID 174c:55aa ASMedia Technology Inc. Name: ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub $ cat /boot/cmdline.txt console=serial0,115200 console=tty1 root=PARTUUID=089c4630-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles $ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 458G 7.1G 427G 2% / devtmpfs 3.7G 0 3.7G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 8.6M 3.9G 1% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/sda1 253M 30M 223M 12% /boot tmpfs 782M 4.0K 782M 1% /run/user/1000 $ sudo dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 920649728 bytes (921 MB, 878 MiB) copied, 4 s, 230 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 6.93637 s, 155 MB/s #M.2-SSDの速度として、155 MB/sくらい出ている

USB boot時(その1)

$ dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 939524096 bytes (940 MB, 896 MiB) copied, 4 s, 235 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 35.7583 s, 30.0 MB/s #USBの速度として、30 MB/sくらい出ている

USB boot時(その2,別デバイス)

$ sudo dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 1067450368 bytes (1.1 GB, 1018 MiB) copied, 68 s, 15.7 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 73.9804 s, 14.5 MB/s #USBの速度として、14.5 MB/sくらい出ている

上のようにUSBはデバイスによって速度が大きく異なるようだ。
(乱暴な言い方だと、同じメーカでも価格が高いほうが速いようだ)

SSD boot時

$ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 458G 7.1G 427G 2% / devtmpfs 3.7G 0 3.7G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 8.6M 3.9G 1% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/sda1 253M 30M 223M 12% /boot tmpfs 782M 4.0K 782M 1% /run/user/1000 $ lsusb -t /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 2: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M $ lsusb Bus 002 Device 002: ID 174c:1153 ASMedia Technology Inc. ASM1153 SATA 3Gb/s bridge Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub $ cat /boot/cmdline.txt console=serial0,115200 console=tty1 root=PARTUUID=a77ed9b6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles $ sudo dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 921698304 bytes (922 MB, 879 MiB) copied, 4 s, 230 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 7.47227 s, 144 MB/s #SSDの速度として、144 MB/sくらい出ている

(1)HDDアダプターとして以下を使用してブートに成功した。
USB3.0接続 2.5型 SATA SSD/HDDケース(ホワイト)
(2)以下は同じSSDを使用してもブートが失敗した。
MOBILE BOX USB3.0接続 SATA6G 2.5インチHDD/SSDケース (CMB25U3SV6G / CMB25U3GD6G / CMB25U3BK6G / CMB25U3BL6G / CMB25U3RD6G)

SSD boot時
(SSDは、そのままで、Driverをuasからusb-storageに変更した例)

$ lsusb -t /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 2: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage(←ここが変更になっている), 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M $ lsusb Bus 002 Device 002: ID 174c:1153 ASMedia Technology Inc. ASM1153 SATA 3Gb/s bridge Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub $ cat /boot/cmdline.txt usb-storage.quirks=174c:1153:u console=serial0,115200 console=tty1 root=PARTUUID=a77ed9b6-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles #↑「usb-storage.quirks=...」によって、usb-storageに切り替わっている sudo dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 931135488 bytes (931 MB, 888 MiB) copied, 4 s, 233 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 9.21296 s, 117 MB/s #SSDの速度として、117 MB/sくらい出ている #Driverがusb-strageになっているので若干遅くなっている?

SSD-bootを成功させるヒント(まとめ)

1.ブートディスク作成には[SD Card Copier]を使用する。
2.HDDアダプター(SATA SSD/HDDケース)にブート成功/失敗が依存する。
(つまり、ブート成功実績があるものを採用する)
3.HDDアダプターの採用チップが「ASMedia Technology Inc」製のものはブートが成功するようだ。

CPUクロック状況

以下の手順でCPUクロックの状況を知ることができる:

#ユーティリティをインストールする sudo apt install cpufrequtils #CPUガバナーを確認する sudo cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor #出力 ondemand #CPUクロックの設定を確認する cpufreq-info | grep "hardware limits" #出力 hardware limits: 600 MHz - 1.50 GHz hardware limits: 600 MHz - 1.50 GHz hardware limits: 600 MHz - 1.50 GHz hardware limits: 600 MHz - 1.50 GHz #実作のクロックを測定する場合 vcgencmd measure_clock arm #出力 frequency(48)=600117184 #1秒毎に実作のクロックを測定する場合 watch -n 1 vcgencmd measure_clock arm #1秒ごとのクロックの変化が表示される #別のセッションで重い処理が動くとクロックが高くなるのが測定できる

参照:How to overclock Raspberry Pi 4

なお、CPUガバナーの設定には ondemand 以外にも、 performance conservativeがあり、 以下のような動作になる:

  • performance: 1.50 GHz固定
  • ondemand: 600MHz 〜 1.50 GHz可変 (負荷に応じて変動)
  • conservative: 600MHz 〜 1.50 GHz可変 (負荷に応じてゆっくりと変動)
  • powersave: 600Mhz固定

32bits SSD boot 方法(おまけ)

32bitsでSSD-bootする場合、 既にeepromが、USB/SSD-bootできる状態になっているので、32bitsのUSB-boot用USBを作り、それでブートしたあと、VNCでログインして、「SD Card Copier」で ブートしたUSBの内容を接続したSSDにコピーすると、 boot-SSDができあがる。

実際には以下の手順になる:

HostPC: 0.32bitsイメージをダウンロードする cd ~/Downloads wget https://downloads.raspberrypi.org/raspios_full_armhf/images/raspios_full_armhf-2021-05-28/2021-05-07-raspios-buster-armhf-full.zip 1.書き込むツール(Etcher)で上でダウンロードしたイメージをUSBにコピーする 2.コピーしたUSBを上で説明した変更を施す。 rpi: 3.このUSBをrpiに挿してブートする。 4.ブート後、raspi-configで、VNCを有効にする。 5.rebootする。 6.VNCでログインする。 7.ブートSSDにしたいSSDを接続する。 8.「SD Card Copier」で、ブートしているUSBの内容を接続しているSSDにコピーする。

32bits SSD boot後の出力例:

$ uname -a Linux xxxx 5.10.17-v7l+ #1421 SMP Thu May 27 14:00:13 BST 2021 armv7l GNU/Linux $ free -h total used free shared buff/cache available Mem: 7.7Gi 151Mi 7.1Gi 30Mi 410Mi 7.3Gi Swap: 99Mi 0B 99Mi df -h Filesystem Size Used Avail Use% Mounted on /dev/root 458G 6.9G 428G 2% / devtmpfs 3.8G 0 3.8G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 8.6M 3.9G 1% /run tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/sda1 253M 48M 205M 19% /boot tmpfs 788M 4.0K 788M 1% /run/user/1000 $ sudo dd if=/dev/zero of=./dd.tmp ibs=1M obs=1M count=1024 status=progress 989855744 bytes (990 MB, 944 MiB) copied, 6 s, 165 MB/s 1024+0 records in 1024+0 records out 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 6.5634 s, 164 MB/s #USBの速度として、164 MB/sくらい出ている #32bitesのほうが64bitsよりも若干速いようだ。

参照URL

Pi OS 64 Bit 5/27/2021 release and libstdc++ #156
arduinoフレームワーク用platformio.ini集

raspi-config
Raspberry Pi 4 bootloader configuration
USB mass storage boot
NVMe SSD Boot (BETA)(CM4 only)

PI4-CASE-ARGON-ONE-M.2
PI4-CASE-ARGON-ONE

USB起動のRaspberry PiでアクセスLEDを点滅をさせない方法
64ビット版Raspberry Pi OSベータテスト版を動かしてみました

SSD関連:
ラズパイ4 で使える外付け2.5インチケースは?
ラズパイ4をUSB接続のSSDから起動する方法(USBブート)
Raspberry Pi 4でUSB3.0接続のSSDがとても遅い

以上

» 続きを読む

| | コメント (0)

2021年5月31日 (月)

vscodeでtexを編集する(lualatex)

2021/5/31
初版

VSCode TeX

VSCode TeX

概要

vscodeでtexを編集する方法について述べる。
Pandoc(+TeX)のインストール方法で述べたインストールが完了している前提とする。
ホスト環境はubuntuを想定する。

プラグインのインスール

VSCodeの以下のプラグインをインストールする:

LaTex Workshop LaTeX language support

LaTeX_Workshopの簡単な説明は「 LaTeX Workshopってなに?どうやって使うの?調べてみた! 」を参照のこと。

プラグイン「LaTex Workshop」の設定

以下のsetting.jsonを編集する:

Windows %APPDATA%\Code\User\settings.json #実際のファイルのロケーションは以下になる: C:\Users\USER\AppData\Roaming\Code\User\setting.json macOS $HOME/Library/Application Support/Code/User/settings.json Linux $HOME/.config/Code/User/settings.json #実際のファイルのロケーションは以下になる: ~/.config/Code/User/Setting.json

具体的には(ubuntuを使用しているので) ~/.config/Code/User/Setting.jsonを編集する。
setting.jsonの後ろに以下を追加する:

<既にあった設定> //LaTeX "latex-workshop.latex.recipes": [ { "name": "lualatex", "tools": [ "lualatex", ] }, { "name": "lualatex twice compile", "tools": [ "lualatex", "lualatex", ] }, ], "latex-workshop.latex.tools": [ { "name": "lualatex", "command": "lualatex", "args": [ "--cmdx", "-file-line-error", "-synctex=1", "-interaction=nonstopmode", "-halt-on-error", "%DOC%", ], }, ], "latex-workshop.latex.autoClean.run": "onBuilt", "latex-workshop.latex.autoBuild.run": "onFileChange", "latex-workshop.latex.autoBuild.interval": 0, "latex-workshop.view.pdf.viewer": "tab", }

・上のようにjson形式を崩さないように追加する

samples

通常のものとlualatexならではのlua言語を利用したものをサンプルとして挙げる。

sample.tex

%\documentclass[a4j,12pt]{jreport} \documentclass[a4j,12pt]{ltjreport} \title{ {\LaTeX} 動作確認テスト・サンプルファイル} \author{情報リテラシTA} \date{\today} \begin{document} \maketitle \chapter{\LaTeX の世界にようこそ!} \section{インストール成功!} \LaTeX の世界にようこそ!この文章が「dviout」というソフトで閲覧できていれば、 インストールに成功しています。 \LaTeX(ラテフ)もしくは\TeX(テフ)は、 組版処理を行うソフトウェアです。 数学者・コンピュータ科学者のドナルド・クヌース氏によって作られました。 このソフトを使うと、きれいな文章の作成ができます。実際に出版の現場でも使われているそうです。 数学者が作ったということもあって、特に数式の出力がきれいにできるのが特徴です。 \begin{eqnarray} & \displaystyle \lim _{x \rightarrow 1} \left( \frac{2}{x-1} - \frac{x+5}{x^3 -1} \right)\; ,\; & \displaystyle \int ^\pi _0 \cos ^2 (x)dx \nonumber \end{eqnarray} 2つの数式が、きちんと表示されていますか? 複雑な数式が入った文章も、きれいに出力することができます。 \section{基本手順} では、\LaTeX で文章を作る際の、基本的な手順をここに示します。 \begin{enumerate} \item ソースファイルをTeraPadなどのエディタで作成する。 ソース(素)となるファイルを作成します。これにはエディタと呼ばれるソフトを使います。 この地点では文章の形にはなっていません。 \item ソースファイルをコンパイルして、dviファイルを作成する。 パソコンに変換を命令して、先ほどつくったソースファイル をdviファイルに変換、文章の形にして確認します。 \item dviファイルができたことを確認したら、PDFに変換する。 dvi形式は、あまり一般的ではありません。 そこで、Adobe Readerなどで閲覧ができるPDF形式に変換します。 \end{enumerate} \end{document}

・lualatex向けに修正してある

neko.tex

%\documentclass[dvipdfmx]{jsarticle} \documentclass{ltjsarticle} \begin{document} 吾輩は猫である。名前はまだ無い。 どこで生れたかとんと見当がつかぬ。 何でも薄暗いじめじめした所で ニャーニャー泣いていた事だけは記憶している。 吾輩はここで始めて人間というものを見た。 \end{document}

・lualatex向けに修正してある

UpperRiemannSum.tex

% Animation for Upper Riemann Sum % Author: Edson Josテゥ Teixeira \documentclass[10pt]{beamer} %%%< \usepackage{verbatim} %%%> \begin{comment} :Title: Animation for Upper Riemann Sum :Tags: Mathematics :Author: Edson Josテゥ Teixeira :Slug: upper-riemann-sum An animation to the area of calculation using the upper Riemann sum. That's an approximation of an integral by a finite sum, named after the German mathematician Riemann. It is calculated by partitioning the region below the the curve into rectangles and summarizing their areas. To get a better approximation, the region is devided more finely. As the rectangles get smaller, the Rieman sum approaches the Riemann integral. This animation shows it. \end{comment} \usepackage[controls]{animate} \usepackage{tikz} \usetikzlibrary{arrows} % Beamer Settings \usetheme{Warsaw} % Counters \newcounter{higher} \setcounter{higher}{1} \begin{document} \begin{frame}[fragile]{Upper Riemann Sum} \begin{figure} \begin{animateinline}[poster = first, controls]{5} \whiledo{\thehigher<30}{ \begin{tikzpicture}[line cap=round, line join=round, >=triangle 45, x=4.0cm, y=1.0cm, scale=1] \draw [->,color=black] (-0.1,0) -- (2.5,0); \foreach \x in {1,2} \draw [shift={(\x,0)}, color=black] (0pt,2pt) -- (0pt,-2pt) node [below] {\footnotesize $\x$}; \draw [color=black] (2.5,0) node [below] {$x$}; \draw [->,color=black] (0,-0.1) -- (0,4.5); \foreach \y in {1,2,3,4} \draw [shift={(0,\y)}, color=black] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$}; \draw [color=black] (0,4.5) node [right] {$y$}; \draw [color=black] (0pt,-10pt) node [left] {\footnotesize $0$}; \draw [domain=0:2.2, line width=1.0pt] plot (\x,{(\x)^2}); \clip(0,-0.5) rectangle (3,5); \draw (2,0) -- (2,4); \foreach \i in {1,...,\thehigher} \draw [fill=black,fill opacity=0.3, smooth,samples=50] ({1+(\i-1)/\thehigher},{(1+(\i)/\thehigher)^2}) --({1+(\i)/\thehigher},{(1+(\i)/\thehigher)^2}) -- ({1+(\i)/\thehigher},0) -- ({1+(\i-1)/\thehigher},0) -- cycle; \end{tikzpicture} % \stepcounter{higher} \ifthenelse{\thehigher<30}{ \newframe }{\end{animateinline} } } \caption{Upper Riemann Sum} \end{figure} \end{frame} \end{document}

totoro.tex

% Totoro sitting in the snow % By Noa Hoffmann and Pascal Gテシnthner, 21.12.2020 \documentclass[tikz,11pt]{{standalone}} %%%< \usepackage{verbatim} %%%> \begin{comment} :Title: Totoro sitting in the snow :Tags: Foreach;Decorations;Pic;To paths;Fractals;Decorative drawings;Fun :Author: Noa Hoffmann;Pascal Gテシnthner :Slug: totoro This is a drawing of Totoro, the star of the Japanese animated fantasy film "My Neighbor Totoro". The Koch snowflake fractal has been used to draw snow, repetitive tasks are done in "foreach" loops. \end{comment} \usepackage{calligra} \usepackage[T1]{fontenc} \usetikzlibrary{% shapes, shadows, patterns, calc, decorations.shapes, decorations.fractals, decorations.markings, decorations.pathmorphing } \colorlet{bodycolor}{black!35!gray!60!brown!98!green} \colorlet{bellycolor}{yellow!70!white!92!green} \tikzset{ furspot/.pic = { \path [draw = black, thick, fill] (0,0) .. controls +(0.3,0) and +(0.25,-0.05) .. ++(0.35,-.45) .. controls +(-0.45,0.25) and +(0.1,0) .. ++(-0.85,-0.05) .. controls +(-0.3,0.1) and +(-0.4, 0) .. cycle; }, claw/.pic = { \path [fill = bodycolor!70, draw] (0,0) arc (0:45:0.2 and 0.8) arc (135:180:0.2 and 0.8) arc (180:360:0.059) -- cycle; }, whiskers/.pic = { \path [fill = bodycolor!70,draw] (0,0) arc (0:45:0.05 and 2.3) arc (135:180:0.3 and 2.3) to[out=-90,in=-90] cycle; }, snowflake/.pic = { \fill [decoration = Koch snowflake, white] decorate{ decorate{ decorate{ (-0.5,-0.3) -- ++(60:1) -- ++(-60:1) -- cycle }}}; \foreach \i in {30, 90, 150, 210, 270, 330} { \draw[blue!50!white,very thin] (0,0) -- +(\i:0.3); } \draw[decoration = Koch snowflake, blue!50!white, very thin] decorate{($(0,0)+(60:0.2)$) -- ($(0,0)+(300:0.2)$) -- ($(0,0)+(180:0.2)$) -- cycle}; } } \tikzset{ snow/.style = {decoration = {random steps, segment length = 2mm, amplitude = 0.4mm}, decorate}, plush/.style = {decoration = {random steps, segment length = 1mm, amplitude = 0.5mm},decorate} } \begin{document} \begin{tikzpicture}[color = bodycolor, draw = black, thick] %---------------------background and tail---------------------- % blue sky \fill[blue!30!white] (-8cm,-11cm) rectangle (8cm,10cm); % random snowflakes \foreach \i in {0.1,0.11,...,1}{ \pic [scale = \i, opacity = 0.9] at (rand*7.5, rnd*18-10.5) {snowflake};} % more tiny snowflakes \foreach \i in {0.1,0.11,...,0.5}{ \pic [scale = \i, opacity = 0.9] at (rand*7.5, rnd*18-10.5) {snowflake};} % cloud with merry christmas \node [cloud,aspect = 6.5, cloud puff arc = 120, cloud puffs = 12.9, fill = white, color = white] at (0,7) {\Huge M \hspace{9.8cm}.}; \node [color = red] at (0,7) {\fontsize{50}{80} \textbf{Merry Christmas \quad }}; % tail \path [draw, fill, rotate = 50] (-4,-7.5) circle (1.5 and 2.2); % snowhill \fill [draw, gray!6, snow] (-8,-11) to[in=200, out=0] (-3,-7.5) to (3,-7.5) to[out=-20, in=180] (8,-11); %--------------------body----------------------------------------- % right ear \path [fill, draw] (0.6,2.3)+(-45:1) arc (-60:35:1 and 1.5) arc (115:210:1 and 1.5); % left ear \path [fill, draw] (-0.6,2.3)+(-135:1) arc (-120:-215:1 and 1.5) arc (65:-30:1 and 1.5); % head \path [draw, fill] ($(0,0)+(170:2.5 and 2)$) arc (170:10:2.5 and 2) arc(35:-20: 3 and 2) -- ($(0,-0.8)+(200:3 and 2)$) arc (200:145:3 and 2) -- cycle; % body \path[fill] ($(0,-4)+(200:4 and 4.5)$) arc (200:-20:4 and 4.5); %----------------------face---------------------------------------- % left eye \path [draw, fill = white] (-1.4,0.7) circle (0.45 and 0.4); \fill [black] (-1.2,0.7) circle (0.16); \fill [white] (-1.24,0.74) circle (0.03); % right eye \path [draw, fill = white, thick] (1.4,0.7) circle (0.4); \fill [black] (1.25,0.7) circle (0.16); \fill [white] (1.20,0.74) circle (0.03); % nose \path [draw] (0.35, 0.7) .. controls (0.2,0.8) and (-0.2, 0.8) .. (-0.35, 0.7); \path [fill = black] (0, 0.53) -- (0.25, 0.6) .. controls (0.3,0.75) and (-0.3, 0.75) .. (-0.25, 0.6) -- cycle; \pic [scale = 0.3] at (0,0.8) {snowflake}; % mouth \draw (-0.05,-0.5) arc (140:85:0.2 and 0.1); % whiskers \foreach \i/\j/\k/\l/\m in {80/1/1.5/-2/0, -90/-1/1.5/-2.2/-0.2, -80/-0.8/1.5/-2.5/-0.5, -80/1/1.3/2.2/0, 90/-1/1.3/2.4/-0.2, 80/-1/1.3/2.6/-0.4} \pic [rotate = \i, scale = \j, yscale = \k] at (\l,\m) {whiskers}; %-----------------------------arms---------------------------------- % handclaws \foreach \i in {-4,-3.8,-3.6,3.9,3.7,3.5} { \pic [rotate = 180] at (\i,-6.5) {claw};} % left arm \path [draw, fill] (-3, -1) .. controls (-5.5,-3.5) and (-4.5,-7.5) .. (-3.35,-6.45); % right arm \path [draw, fill] (3, -1) .. controls (5.5,-3.5) and (4.5,-7.5) .. (3.35,-6.45); %------------------------belly---------------------------------- \draw[fill = bellycolor] ($(0,-4.7)+(230:3.8 and 4)$) to [out = -10,in = 190] ($(0,-4.7)+(-50:3.8 and 4)$) to ($(0,-4)+(-50:4.5)$) to [out = 60, in = -70] ($(0,-4.7)+(50:3.8 and 4)$) arc (50:130:3.8 and 4) to [out = -110, in = 120] ($(0,-4)+(-130:4.5)$) to cycle; % fur spots \foreach \i/\j/\k in {0/0/-1.3, -15/1.6/-1.5, 15/-1.6/-1.5, -8/0.7/-2.2, 8/-0.7/-2.2, -22/2.2/-2.5, 22/-2.2/-2.5} { \pic [rotate = \i] at (\j, \k) {furspot};} %------------------------legs and feet-------------------------- %legs \path [draw, rotate = 32, fill] (-5.8,-5.2) circle (0.9 and 1.4); \path [draw, rotate = -32, fill] (5.8,-5.2) circle (0.9 and 1.4); % left feet \path [draw, fill, rotate = 30] (-5.6,-6.1) circle (0.65 and 0.6); \path [draw, fill, rotate = -30] (5.6,-6.1) circle (0.65 and 0.6); % toe beans \path [draw, fill = bodycolor!50!white, rotate = 45] (-7,-4.7) circle (0.3 and 0.17); \path [draw ,fill = bodycolor!50!white, rotate = -45] (7,-4.7) circle (0.3 and 0.17); % footclaws \foreach \i/\j/\k in {50/-2.2/-7.9,40/-2/-7.7,30/-1.75/-7.55, -50/2.3/-8,-40/2.1/-7.8,-30/1.85/-7.65} { \pic [rotate = \i] at (\j,\k) {claw};} % hat \path [draw, fill = red] (43:2.5) to [in = -170, out = 130] ($(0.7,3)+(195:0.4)$) to [in = 180, out = 90] (0.7,3.1) to [out = 150, in = 0] (0,3.3) to [in = 50, out = 180] (137:2.5); \fill [draw, plush, fill = white, thin] (145:2.5 and 2) to [in = 160, out = 20] (35:2.5 and 2) to [out = 80, in = -80] ++(0,0.5) to [out = 160, in = 20] ($(145:2.5 and 2) +(0,0.5)$) to [in = 100, out = -100] cycle; \fill [draw, plush, fill = white, thin] (0.7,3.1) circle (0.5); \end{tikzpicture} \end{document}

mandelbrot.tex

\documentclass[border=10pt]{standalone} \usepackage{pgfplots} \pgfplotsset{width=7cm,compat=1.8} \usepackage{luacode} \begin{luacode} function mandelbrot(cx,cy, max_iter, max) local x,y,xtemp,ytemp,squaresum,iter squaresum = 0 x = 0 y = 0 iter = 0 while (squaresum <= max) and (iter < max_iter) do xtemp = x * x - y * y + cx ytemp = 2 * x * y + cy x = xtemp y = ytemp iter = iter + 1 squaresum = x * x + y * y end local result = 0 if (iter < max_iter) then result = iter end -- result = squaresum -- io.write("" .. cx .. ", " .. cy .. " = " .. result .. " (iter " .. iter .. " squaresum " .. squaresum .. ") \string\n") tex.print(result); end \end{luacode} \begin{document} \begin{tikzpicture} \begin{axis}[ colorbar, point meta max=30, tick label style={font=\tiny}, view={0}{90}] \addplot3 [surf,domain=-1.5:0.5,shader=interp,domain y=-1:1,samples=200] { \directlua{mandelbrot(\pgfmathfloatvalueof\x,\pgfmathfloatvalueof\y,10000,4)} }; \end{axis} \end{tikzpicture} \end{document}

・PDF生成に時間がかかる。

julia.tex

%!TEX lualatex \documentclass[border=5pt]{standalone} \usepackage{pgfplots} \pgfplotsset{width=7cm,compat=1.8} \usepackage{luacode} \begin{luacode} function julia(cx,cy, max_iter, max) local x,y,xtemp,ytemp,squaresum,iter squaresum = 0 x = cx y = cy iter = 0 while (squaresum <= max) and (iter < max_iter) do xtemp = x * x - y * y - 0.742 ytemp = 2 * x * y + 0.1 x = xtemp y = ytemp iter = iter + 1 squaresum = x * x + y * y end local result = 0 if (iter < max_iter) then result = iter end -- result = squaresum -- io.write("" .. cx .. ", " .. cy .. " = " .. result .. " (iter " .. iter .. " squaresum " .. squaresum .. ") \string\n") tex.print(result); end \end{luacode} \begin{document} \begin{tikzpicture} \begin{axis}[ colormap/hot2, colorbar, axis equal, point meta max=50, tick label style={font=\tiny}, view={0}{90}] \addplot3 [surf, domain = -1.82:1.82, shader = interp, domain y = -1.5:1.5, samples = 350] {\directlua{julia(\pgfmathfloatvalueof\x,\pgfmathfloatvalueof\y,10000,4)} }; \end{axis} \end{tikzpicture} \end{document}

・PDF生成に時間がかかる。

build/preview

.texを読み込むと、画面の上の右側にアイコンが並ぶ。右矢印のアイコンが「Build LaTeX project」、その右のアイコンが「Preview LaTeX PDF」になる。右矢印をクリックするとbuildが開始され終了するとPDFが生成される。 その後「Preview LaTeX PDF」をクリックすると画面の右側にPDFの内容がプレビューされる。
ファイル保存([Ctrl]+[S])を行っても自動的にbuildが実行される。
なお、build中は画面の最下行にbuild中を表す回転マークが表示され、 終了するとチェックマークに変わる。

参考情報

James-Yu/LaTeX-Workshop
LaTeX Workshopってなに?どうやって使うの?調べてみた!
User and Workspace Settings
【LuaTeX】LuaTeXテンプレート
「pLaTeXからLuaLaTeXへの移行」に関するクイズ

samples:
http://www.damp.tottori-u.ac.jp/~hoshi/info/doc-info-2009/sample.tex
TeX Wiki / LaTeX入門/最初の例
The recent 10 examples
Fraktale mit pgfplots

以上

» 続きを読む

| | コメント (0)

2021年5月19日 (水)

Arduino-CLIのインストール

2021/5/19
初版

Arduino-CLI Install

Arduino-CLI Install

概要

Arduino-CLIのインストール方法について記述する。
これはArduino-IDEを使わずにCLIだけでArduinoのcompile/uploadなどができる。
ホスト環境はubuntuを想定する。
なお、(インストールしたライブラリなどを流用する関係上)既にArduino-IDEがインストール済みであることが前提となる。

インストール手順

以下の手順を実行する:

cd ~ curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh #出力例 Installing in /home/USER/bin ARCH=64bit OS=Linux Using curl as download tool TAG=0.18.3 CLI_DIST=arduino-cli_0.18.3_Linux_64bit.tar.gz Downloading https://downloads.arduino.cc/arduino-cli/arduino-cli_0.18.3_Linux_64bit.tar.gz arduino-cli not found. You might want to add /home/USER/bin to your $PATH arduino-cli alpha Version: 0.18.3 Commit: d710b642 Date: 2021-05-14T12:36:58Z installed successfully in /home/USER/bin # 実行パスを設定する(.bashrcにも登録する) export PATH=$PATH:$HOME/bin/

動作確認

mkdir ard_ws cd ard_ws/ # configファイルを初期化する arduino-cli config init #出力例 Config file written to: /home/USER/.arduino15/arduino-cli.yaml # arduino-cli.yamlファイルが$HOME/.arduino15/にできる # 新規のスケッチの作成 arduino-cli sketch new MyFirstSketch #出力例 Sketch created in: /home/USR/ard_ws/MyFirstSketch # 新規スケッチの内容の確認 cat MyFirstSketch/MyFirstSketch.ino void setup() { } void loop() { } # インストールされているボード・ライブラリの確認 arduino-cli board listall uno #出力 Board Name FQBN Arduino Uno arduino:avr:uno Arduino Uno WiFi arduino:avr:unowifi arduino-cli board listall xiao #出力 Board Name FQBN Seeeduino XIAO Seeeduino:samd:seeed_XIAO_m0 arduino-cli board listall wio #出力 Board Name FQBN Seeed Wio Link esp8266:esp8266:wiolink Seeeduino Wio GPS Board Seeeduino:samd:WioGPS Seeeduino Wio Terminal Seeeduino:samd:seeed_wio_terminal Seeeduino Wio lite MG126 Seeeduino:samd:Wio_Lite_MG126 arduino-cli board listall pico #出力 Board Name FQBN Adafruit Feather RP2040 (Picoprobe) rp2040:rp2040:adafruitfeatherpicoprobe Generic RP2040 (Picoprobe) rp2040:rp2040:genericpicoprobe Raspberry Pi Pico rp2040:rp2040:rpipico Raspberry Pi Pico arduino:mbed_rp2040:pico Raspberry Pi Pico (Picoprobe) rp2040:rp2040:rpipicopicoprobe #--------------------------------- # Install the core for your board arduino-cli core install Seeeduino:samd #出力 Platform Seeeduino:samd@1.8.1 already installed #Arduino-IDEでインストール済みなので「already installed」 arduino-cli core update-index #出力 Updating index: package_index.json downloaded Updating index: package_index.json.sig downloaded #---------------------------------- # 任意のスケッチに編集する gedit MyFirstSketch/MyFirstSketch.ino # Compile and upload the sketch #compile arduino-cli compile -b arduino:avr:uno MyFirstSketch #出力例 Sketch uses 932 bytes (2%) of program storage space. Maximum is 32256 bytes. Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes. #upload arduino-cli upload -p /dev/ttyUSB0 -b arduino:avr:uno MyFirstSketch #特に出力はないようだ

既存のスケッチのcompile/upload

既存のスケッチのcompile/uploadについては
以下のように行なう:

cd ~/Arduino # ディレクトリ内容の確認 ls ASCIITablePico ASCIITable_M5Atom BlinkPico MB_graphicstest libraries # ビルドしたいスケッチのディレクトリに入る cd ASCIITablePico # compile arduino-cli compile -b rp2040:rp2040:rpipico #出力例 Sketch uses 214480 bytes (10%) of program storage space. Maximum is 2093056 bytes. Global variables use 17064 bytes (6%) of dynamic memory, leaving 245080 bytes for local variables. Maximum is 262144 bytes. # upload arduino-cli upload -p /dev/ttyACM0 -b rp2040:rp2040:rpipico #出力例 Resetting /dev/ttyACM0 Converting to uf2, output size: 442880, start address: 0x2000 Flashing /media/USER/RPI-RP2 (RPI-RP2) Wrote 442880 bytes to /media/USER/RPI-RP2/NEW.UF2 #------------------------------ # 同じスケッチでboardを切り替える # ボード確認 arduino-cli board listall Atom #出力例 Board Name FQBN M5Stack-ATOM m5stack:esp32:m5stack-atom # compile arduino-cli compile -b m5stack:esp32:m5stack-atom #出力例 Sketch uses 213585 bytes (16%) of program storage space. Maximum is 1310720 bytes. Global variables use 15380 bytes (4%) of dynamic memory, leaving 312300 bytes for local variables. Maximum is 327680 bytes. # upload arduino-cli upload -p /dev/ttyUSB0 -b m5stack:esp32:m5stack-atom #出力例 esptool.py v3.0-dev Serial port /dev/ttyUSB0 Connecting..... Chip is ESP32-PICO-D4 (revision 1) Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, VRef calibration in efuse, Coding Scheme None Crystal is 40MHz MAC: 50:02:91:90:04:e4 Uploading stub... Running stub... Stub running... Changing baud rate to 1500000 Changed. Configuring flash size... Auto-detected Flash size: 4MB Compressed 8192 bytes to 47... Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 15527.2 kbit/s)... Hash of data verified. Compressed 15856 bytes to 10276... Wrote 15856 bytes (10276 compressed) at 0x00001000 in 0.1 seconds (effective 1129.5 kbit/s)... Hash of data verified. Compressed 213696 bytes to 108970... Wrot  e 213696 bytes (108970 compressed) at 0x00010000 in 1.8 seconds (effective 960.5 kbit/s)... Hash of data verified. Compressed 3072 bytes to 128... Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.0 seconds (effective 6202.5 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin...

3rd-partyのボード・ライブラリのインストール

例:

# install arduino-cli core update-index --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json #出力例 Updating index: package_index.json downloaded Updating index: package_index.json.sig downloaded Updating index: package_esp8266com_index.json downloaded # check arduino-cli core search esp8266 --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json #出力例 ID Version Name esp8266:esp8266 3.0.0 esp8266 # ボード・ライブラリ確認 arduino-cli board listall 8266 #出力例 Board Name FQBN 4D Systems gen4 IoD Range esp8266:esp8266:gen4iod Adafruit Feather HUZZAH ESP8266 esp8266:esp8266:huzzah Amperka WiFi Slot esp8266:esp8266:wifi_slot Arduino esp8266:esp8266:arduino-esp8266 DOIT ESP-Mx DevKit (ESP8285) esp8266:esp8266:espmxdevkit Digistump Oak esp8266:esp8266:oak ESPDuino (ESP-13 Module) esp8266:esp8266:espduino ESPectro Core esp8266:esp8266:espectro ESPino (ESP-12 Module) esp8266:esp8266:espino <省略>

参照情報

Arduino-CLI関連:
Arduino-CLI
getting-started
Arduino-cli: compile, upload and manage libraries, cores, and boards

Arduino-CLI内部関連:
Platform specification
Pre-Processing

以上

» 続きを読む

| | コメント (0)

2021年5月16日 (日)

Pandoc(+TeX)のインストール方法

2021/6/5+
yamlヘッダー・サンプルを追加した。

2021/6/2+
settings.jsonの編集について追加した。

2021/5/28++
スクリーンショットの張り込み方について追加した。

2021/5/26+
mermaid.jsによるチャート描画について追加した。

2021/5/23p
プラグインvscode-pandoc[Pandoc Render]の設定値を追加した。

2021/5/23
docxの扱いを追加した。

2021/5/16p+
数式(MathJax)の扱いを追加した。

2021/5/16
初版

Pandoc(+TeX) Install

Pandoc(+TeX) Install

概要

Pandoc(+TeX)のインストール方法について記述する。
ホスト環境はubuntuを想定する。

インストール方法

以下の手順を実行する:

cd ~/Downloads # pandocのインストール wget https://github.com/jgm/pandoc/releases/download/2.13/pandoc-2.13-1-amd64.deb sudo dpkg -i pandoc-2.13-1-amd64.deb # TeX Liveのインストール # (再インストールする場合、以下を実行する) sudo rm -rf /usr/local/texlive/2021 rm -rf ~/.texlive2021 # isoイメージのダウンロード(時間がかかるので注意のこと) wget https://ftp.kddilabs.jp/CTAN/systems/texlive/Images/texlive2021-20210325.iso # ダウンロード後、isoイメージをマウントする cd ~/Downloads sudo mkdir /media/cdrom0 sudo mount -o loop ./texlive2021-2021032 cd /media/cdrom0 # インストーラーを実行する(インストールに時間がかかるので注意) sudo ./install-tl # メニューに従って "I" を入力する # インストールが実行される。 # 以下のようなメッセージが表示されればインストールが完了となる TeX Live へようこそ! ドキュメントの一覧は /usr/local/texlive/2021/index.html をご覧ください. TeX Live のウェブサイト (https://tug.org/texlive/) にはすべてのアップデートとコレクションの情報が掲載されています. TeX Live は全世界の TeX ユーザ会有志による合同プロジェクトです. TeX Live プロジェクトをサポートしていただける場合お好きな TeX ユーザ会に入会することをご検討ください. TeX ユーザ会の一覧はhttps://tug.org/usergroups.html でご確認いただけます. <省略> # 以下でisoイメージをアンマウントする cd ~ sudo umount /media/cdrom0 # 実行パスを設定する(.bashrcに登録する) export PATH=$PATH:/usr/local/texlive/2021/bin/x86_64-linux/ # wkhtmltopdfのインストール # (webレンダリングからPDFを作成するプログラム) wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb sudo dpkg -i wkhtmltox_0.12.6-1.focal_amd64.deb

関連スクリプト(MathJax関連)作成

以下のファイルを作成する:
mathjax0.js

var fileref=document.createElement('script') fileref.setAttribute("type","text/javascript") fileref.setAttribute("src", "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML") document.getElementsByTagName("head")[0].appendChild(fileref)

・このファイルをカレント・デレクトリに置く。

数式の扱い(MathJax)

数式を扱う方法は色々あるが、ここでは、markdownの先頭にjavascriptのスクリプトを置く方法について紹介する。
markdownの先頭に以下のスクリプトを置くと、
数式(mathjax)が扱えるようになる。

<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML' async></script> <script type="text/x-mathjax-config"> MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: "AMS" }, Macros: { tcdegree: ['\\unicode{xb0}'], tccelsius: ['\\unicode{x2103}'], tcperthousand: ['\\unicode{x2030}'], tcmu: ['\\unicode{x3bc}'], tcohm: ['\\unicode{x3a9}'], div: '{\\mathrm{div}}', rot: '{\\mathrm{rot}}', grad: '{\\mathrm{grad}}', diff: '{\\mathrm{d}}', log: '{\\mathrm{log}}', ln: '{\\mathrm{ln}}', b: ['{\\boldsymbol{#1}}',1], vm: ['{\\boldsymbol{#1}}', 1], pdiffA: ['{\\frac{\\partial #1}{\\partial #2}}', 2], pdiffB: ['{\\frac{\\partial^{#1} #2}{\\partial #3^{#1}}}', 3], unit: ['{\\,[\\mathrm{#1}]\\,}', 1], } }, tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], processEscapes: true}, "HTML-CSS": { matchFontHeight: false }, displayAlign: "left", displayIndent: "2em" }); </script> <!-- 以下に数式を含むmarkdownを置く -->

コマンドライン(実行例)

テスト用のファイルを以下からダウンロードする:
markdown_example00.md
mycss2.css
mathjax00.md
reference.docx(pandoc自動生成版)

md2html(html出力)

pandoc -s --self-contained -f gfm -c mycss2.css -o out.html markdown_example00.md # 数式(MathJax)を含むmarkdownをhtml出力する pandoc -s --self-contained -f markdown -c mycss2.css --mathjax=mathjax0.js -o out.html mathjax00.md

・ファイルが全てカレントディレクトリにある前提

md2pdf(PDF出力)

pandoc -f gfm -c mycss2.css --pdf-engine=wkhtmltopdf -o out.pdf markdown_example00.md pandoc --pdf-engine=lualatex -V documentclass=ltjsarticle -V indent=true -o out.pdf markdown_example00.md pandoc --pdf-engine=lualatex -V documentclass=ltjsarticle -V luatexjapresetoption=ms -V indent=true -o out.pdf markdown_example00.md # luatexjapresetoption=でフォントを指定できる # 以下が選択できる noembed: 非埋込 kozuka-pro: 小塚フォント (Pro) kozuka-pr6: 小塚フォント (ProVI) kozuka-pr6n: 小塚フォント (Pr6N) hiragino-pro: ヒラギノフォント (Pro, Std) hiragino-pron: ヒラギノフォント (ProN, StdN) morisawa-pro: モリサワフォント (Pro) morisawa-pr6n: モリサワフォント (Pr6N) ipa: IPAフォント ipaex: IPAexフォント ms: MS 明朝,MS ゴシック moga-mobo: MogaMincho, MogaGothic, MoboGothic(20150420.0 以降) yu-win: Windows 8.1 に付属する游書体(20140114.0 以降) yu-osx: OS X 10.9 に付属する游書体(20140114.0 以降) sourcehan: 源ノ明朝,源ノ角ゴシック

・ファイルが全てカレントディレクトリにある前提

VSCodeのプラグインのインストール

pandoc,markdown関連のプラグインとして以下をインストールする:

vscode-pandoc Markdown PDF Markdown Pfeview Enhanced Pandoc Markdown Preview Paste Image

インストールしたプラグインの機能
[View/Command Plalette]の入力欄から機能名を検索して実行する:

  1. vscode-pandoc
    1. [Pandoc Render]
      出力するファイルタイプのメニューが出るので、希望のファイルタイプを選択する。VSCodeの編集中のディレクトリに出力される。
  2. Markdown PDF
    1. [Markdown PDF: Export(html)]
      vscodeの編集中の.mdのあるディレクトリにhtmlファイルを出力する。
    2. [Markdown PDF: Export(PDF)]
      vscodeの編集中の.mdのあるディレクトリにhtmlファイルを出力する。
  3. Markdown Preview Enhanced
    1. [Markdown Markdown Preview Enhanced: Open Preview to the side]
      プレビュー画面で右クリックするとメニューが出現するので以下の機能を選択する:
      1. Pandoc
        編集中の.mdのyamlヘッダーの情報に応じてファイル出力する。
      2. eBook/ePub
        電子ブック用のePubフォーマットでファイル出力される。
      3. eBook/mobi
        kindle用のmobiフォーマットでファイル出力される。
  4. Pandoc Markdown Preview
    1. [Open Pandoc Markdown Preview]
      Pandoc仕様のMarkdown仕様でプリビューされる。
  5. Paste Image
    [Ctrl]+[Alt]+[V]でmarkdownテキストにペーストバッファにある画像が張り込めるようになる。

プラグインではないが内蔵の[Markdown: Open Preview to the Side] は、(だいたい?)Github-Flavor-Markdown仕様のプレビューとして動作するようだ。

yamlヘッダー

編集中の.mdの先頭に以下を置くとpandoc使用時に、その情報を参照できる。

--- title: "文書名" author: 作者 date: 日付 output: word_document: path: out.docx toc: true pandoc_args: ["--reference-doc=ref00.docx"] ---

プラグイン[Markdown Markdown Preview Enhanced: Open Preview to the side]のPandocを選択すると上のヘッダーに応じてpandocがファイルを出力するので、この場合、出力ファイルは、out.docxで、pandocに与える引数は 「"--reference-doc=ref00.docx"]」になる。

reference-doc作成

以下の手順でreference-docの雛形を作成できる:

cd ~ mkdir .pandoc cd .pandoc pandoc --print-default-data-file reference.docx > reference.docx

このまま利用することも可能だがMS-WORDまたはLibreOffice-Writterで編集してカスタマイズすることも可能である。カスタマイズする点としては、ヘッダー/フッターの追加、章番号付け、表紙などの文字やスタイル変更などが考えられる。
環境(window10環境?)によってreference.docxが壊れている場合がある。(Writer/WORDなどで開くとデータが壊れている)
この場合、以下から既にカスタマイズしたものをダウンロードする:

wget https://github.com/mottox2/pandoc-word-starter/blob/master/custom-reference.docx

コメントや履歴が残っていると変換が失敗することあるので、一度、Writer/WORDで履歴の解消、コメントの削除を行なう。

ここでは、カスタマイズしたものを、ref00.docxとして編集中のディレクトリに置くこととする。

これにより上のプラグインでの出力結果であるout.docxはカスタマイズしたreference-docに従ったスタイルの文書になる。

なお、章番号の追加は以下のものを参照のこと:
Writerで見出しに段落番号を設定する
操作はMS-WORDよりも簡単なので通常MS-WORDを使っていたとしてもwriterを使ってカスタマイズしても良いかもしれない。

目次の作成

out.docxには既に目次はあるので以下の手順で目次を更新する必要がある。

  1. 目次を右クリックして、目次と索引の更新 を選択する。
  2. [メニュー ツール/更新 /すべての目次と索引]を選択する。

プラグイン[Pandoc Render]の設定

プラグインvscode-pandoc[Pandoc Render]の設定は以下を設定する:
(「:」の右側の文字列を「"」無しで入力する)

"pandoc.asciidocOptString": "-f gfm -c /home/USER/.pandoc/github.css " "pandoc.docbookOptString": "-f gfm -c /home/USER/.pandoc/github.css " "pandoc.docxOptString": "--standalone -f gfm -t docx --reference-doc=/home/USER/.pandoc/ref00.docx --toc " "pandoc.epubOptString": "-f gfm -c /home/USER/.pandoc/github.css " #数式無しの場合 "pandoc.htmlOptString": " -s --self-contained -f gfm -c /home/USER/.pandoc/github.css -t html5 " #数式付きの場合 "pandoc.htmlOptString": " -s --self-contained -f markdown -c /home/USER/.pandoc/github.css --mathjax=/home/USER/.pandoc/mathjax0.js -t html5 " #PDF出力にwkhtmltopdfを利用する場合 "pandoc.pdfOptString": "-f gfm -c /home/USER/.pandoc/github.css --pdf-engine=wkhtmltopdf " #PDF出力にlualatexを利用する場合 #luatexjapresetoptions= には以下のフォントを指定する; # morisawa,ipa,ipaex,hiragino,kozuka,moga,yu,source "pandoc.pdfOptString": " --pdf-engine=lualatex -V documentclass=ltjsarticle -V luatexjapresetoptions=morisawa " "pandoc.rstOptString": "-f gfm -c /home/USER/.pandoc/github.css "

・ref00.docx, mathjax0.js, github.css(=mycss2.css)は「~/.pandoc」のディレクトリに置くこと。
・USERは環境依存なので自分の環境に合わせること。

mermaid.jsでのチャート表示

プラグイン[Markdown Preview Enhanced: Open Review ...]にはmermaid.jsが内蔵されいるので、以下のようなコードブロックでチャートが表示できる。
注意:
・PDF化、HTML化、PNG化を動かすにはchromeインストールが前提になる。
・初期化に問題があるせいか、PNG化を最初に動かす必要にある。

```mermaid graph TB a --> b & c --> d --> e --> f --> d ```
```mermaid sequenceDiagram participant Alice participant Bob Alice->>John: Hello John, how are you? loop Healthcheck John->>John: Fight against hypochondria end Note right of John: Rational thoughts <br/>prevail! John-->>Alice: Great! John->>Bob: How about you? Bob-->>John: Jolly good! ```
```mermaid gantt dateFormat YYYY-MM-DD title Adding GANTT diagram to mermaid excludes weekdays 2014-01-10 section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d Future task : des3, after des2, 5d Future task2 : des4, after des3, 5d ```
```mermaid classDiagram Class01 <|-- AveryLongClass : Cool Class03 *-- Class04 Class05 o-- Class06 Class07 .. Class08 Class09 --> C2 : Where am i? Class09 --* C3 Class09 --|> Class07 Class07 : equals() Class07 : Object[] elementData Class01 : size() Class01 : int chimp Class01 : int gorilla Class08 <--> C2: Cool label ```
```mermaid erDiagram CUSTOMER ||--o{ ORDER : places ORDER ||--|{ LINE-ITEM : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses ```

実際のチャートの表示を見たい場合、以下をクリックする:
mermaid_exaples

スクリーンショットを張り込む(ubuntuの場合)

  1. スクリーンショット
    [Ctrl]+[Shift]+[PrintScreen]を押すと画面の範囲指定ができるようになるので 画面の希望の範囲を指定するとスクリーンショット画像がペーストバッファに保存される。
  2. ペースト
    その後、VSCodeのmarkdownの編集画面で画像を張り込みたい場所にカーソルを移動して[Ctrl]+[Alt]+[V]を押すと画像が張り込まれる。

その際、以下のようなmarkdownテキストで張り込まれる。

![](2021-05-29-00-40-27.png)

(デフォルトの設定では)カレント・ディレクトリに画像ファイルが置かれる。

スクリーンショットを張り込む(windows10の場合)

  1. スクリーンショット
    [Windows]+[Shift]+[S]を押すと画面の範囲指定ができるようになるので 画面の希望の範囲を指定するとスクリーンショット画像がペーストバッファに保存される。
  2. ペースト
    その後、VSCodeのmarkdownの編集画面で画像を張り込みたい場所にカーソルを移動して[Ctrl]+[Alt]+[V]を押すと画像が張り込まれる。

以下、ubuntuと同様

プラグイン「Paste Image」の設定(ubuntu/windows10共通)

デフォルトの設定のままだとカレント・ディレクトリに.pngが増えて、うるさくなるので、PNGディレクトリのなかに.pngを置くように設定を以下のように変更する:

"pasteImage.path": "PNG" "pasteImage.prefix": "./"

settings.json

プラグイン設定をまとめて設定する場合は、以下のsettings.jsonを編集する:

Windows %APPDATA%\Code\User\settings.json #実際のファイルのロケーションは以下になる: C:\Users\USER\AppData\Roaming\Code\User\settings.json #USERは実際のユーザー名になる macOS $HOME/Library/Application Support/Code/User/settings.json Linux $HOME/.config/Code/User/settings.json #実際のファイルのロケーションは以下になる: ~/.config/Code/User/Settings.json

実際には以下のように編集する:

ubuntuの場合
~/.config/Code/User/Settings.json

{ <既にある設定値> "pandoc.htmlOptString": " -s --self-contained -f markdown -c /home/USER/.pandoc/github.css --mathjax=/home/USER/.pandoc/mathjax0.js -t html5 ", "pandoc.docxOptString": "--standalone -f gfm -t docx --reference-doc=/home/USER/.pandoc/ref00.docx --toc ", "pandoc.epubOptString": "-f gfm -c /home/USER/.pandoc/github.css ", "pandoc.asciidocOptString": "-f gfm -c /home/USER/.pandoc/github.css ", "pandoc.docbookOptString": "-f gfm -c /home/USER/.pandoc/github.css ", "pandoc.rstOptString": "-f gfm -c /home/USER/.pandoc/github.css ", "pandoc.pdfOptString": " --pdf-engine=lualatex -V documentclass=ltjsarticle -V luatexjapresetoptions=morisawa ", "pasteImage.path": "PNG", "pasteImage.prefix": "./", //LaTeX "latex-workshop.latex.recipes": [ { "name": "lualatex", "tools": [ "lualatex", ] }, { "name": "lualatex twice compile", "tools": [ "lualatex", "lualatex", ] }, ], "latex-workshop.latex.tools": [ { "name": "lualatex", "command": "lualatex", "args": [ "--cmdx", "-file-line-error", "-synctex=1", "-interaction=nonstopmode", "-halt-on-error", "%DOC%", ], }, ], "latex-workshop.latex.autoClean.run": "onBuilt", "latex-workshop.latex.autoBuild.run": "onFileChange", "latex-workshop.latex.autoBuild.interval": 0, "latex-workshop.view.pdf.viewer": "tab", }

・「USER」は、環境依存のユーザー名となる。

windows10の場合
C:\Users\USER\AppData\Roaming\Code\User\settings.json

{ <既にある設定値> "pandoc.docxOptString": "--standalone -f gfm -t docx --reference-doc=C:\\Users\\USER\\.pandoc\\ref00.docx --toc ", "pandoc.asciidocOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css ", "pandoc.docbookOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css ", "pandoc.epubOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css ", "pandoc.rstOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css ", "pandoc.pdfOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css --pdf-engine=wkhtmltopdf ", "pandoc.htmlOptString": "-f gfm -c C:\\Users\\USER\\.pandoc\\github.css ", "pasteImage.path": "PNG", "pasteImage.prefix": "./", //LaTeX "latex-workshop.latex.recipes": [ { "name": "lualatex", "tools": [ "lualatex", ] }, { "name": "lualatex twice compile", "tools": [ "lualatex", "lualatex", ] }, ], "latex-workshop.latex.tools": [ { "name": "lualatex", "command": "lualatex", "args": [ "--cmdx", "-file-line-error", "-synctex=1", "-interaction=nonstopmode", "-halt-on-error", "%DOC%", ], }, ], "latex-workshop.latex.autoClean.run": "onBuilt", "latex-workshop.latex.autoBuild.run": "onFileChange", "latex-workshop.latex.autoBuild.interval": 0, "latex-workshop.view.pdf.viewer": "tab", }

・「\」は、エスケープ文字付きに「\\」となる。
・「USER」は、環境依存のユーザー名となる。

注意:プラグインの実行パス(windows10限定)

たぶん、セキュリティの考慮のため外部で設定した実行パスはプラグインで実行する環境には継承されないようだ。したがってPowerScriptのスクリプトで実行パスを設定しても無効になる。
また、VSCodeのなかのTerminalで実行パスを設定すると、そのTerminalの環境としては有効になるが、プラグインには継承されない。
したがって、プラグインでも有効になる実行パス設定としては、システム設定を利用する。操作については以下を参照のこと。

Windows10で実行ファイルへのパスを通す手順

実行パスが有効になったことの確認は以下のようなコマンドをPowerShellで実行する:

gcm wkhtmltopdf CommandType Name Version Source ----------- ---- ------- ------ Application wkhtmltopdf.exe 0.12.6.0 C:\Program Files\wkhtmltopdf\bin\wkhtm...

yamlヘッダー・サンプル

yamlヘッダーを差し替えると出力形式を切り替えられるが、実際に動作確認したものを以下に挙げる:

なお、操作としては以下になる: [Markdown Markdown Preview Enhanced: Open Preview to the side]のプレビュー画面で右クリックして、[Pandoc]を選択する。

PDF出力用(目次付き)#1:

--- title: "タイトル" author: "作者" date: "日付" output: pdf_document: path: out.pdf latex_engine: lualatex pandoc_args: [ "--toc", "--toc-depth=2", ] documentclass: ltjsarticle classoption: luatexjapresetoption=morisawa,a4paper,14pt ---

PDF出力用(目次付き)#2:

--- title: "タイトル" author: "作者" date: "日付" output: pdf_document: path: out.pdf latex_engine: lualatex pandoc_args: [ "--toc", "--toc-depth=2" ] documentclass: ltjltxdoc classoption: a4paper,12pt ---

PDF出力用:

--- title: "タイトル" author: "作者" date: "日付" output: pdf_document: path: out.pdf latex_engine: lualatex documentclass: bxjsarticle classoption: pandoc,jafont=morisawa,a4paper ---

docx出力用:

--- title: "タイトル" author: "作者" date: "日付" output: word_document: path: out.docx toc: true pandoc_args: ["--reference-doc=ref03.docx"] ---

・「ref03.docx」は、カレント・ディレクトリに置くこと。

参考情報

Pandoc User’s Guide 日本語版
LuaTeX-ja の使い方
TeX WiKi - LuaTeX-ja
VScode+pandoc+Lualatexで日本語pdfをMarkdownから出力する
rmarkdownのYAMLヘッダ

MathJax | Beautiful math in all browsers.
WiKi - MathJax

数式・画像付きのmarkdownをhtmlに変換
Markdown記法 サンプル集
メモ: Pandoc+LaTeXで気軽に日本語PDFを出力する
Pandocを使ったWord組版のはじめ方
Mermaid.jsでグラフを簡単に描く方法
Mermaid lets you create diagrams and visualizations using text and code.
mermaid-cli

Markdownでスクショ画像をペーストする(VS Code)
ubuntu関連:
How to printscreen direct to clipboard
Ubuntu, Linux Mintでスクリーンショットを撮る
windows10関連:
スクショがより手軽に!「Snipping Tool」アプリに代わる新しいスクリーンショット機能

Windows10で実行ファイルへのパスを通す手順
Equivalent of *Nix 'which' command in PowerShell?

以上

» 続きを読む

| | コメント (0)

2021年5月 6日 (木)

microbit-v2にMicropythonをインストールする

2021/5/10
LCD表示スクリプトを追加した。

2021/5/6
初版

microbit-v2 MicroPython Install

microbit-v2 MicroPython Install

概要

microbit-v2にMicropythonをインストールする方法について記載する
webブラウザーから「micro:bit python editor」にアクセスしてプログラムを作成する方法があるが、ここではmicrobit-v2のボードにmicropythonインタープリタを書き込んで使用する。
(ホストPCとしてはubuntuを想定している)

注意:
microbit-v1のmicropythonの書き込み/実行には以下のエディタを使用すること。
micro:bit python editor

事前準備

(1)Thonny(pythonエディタ)
以下の手順でインストールする:

bash <(wget -O - https://thonny.org/installer-for-linux)

(2)picocom(通信ソフト)
以下の手順でインストールする:

sudo apt-get install picocom

ビルド手順

以下の手順でmicrobit-v2用のmicropythonをビルドする:

mkdir mb2_mp cd mb2_mp git clone https://github.com/microbit-foundation/micropython-microbit-v2.git cd micropython-microbit-v2 git submodule update --init make -C lib/micropython/mpy-cross cd src gedit Makefile # Makefileを自分のビルド環境にあわせて変更する

Makefile
以下の部分を自分の実行パスに合わせて変更する:
(実行パスは、which rm,which mkdirなどを実行すると分かる)

<省略> RM = /usr/bin/rm MKDIR = /usr/bin/mkdir PYTHON3 ?= python3 <省略>

続き:

make # makeが完了すると以下のようにMICROBIT.hexが生成される: ls MICROBIT.hex addlayouttable.py codal.patch codal_port Makefile build codal_app # miicrobit-v2ボードを接続してファームウェアを描き込む cp MICROBIT.hex /media/USER/MICROBIT/

以上でfirmwareがボードに書き込まれる。
・USERは環境依存なので、自分の環境に合わせること。

動作確認

picocomを使いボードとシリアルで通信する。
以下、通信例:

$ picocom /dev/ttyACM0 -b115200 MPY: soft reboot MicroPython v1.15-64-g1e2f0d280 on 2021-05-06; micro:bit v2.0.0-beta.5 with nRF52833 Type "help()" for more information. >>> import os >>> os.uname() (sysname='microbit', nodename='microbit', release='2.0.0-beta.5', version='micro:bit v2.0.0-beta.5+c28e6bd-dirty on 2021-05-06; MicroPython v1.15-64-g1e2f0d280 on 2021-05-06', machine='micro:bit with nRF52833') >>> import gc >>> gc.collect() >>> gc.mem_free() 62272 >>> list(5 * x + y for x in range(10) for y in [4, 2, 1]) [4, 2, 1, 9, 7, 6, 14, 12, 11, 19, 17, 16, 24, 22, 21, 29, 27, 26, 34, 32, 31, 39, 37, 36, 44, 42, 41, 49, 47, 46] >>> >>> dir() ['pin_logo', 'panic', 'pin2', 'pin3', 'pin0', 'pin1', 'pin6', 'compass', 'pin4', 'pin5', 'pin7', 'sleep', 'temperature', 'pin9', 'pin8', 'ws2812_write', 'SoundEvent', 'pin13', 'pin12', 'pin11', 'pin10', 'running_time', 'spi', 'pin15', 'pin14', 'display', 'accelerometer', 'pin16', 'pin19', '__thonny_helper', 'audio', '__thonny_relevant', 'button_a', 'button_b', 'Sound', 'os', 'speaker', 'pin_speaker', 'pin20', 'i2c', '__name__', 'uart', 'set_volume', 'Image', 'microphone', 'gc', 'reset'] >>> help('modules') __main__ machine os uerrno antigravity math radio urandom audio microbit speech ustruct builtins micropython this usys gc music uarray utime love neopixel ucollections Plus any modules on the filesystem >>> #オンライン・ヘルプ >>> help() Welcome to MicroPython on the micro:bit! Try these commands: display.scroll('Hello') running_time() sleep(1000) button_a.is_pressed() What do these commands do? Can you improve them? HINT: use the up and down arrow keys to get your command history. Press the TAB key to auto-complete unfinished words (so 'di' becomes 'display' after you press TAB). These tricks save a lot of typing and look cool! Explore: Type 'help(something)' to find out about it. Type 'dir(something)' to see what it can do. Type 'dir()' to see what stuff is available. For goodness sake, don't type 'import this'. Control commands: CTRL-C -- stop a running program CTRL-D -- on a blank line, do a soft reset of the micro:bit CTRL-E -- enter paste mode, turning off auto-indent For a list of available modules, type help('modules') For more information about Python, visit: http://python.org/ To find out about MicroPython, visit: http://micropython.org/ Python/micro:bit documentation is here: https://microbit-micropython.readthedocs.io/ >>>

サンプルスクリプト

helloWorld.py

from microbit import * while True: display.scroll('Hello, World!') display.show(Image.HEART) sleep(2000)

blink.py

from microbit import * while True: pin0.write_digital(0) sleep(500) pin0.write_digital(1) sleep(500)

・接続しているLED(pin0)が点滅する。

dimmer.py

from microbit import * min_power = 50 max_power = 1023 power_step = (max_power - min_power) / 9 brightness = 0 def set_power(brightness): display.show(str(brightness)) if brightness == 0: pin0.write_analog(0) else: pin0.write_analog(brightness * power_step + min_power) set_power(brightness) while True: if button_a.was_pressed(): brightness -= 1 if brightness < 0: brightness = 0 set_power(brightness) elif button_b.was_pressed(): brightness += 1 if brightness > 9: brightness = 9 set_power(brightness) sleep(100)

・ボタンBを押すと接続しているLEC(pin0)の光量が増す。
・ボタンAを押すと接続しているLEC(pin0)の光量が減る。

linghtsensor.py

from microbit import * while True: if display.read_light_level() < 100: display.show(Image.HEART) else: display.clear() sleep(2000)

・光をLED-Matrixに当てると表示されているLEDのハートマークが消える。
 (強い光を当てないと光センサーが動作しないようだ)

conway.py

''' Conway's Game Of Life for the micro:bit Press button A or tap the micro:bit to generate a fresh layout. ''' import microbit import random arena1 = bytearray(7 * 7) arena2 = bytearray(7 * 7) def show(): img = microbit.Image(5,5) for y in range(5): for x in range(5): img.set_pixel(x, y, arena1[8 + y * 7 + x]*9) microbit.display.show(img) # do 1 iteration of Conway's Game of Life def conway_step(): global arena1, arena2 for i in range(5 * 5): # loop over pixels i = 8 + (i // 5) * 7 + i % 5 # count number of neighbours num_neighbours = (arena1[i - 8] + arena1[i - 7] + arena1[i - 6] + arena1[i - 1] + arena1[i + 1] + arena1[i + 6] + arena1[i + 7] + arena1[i + 8]) # check if the centre cell is alive or not self = arena1[i] # apply the rules of life if self and not (2 <= num_neighbours <= 3): arena2[i] = 0 # not enough, or too many neighbours: cell dies elif not self and num_neighbours == 3: arena2[i] = 1 # exactly 3 neighbours around an empty cell: cell is born else: arena2[i] = self # stay as-is # swap the buffers (arena1 is now the new one to display) arena1, arena2 = arena2, arena1 while True: # randomise the start for i in range(5 * 5): # loop over pixels i = 8 + (i // 5) * 7 + i % 5 arena1[i] = random.randrange(2) # set the pixel randomly show() microbit.sleep(1) # need to yield to update accelerometer (not ideal...) # loop while button a is not pressed while not microbit.button_a.is_pressed() and microbit.accelerometer.get_z() < -800: conway_step() show() microbit.sleep(150)

neopixel_random.py

""" neopixel_random.py Repeatedly displays random colours onto the LED strip. This example requires a strip of 8 Neopixels (WS2812) connected to pin0. """ from microbit import * import neopixel from random import randint # Setup the Neopixel strip on pin0 with a length of 8 pixels #np = neopixel.NeoPixel(pin0, 8) np = neopixel.NeoPixel(pin0, 64) while True: #Iterate over each LED in the strip for pixel_id in range(0, len(np)): red = randint(0, 60) green = randint(0, 60) blue = randint(0, 60) # Assign the current LED a random red, green and blue value between 0 and 60 np[pixel_id] = (red, green, blue) # Display the current pixel data on the Neopixel strip np.show() #sleep(100)

・使用するneopixelの数に応じてsleep時間は調整すること。

firefly.py

# A micro:bit Firefly. # By Nicholas H.Tollervey. Released to the public domain. import radio import random from microbit import display, Image, button_a, sleep # Create the "flash" animation frames. Can you work out how it's done? flash = [Image().invert()*(i/9) for i in range(9, -1, -1)] # The radio won't work unless it's switched on. radio.on() # Event loop. while True: # Button A sends a "flash" message. if button_a.was_pressed(): radio.send('flash') # a-ha # Read any incoming messages. incoming = radio.receive() if incoming == 'flash': # If there's an incoming "flash" message display # the firefly flash animation after a random short # pause. sleep(random.randint(50, 350)) display.show(flash, delay=100, wait=False) # Randomly re-broadcast the flash message after a # slight delay. if random.randint(0, 9) == 0: sleep(500) radio.send('flash') # a-ha

・2つのmicrobitを用意して上のプログラムを描き込み実行する。
・Aボタンを押すとbluetooth経由で信号を受信して対向のmicrobitのLEDが光る。
(対向のmicrobitはv2でなくても良い)

performanceTest.py

import time def performanceTest(): msec = time.ticks_ms endTime = msec() + 10000 count = 0 while msec() < endTime: count += 1 print("Count: ", count) performanceTest()

以下が出力される:(出力例)

Count: 669283

LCD表示スクリプト(2021/5/10)

以下は 「DEPRECATED LIBRARY micropython-adafruit-rgb-display」のソースをmicrobit-v2のmicropythonに合わせて修正したものになる:
(使用しているLCDは以下のもの)
1.8inch colorful display module for micro:bit, 160x128

rgb.py

import utime import ustruct def color565(r, g, b): return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3 class DummyPin: """A fake gpio pin for when you want to skip pins.""" OUT = 0 IN = 0 PULL_UP = 0 PULL_DOWN = 0 OPEN_DRAIN = 0 ALT = 0 ALT_OPEN_DRAIN = 0 LOW_POWER = 0 MED_POWER = 0 HIGH_PWER = 0 IRQ_FALLING = 0 IRQ_RISING = 0 IRQ_LOW_LEVEL = 0 IRQ_HIGH_LEVEL = 0 def __call__(self, *args, **kwargs): return False init = __call__ value = __call__ out_value = __call__ toggle = __call__ high = __call__ low = __call__ on = __call__ off = __call__ mode = __call__ pull = __call__ drive = __call__ irq = __call__ class Display: _PAGE_SET = None _COLUMN_SET = None _RAM_WRITE = None _RAM_READ = None _INIT = () _ENCODE_PIXEL = ">H" _ENCODE_POS = ">HH" _DECODE_PIXEL = ">BBB" def __init__(self, width, height): self.width = width self.height = height self.init() def init(self): """Run the initialization commands.""" for command, data in self._INIT: self._write(command, data) def _block(self, x0, y0, x1, y1, data=None): """Read or write a block of data.""" self._write(self._COLUMN_SET, self._encode_pos(x0, x1)) self._write(self._PAGE_SET, self._encode_pos(y0, y1)) if data is None: size = ustruct.calcsize(self._DECODE_PIXEL) return self._read(self._RAM_READ, (x1 - x0 + 1) * (y1 - y0 + 1) * size) self._write(self._RAM_WRITE, data) def _encode_pos(self, a, b): """Encode a postion into bytes.""" return ustruct.pack(self._ENCODE_POS, a, b) def _encode_pixel(self, color): """Encode a pixel color into bytes.""" return ustruct.pack(self._ENCODE_PIXEL, color) def _decode_pixel(self, data): """Decode bytes into a pixel color.""" return color565(*ustruct.unpack(self._DECODE_PIXEL, data)) def pixel(self, x, y, color=None): """Read or write a pixel.""" if color is None: return self._decode_pixel(self._block(x, y, x, y)) if not 0 <= x < self.width or not 0 <= y < self.height: return self._block(x, y, x, y, self._encode_pixel(color)) def fill_rectangle(self, x, y, width, height, color): """Draw a filled rectangle.""" x = min(self.width - 1, max(0, x)) y = min(self.height - 1, max(0, y)) w = min(self.width - x, max(1, width)) h = min(self.height - y, max(1, height)) self._block(x, y, x + w - 1, y + h - 1, b'') chunks, rest = divmod(w * h, 512) pixel = self._encode_pixel(color) if chunks: data = pixel * 512 for count in range(chunks): self._write(None, data) if rest: self._write(None, pixel * rest) def fill(self, color=0): """Fill whole screen.""" self.fill_rectangle(0, 0, self.width, self.height, color) def hline(self, x, y, width, color): """Draw a horizontal line.""" self.fill_rectangle(x, y, width, 1, color) def vline(self, x, y, height, color): """Draw a vertical line.""" self.fill_rectangle(x, y, 1, height, color) def blit_buffer(self, buffer, x, y, width, height): """Copy pixels from a buffer.""" if (not 0 <= x < self.width or not 0 <= y < self.height or not 0 < x + width <= self.width or not 0 < y + height <= self.height): raise ValueError("out of bounds") self._block(x, y, x + width - 1, y + height - 1, buffer) class DisplaySPI(Display): def __init__(self, spi, dc, cs=None, rst=None, width=1, height=1): self.spi = spi self.cs = cs self.dc = dc self.rst = rst if self.rst is None: self.rst = DummyPin() if self.cs is None: self.cs = DummyPin() #self.cs.init(self.cs.OUT, value=1) #self.dc.init(self.dc.OUT, value=0) #self.rst.init(self.rst.OUT, value=1) self.cs.write_digital(1) self.dc.write_digital(0) self.rst.write_digital(1) self.reset() super().__init__(width, height) def reset(self): #self.rst(0) self.rst.write_digital(0) utime.sleep_ms(50) #self.rst(1) self.rst.write_digital(1) utime.sleep_ms(50) def _write(self, command=None, data=None): if command is not None: #self.dc(0) #self.cs(0) self.dc.write_digital(0) self.cs.write_digital(0) self.spi.write(bytearray([command])) #self.cs(1) self.cs.write_digital(1) if data is not None: #self.dc(1) #self.cs(0) self.dc.write_digital(1) self.cs.write_digital(0) self.spi.write(data) #self.cs(1) self.cs.write_digital(1) def _read(self, command=None, count=0): #self.dc(0) #self.cs(0) self.dc.write_digital(0) self.cs.write_digital(0) if command is not None: self.spi.write(bytearray([command])) if count: data = self.spi.read(count) #self.cs(1) self.cs.write_digital(1) return data

・ピン制御の部分をmicrobitのmicropythonに合わせて修正した。

st7735.py

from rgb import DisplaySPI, color565 import ustruct _NOP=const(0x00) _SWRESET=const(0x01) _RDDID=const(0x04) _RDDST=const(0x09) _SLPIN=const(0x10) _SLPOUT=const(0x11) _PTLON=const(0x12) _NORON=const(0x13) _INVOFF=const(0x20) _INVON=const(0x21) _DISPOFF=const(0x28) _DISPON=const(0x29) _CASET=const(0x2A) _RASET=const(0x2B) _RAMWR=const(0x2C) _RAMRD=const(0x2E) _PTLAR=const(0x30) _COLMOD=const(0x3A) _MADCTL=const(0x36) _FRMCTR1=const(0xB1) _FRMCTR2=const(0xB2) _FRMCTR3=const(0xB3) _INVCTR=const(0xB4) _DISSET5=const(0xB6) _PWCTR1=const(0xC0) _PWCTR2=const(0xC1) _PWCTR3=const(0xC2) _PWCTR4=const(0xC3) _PWCTR5=const(0xC4) _VMCTR1=const(0xC5) _RDID1=const(0xDA) _RDID2=const(0xDB) _RDID3=const(0xDC) _RDID4=const(0xDD) _PWCTR6=const(0xFC) _GMCTRP1=const(0xE0) _GMCTRN1=const(0xE1) class ST7735(DisplaySPI): """ A simple driver for the ST7735-based displays. >>> from machine import Pin, SPI >>> import st7735 >>> display = st7735.ST7735(SPI(1), dc=Pin(12), cs=Pin(15), rst=Pin(16)) >>> display = st7735.ST7735R(SPI(1, baudrate=40000000), dc=Pin(12), cs=Pin(15), rst=Pin(16)) >>> display.fill(0x7521) >>> display.pixel(64, 64, 0) """ _COLUMN_SET = _CASET _PAGE_SET = _RASET _RAM_WRITE = _RAMWR _RAM_READ = _RAMRD _INIT = ( (_SWRESET, None), (_SLPOUT, None), (_MADCTL, b'\x08'), # bottom to top refresh (_COLMOD, b'\x05'), # 16bit color (_INVCTR, b'0x00'), # line inversion # 1 clk cycle nonoverlap, 2 cycle gate rise, 3 sycle osc equalie, # fix on VTL (_DISSET5, b'\x15\x02'), # fastest refresh, 6 lines front porch, 3 line back porch (_FRMCTR1, b'\x00\x06\x03'), (_PWCTR1, b'\x02\x70'), # GVDD = 4.7V, 1.0uA (_PWCTR2, b'\x05'), # VGH=14.7V, VGL=-7.35V (_PWCTR3, b'\x01\x02'), # Opamp current small, Boost frequency (_PWCTR6, b'\x11\x15'), (_VMCTR1, b'\x3c\x38'), # VCOMH = 4V, VOML = -1.1V (_GMCTRP1, b'\x09\x16\x09\x20\x21\x1b\x13\x19' b'\x17\x15\x1e\x2b\x04\x05\x02\x0e'), # Gamma (_GMCTRN1, b'\x08\x14\x08\x1e\x22\x1d\x18\x1e' b'\x18\x1a\x24\x2b\x06\x06\x02\x0f'), (_CASET, b'\x00\x02\x00\x81'), # XSTART = 2, XEND = 129 (_RASET, b'\x00\x02\x00\x81'), # YSTART = 2, YEND = 129 (_NORON, None), (_DISPON, None), ) _ENCODE_PIXEL = ">H" _ENCODE_POS = ">HH" def __init__(self, spi, dc, cs, rst=None, width=128, height=128): super().__init__(spi, dc, cs, rst, width, height) class ST7735R(ST7735): _INIT = ( (_SWRESET, None), (_SLPOUT, None), (_MADCTL, b'\xc8'), (_COLMOD, b'\x05'), # 16bit color (_INVCTR, b'\x07'), (_FRMCTR1, b'\x01\x2c\x2d'), (_FRMCTR2, b'\x01\x2c\x2d'), (_FRMCTR3, b'\x01\x2c\x2d\x01\x2c\x2d'), (_PWCTR1, b'\x02\x02\x84'), (_PWCTR2, b'\xc5'), (_PWCTR3, b'\x0a\x00'), (_PWCTR4, b'\x8a\x2a'), (_PWCTR5, b'\x8a\xee'), (_VMCTR1, b'\x0e'), (_INVOFF, None), (_GMCTRP1, b'\x02\x1c\x07\x12\x37\x32\x29\x2d' b'\x29\x25\x2B\x39\x00\x01\x03\x10'), # Gamma (_GMCTRN1, b'\x03\x1d\x07\x06\x2E\x2C\x29\x2D' b'\x2E\x2E\x37\x3F\x00\x00\x02\x10'), ) def __init__(self, spi, dc, cs, rst=None, width=128, height=160): super().__init__(spi, dc, cs, rst, width, height) def init(self): super().init() cols = ustruct.pack('>HH', 0, self.width - 1) rows = ustruct.pack('>HH', 0, self.height - 1) for command, data in ( (_CASET, cols), (_RASET, rows), (_NORON, None), (_DISPON, None), ): self._write(command, data)

・特に修正はない。

displayLCD.py

from microbit import * from st7735 import ST7735, ST7735R from rgb import color565 spi.init(mode=3, baudrate=300000000, sclk=pin13, mosi=pin15, miso=pin14) #spi.init(0) lcd = ST7735R(spi, dc=pin12, cs=pin16, rst=pin8) lcd.fill(0) for x in range(128): for y in range(160): lcd.pixel(x,y,color565(x*2, y*3//2, 255-x-y*3//4))

・転送速度が遅いようで描画速度が遅い。
 (設定の問題だと思うが画面端にゴミが表示される)
・他のmicropythonと異なり最初からSPIのインスタンスが用意されているので、コーディング時は、そこに注意する必要がある。(メモリの制約と推測する)

main.py

電源オン時に自動的にmain.pyが実行されるので、直接実行したいプログラムをmain.pyに置くことができる。
直接実行したいプログラムがxxxx.pyの場合は、
main.pyを以下のようにしても良い。

main.py

# main.py import xxxx

参照URL

micro:bit-v2_MicroPython関連:
MicroPython on the micro:bit via CODAL
Hello, World! (v2-doc)日本語版
micro:bit v2 用 MicroPython で新機能を試してみる
Hello, World! (v2-doc)
Out of box experience(factory reset)
Python guide(examples)
micropython/examples

Thonny関連:
Thonny (Python IDE for beginners)
Thonnyインストール方法(PicoボードにMicropython/CircuitPythonをインストールする)

(別の)MicroPython関連:
TFT LCD(ST7735R)をMicroPythonで動かしてみた
DEPRECATED LIBRARY micropython-adafruit-rgb-display

MakeCode(python)関連:(参考)
(the difference between) MakeCode Python and MicroPython
micro:bit v2(マイクロビット)に関する技術情報を集約

以上

» 続きを読む

| | コメント (0)

2021年4月30日 (金)

LCDをmicrobit_arduinoで動かす

2021/5/3
スケッチをハードウェアSPIに切り替えた。

2021/4/30
初版

pio Microbit Arduino ST7735S

pio Microbit Arduino ST7735S

概要

以下のLCDをmicrobit_arduinoで動かす
1.8inch colorful display module for micro:bit, 160x128 (ST7735S)
(ホストはubuntu20.04を想定している)
platformioが既にインストールされている前提で説明する。

platformioのインストールについては以下などを参照のこと:
arduinoフレームワーク用platformio.ini集

platformio.ini

以下のplatformio.iniを利用する:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:bbcmicrobit] platform = nordicnrf51 board = bbcmicrobit framework = arduino build_flags = -DMICROBIT -DNRF51_S110 monitor_speed = 115200 lib_ldf_mode = deep+ #upload_port = /media/USER/MICROBIT #upload_protocol = mbed upload_protocol = cmsis-dap lib_deps = https://github.com/adafruit/Adafruit_BusIO/archive/master.zip https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/archive/master.zip https://cdn-learn.adafruit.com/assets/assets/000/046/217/original/MMA8653.zip https://github.com/stm32duino/LSM303AGR/archive/master.zip https://github.com/adafruit/Adafruit-GFX-Library/archive/master.zip # https://github.com/sandeepmistry/arduino-BLEPeripheral/archive/master.zip https://github.com/adafruit/Adafruit_Microbit/archive/master.zip # https://github.com/ht-deko/microbit_Screen/archive/master.zip # adafruit/Adafruit ST7735 and ST7789 Library @ ^1.7.2

graphicstest.ino

テスト用プログラムを以下のように作成する:
src/graphicstest.ino

// modified for Waveshare 1.8inch LCD for micro:bit, controler:ST7735S (2021/4/30) /************************************************************************** This is a library for several Adafruit displays based on ST77* drivers. Works with the Adafruit 1.8" TFT Breakout w/SD card ----> http://www.adafruit.com/products/358 The 1.8" TFT shield ----> https://www.adafruit.com/product/802 The 1.44" TFT breakout ----> https://www.adafruit.com/product/2088 The 1.14" TFT breakout ----> https://www.adafruit.com/product/4383 The 1.3" TFT breakout ----> https://www.adafruit.com/product/4313 The 1.54" TFT breakout ----> https://www.adafruit.com/product/3787 The 2.0" TFT breakout ----> https://www.adafruit.com/product/4311 as well as Adafruit raw 1.8" TFT display ----> http://www.adafruit.com/products/618 Check out the links above for our tutorials and wiring diagrams. These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional). Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution **************************************************************************/ #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library for ST7735 #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789 #include <SPI.h> #ifndef MICROBIT #if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32 #define TFT_CS 14 #define TFT_RST 15 #define TFT_DC 32 #elif defined(ESP8266) #define TFT_CS 4 #define TFT_RST 16 #define TFT_DC 5 #else // For the breakout board, you can use any 2 or 3 pins. // These pins will also work for the 1.8" TFT shield. #define TFT_CS 10 #define TFT_RST 9 // Or set to -1 and connect to Arduino RESET pin #define TFT_DC 8 #endif // OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique // to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and // SCLK = pin 13. This is the fastest mode of operation and is required if // using the breakout board's microSD card. // For 1.44" and 1.8" TFT with ST7735 use: Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789: //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // OPTION 2 lets you interface the display using ANY TWO or THREE PINS, // tradeoff being that performance is not as fast as hardware SPI above. //#define TFT_MOSI 11 // Data out //#define TFT_SCLK 13 // Clock out // For ST7735-based displays, we will use this call //Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); // OR for the ST7789-based displays, we will use this call //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); #endif #ifdef MICROBIT // setup for Waveshare LCD #define TFT_CS 16 #define TFT_RST 8 #define TFT_DC 12 #define TFT_MOSI 15 // Data out #define TFT_SCLK 13 // Clock out #define BL_EN 1 // backlit enable //Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // use Hardware SPI #endif float p = 3.1415926; void setup(void) { //pinMode(BL_EN, OUTPUT); //digitalWrite(BL_EN, HIGH); //Serial.begin(9600); Serial.begin(115200); Serial.print(F("Hello! ST77xx TFT Test")); #ifndef MICROBIT // Use this initializer if using a 1.8" TFT screen: tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare: // tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab // OR use this initializer (uncomment) if using a 1.44" TFT: //tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT: //tft.initR(INITR_MINI160x80); // Init ST7735S mini display // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT: //tft.init(240, 240); // Init ST7789 240x240 // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT: //tft.init(240, 320); // Init ST7789 320x240 // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT: //tft.init(135, 240); // Init ST7789 240x135 // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you // may end up with a black screen some times, or all the time. //tft.setSPISpeed(40000000); #endif #ifdef MICROBIT tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab for WaveShare //tft.setRotation(1); // landscape (microbit board upside) tft.setRotation(2); // portrait (microbit board leftside) tft.setSPISpeed(40000000); #endif Serial.println(F("Initialized")); uint16_t time = millis(); tft.fillScreen(ST77XX_BLACK); time = millis() - time; Serial.println(time, DEC); delay(500); // large block of text tft.fillScreen(ST77XX_BLACK); testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE); delay(1000); // tft print function! tftPrintTest(); delay(4000); // a single pixel tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN); delay(500); // line draw test testlines(ST77XX_YELLOW); delay(500); // optimized lines testfastlines(ST77XX_RED, ST77XX_BLUE); delay(500); testdrawrects(ST77XX_GREEN); delay(500); testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA); delay(500); tft.fillScreen(ST77XX_BLACK); testfillcircles(10, ST77XX_BLUE); testdrawcircles(10, ST77XX_WHITE); delay(500); testroundrects(); delay(500); testtriangles(); delay(500); mediabuttons(); delay(500); Serial.println("done"); delay(1000); } void loop() { tft.invertDisplay(true); delay(500); tft.invertDisplay(false); delay(500); } void testlines(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, 0, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, 0, 0, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, tft.height()-1, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color); delay(0); } } void testdrawtext(char *text, uint16_t color) { tft.setCursor(0, 0); tft.setTextColor(color); tft.setTextWrap(true); tft.print(text); } void testfastlines(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t y=0; y < tft.height(); y+=5) { tft.drawFastHLine(0, y, tft.width(), color1); } for (int16_t x=0; x < tft.width(); x+=5) { tft.drawFastVLine(x, 0, tft.height(), color2); } } void testdrawrects(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color); } } void testfillrects(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=tft.width()-1; x > 6; x-=6) { tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1); tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2); } } void testfillcircles(uint8_t radius, uint16_t color) { for (int16_t x=radius; x < tft.width(); x+=radius*2) { for (int16_t y=radius; y < tft.height(); y+=radius*2) { tft.fillCircle(x, y, radius, color); } } } void testdrawcircles(uint8_t radius, uint16_t color) { for (int16_t x=0; x < tft.width()+radius; x+=radius*2) { for (int16_t y=0; y < tft.height()+radius; y+=radius*2) { tft.drawCircle(x, y, radius, color); } } } void testtriangles() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 0xF800; int t; int w = tft.width()/2; int x = tft.height()-1; int y = 0; int z = tft.width(); for(t = 0 ; t <= 15; t++) { tft.drawTriangle(w, y, y, x, z, x, color); x-=4; y+=4; z-=4; color+=100; } } void testroundrects() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 100; int i; int t; for(t = 0 ; t <= 4; t+=1) { int x = 0; int y = 0; int w = tft.width()-2; int h = tft.height()-2; for(i = 0 ; i <= 16; i+=1) { tft.drawRoundRect(x, y, w, h, 5, color); x+=2; y+=3; w-=4; h-=6; color+=1100; } color+=100; } } void tftPrintTest() { tft.setTextWrap(false); tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST77XX_RED); tft.setTextSize(1); tft.println("Hello World!"); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println("Hello World!"); tft.setTextColor(ST77XX_GREEN); tft.setTextSize(3); tft.println("Hello World!"); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(4); tft.print(1234.567); delay(1500); tft.setCursor(0, 0); tft.fillScreen(ST77XX_BLACK); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(0); tft.println("Hello World!"); tft.setTextSize(1); tft.setTextColor(ST77XX_GREEN); tft.print(p, 6); tft.println(" Want pi?"); tft.println(" "); tft.print(8675309, HEX); // print 8,675,309 out in HEX! tft.println(" Print HEX!"); tft.println(" "); tft.setTextColor(ST77XX_WHITE); tft.println("Sketch has been"); tft.println("running for: "); tft.setTextColor(ST77XX_MAGENTA); tft.print(millis() / 1000); tft.setTextColor(ST77XX_WHITE); tft.print(" seconds."); } void mediabuttons() { // play tft.fillScreen(ST77XX_BLACK); tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE); tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED); delay(500); // pause tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE); tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN); delay(500); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE); delay(50); // pause color tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN); }

・「Adafruit ST7735 and ST7789 Library 」にあるExamplesを修正したもの。
・「#ifdef MICROBIT ... #endif」などで囲まれた部分が修正部分になる。

ビルド&書き込み

以下の手順でビルトと書き込みができる:

cd pico_proj # ツールなどのインストール(最初の1回のみ) pio run -t clean # ビルド&書き込み pio run -t upload # この時点で書き込みが完了する

書き込みが上手く行かない場合は、platformio.iniを以下のように変更すると正常に動作するようだ。
いったん、書き込みが正常動作した跡は、元に戻しても書き込みが正常動作するようだ。

#upload_port = /media/USER/MICROBIT #upload_protocol = mbed upload_protocol = cmsis-dap → upload_port = /media/USER/MICROBIT upload_protocol = mbed #upload_protocol = cmsis-dap

・USERは環境依存なので、実際の環境に合わせて変更する。

micro:bit-V2対応

以下のplatformio.iniでmicrobit-v2でビルド&書き込みができるが、正常動作しないようだ。
(原因不明)

platformio.ini

[env:bbcmicrobit_v2] platform = nordicnrf52 board = bbcmicrobit_v2 framework = arduino ;build_flags = -DMICROBIT_V2 build_flags = -DMICROBIT monitor_speed = 115200 lib_ldf_mode = deep+ #upload_port = /media/USER/MICROBIT #upload_protocol = mbed upload_protocol = cmsis-dap lib_deps = https://github.com/adafruit/Adafruit_BusIO/archive/master.zip https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/archive/master.zip https://cdn-learn.adafruit.com/assets/assets/000/046/217/original/MMA8653.zip https://github.com/stm32duino/LSM303AGR/archive/master.zip https://github.com/adafruit/Adafruit-GFX-Library/archive/master.zip # adafruit/Adafruit ST7735 and ST7789 Library @ ^1.7.2

参考情報

LCD関連:
1.8inch LCD for micro:bit
1.8inch colorful display module for micro:bit, 160x128

Microbit_Arduino関連:
micro:bit Arduino/MBED開発ツール(v2)(micro:bit-v2対応,linux版)
micro:bitでmicrobit_screenライブラリを利用する(micro:bit-v2対応,linux版)
arduinoフレームワーク用platformio.ini集

platformio関連:
PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
arduinoフレームワーク用platformio.ini集
ubuntu20.04をインストールする

以上

» 続きを読む

| | コメント (0)

2021年4月26日 (月)

Display_Packをpico_arduinoで動かす

2021/4/28
LEDとSWの制御スケッチを追加した。

2021/4/25
初版

pio Pico Arduino Display Pack

pio Pico Arduino Display Pack

概要

以下のDisplay_Packをpico_arduinoで動かす
Pico Display Pack
(ホストはubuntu20.04を想定している)
platformioが既にインストールされている前提で説明する。

platformioのインストールについては以下などを参照のこと:
arduinoフレームワーク用platformio.ini集

platformio.ini

以下のplatformio.iniを利用する:

[env:pico] platform = https://github.com/platformio/platform-raspberrypi.git framework = arduino board = pico build_flags = -DPICO upload_port = /dev/ttyACM0 monitor_port = /dev/ttyACM0 monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = adafruit/Adafruit BusIO @ ^1.7.3 adafruit/Adafruit ST7735 and ST7789 Library @ ^1.7.1

graphicstest.ino

テスト用プログラムを以下のように作成する:
src/graphicstest.ino

// modified for pimoroni display pack (2021/4/25) /************************************************************************** This is a library for several Adafruit displays based on ST77* drivers. Works with the Adafruit 1.8" TFT Breakout w/SD card ----> http://www.adafruit.com/products/358 The 1.8" TFT shield ----> https://www.adafruit.com/product/802 The 1.44" TFT breakout ----> https://www.adafruit.com/product/2088 The 1.14" TFT breakout ----> https://www.adafruit.com/product/4383 The 1.3" TFT breakout ----> https://www.adafruit.com/product/4313 The 1.54" TFT breakout ----> https://www.adafruit.com/product/3787 The 2.0" TFT breakout ----> https://www.adafruit.com/product/4311 as well as Adafruit raw 1.8" TFT display ----> http://www.adafruit.com/products/618 Check out the links above for our tutorials and wiring diagrams. These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional). Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution **************************************************************************/ #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library for ST7735 #include <Adafruit_ST7789.h> // Hardware-specific library for ST7789 #include <SPI.h> #ifndef PICO #if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32 #define TFT_CS 14 #define TFT_RST 15 #define TFT_DC 32 #elif defined(ESP8266) #define TFT_CS 4 #define TFT_RST 16 #define TFT_DC 5 #else // For the breakout board, you can use any 2 or 3 pins. // These pins will also work for the 1.8" TFT shield. #define TFT_CS 10 #define TFT_RST 9 // Or set to -1 and connect to Arduino RESET pin #define TFT_DC 8 #endif // OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique // to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and // SCLK = pin 13. This is the fastest mode of operation and is required if // using the breakout board's microSD card. // For 1.44" and 1.8" TFT with ST7735 use: Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // For 1.14", 1.3", 1.54", and 2.0" TFT with ST7789: //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // OPTION 2 lets you interface the display using ANY TWO or THREE PINS, // tradeoff being that performance is not as fast as hardware SPI above. //#define TFT_MOSI 11 // Data out //#define TFT_SCLK 13 // Clock out // For ST7735-based displays, we will use this call //Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); // OR for the ST7789-based displays, we will use this call //Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); #endif #ifdef PICO // setup for pico display pack #define TFT_CS 17 #define TFT_RST -1 #define TFT_DC 16 #define TFT_MOSI 19 // Data out #define TFT_SCLK 18 // Clock out #define BL_EN 20 // backlit enable Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); #endif float p = 3.1415926; void setup(void) { //pinMode(BL_EN, OUTPUT); //digitalWrite(BL_EN, HIGH); //Serial.begin(9600); Serial.begin(115200); Serial.print(F("Hello! ST77xx TFT Test")); #ifndef PICO // Use this initializer if using a 1.8" TFT screen: tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare: // tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab // OR use this initializer (uncomment) if using a 1.44" TFT: //tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT: //tft.initR(INITR_MINI160x80); // Init ST7735S mini display // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT: //tft.init(240, 240); // Init ST7789 240x240 // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT: //tft.init(240, 320); // Init ST7789 320x240 // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT: //tft.init(135, 240); // Init ST7789 240x135 // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you // may end up with a black screen some times, or all the time. //tft.setSPISpeed(40000000); #endif #ifdef PICO tft.init(135, 240); // Init ST7789 240x135 //tft.setRotation(3); // landscape tft.setRotation(2); // rotate for matching printing chars on the board tft.setSPISpeed(40000000); #endif Serial.println(F("Initialized")); uint16_t time = millis(); tft.fillScreen(ST77XX_BLACK); time = millis() - time; Serial.println(time, DEC); delay(500); // large block of text tft.fillScreen(ST77XX_BLACK); testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE); delay(1000); // tft print function! tftPrintTest(); delay(4000); // a single pixel tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN); delay(500); // line draw test testlines(ST77XX_YELLOW); delay(500); // optimized lines testfastlines(ST77XX_RED, ST77XX_BLUE); delay(500); testdrawrects(ST77XX_GREEN); delay(500); testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA); delay(500); tft.fillScreen(ST77XX_BLACK); testfillcircles(10, ST77XX_BLUE); testdrawcircles(10, ST77XX_WHITE); delay(500); testroundrects(); delay(500); testtriangles(); delay(500); mediabuttons(); delay(500); Serial.println("done"); delay(1000); } void loop() { tft.invertDisplay(true); delay(500); tft.invertDisplay(false); delay(500); } void testlines(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, 0, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, 0, 0, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(0, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(0, tft.height()-1, tft.width()-1, y, color); delay(0); } tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color); delay(0); } for (int16_t y=0; y < tft.height(); y+=6) { tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color); delay(0); } } void testdrawtext(char *text, uint16_t color) { tft.setCursor(0, 0); tft.setTextColor(color); tft.setTextWrap(true); tft.print(text); } void testfastlines(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t y=0; y < tft.height(); y+=5) { tft.drawFastHLine(0, y, tft.width(), color1); } for (int16_t x=0; x < tft.width(); x+=5) { tft.drawFastVLine(x, 0, tft.height(), color2); } } void testdrawrects(uint16_t color) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=0; x < tft.width(); x+=6) { tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color); } } void testfillrects(uint16_t color1, uint16_t color2) { tft.fillScreen(ST77XX_BLACK); for (int16_t x=tft.width()-1; x > 6; x-=6) { tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1); tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2); } } void testfillcircles(uint8_t radius, uint16_t color) { for (int16_t x=radius; x < tft.width(); x+=radius*2) { for (int16_t y=radius; y < tft.height(); y+=radius*2) { tft.fillCircle(x, y, radius, color); } } } void testdrawcircles(uint8_t radius, uint16_t color) { for (int16_t x=0; x < tft.width()+radius; x+=radius*2) { for (int16_t y=0; y < tft.height()+radius; y+=radius*2) { tft.drawCircle(x, y, radius, color); } } } void testtriangles() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 0xF800; int t; int w = tft.width()/2; int x = tft.height()-1; int y = 0; int z = tft.width(); for(t = 0 ; t <= 15; t++) { tft.drawTriangle(w, y, y, x, z, x, color); x-=4; y+=4; z-=4; color+=100; } } void testroundrects() { tft.fillScreen(ST77XX_BLACK); uint16_t color = 100; int i; int t; for(t = 0 ; t <= 4; t+=1) { int x = 0; int y = 0; int w = tft.width()-2; int h = tft.height()-2; for(i = 0 ; i <= 16; i+=1) { tft.drawRoundRect(x, y, w, h, 5, color); x+=2; y+=3; w-=4; h-=6; color+=1100; } color+=100; } } void tftPrintTest() { tft.setTextWrap(false); tft.fillScreen(ST77XX_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST77XX_RED); tft.setTextSize(1); tft.println("Hello World!"); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println("Hello World!"); tft.setTextColor(ST77XX_GREEN); tft.setTextSize(3); tft.println("Hello World!"); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(4); tft.print(1234.567); delay(1500); tft.setCursor(0, 0); tft.fillScreen(ST77XX_BLACK); tft.setTextColor(ST77XX_WHITE); tft.setTextSize(0); tft.println("Hello World!"); tft.setTextSize(1); tft.setTextColor(ST77XX_GREEN); tft.print(p, 6); tft.println(" Want pi?"); tft.println(" "); tft.print(8675309, HEX); // print 8,675,309 out in HEX! tft.println(" Print HEX!"); tft.println(" "); tft.setTextColor(ST77XX_WHITE); tft.println("Sketch has been"); tft.println("running for: "); tft.setTextColor(ST77XX_MAGENTA); tft.print(millis() / 1000); tft.setTextColor(ST77XX_WHITE); tft.print(" seconds."); } void mediabuttons() { // play tft.fillScreen(ST77XX_BLACK); tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE); tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED); delay(500); // pause tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE); tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN); delay(500); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE); delay(50); // pause color tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED); tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED); // play color tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN); }

・「Adafruit ST7735 and ST7789 Library 」にあるExamplesをDisplay_Pack向けに修正したもの。
・「#ifdef PICO ... #endif」などで囲まれた部分が修正部分になる。

ビルド&書き込み

以下の手順でビルトと書き込みができる:

cd pico_proj # ツールなどのインストール(最初の1回のみ) pio run -t clean # ビルドと書き込み # bootselボタンを押しながらホストにUSB接続して # その後、bootselボタンを離すると、書き込み用ストレージが出現する pio run -t upload # この時点で書き込みが完了する

Pico_LED_SW.ino (2021/4/28)

Display_PackのLEDとSWの制御スケッチを以下に紹介する:

src/Pico_LED_SW.ino

// for pimoroni Display Pack (2021/4/28) // setup LEDs & SWs #define LED_R 6 #define LED_G 7 #define LED_B 8 #define SW_A 12 #define SW_B 13 #define SW_X 14 #define SW_Y 15 int swn = 0; int sSW_A = LOW; int sSW_B = LOW; int sSW_X = LOW; int sSW_Y = LOW; int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by void setup(void) { // init LEDs (negative logic) pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); //digitalWrite(LED_R, LOW); //digitalWrite(LED_G, LOW); //digitalWrite(LED_B, LOW); // setup SWs pinMode(SW_A, INPUT_PULLUP); pinMode(SW_B, INPUT_PULLUP); pinMode(SW_X, INPUT_PULLUP); pinMode(SW_Y, INPUT_PULLUP); Serial.begin(115200); Serial.print(F("LEDs and SWs Test")); } void loop() { // set the brightness switch(swn) { case 0: analogWrite(LED_R, brightness); // other LEDs off pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); break; case 1: analogWrite(LED_G, brightness); // other LEDs off pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); break; case 2: analogWrite(LED_B, brightness); // other LEDs off pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); break; default: pinMode(LED_R, OUTPUT); digitalWrite(LED_R, HIGH); pinMode(LED_G, OUTPUT); digitalWrite(LED_G, HIGH); pinMode(LED_B, OUTPUT); digitalWrite(LED_B, HIGH); analogWrite(LED_R, brightness); analogWrite(LED_G, brightness); analogWrite(LED_B, brightness); } // change the brightness for next time through the loop: brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: if (brightness <= 0 || brightness >= 255) { fadeAmount = -fadeAmount; } sSW_A = digitalRead(SW_A); sSW_B = digitalRead(SW_B); sSW_X = digitalRead(SW_X); sSW_Y = digitalRead(SW_Y); if (sSW_A == LOW) {swn=0; Serial.println("SW_A: pressed");} if (sSW_B == LOW) {swn=1; Serial.println("SW_B: pressed");} if (sSW_X == LOW) {swn=2; Serial.println("SW_X: pressed");} if (sSW_Y == LOW) {swn=3; Serial.println("SW_Y: pressed");} do { sSW_A = digitalRead(SW_A); sSW_B = digitalRead(SW_B); sSW_X = digitalRead(SW_X); sSW_Y = digitalRead(SW_Y); delay(50); } while ((sSW_A == LOW)||(sSW_B == LOW)||(sSW_X == LOW)||(sSW_Y == LOW)) ; }

(1)スイッチ(SW_A,SW_B,SW_X,SW_Y)を押すとスイッチの状態がシリアル出力される。
(2)SW_Aを押すとLEDが赤、SW_Bを押すとLEDが緑、SW_Xを押すとLEDが青、SW_Yを押すと白に、明るさが変化しながら光る。

ただし、Arduino純正ボードライブラリ(platformio,Arduino-IDEとも)にバグがあるようで、SW_Yは動作せず、LEDの色も混じった色になり意図したものと異なる。(pinModeのbug??)

earlephilhower版Arduino-IDE(以下のjsonファイルを設定するもの)のボードライブラリは問題が無いようで、SW_Yも正常動作するし、LEDの色も混ざらない。

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

参考情報

Arduino-IDE関連:
Arduino-IDEでPicoを動かす

Pico-Platformio(Arduino)関連:
platformioでpicoを動かす
Official PlatformIO + Arduino IDE support for the Raspberry Pi Pico is now available!

platformio関連:
PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
arduinoフレームワーク用platformio.ini集
ubuntu20.04をインストールする

以上

» 続きを読む

| | コメント (0)

2021年4月22日 (木)

platformioでpicoを動かす

2021/4/24+
arduino-frameworkの対応を追加した、

2021/4/22
初版

Pico Platformio Pico-SDK/Arduino

Pico Platformio Pico-SDK/Arduino

概要

platformioでpicoを動かす
(ホストはubuntu20.04を想定している)
platformioが既にインストールされている前提で説明する。

platformioのインストールについては以下などを参照のこと:
arduinoフレームワーク用platformio.ini集

プロジェクトの作成

プロジェクトのディレクトリを作成して、その中に以下に述べるファイルを作成する:
(このディレクトリ名は任意だが、ここでは、pico_projとする)

# platformioの環境に入っている前提 mkdir pico_proj cd pico_proj # platformio.iniを作成する gedit platformio.ini

platformio.ini

[env:raspberry-pi-pico] platform = https://github.com/Wiz-IO/wizio-pico.git ;platform = wizio-pico board = raspberry-pi-pico framework = baremetal upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage monitor_port = /dev/ttyACM0 ; directory for usb-over-serial monitor_speed = 115200 board_build.bynary_type = copy_to_ram build_flags = -D PICO_STDIO_USB ; enable stdio over USB build_unflags = -D PICO_STDIO_UART ;lib_deps =

・USERは環境依存なので、自分の環境に合わせて変更すること。
・frameworkとしては、baremetal(Pico-SDK)を設定する。

テスト用プログラムを以下のように作成する:
src/main.c

/* * --------------------------------------- * Copyright (c) Sebastian Günther 2021 | * | * devcon@admantium.com | * | * SPDX-License-Identifier: BSD-3-Clause | * --------------------------------------- */ #include <stdio.h> #include <stdbool.h> #include "pico/stdlib.h" int LED_BUILTIN = 25; int LED_GREEN = 15; void setup() { stdio_init_all(); gpio_init(LED_BUILTIN); gpio_set_dir(LED_BUILTIN, GPIO_OUT); gpio_init(LED_GREEN); gpio_set_dir(LED_GREEN, GPIO_OUT); } void blink() { gpio_put(LED_BUILTIN, 1); gpio_put(LED_GREEN, 1); //sleep_ms(750); sleep_ms(200); gpio_put(LED_BUILTIN, 0); gpio_put(LED_GREEN, 0); //sleep_ms(1050); sleep_ms(200); } int main() { setup(); printf("Starting...\n"); while (true) { printf("Hello World\n"); //printf("."); blink(); } return 0; }

・「Raspberry Pico: The Simple Startup with PlatformIO 」にあるサンプルを一部修正したものになる。

ビルド&書き込み

以下の手順でビルトと書き込みができる:

cd pico_proj # ツールなどのインストール(最初の1回のみ) pio run -t clean # ビルドと書き込み # bootselボタンを押しながらホストにUSB接続して # その後、bootselボタンを離すると、書き込み用ストレージが出現する pio run -t upload # この時点で書き込みが完了する

出力例:

<省略> Archiving .pio/build/raspberry-pi-pico/sdk/libSDK.a Indexing .pio/build/raspberry-pi-pico/sdk/libSDK.a Linking .pio/build/raspberry-pi-pico/APPLICATION.elf Building .pio/build/raspberry-pi-pico/APPLICATION.bin Checking size .pio/build/raspberry-pi-pico/APPLICATION.elf DONE Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM: [ ] 2.2% (used 5848 bytes from 262144 bytes) Flash: [ ] 2.0% (used 41728 bytes from 2097152 bytes) Configuring upload protocol... AVAILABLE: cmsis-dap, dap, picoprobe, uf2 CURRENT: upload_protocol = uf2 Uploading... Converting to UF2 Start address: 0x10000000 FamilyID: 0xe48bff56 Output size: 84480 bytes Wrote 84480 bytes to /media/USER/RPI-RP2/APPLICATION.uf2 DONE ========================= [SUCCESS] Took 3.39 seconds =========================

・書き込み終了後、プログラムが起動する。ボード上のLEDが点滅して、
USBシリアルには「Hello World」の文字列が繰り返し出力される。

他のサンプル(morse_blinky)

morse_blinky
src/main.c

cat src/main.c // morse_blinky // modified on 2021/2/6 /** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include <stdio.h> #include "pico/stdlib.h" #include "hardware/gpio.h" char str[100]; const uint LED_PIN = 25; const uint DOT_PERIOD_MS = 100; const char *morse_letters[] = { ".-", // A "-...", // B "-.-.", // C "-..", // D ".", // E "..-.", // F "--.", // G "....", // H "..", // I ".---", // J "-.-", // K ".-..", // L "--", // M "-.", // N "---", // O ".--.", // P "--.-", // Q ".-.", // R "...", // S "-", // T "..-", // U "...-", // V ".--", // W "-..-", // X "-.--", // Y "--.." // Z }; void put_morse_letter(const char *pattern) { for (; *pattern; ++pattern) { gpio_put(LED_PIN, 1); if (*pattern == '.') sleep_ms(DOT_PERIOD_MS); else sleep_ms(DOT_PERIOD_MS * 3); gpio_put(LED_PIN, 0); sleep_ms(DOT_PERIOD_MS * 1); } sleep_ms(DOT_PERIOD_MS * 2); } void put_morse_str(const char *str) { for (; *str; ++str) { if (*str >= 'A' && *str <= 'Z') { put_morse_letter(morse_letters[*str - 'A']); } else if (*str >= 'a' && *str <= 'z') { put_morse_letter(morse_letters[*str - 'a']); } else if (*str == ' ') { sleep_ms(DOT_PERIOD_MS * 4); } } } int main() { stdio_init_all(); gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { printf("Enter String for Morse\n"); fflush(stdin); scanf("%s",str); //gets(str); // does not work?? printf("morse: %s\n", str); //puts(str); //put_morse_str("Hello world"); put_morse_str(str); //sleep_ms(1000); } }

・USBシリアル経由で文字列を入力すると、それに対応したモールス信号でLEDが点滅する。

Arduino framework 対応(2021/4/24)

arduinoのframeworkとして使用する場合は以下のplatformio.iniを使用する:

platformio.ini

[env:pico] platform = https://github.com/platformio/platform-raspberrypi.git framework = arduino board = pico upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage monitor_port = /dev/ttyACM0 ; directory for usb-over-serial monitor_speed = 115200 ;lib_deps =

・USERは、環境依存なので、自分の環境の合わせること。

(1)プログラム(スケッチ)のファイルタイプは.cppではなく.inoを使用すること。
(2)platformio.ini,src/main.inoを作成した後、
以下を実行してudev-ruleを登録する:(src/main.inoはダミーで良い)

# プロジェクト・ディレクトリの中で以下を実行して関係ツールをダウンロードする pio run -t clean # udev-ruleを登録する cd ~/.platformio/packages/framework-arduino-mbed sudo bash ./post_install.sh

udev-rule登録が完了して、書き込みが正常に動作した場合、
以下のような出力になる:

$ pio run -v -t upload # 詳細情報を出力するために「-v」を付けている <省略> Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM: [== ] 18.7% (used 50500 bytes from 270336 bytes) Flash: [ ] 3.5% (used 73048 bytes from 2097152 bytes) .pio/build/pico/firmware.elf : section size addr .boot2 256 268435456 .text 53048 268435712 .rodata 8620 268488760 .ARM.exidx 8 268497380 .ram_vector_table 192 536870912 .data 11372 536871104 .uninitialized_ram.magic_location 12 536882476 .uninitialized_data 0 536882488 .scratch_x 0 537133056 .scratch_y 0 537137152 .bss 39128 536882488 .heap 210416 536921616 .ARM.attributes 40 0 .comment 132 0 .debug_frame 5144 0 .stab 60 0 .stabstr 118 0 Total 328546 <lambda>(["upload"], [".pio/build/pico/firmware.elf"]) AVAILABLE: cmsis-dap, raspberrypi-swd, stlink BeforeUpload(["upload"], [".pio/build/pico/firmware.elf"]) Use manually specified: /media/USER/RPI-RP2/ Forcing reset using 1200bps open/close on port /media/USER/RPI-RP2/ # バグ?で間違ったシリアルポートが選択されているので、ボートがリセットできない /home/USER/.platformio/packages/tool-rp2040tools/rp2040load -v -D .pio/build/pico/firmware.elf rp2040load 1.0.1 - compiled with go1.15.8 .Loading into Flash: [ ] 0% Loading into Flash: [= ] 5% Loading into Flash: [=== ] 11% Loading into Flash: [==== ] 16% Loading into Flash: [====== ] 22% Loading into Flash: [======== ] 27% Loading into Flash: [========= ] 33% Loading into Flash: [=========== ] 39% Loading into Flash: [============= ] 44% Loading into Flash: [=============== ] 50% Loading into Flash: [================ ] 55% Loading into Flash: [================== ] 61% Loading into Flash: [=================== ] 66% Loading into Flash: [===================== ] 72% Loading into Flash: [======================= ] 78% Loading into Flash: [======================== ] 83% Loading into Flash: [========================== ] 89% Loading into Flash: [============================ ] 94% Loading into Flash: [==============================] 100% ========================= [SUCCESS] Took 2.73 seconds =========================

重要:
・現状、バグ?で、USBシリアル経由のボード・リセットができない。
そのため、書き込み前に、ボードのbootselボタンを押しながらホストのUSBに接続して、
その後、bootselボタンを離して、書き込みストレージを出現させる必要がある。
・または、以下のようにplatformio.iniを一部修正すると ボード・リセットが正常に動き、書き込みが成功するようだ。
(もしかして、これが仕様なのかも知れない)

upload_port = /dev/ttyACM0 ;upload_port = /media/USER/RPI-RP2/ ; directory for mass-storage


Arduino用デモ・スケッチ

ASCIITablePico:
src/main.ino

/* ASCII table Prints out byte values in all possible formats: - as raw binary values - as ASCII-encoded decimal, hex, octal, and binary values For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII The circuit: No external hardware needed. created 2006 by Nicholas Zambetti <http://www.zambetti.com> modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/ASCIITable */ void setup() { //Initialize serial and wait for port to open: //Serial.begin(9600); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // prints title with ending line break Serial.println("ASCII Table ~ Character Map"); } // first visible ASCIIcharacter '!' is number 33: int thisByte = 33; // you can also write ASCII characters in single quotes. // for example, '!' is the same as 33, so you could also use this: // int thisByte = '!'; void loop() { // prints value unaltered, i.e. the raw binary version of the byte. // The Serial Monitor interprets all bytes as ASCII, so 33, the first number, // will show up as '!' Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). // Decimal is the default format for Serial.print() and Serial.println(), // so no modifier is needed: Serial.print(thisByte); // But you can declare the modifier for decimal if you want to. // this also works if you uncomment it: // Serial.print(thisByte, DEC); Serial.print(", hex: "); // prints value as string in hexadecimal (base 16): Serial.print(thisByte, HEX); Serial.print(", oct: "); // prints value as string in octal (base 8); Serial.print(thisByte, OCT); Serial.print(", bin: "); // prints value as string in binary (base 2) also prints ending line break: Serial.println(thisByte, BIN); // if printed last visible character '~' or 126, stop: if (thisByte == 126) { // you could also use if (thisByte == '~') { thisByte = 33-1; Serial.println("----------------------------------------------"); Serial.println(""); delay(500); /* // This loop loops forever and does nothing while (true) { continue; } */ } // go on to the next character thisByte++; }

・標準のスケッチをベースにPicoボードにリセットがないので繰り返し実行するように変更したもの

Blink:
src/main.ino

/* Blink Turns an LED on for one second, then off for one second, repeatedly. Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to the correct LED pin independent of which board is used. If you want to know what pin the on-board LED is connected to on your Arduino model, check the Technical Specs of your board at: https://www.arduino.cc/en/Main/Products modified 8 May 2014 by Scott Fitzgerald modified 2 Sep 2016 by Arturo Guadalupi modified 8 Sep 2016 by Colby Newman This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Blink */ // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }

・標準のスケッチ(変更なし)

参考情報

Pico-Platformio(Pico-SDK)関連:
Raspberry Pico: The Simple Startup with PlatformIO
BAREMETAL(pico-sdk)
Examples
Raspberry Pi Pico RP2040 - PlatformIO (Pico-SDK & Arduino)

Pico-Platformio(Arduino)関連:
Official PlatformIO + Arduino IDE support for the Raspberry Pi Pico is now available!

platformio関連:
PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
arduinoフレームワーク用platformio.ini集
ubuntu20.04をインストールする

以上

» 続きを読む

| | コメント (0)

2021年4月17日 (土)

PimoroniボードをPicoで動かす

2021/2/17
初版

rpi Pico Pimoroni board

rpi Pico Pimoroni board

概要

以下のPimoroniボードをPicoで動かす
デモとしてC++のデモとmicropythonのデモを動かしてみる。
(ホストPCとしてはubuntuを想定している)

Pico Display Pack
Pico Unicorn Pack

C++デモのビルド

以下の手順でビルドする:

# Pico-SDKがインストールされている前提 export PICO_SDK_PATH=~/pico/pico-sdk cd ~/pico git clone https://github.com/pimoroni/pimoroni-pico.git cd pimoroni-pico mkdir build cd build cmake .. make # 以上でデモプログラムのuf2fが出来る

C++デモの書き込み

# pico_unicorn_plasma デモを書き込む(unicornボードの場合) cd ~/pico/pimoroni-pico/build/examples/pico_unicorn_plasma cp unicornplasma.uf2 /media/<USER>/RPI-RP2/ # pico_display デモを書き込む(displayボードの場合) cd ~/pico/pimoroni-pico/build/examples/pico_display cp display.uf2 /media/<USER>/RPI-RP2/

<USER>は、環境依存なので、自分の環境に合わせる。

C++デモ・ソース

以下、デモのソース:(特に修正していない)

pico_display/demo.cpp

#include <string.h> #include <math.h> #include <vector> #include <cstdlib> #include "pico_display.hpp" using namespace pimoroni; extern unsigned char image_tif[]; extern unsigned int image_tif_len; uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT]; PicoDisplay pico_display(buffer); /* void pixel(int x, int y, uint16_t c) { x *= 2; y *= 2; pico_display.frame_buffer[x + y * 240] = c; pico_display.frame_buffer[x + 1 + y * 240] = c; pico_display.frame_buffer[x + 1 + (y + 1) * 240] = c; pico_display.frame_buffer[x + (y + 1) * 240] = c; } void rect(int x, int y, int w, int h, uint16_t c) { for(int rx = x; rx < x + w; rx++) { for(int ry = y; ry < y + h; ry++) { pixel(rx, ry, c); } } }*/ uint8_t arrow[] = { 0b00010000, 0b00110000, 0b01110000, 0b11111111, 0b11111111, 0b01110000, 0b00110000, 0b00010000 }; uint8_t tick[] = { 0b00000000, 0b00000010, 0b00000111, 0b01001110, 0b11111100, 0b00111000, 0b00010000, 0b00000000, }; /* void sprite(uint8_t *p, int x, int y, bool flip, uint16_t c) { for(int ay = 0; ay < 8; ay++) { uint8_t sl = p[ay]; for(int ax = 0; ax < 8; ax++) { if(flip) { if((0b10000000 >> ax) & sl) { pixel(ax + x, ay + y, c); } }else{ if((0b1 << ax) & sl) { pixel(ax + x, ay + y, c); } } } } }*/ int main() { pico_display.init(); pico_display.set_backlight(100); // uint16_t white = pico_display.create_pen(255, 255, 255); // uint16_t black = pico_display.create_pen(0, 0, 0); // uint16_t red = pico_display.create_pen(255, 0, 0); // uint16_t green = pico_display.create_pen(0, 255, 0); // uint16_t dark_grey = pico_display.create_pen(20, 40, 60); // uint16_t dark_green = pico_display.create_pen(10, 100, 10); // uint16_t blue = pico_display.create_pen(0, 0, 255); bool a_pressed = false; bool b_pressed = false; bool x_pressed = false; bool y_pressed = false; struct pt { float x; float y; uint8_t r; float dx; float dy; uint16_t pen; }; std::vector<pt> shapes; for(int i = 0; i < 1000; i++) { pt shape; shape.x = rand() % 240; shape.y = rand() % 135; shape.r = (rand() % 10) + 3; shape.dx = float(rand() % 255) / 128.0f; shape.dy = float(rand() % 255) / 128.0f; shape.pen = pico_display.create_pen(rand() % 255, rand() % 255, rand() % 255); shapes.push_back(shape); } uint32_t i = 0; while(true) { pico_display.set_pen(120, 40, 60); pico_display.clear(); for(auto &shape : shapes) { shape.x += shape.dx; shape.y += shape.dy; if(shape.x < 0) shape.dx *= -1; if(shape.x >= pico_display.bounds.w) shape.dx *= -1; if(shape.y < 0) shape.dy *= -1; if(shape.y >= pico_display.bounds.h) shape.dy *= -1; pico_display.set_pen(shape.pen); pico_display.circle(Point(shape.x, shape.y), shape.r); } float led_step = fmod(i / 20.0f, M_PI * 2.0f); int r = (sin(led_step) * 25.0f) + 25.0f; pico_display.set_led(r, r / 1.2f, r); std::vector<Point> poly; poly.push_back(Point(30, 30)); poly.push_back(Point(50, 35)); poly.push_back(Point(70, 25)); poly.push_back(Point(80, 65)); poly.push_back(Point(50, 85)); poly.push_back(Point(30, 45)); pico_display.set_pen(255, 255, 0); pico_display.polygon(poly); pico_display.set_pen(0, 255, 255); pico_display.triangle(Point(50, 50), Point(130, 80), Point(80, 110)); pico_display.set_pen(255, 255, 255); pico_display.line(Point(50, 50), Point(120, 80)); pico_display.line(Point(20, 20), Point(120, 20)); pico_display.line(Point(20, 20), Point(20, 120)); for(int r = 0; r < 30; r++) { for(int j = 0; j < 10; j++) { float rads = ((M_PI * 2) / 30.0f) * float(r); rads += (float(i) / 100.0f); rads += (float(j) / 100.0f); float cx = sin(rads) * 300.0f; float cy = cos(rads) * 300.0f; pico_display.line(Point(120, 67), Point(cx + 120, cy + 67)); } } /* if(pico_display.is_pressed(pico_display.A)) { pico_display.rectangle(0, 0, 18, 18); //sprite(tick, 5, 5, true, green); }else{ //sprite(arrow, 10 + bounce, 10, true, white); } if(pico_display.is_pressed(pico_display.B)) { pico_display.rectangle(0, 49, 18, 18); //sprite(tick, 5, 54, true, green); }else{ //sprite(arrow, 10 - bounce, 50, true, white); } if(pico_display.is_pressed(pico_display.X)) { pico_display.rectangle(102, 0, 18, 18); //sprite(tick, 107, 5, true, green); }else{ //sprite(arrow, 102 - bounce, 10, false, white); } if(pico_display.is_pressed(pico_display.Y)) { pico_display.rectangle(102, 49, 18, 18); //sprite(tick, 107, 54, true, green); }else{ //sprite(arrow, 102 + bounce, 50, false, white); } */ // update screen pico_display.update(); i++; } return 0; }

pico_display/image_data.cpp

unsigned char image_tif[] = { 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0xfe, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x03, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x12, 0x01, <> 0x08, 0x0a, 0x04, 0x08, 0x09, 0x04, 0x07, 0x08, 0x03, 0x07, 0x08, 0x03, 0x07, 0x08, 0x03, 0x07, 0x07, 0x02, 0x06, 0x07, 0x03, 0x06, 0x07, 0x02, 0x06, 0x07, 0x03, 0x06, 0x07, 0x02, 0x06, 0x07, 0x03, 0x06, 0x06, 0x02, 0x06, 0x07, 0x03, 0x06 }; unsigned int image_tif_len = 97492;

pico_unicorn_plasma/demo.cpp

/* Pico Unicorn Plasma Example Written by Tim Kerby https://github.com/tkerby Hardware: Raspberry Pi Pico with Pimoroni Unicorn Pico Display Printf over USB 9600 8N1 (see makefile) Based on Adafruit Arduino Example for 32x32 panel Originally written by Limor Fried/Ladyada & Phil Burgess/PaintYourDragon for Adafruit Industries. https://github.com/adafruit/RGB-matrix-Panel/blob/master/examples/plasma_32x32/plasma_32x32.ino BSD License */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include "pico/stdlib.h" #include <time.h> #include "pico_unicorn.hpp" using namespace pimoroni; PicoUnicorn pico_unicorn; // Sine table to speed up execution static const int8_t sinetab[256] = { 0, 2, 5, 8, 11, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 56, 59, 62, 65, 67, 70, 72, 75, 77, 80, 82, 85, 87, 89, 91, 93, 96, 98, 100, 101, 103, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 126, 126, 127, 126, 126, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 118, 117, 116, 114, 113, 111, 110, 108, 107, 105, 103, 101, 100, 98, 96, 93, 91, 89, 87, 85, 82, 80, 77, 75, 72, 70, 67, 65, 62, 59, 56, 54, 51, 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 11, 8, 5, 2, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -52, -55, -57, -60, -63, -66, -68, -71, -73, -76, -78, -81, -83, -86, -88, -90, -92, -94, -97, -99,-101,-102,-104, -106,-108,-109,-111,-112,-114,-115,-117, -118,-119,-120,-121,-122,-123,-124,-124, -125,-126,-126,-127,-127,-127,-127,-127, -128,-127,-127,-127,-127,-127,-126,-126, -125,-124,-124,-123,-122,-121,-120,-119, -118,-117,-115,-114,-112,-111,-109,-108, -106,-104,-102,-101, -99, -97, -94, -92, -90, -88, -86, -83, -81, -78, -76, -73, -71, -68, -66, -63, -60, -57, -55, -52, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3 }; // We have four objects with radius and centre points as configured for the 16x7 display const float radius1 =8.2, radius2 =11.5, radius3 =20.4, radius4 =22.1, centerx1=8.0, centerx2=5.8, centerx3=12.7, centerx4= 2.0, centery1= 2.1, centery2= 1.5, centery3=3.2, centery4=-0.5; float angle1 = 0.0, angle2 = 0.0, angle3 = 0.0, angle4 = 0.0; long hueShift= 0; #define FPS 30 // Maximum frames-per-second // HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel // Outputs are rgb in the range 0-255 for each channel void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { float i = floor(h * 6.0f); float f = h * 6.0f - i; v *= 255.0f; uint8_t p = v * (1.0f - s); uint8_t q = v * (1.0f - f * s); uint8_t t = v * (1.0f - (1.0f - f) * s); switch (int(i) % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } } int main() { stdio_init_all(); pico_unicorn.init(); pico_unicorn.clear(); while(true) { int x1, x2, x3, x4, y1, y2, y3, y4, sx1, sx2, sx3, sx4; unsigned char x, y; int8_t value; uint8_t r, g, b,j,k,l,m; // Setup a delay to slow the framerate. // Would be better to read from a timer as some math operations take variable time sleep_ms(1000 / FPS); sx1 = (int)(cos(angle1) * radius1 + centerx1); sx2 = (int)(cos(angle2) * radius2 + centerx2); sx3 = (int)(cos(angle3) * radius3 + centerx3); sx4 = (int)(cos(angle4) * radius4 + centerx4); y1 = (int)(sin(angle1) * radius1 + centery1); y2 = (int)(sin(angle2) * radius2 + centery2); y3 = (int)(sin(angle3) * radius3 + centery3); y4 = (int)(sin(angle4) * radius4 + centery4); for(y=0; y<7; y++) { x1 = sx1; x2 = sx2; x3 = sx3; x4 = sx4; for(x=0; x<16; x++) { j = (x1 * x1 + y1 * y1) >> 2; k = (x2 * x2 + y2 * y2) >> 2; l = (x3 * x3 + y3 * y3) >> 3; m = (x4 * x4 + y4 * y4) >> 3; //printf("X: %i, Y: %i, \t%i, %i, %i, %i\n",x,y,j,k,l,m); value = (int8_t)(hueShift + (int8_t)*(sinetab + j) + (int8_t)*(sinetab + k) + (int8_t)*(sinetab + l) + (int8_t)*(sinetab + m)); //printf("X: %i, Y: %i, H: %i\n",x,y,value); from_hsv(((value+128.0f)/256.0f), 1, 1, r, g, b); pico_unicorn.set_pixel(x, y, r, g, b); x1--; x2--; x3--; x4--; } y1--; y2--; y3--; y4--; } angle1 += 0.03; angle2 -= 0.07; angle3 += 0.13; angle4 -= 0.15; hueShift += 2; } return 0; }

micorpythonの準備

pinoroni用モジュールを利用する都合上、
純正のmicropythonのファームウェアではなく
以下のpimoroni用のmicropythonのファームウェアを使用する:

cd ~/Downloads wget https://github.com/pimoroni/pimoroni-pico/releases/download/v0.1.1/pimoroni-pico-micropython.uf2 cp pimoroni-pico-micropython.uf2 /media/<USER>/RPI-RP2/

・<USER>は、環境依存なので、自分の環境に合わせる。

micropythonデモ・ソース

以下、デモのソース:(特に修正なし)

displayボード用:
display_demo.py

import time import random import picodisplay as display width = display.get_width() height = display.get_height() display_buffer = bytearray(width * height * 2) # 2-bytes per pixel (RGB565) display.init(display_buffer) display.set_backlight(1.0) class Ball: def __init__(self, x, y, r, dx, dy, pen): self.x = x self.y = y self.r = r self.dx = dx self.dy = dy self.pen = pen # initialise shapes balls = [] for i in range(0, 100): r = random.randint(0, 10) + 3 balls.append( Ball( random.randint(r, r + (width - 2 * r)), random.randint(r, r + (height - 2 * r)), r, (14 - r) / 2, (14 - r) / 2, display.create_pen(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), ) ) while True: display.set_pen(40, 40, 40) display.clear() for ball in balls: ball.x += ball.dx ball.y += ball.dy xmax = width - ball.r xmin = ball.r ymax = height - ball.r ymin = ball.r if ball.x < xmin or ball.x > xmax: ball.dx *= -1 if ball.y < ymin or ball.y > ymax: ball.dy *= -1 display.set_pen(ball.pen) display.circle(int(ball.x), int(ball.y), int(ball.r)) display.update() time.sleep(0.01)

unicornボード用:
unicorn_demo.py

import picounicorn picounicorn.init() # From CPython Lib/colorsys.py def hsv_to_rgb(h, s, v): if s == 0.0: return v, v, v i = int(h * 6.0) f = (h * 6.0) - i p = v * (1.0 - s) q = v * (1.0 - s * f) t = v * (1.0 - s * (1.0 - f)) i = i % 6 if i == 0: return v, t, p if i == 1: return q, v, p if i == 2: return p, v, t if i == 3: return p, q, v if i == 4: return t, p, v if i == 5: return v, p, q w = picounicorn.get_width() h = picounicorn.get_height() # Display a rainbow across Pico Unicorn for x in range(w): for y in range(h): r, g, b = [int(c * 255) for c in hsv_to_rgb(x / w, y / h, 1.0)] picounicorn.set_pixel(x, y, r, g, b) print("Press Button A") while not picounicorn.is_pressed(picounicorn.BUTTON_A): # Wait for Button A to be pressed pass # Clear the display for x in range(w): for y in range(h): picounicorn.set_pixel(x, y, 0, 0, 0) print("Button A pressed!")

参照情報

PicoボードにPico_SDKでC言語をビルドする
Pimoroni Pico Libraries and Examples

Pinout for Pico Display Pack
Pinout for Pico Unicorn Pack
Pinout for Pico Audio Pack

How to add a reset button to your Raspberry Pi Pico
All you need to do is to wire the GND and RUN pins together and add an extra momentary contact button to your breadboard. Pushing the button will reset the board.

Programmable I/O with Raspberry Pi Pico

Raspberry Pi Picoスタートガイド C/C++
Pico C/C++ SDK
Pico SDK docs

Raspberry Pi Pico Datasheet
RP2040 Datasheet

Pico Pinout

Ubuntu 18.04 に Cmake の Latest Release をインストールする

Ubuntu 20.04のPCでRaspberry Pi Picoを2台使ってOpenOCDによるデバッグ

以上

» 続きを読む

| | コメント (0)

2021年4月 1日 (木)

Arduino-IDEでPicoを動かす

2021/4/29
earlephilhower版専用になるがMulticoreのスケッチを追加した。

2021/4/23
もう一つの実装であるarduino純正ボード・ライブラリでの使用方法を追加した。
また、書き込みでエラーになるので、その解決方法についても記述した。

2021/4/5+
Arduno-IDEのwindows版でPicoの書き込みで
エラーになる場合の対応方法を追加した。

2021/4/4
LittleFSを使用したスケッチを追加した。

2021/4/3+
動作確認したスケッチを追加した。

2021/4/1+
初版

Pico Arduino Install

Pico Arduino Install

概要

Arduino-IDEでPicoを動かす。
ホスト環境は、ubuntu20.04とする。
なお、Arduino-IDEの最新版がインストール済みのものとする。

linuxのArduino-IDEのインストールについては以下を参照のこと。
Install the Arduino Software (IDE) on Linux

本記事は、linux版Arduino-IDEについて記述したものであるが、 ほとんど、そのままwindows版でも適応可能である。

ボード情報(*.json)のインストール

Arduino-IDEを起動して以下を実行する:
1.[ファイル]/[環境設定]を選択する
2.画面の「追加のボードマネージャーのURL」に以下を入力(追加)する

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json # 今後、このjsonを利用したものをearlephilhower版と呼ぶことにする。

3.入力後、[OK]をクリックする
4.[ツール]/[ボード]/[ボードマネージャー]を選択する
5.検索欄に「pico」と入力する
6.検索結果から「Raspberry Pi Pico/RP2040」を選び、[インストール]をクリックする
7.インストール後、[閉じる]をクリックする

8.[ツール]/[ボード]/[Raspberry RP2040 boards]/[Raspberry Pi Pico]を選択する

以上で、ボードとして[Raspberry PiPico]が選択されたことになる。

なお、これ以外に以下のボードが選択できる:

Raspberry Pi Pico Raspberry Pi Pico (Picoprobe) Adafruit Feather RP2040 Adafruit Feather RP2040 (Picoprobe) Generic PR2040 Generic PR2040 (Picoprobe)

「(Picoprobe)」付きは、書き込みにopenocd(picoprobe)を使用するものになる。

Picoprobeを使った書き込み

Picoprobeを接続した場合、Arduino-IDEでボードを「Raspberry Pi Pico (Picoprobe)」を切り替える。その後は従来どおりの操作で書き込みができる。

以下、書き込み時の出力例:

<省略> Open On-Chip Debugger 0.10.0+dev-gd58c2ef5e-dirty (2021-03-28-18:41) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Info : only one transport option; autoselect 'swd' Warn : Transport "swd" was already selected adapter speed: 5000 kHz Info : Hardware thread awareness created Info : Hardware thread awareness created Info : RP2040 Flash Bank Command Info : clock speed 5000 kHz Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x00000001 Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x10000001 Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints Info : starting gdb server for rp2040.core0 on 3333 Info : Listening on port 3333 for gdb connections target halted due to debug-request, current mode: Thread xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00 ** Programming Started ** Info : RP2040 B0 Flash Probe: 2097152 bytes @10000000, in 512 sectors target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ... <省略> ... target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ** Programming Finished ** ** Verify Started ** target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00 ** Verified OK ** ** Resetting Target ** shutdown command invoked Info : SWD DPIDR 0x0bc12477 Info : SWD DLPIDR 0x00000001

留意点:
・シリアルを使っているスケッチは、USBシリアルを前提にしているので、そのままでは動かない。
・picoprobe接続時でもシリアルが利用可能だが、USBシリアルではなく、普通のシリアルにpicobrobe経由で接続している。(したがって、picoprobe経由でシリアルを使用する場合、スケッチの「Serial」を「Serial1」に置き換えると使用できる)

サンプルスケッチ

ボード設定が完了した後は、通常のArduinoボードとして使用できる。
リセットボタンがないので、リセットボタンを押されることを前提にしているスケッチは、無限ループにするなどの工夫が必要となる。
なお、(Picoprobeを使用していない場合は)書き込み前に書き込み用ストレージ(RPI-RP2)が見える状態にする必要がある。
# ただし、ボードのUSBシリアルが有効になっている場合、
# 自動的にリセットするのでbootselボタンを押してのUSBの抜き差しは
# 不要となる

以下、実際に動かしたスケッチを挙げる:

ASCIITablePico.ino

/* ASCII table Prints out byte values in all possible formats: - as raw binary values - as ASCII-encoded decimal, hex, octal, and binary values For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII The circuit: No external hardware needed. created 2006 by Nicholas Zambetti <http://www.zambetti.com> modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/ASCIITable */ void setup() { //Initialize serial and wait for port to open: //Serial.begin(9600); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // prints title with ending line break Serial.println("ASCII Table ~ Character Map"); } // first visible ASCIIcharacter '!' is number 33: int thisByte = 33; // you can also write ASCII characters in single quotes. // for example, '!' is the same as 33, so you could also use this: // int thisByte = '!'; void loop() { // prints value unaltered, i.e. the raw binary version of the byte. // The Serial Monitor interprets all bytes as ASCII, so 33, the first number, // will show up as '!' Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). // Decimal is the default format for Serial.print() and Serial.println(), // so no modifier is needed: Serial.print(thisByte); // But you can declare the modifier for decimal if you want to. // this also works if you uncomment it: // Serial.print(thisByte, DEC); Serial.print(", hex: "); // prints value as string in hexadecimal (base 16): Serial.print(thisByte, HEX); Serial.print(", oct: "); // prints value as string in octal (base 8); Serial.print(thisByte, OCT); Serial.print(", bin: "); // prints value as string in binary (base 2) also prints ending line break: Serial.println(thisByte, BIN); // if printed last visible character '~' or 126, stop: if (thisByte == 126) { // you could also use if (thisByte == '~') { thisByte = 33-1; Serial.println("----------------------------------------------"); Serial.println(""); delay(500); /* // This loop loops forever and does nothing while (true) { continue; } */ } // go on to the next character thisByte++; }

・標準に提供されているスケッチを無限ループにしたもの。
・シリアルはUSBシリアルを使用する。

Blink.ino

/* Blink Turns an LED on for one second, then off for one second, repeatedly. Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to the correct LED pin independent of which board is used. If you want to know what pin the on-board LED is connected to on your Arduino model, check the Technical Specs of your board at: https://www.arduino.cc/en/Main/Products modified 8 May 2014 by Scott Fitzgerald modified 2 Sep 2016 by Arturo Guadalupi modified 8 Sep 2016 by Colby Newman This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Blink */ // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }

・標準に提供されているスケッチが無修正で動作する。

bootselBlink.ino
bootselボタンをLED点滅のボタンに使用したスケッチ(トグル動作)

// bootselBlink int toggle = false; void setup() { Serial.begin(115200); delay(5000); // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); //Serial.println("I dare you to hit the BOOTSEL button..."); } int c = 0; void loop() { if (toggle) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); if (BOOTSEL) { Serial.printf("You pressed BOOTSEL %d times!\n", ++c); toggle = !toggle; // Wait for BOOTSEL to be released while (BOOTSEL) { delay(1); } } }

temperature.ino
CPUのコア温度を測ってシリアルに出力するスケッチ

/* Released into the public domain */ void setup() { Serial.begin(115200); delay(5000); } void loop() { Serial.printf("Core temperature: %2.1fC\n", analogReadTemp()); delay(1000); }

・このスケッチはearlephilhower版専用となる。

fade.ino

/* Fade This example shows how to fade the onboard Raspberry Pi Pico LED This example code is in the public domain. http://www.arduino.cc/en/Tutorial/Fade */ int led = LED_BUILTIN; // the PWM pin the LED is attached to int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by // the setup routine runs once when you press reset: void setup() { // declare pin to be an output: pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { // set the brightness analogWrite(led, brightness); // change the brightness for next time through the loop: brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: if (brightness <= 0 || brightness >= 255) { fadeAmount = -fadeAmount; } // wait for 30 milliseconds to see the dimming effect //delay(30); delay(15); }

morse_blinky.ino
シリアルから入力した文字列をLED点滅のモールス信号で出力するスケッチ
(pico-sdkのサンプルのaruduino移植版)

// ported into Arduino platform on 2021/4/4 // modified on 2021/2/6 /** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ /* #include <stdio.h> #include "pico/stdlib.h" #include "hardware/gpio.h" */ char str[100]; const uint LED_PIN = 25; const uint DOT_PERIOD_MS = 100; const char *morse_letters[] = { ".-", // A "-...", // B "-.-.", // C "-..", // D ".", // E "..-.", // F "--.", // G "....", // H "..", // I ".---", // J "-.-", // K ".-..", // L "--", // M "-.", // N "---", // O ".--.", // P "--.-", // Q ".-.", // R "...", // S "-", // T "..-", // U "...-", // V ".--", // W "-..-", // X "-.--", // Y "--.." // Z }; // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); //Initialize serial and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } } void put_morse_letter(const char *pattern) { for (; *pattern; ++pattern) { //gpio_put(LED_PIN, 1); digitalWrite(LED_BUILTIN, HIGH); if (*pattern == '.') //sleep_ms(DOT_PERIOD_MS); delay(DOT_PERIOD_MS); else //sleep_ms(DOT_PERIOD_MS * 3); delay(DOT_PERIOD_MS * 3); //gpio_put(LED_PIN, 0); digitalWrite(LED_BUILTIN, LOW); //sleep_ms(DOT_PERIOD_MS * 1); delay(DOT_PERIOD_MS * 1); } //sleep_ms(DOT_PERIOD_MS * 2); delay(DOT_PERIOD_MS * 2); } void put_morse_str(const char *str) { for (; *str; ++str) { if (*str >= 'A' && *str <= 'Z') { put_morse_letter(morse_letters[*str - 'A']); } else if (*str >= 'a' && *str <= 'z') { put_morse_letter(morse_letters[*str - 'a']); } else if (*str == ' ') { //sleep_ms(DOT_PERIOD_MS * 4); delay(DOT_PERIOD_MS * 4); } } } void loop() { Serial.printf("Enter String for Morse\n"); delay(1000); if (Serial.available()){ String sline = Serial.readStringUntil('\n'); sline.toCharArray(str, 100); Serial.printf("morse: %s\n", str); put_morse_str(str); } } /* int main() { stdio_init_all(); gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { printf("Enter String for Morse\n"); fflush(stdin); scanf("%s",str); //gets(str); // does not work?? printf("morse: %s\n", str); //puts(str); //put_morse_str("Hello world"); put_morse_str(str); //sleep_ms(1000); } } */

内蔵ファイルシステム(FLASH)を使用したスケッチ

Pico用のLittleFSの書き込みツールを以下の手順でインストールする:

cd ~Downloads wget https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases/download/0.2.0/PicoLittleFS-0.2.0.zip # ダウンロードしたzipを解凍して # そのなかの picolittlefs.jar を次のディレクトリにコピーする mkdir -p ~/Arduino/tools/PicoLittleFS/tool cd ~/Arduino/tools/PicoLittleFS/tool #確認 ls picolittlefs.jar # Arduino-IDEを再起動する

スケッチのディレクトリ「FSUploadPico」にファイルシステムのデータ用の ディクトリ「data」を作り、保存したいファイルを置く。

cd FSUploadPico mkdir data cd data gedit file1.txt #任意のテキスト内容を編集する

FSUploadPico.ino

// Released to the public domain // // This sketch will read an uploaded file and increment a counter file // each time the sketch is booted. // Be sure to install the Pico LittleFS Data Upload extension for the // Arduino IDE from: // https://github.com/earlephilhower/arduino-pico-littlefs-plugin/ // The latest release is available from: // https://github.com/earlephilhower/arduino-pico-littlefs-plugin/releases // Before running: // 1) Select Tools->Flash Size->(some size with a FS/filesystem) // 2) Use the Tools->Pico Sketch Data Upload tool to transfer the contents of // the sketch data directory to the Pico #include <LittleFS.h> void setup() { Serial.begin(115200); delay(5000); LittleFS.begin(); char buff[32]; int cnt = 1; File f = LittleFS.open("counts.txt", "r"); if (f) { bzero(buff, 32); if (f.read((uint8_t *)buff, 31)) { sscanf(buff, "%d", &cnt); Serial.printf("I have been run %d times\n", cnt); } f.close(); } cnt++; sprintf(buff, "%d\n", cnt); f = LittleFS.open("counts.txt", "w"); if (f) { f.write(buff, strlen(buff)); f.close(); } Serial.println("---------------"); while(true) { File i = LittleFS.open("file1.txt", "r"); if (i) { while (i.available()) { Serial.write(i.read()); } Serial.println("---------------"); i.close(); } } // while forever } void loop() { }

・リセットボタンがないのでシリアル出力部分を無限ループに変更した。
・ボードのライブラリが最新版である必要がある。(ボードマネージャーで更新する)

書き込みと実行:
以下の手順でdata書き込みとスケッチの書き込みを行なう:
(1)Arduino-IDEで[ツール(tools)]/[Flash Size]で任意(ゼロ以外)を設定する
(2)Arduino-IDEで[ツール(tools)]/[PicoLittleFS Data Upload]を選択して dataディレクトリの内容をPicoのflashに書き込む
(3)書き込み(Upload)アイコンを押してスケッチのコンパイルと書き込みを実行する

出力例(USBシリアル):

# 以下のfile1.txtの内容を繰り返し出力する Hello! Welcome to the Raspberry Pi Pico using arduino-pico! this is LittleFS test#1. this is LittleFS test#2. this is LittleFS test#3. this is LittleFS test#4. this is LittleFS test#5. this is LittleFS test#6.

windows版Arduino-IDEでの書き込みエラーの対応方法

windows版Arduino-IDEでは、動作環境によっては、Pico書き込み時にエラーになり書き込めないことがある。

これは、windowsのドライブのボリューム名として、半角カタカナが使われている場合、 書き込みツールとして使用しているuf2conv.pyでutf8文字列変換がエラーになっていることが原因である。

この対応として、日本語のボリューム名を英語などに変更することで、エラーを回避でき、書き込みが正常に動作するようになる。

または、ボリューム名を(手動で)変更せずにwindowsのシステム言語を英語に変更することでボリューム名も英語に変更することで書き込みが可能になる。
ここでは、システム言語を変更する方法でエラーを回避する。

システム言語を英語にする方法については以下などを参照のこと:
Windows 10 表示言語を英語版にする

重要な注意:
[Windows display], [Apps & websites]のみを英語に変更すること。 他も英語にすると日本語キーボードなどが使用できなくなるなどの不都合が生じる。

参考:
日本語から英語にシステム言語を変更すると、uf2conv.pyの変数r(bytearray)の内容が以下のように変化する:(環境依存あり)

日本語の場合: b'DeviceID DriveType FileSystem VolumeName \r\r\nC: 3 NTFS Windows \r\r\nD: 3 NTFS \x83{\x83\x8a\x83\x85\x81[\x83\x80 \r\r\nE: 2 FAT RPI-RP2 \r\r\n\r\r\n' 英語の場合: b'DeviceID DriveType FileSystem VolumeName \r\r\nC: 3 NTFS Windows \r\r\nD: 3 NTFS Volume \r\r\nE: 2 FAT RPI-RP2 \r\r\n\r\r\n'

・この例ではドライブDのボリューム名が変化していることが分かる。
・「\x83{\x83\x8a\x83\x85\x81[\x83\x80」(83 7B 83 8A 83 85 81 5B 83 80)は半角カナの部分になる。

他の対応方法としては、uf2conv.pyの変数rの中の半角カナ部分をutf8変換可能な文字に置き換えるパッチが考えられる。
それには以下のように修正する:
uf2conv.py

#修正前 def to_str(b): return b.decode("utf-8") ↓ #修正後 def to_str(b): return b.decode("utf-8",errors="replace")


Multicore用スケッチ (2021/4/29)

PicoはDualCoreのCPUなので、2つのCPUをスケッチで動作させることができる。
以下のexamplesにあったものを掲載する。
examples(earlephilhower)

残念ながら自分の環境では1コア(core0)としてしか動作しなかった。
(今後のupdateでfixするものと思われる)

Multicore.ino

// Demonstrates a simple use of the setup1()/loop1() functions // for a multiprocessor run. // Will output something like, where C0 is running on core 0 and // C1 is on core 1, in parallel. // 11:23:07.507 -> C0: Blue leader standing by... // 11:23:07.507 -> C1: Red leader standing by... // 11:23:07.507 -> C1: Stay on target... // 11:23:08.008 -> C1: Stay on target... // 11:23:08.505 -> C0: Blue leader standing by... // 11:23:08.505 -> C1: Stay on target... // 11:23:09.007 -> C1: Stay on target... // 11:23:09.511 -> C0: Blue leader standing by... // 11:23:09.511 -> C1: Stay on target... // 11:23:10.015 -> C1: Stay on target... // Released to the public domain // The normal, core0 setup void setup() { Serial.begin(); delay(5000); } void loop() { Serial.printf("C0: Blue leader standing by...\n"); delay(1000); } // Running on core1 void setup1() { delay(5000); Serial.printf("C1: Red leader standing by...\n"); } void loop1() { Serial.printf("C1: Stay on target...\n"); delay(500); }

・このスケッチはearlephilhower版専用となる。

Arduino純正のボード・ライブラリを使用する(2021/4/23)

最近、Arduino純正のボード・ライブラリもサポートされたので、その使い方について述べる。
純正ライブラリなので.jsonの設定などは不要で、ボード・ライブラリのアップデートをするだけで良い。
(この版をearlephilhower版と区別するために純正版と呼ぶ)

ボード・ライブラリ設定は以下の手順で行なう:

(1)[ツール(tools)]/[ボードマネージャ]を選択する。 (2)「pico」で検索する。 (3)検索された候補のなかで[Arduino Mbed OS RP2040 Boards]を選択する。 (4)[インストール]をクリックする。 (5)[閉じる]をクリックする。

ボードを選択するためには以下の手順で行なう:

(1)[ツール(tools)]/[Arduino Mbed OS RP2040 Boards]/[Raspberry Pi Pico]を選択する。 (2)[ツール(tools)]/[シリアルポート]を選択する。

あとは、通常の方法でビルドと書き込みができる。

重要:
書き込み時にエラーになった場合、udev-ruleが登録されていない可能性があるので、
その場合、以下を実行してudev-ruleを登録する:

sudo ~/.arduino15/packages/arduino/hardware/mbed_rp2040/2.0.0/post_install.sh

書き込みが正常に動作すると以下のようなメッセージが出る:
(設定で「より詳細な情報を表示する:」で[書き込み]にチェックしている場合)

/home/xxxx/.arduino15/packages/arduino/tools/rp2040tools/1.0.2/rp2040load -v -D /tmp/arduino_build_yyyyy/zzzzz.ino.elf rp2040load 1.0.1 - compiled with go1.15.8 Loading into Flash: [==============================] 100%%

参考情報

earlephilhower版関連:
Arduino-Pico(Detailed Documentation)
examples(earlephilhower)

Pico-Arduino関連:
Arduino IDE support for RP2040 and Pico arrives
Display_Packをpico_arduinoで動かす

Arduino関連:
Arduino-Pico
Install the Arduino Software (IDE) on Linux
How to Program Raspberry Pi Pico With the Arduino IDE
pico-setup-windows installer
Arduino IDEライブラリのインストールとディレクトリ(フォルダ)構成 (Windows, Mac, Linux対応)

FS関連:
Arduino Pico LittleFS Filesystem Uploader
Filesystem
LittleFS
Arduino ESP8266 LittleFS Filesystem Uploader

OpenOCD関連:
PicoボードにPico_SDKでC言語をビルドする(Picoprobeの説明あり)
Debugging the Raspberry Pi Pico on Windows 10

Pico関連:
Raspberry Pi Pico – How to Interface (almost) Everything!

WSL2関連:
WSL2でRDPサーバーを動かす
WSL2でSSHサーバーを動かす
WSL2でのplatformioやPico-SDKの利用方法

python3関連:
How to permissively decode a UTF-8 bytearray?
bytes, bytearray/日本語エンコード名

その他:
文字コードの16進ダンプ

以上

» 続きを読む

| | コメント (0)

2021年3月27日 (土)

WSL2でRustを動かす

2021/3/27

WSL2 Rust Install

WSL2 Rust Install

概要

WSL2でRustを動かす。
WSL2のUbuntu20.04をホストにする前提で
PicoボードをターゲットとしてRustをインストールからビルド書き込みまで説明している。

Rustのインストール

Ubuntu20.04/WSL2で以下を実行する:

# 必要なディレクトリを用意する mkdir ~/rust_ws mkdir /mnt/c/temp # Rustをインストールする curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # 入力を促されるので「1」を入力する source $HOME/.cargo/env # 関連ツールのインストール rustup target add thumbv6m-none-eabi rustup component add llvm-tools-preview cargo install uf2conv cargo-binutils

書き込みスクリプト

WSL2はUSBストレージをサポートしていないので、PowerShell.exe経由で、書き込むスクリプトを用意する。
pico_UF2.sh

#!/bin/bash uf2conv firmware.bin --base 0x10000000 --family 0xe48bff56 --output firmware.uf2 rm /mnt/c/temp/* cp firmware.uf2 /mnt/c/temp/ PowerShell.exe copy c:/temp/*.uf2 e: exit 0

・実行属性を与えること。
・「e:」は環境依存なので、自分の環境で、uf2ファイルを書き込むドライブ・レターを設定すること。

Pico用環境をダウンロードする

cd ~/rust_ws git clone https://github.com/jannic/rp-microcontroller-rs.git

ビルド

cd rp-microcontroller-rs/boards/rp-pico # binまでビルドする cargo build --target thumbv6m-none-eabi --example=blink --release cargo objcopy --example blink --release -- -O binary firmware.bin

書き込み

# BOOTSELボタンを押しながら、PCのUSBコネクタに接続し # 接続後、BOOTSELボタンを離す。 # RPI-RP2のディレクトリが出現する。 # このタイミングで以下を実行する。 ./pico_UF2.sh

書き込みが完了するとLEDが点滅する。

参考情報

Rust関連:
Rustをインストール
`llvm-tools`, a new rustup component for binary inspection (objdump, nm, size) and profiling (profdata)
Rust support for RP2040 microcontrollers

WSL2関連:
WSL2でRDPサーバーを動かす
WSL2でSSHサーバーを動かす
WSL2でのplatformioやPico-SDKの利用方法

以上

» 続きを読む

| | コメント (0)

2021年3月25日 (木)

WSL2でTinyGOを動かす

2021/3/25

WSL2 TinyGO Install

WSL2 TinyGO Install

概要

WSL2でTinyGOを動かす。
WSL2のUbuntu20.04をホストにする前提で
XIAOボードを中心としてインストールからビルド書き込みまで説明している。
target名を変更することで他のボードのビルドなども行うことができる。

Go/TinyGoのインストール

Ubuntu20.04/WSL2で以下を実行する:

mkdir ~/tigo_ws cd ~/Downloads # goのインストール wget https://golang.org/dl/go1.16.2.linux-amd64.tar.gz sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf go1.16.2.linux-amd64.tar.gz export PATH=$PATH:/usr/local/go/bin # tinygoのインストール wget https://github.com/tinygo-org/tinygo/releases/download/v0.17.0/tinygo_0.17.0_amd64.deb sudo dpkg -i tinygo_0.17.0_amd64.deb export PATH=$PATH:/usr/local/tinygo/bin # その他のexport export GOPATH=$HOME/tigo_ws export TIGOLIBS=$GOPATH/pkg/mod/tinygo.org/x/drivers@v0.15.1 # 書き込み用のディレクトリを作る mkdir /mnt/c/temp

以下を.bashrcに追加する:

# tinygo/go export PATH=$PATH:/usr/local/go/bin export PATH=$PATH:/usr/local/tinygo/bin export GOPATH=$HOME/tigo_ws export TIGOLIBS=$GOPATH/pkg/mod/tinygo.org/x/drivers@v0.15.1

書き込みスクリプト

WSL2はUSBデバイス(USBストレージも含む)をサポートしていないので、
WSL2でhexまたはuf2のファイルまで作成した後、
PowerShell.exe経由で USBストレージに書き込むことで、ボード書き込みを行う。

このスクリプトは、「~/tigo_ws」に置いて、実際のプロジェクト・ディレクトリにコピーして使用することとする。
以下、対応ボードごとのbashスクリプトになる。

fUF2.sh

#!/bin/bash rm /mnt/c/temp/* cp *.uf2 /mnt/c/temp/ PowerShell.exe copy c:/temp/*.uf2 e: exit 0

・実行属性を与えること。
・「e:」は環境依存なので、自分の環境で、uf2ファイルを書き込むドライブ・レターを設定すること。

fHEX.sh

#!/bin/bash rm /mnt/c/temp/* cp *.hex /mnt/c/temp/ PowerShell.exe copy c:/temp/*.hex e: exit 0

・実行属性を与えること。
・「e:」は環境依存なので、自分の環境で、uf2ファイルを書き込むドライブ・レターを設定すること。

インストール時付属サンプルのビルド例

cd ~/tigo_ws # microbit系 tinygo build -size full -o=mb.hex -target=microbit examples/microbit-blink tinygo build -size full -o=mb2.hex -target=microbit-v2 examples/microbit-blink # SAMD系 tinygo build -size full -o=cpx.uf2 -target=circuitplay-express examples/blinky1 tinygo build -size full -o=fm4.uf2 -target=feather-m4 examples/blinky1 tinygo build -size full -o=xiao.uf2 -target=xiao examples/blinky1 tinygo build -size full -o=wiot.uf2 -target=wioterminal examples/blinky1 # mbed系 tinygo build -size full -o f103.hex -target nucleo-f103rb examples/blinky1

独自プロジェクト(blinky)の作成

独自プロジェクト(blinky)を作成するには
ディレクトリblinkyを作成して、

(1)その中に以下のファイルを作成する:
blinky.go

package main // This is the most minimal blinky example and should run almost everywhere. import ( "machine" "time" ) func main() { led := machine.LED led.Configure(machine.PinConfig{Mode: machine.PinOutput}) for { led.Low() time.Sleep(time.Millisecond * 1000) led.High() time.Sleep(time.Millisecond * 1000) } }

(2)go.modの作成
以下を実行してgo.modを作成する:

go mod init blinky

「blinky」は任意のようだが プロジェクト名(ディレクトリ名)に合わせる。

(3)ビルド
以下を実行してビルドする:

tinygo build -size full -o=xiao.uf2 -target=xiao .

これで、xiao.uf2が作成される。

出力例:

$ tinygo build -size full -o=xiao.uf2 -target=xiao . code rodata data bss | flash ram | package 2574 13 0 130 | 2587 130 | (bootstrap) 0 36 0 0 | 36 0 | handleHardFault$string 164 24 4 4 | 192 8 | internal/task 2844 18 13 2054 | 2875 2067 | machine 0 16 0 0 | 16 0 | machine$alloc 40 0 0 0 | 40 0 | main 2352 79 0 48 | 2431 48 | runtime 28 0 0 0 | 28 0 | runtime/volatile 92 0 0 0 | 92 0 | time 8094 186 17 2236 | 8297 2253 | (sum) 8508 - 20 4312 | 8528 4332 | (all) $ ls -l *.uf2 -rw-r--r-- 1 xxxx xxxx 17408 3月 25 08:10 xiao.uf2

(4)書き込み
以下を実行して書き込む:

# 書き込みスクリプトをカレント・ディレクトリにコピーする cp ~/tigo_ws/fUF2.sh . # ボードとホストPCをUSBで接続する。 # RSTパッドを2度GNDショートして、bootloader-modeに入る。 # Arduinoのディレクトリが現れる。 #書き込み ./fUF2.sh

ボードの赤いLED(D13)が1秒周期で点滅すれば動作としてはOKとなる。

serialを動かす

(1)以下のようにプロジェクト用ディレクトリを作成する:

cd tigo_ws mkdir serial cd serial

(2)プロジェクト(serial)ディレクトリに
以下のファイルを作成する:
serial.go

package main import "time" func main() { for { println("hello world!") time.Sleep(time.Second) } }

(3)go.modの作成
以下を実行してgo.modを作成する:

go mod init serial

「serial」は任意のようだが プロジェクト名(ディレクトリ名)に合わせる。

(4)ビルド/書き込み 以下を実行する:

# ビルド tinygo build -size full -o=xiao.uf2 -target=xiao . # 書き込みスクリプトをカレント・ディレクトリにコピーする cp ~/tigo_ws/fUF2.sh . # ボードとホストPCをUSBで接続する。 # RSTパッドを2度GNDショートして、bootloader-modeに入る。 # Arduinoのディレクトリが現れる。 #書き込み ./fUF2.sh

以上で、プログラムが起動する。

(4)シリアル通信の起動
windows側の通信ソフト(teratermなど)でシリアル接続すると
以下のような出力が得られる。(通信速度:115200 bps)

hello world! hello world! hello world! hello world! hello world! hello world! hello world! hello world! hello world! ...

TinyGOのモジュールを利用する

実行例: # 以下で、モジュールをインストールする go get tinygo.org/x/drivers # インストールしたモジュールのパスを設定する #(この場合は設定済みなので特にやることはない) # インポートしたいモジュールを確認する ls $TIGOLIBS #出力 CHANGELOG.md bmp280 hcsr04 microbitmatrix st7789 CONTRIBUTING.md bmp388 hd44780 microphone tester LICENSE buzzer hd44780i2c mma8653 thermistor Makefile dht hub75 mpu6050 tmp102 README.md displayer.go i2c.go net touch adt7410 drivers.go ili9341 pcd8544 veml6070 adxl345 ds1307 l293x semihosting version.go amg88xx ds3231 l9110x shifter vl53l1x apa102 easystepper lis2mdl shiftregister waveshare-epd at24cx espat lis3dh sht3x wifinina bh1750 examples lsm303agr spi.go ws2812 blinkm flash lsm6ds3 ssd1306 bme280 go.mod mag3110 ssd1331 bmi160 go.sum mcp23017 ssd1351 bmp180 gps mcp3008 st7735 # ここでは例として「ws2812」を使用してみる mkdir ws2812 cd ws2812 # exampleのmain.goをコピーする cp $TIGOLIBS/examples/ws2812/main.go . chmod +rw main.go # main.goを編集する nano main.go # 以下のように修正する:
// Connects to an WS2812 RGB LED strip with 10 LEDS. // // See either the others.go or digispark.go files in this directory // for the neopixels pin assignments. package main import ( "image/color" "machine" "time" "tinygo.org/x/drivers/ws2812" ) // 以下は接続するneopixelの数に合わせる var leds [64]color.RGBA //var leds [10]color.RGBA func main() { led := machine.LED led.Configure(machine.PinConfig{Mode: machine.PinOutput}) neo := machine.D4 // for Feater-M4/XIAO // neo := machine.NEOPIXELS neo.Configure(machine.PinConfig{Mode: machine.PinOutput}) ws := ws2812.New(neo) rg := false for { rg = !rg for i := range leds { rg = !rg if rg { // Alpha channel is not supported by WS2812 so we leave it out //leds[i] = color.RGBA{R: 0xff, G: 0x00, B: 0x00} leds[i] = color.RGBA{R: 0x0f, G: 0x00, B: 0x00} } else { //leds[i] = color.RGBA{R: 0x00, G: 0xff, B: 0x00} leds[i] = color.RGBA{R: 0x00, G: 0x0f, B: 0x00} } } ws.WriteColors(leds[:]) led.Set(rg) time.Sleep(100 * time.Millisecond) } }

続き:

# go.modを初期化する go mod init ws2812 # 以下のコマンドで必要なモジュールを自動設定する go mod tidy # ビルド tinygo build -size full -o=xiao.uf2 -target=xiao . # 書き込みスクリプトをカレント・ディレクトリにコピーする cp ~/tigo_ws/fUF2.sh . # ボードとホストPCをUSBで接続する。 # RSTパッドを2度GNDショートして、bootloader-modeに入る。 # Arduinoのディレクトリが現れる。 #書き込み ./fUF2.sh

D4をneopixelsのDIN,3V3をVCC,GNDをGNDに接続する。
書き込んで実行すると、接続したneopixelsが色を変えて光る。

tmp102(i2c)を動かす

mkdir tmp102 cd tmp102 cp $TIGOLIBS/examples/tmp102/main.go . chmod a+rw main.go nano main.go # 以下の内容にする: (修正点は無いはずだが以下の内容であることを確認する)
package main import ( "fmt" "machine" "time" "tinygo.org/x/drivers/tmp102" ) func main() { machine.I2C0.Configure(machine.I2CConfig{ Frequency: machine.TWI_FREQ_400KHZ, }) thermo := tmp102.New(machine.I2C0) thermo.Configure(tmp102.Config{}) for { temp, _ := thermo.ReadTemperature() print(fmt.Sprintf("%.2f°C\r\n", float32(temp)/1000.0)) time.Sleep(time.Millisecond * 1000) } }

続き:

# go.modを設定する go mod init tmp102 go mod tidy # 以下、ビルド&書き込み tinygo build -size full -o=xiao.uf2 -target=xiao . # 書き込みスクリプトをカレント・ディレクトリにコピーする cp ~/tigo_ws/fUF2.sh . # ボードとホストPCをUSBで接続する。 # RSTパッドを2度GNDショートして、bootloader-modeに入る。 # Arduinoのディレクトリが現れる。 #書き込み ./fUF2.sh

XIAOのピン定義

port pin
PA02 A0/D0
PA04 A1/D1
PA10 A2/D2
PA11 A3/D3
PA08 A4/D4
PA09 A5/D5
PB08 A6/D6
PB09 A7/D7
PA07 A8/D8
PA05 A9/D9
PA06 A10/D10

ボードのターゲット名

「-target=nxiao」を以下にあるターゲット名に変更すると
他のボード用にビルドできる。

主なもの(ビルド時にhexまたはuf2を生成するもの)

(1)Adafruit Circuit Playground Bluefruit circuitplay-bluefruit (2)Adafruit Circuit Playground Express circuitplay-express (3)Adafruit Feather M0 feather-m0 (4)Adafruit Feather M4 feather-m4 (5)Adafruit ItsyBitsy M0 itsybitsy-m0 (6)Adafruit ItsyBitsy M4 itsybitsy-m4 (7)BBC micro:bit microbit (8)BBC micro:bit v2 microbit-v2 (9)seeed XIAO xiao (10)seeed wio-terminal wioterminal (11)ST Micro "Nucleo F103RB" nucleo-f103rb

・mbed系(nucleo,microbitなど)のボードは、hexファイルで書き込むので、
書き込みの際は、fHEX.shを使用すること。
・上で上げているadafruitならびにseeedのボードは、uf2ファイルで書き込むので、
書き込みの際は、fUF2.shを使用すること。

参考情報

(古い情報も含まれているので注意のこと)

https://github.com/tinygo-org/tinygo
https://tinygo.org/
https://tinygo.org/getting-started/linux/

コンピュータボードでTinyGOを動かす
docker/TinyGO Helper Script
TinyGOでLightSensorを動かす

TinyGoで始める組み込みプログラミング
TinyGo on Arduino Uno: An Introduction

Circuit Playground Express
Adafruit Circuit Playground Express - Overview
Infrared Receive and Transmit with Circuit Playground Express

Adafruit Circuit Playground Express - PINOUT
Adafruit Circuit Playground Express Pin Assign

NUCLEO-F103RB mbed pinout
NUCLEO-F103RB Pin Assign
STM32F4DISCO Pin Assign
MICROBIT Pin Assign
ARDUINO-NANO Pin Assign
ARDUINO Pin Assign

TinyGo Drivers

USB Flashing Format (UF2)

XIAO Schematic(zip)
How to use Seeeduino XIAO to log in to your Raspberry PI

WSL2関連:
WSL2でRDPサーバーを動かす
WSL2でSSHサーバーを動かす
WSL2でのplatformioやPico-SDKの利用方法

以上

» 続きを読む

| | コメント (0)

2021年3月17日 (水)

WSL2でRDPサーバーを動かす

2021/3/22
・日本語変換のインストール方法について追加した。

2021/3/21+
・「「localhost:3390」で接続する際、接続できないことがある。」問題があり、
それは、localhostの実IPへの変換が安定していないせいだったが、
.wslconfig設定を追加することで修正した。

2021/3/18++
・SSH環境を修正したので、RDPログイン環境下でも、PowerShell.exeが動作するようになった。
参照:WSL2でSSHサーバーを動かす
 
2021/3/17
初版

WSL2 RDP server

WSL2 RDP server

概要

WSL2でRDPサーバーを動かす。
以下での環境整備が完了している前提でのRDPサーバーのインストール方法について述べる。
WSL2でSSHサーバーを動かす

.wslconfig設定(2021/3/21追加)

localhostの実IPへの変換を正常にさせるために以下を設定する。

windows側のc:\Users\<ユーザ名>\.wslconfigを作成して
以下の内容を設定する:

.wslconfig

localhostForwarding=True

以上を設定した後、以下を実行する:

PowerShell

wsl --shutdown

以上の実行でwslをシャットダウン(その後自動で起動される)。
これは、windows10のPCを起動するたびに実行する必要があるので
SSHサーバーで自動実行のbatに登録すると便利になる。

setup-ubuntu-ssh.bat

wsl --shutdown for /F %%i in ('wsl -d Ubuntu-20.04 exec hostname -I') do set ip=%%i netsh interface portproxy delete v4tov4 listenport=22 netsh interface portproxy add v4tov4 listenport=22 connectaddress=%ip% wsl -d Ubuntu-20.04 -u root bash /opt/service_start.sh

RDPサーバーのインストール

以下の手順でインストールする:
ubuntu20.04/WSL2

sudo apt update && sudo apt -y upgrade sudo apt -y install xfce4 sudo apt install xfce4 xfce4-goodies sudo apt install xrdp sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini echo xfce4-session > ~/.xsession #startwm.shを編集する sudo nano /etc/xrdp/startwm.sh #最後の2行をコメントアウトする。 #そして、末尾に #startxfce4 #を追加する。

編集後のstartwm.sh

/etc/xrdp/startwm.sh
(修正部分のみ)

<省略> ##test -x /etc/X11/Xsession && exec /etc/X11/Xsession ##exec /bin/sh /etc/X11/Xsession # xfce startxfce4

RDPサーバーの起動

sshでWSL2-ubuntuにログインして 以下を実行する:

sudo service xrdp start #出力 * Starting Remote Desktop Protocol server

RDPサーバーの起動状況を確認したい場合、
以下のコマンドを実行する:

service xrdp status #出力 * xrdp-sesman is running * xrdp is running

ある程度、自動的にxrdpサーバーを起動する場合は
以下を~/.profileの末尾に追加する:
.profile

<省略> # xrdp retval=$(service xrdp status >/dev/null 2>&1; echo $?) if [ ! $retval == "0" ]; then echo xrdp server start... sudo service xrdp start fi # dbus retval=$(service dbus status >/dev/null 2>&1; echo $?) if [ ! $retval == "0" ]; then echo dbug start... sudo service dbus start fi

このスクリプトでログイン時に
serviceの状態をチェックしているので、
xrdp serverが停止している場合、
「xrdp server start...」が表示されるので、
パスワードを入力する。

RDPで接続する

windows10の「リモートデスクトップ接続」で
localhost:3390 に接続する。
この後、プロンプトが表示されるので、
セッションをxorgのままにして、
WSL2のユーザー名とパスワードを入力する。
ここで、xfce4のディスクトップ画面が表示される。

現在、以下のような制限があるようだ:
(1)PATHが変更になっているのか、PowerShell.exeが動かない。
2021/3/18: SSH環境の改善で動作するようになった。
参照:WSL2でSSHサーバーを動かす
(2)コマンドラインからGUIアプリを起動した場合は、(Xserverが起動している場合)Xserverによる表示になる。
以下の場合はRDPによる表示になる:
・ファイラーでファイルを指定してアプリを選択してクリックするとGUIアプリを起動する。また、アプリ・アイコンをクリックしての起動やアプリケーション・メニューからの起動などができる。
(3)外部からのアクセスでもRDP接続できるようだが、画面が黒いままで使用不可である。
  
/********** 以下の解決済み(2021/3/21) **********
トラブルシュート:
「localhost:3390」で接続する際、接続できないことがある。
原因不明だが、windows10のPCのIPアドレスがDHCPで払い出されて、
実質的にIPアドレスが変わったときに接続できない状況になっている印象がある。
確定的な解決方法は今のところないが、何度も再起動からトライしていると接続できるようだ。
************************************************/

日本語変換のインストール(2021/3/22)

RDPディスクトップのターミナルで以下を実行する:

# 日本語化 sudo apt -y install language-pack-ja sudo update-locale LANG=ja_JP.UTF8 # fcitx-mozc(日本語入力)のインストール sudo apt install -y fcitx-mozc dbus-x11 sudo sh -c "dbus-uuidgen > /var/lib/dbus/machine-id" # fcitx設定 # profileの編集 sudo nano /etc/profile #以下を末尾に追加する: #fcitx export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitx export DefaultIMModule=fcitx fcitx-autostart > /dev/null 2>&1 xset -r 49 > /dev/null 2>&1 ##

以上のインストールが終了したら、WSL2を再起動する。 再度、RDPログインすれば、日本語変換が使用可能になる。

おまけ(chromeのインストール)

以下の手順でchromeをインストールできる:

sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - sudo apt update sudo apt install google-chrome-stable

デスクトップのプリケーション・メニューから起動できる。

参考情報

localhost関連:
WSL2の2つの設定ファイル「.wslconfig」と「wsl.conf」
「WSL 2」最大の課題であった“localhost”問題が解決 ~「Windows 10」Build 18945 すべてのWSLディストロに共通のグローバル設定、カスタムLinuxカーネルの利用にも対応
WSL2: UbuntuでLocalhostを表示させる方法

RDP関連:
Linux on Windows: WSL with Desktop Environment via RDP
WSL2+ubuntu20.04: GUI化して使う方法

SSH関連:
WSL2のUbuntuにsshできるようにする
Windows10で特定のポートを開放する
WSL2 に外部からアクセスする
MobaXterm - Enhanced terminal for Windows with X11 server, tabbed SSH client, network tools and much more

日本語変換関連:
WSL2+Ubuntu 20.04LTSでデスクトップ(xfce4)を表示する。
Windows10 の WSL(Windows Subsystem for Linux) の Ubuntu18.04 で日本語入力する設定

その他:(未確認)
WSL2+Ubuntu 20.04環境から音声を出力する

以上

» 続きを読む

| | コメント (0)

2021年3月14日 (日)

WSL2でSSHサーバーを動かす

2021/3/20
・Documents/setup-ubuntu-ssh.batの自動起動方法を
PowerShellの自動起動スクリプトから
タスクスケジュールによる起動に変更した。
なので、windows10のPCを起動すると
自動的にsetup-ubuntu-ssh.batが起動する。

2021/3/18
・SSHログイン環境下でも、PowerShell.exeが動作するようにした。

2021/3/15
・SSHで外部からアクセスした際のDISPLAY変数の設定値を追加した。
・GUIアプリ起動時に出ているエラーの解消方法について追加した。

2021/3/13+
初版

WSL2 SSH server

WSL2 SSH server

概要

WSL2でSSHサーバーを動かす。
WSL2ならびにbuntu20.04のインストールが終了している前提で SSHサーバーを動かす方法について述べる。

SSHサーバーのインストール

以下の手順でインストールする:
ubuntu20.04/WSL2

sudo apt update sudo apt install openssh-server

WSL2の起動用スクリプト

WSL2は起動時にデーモンが動いていないので
以下のサービス起動用のスクリプトを作成する:
/opt/service_start.sh

#!/bin/bash service ssh start service dbus start service avahi-daemon start service cron start

以下のコマンドで実行権限を与える:

sudo chmod a+x /opt/service_start.sh

windows10側(PowerShell側)のスクリプト

以下のWSL2側の設定を行うbatを作成する:

Documents/setup-ubuntu-ssh.bat

wsl -d Ubuntu-20.04 -u root bash /opt/service_start.sh for /F %%i in ('wsl -d Ubuntu-20.04 exec hostname -I') do set ip=%%i netsh interface portproxy delete v4tov4 listenport=22 netsh interface portproxy add v4tov4 listenport=22 connectaddress=%ip%

/********* 以下、起動方法の変更により廃止 *********

該当のbatを自動実行させるために、
自動実行されるPowerShellのスクリプト(Microsoft.PowerShell_profile.ps1)の
末尾に以下を追加する:
Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
(存在しない場合、新規に作成する)

Documents/setup-ubuntu-ssh.bat

これで、PowerShellを管理者権限で立ち上げると
該当のbatが実行されて WSL2でSSHサーバーが起動することになる。

*********************************************************/

タスク・スケジューラによる自動起動の設定

タスク・スケジューラで以下のように設定する:

全般: ユーザーがログオンしているのみ実行する:on 最上位の特権で実行する: on 構成:[windows10] (重要:これを設定しないと動作しないようだ) トリガー: タスクの開始: ログオン時 遅延時間を指定する: 30秒間 操作」 操作:[プログラムの開始] プログラム/スクリプト: Documents/setup-ubuntu-ssh.batを置いたフル・パス 条件: タスクを実行するためにスリープを解除する:on それ以外、off

参照:Windows10 - 管理者権限が必要なアプリを自動起動(スタートアップ)

この設定で、windows10のPCを再起動すると自動的に
setup-ubuntu-ssh.batが実行される。

これで、<WSL2のユーザー名>@<windowsの外部から見えるIP>で SSHログインできる。

なお、<windowsの外部から見えるIP>は、 PowerShellで以下を実行した出力から分かる:
PowerShell

ipconfig # 出力 Windows IP 構成 <省略> Wireless LAN adapter Wi-Fi: 接続固有の DNS サフィックス . . . . .: リンクローカル IPv6 アドレス. . . . .: xxxxxxxxxxxxxxx IPv4 アドレス . . . . . . . . . . . .: 192.168.0.13 サブネット マスク . . . . . . . . . .: 255.255.255.0 デフォルト ゲートウェイ . . . . . . .: 192.168.0.1 イーサネット アダプター vEthernet (Default Switch): <省略> イーサネット アダプター vEthernet (WSL): <省略>

WiFiで接続している場合、「Wireless LAN adapter Wi-Fi:」のIPアドレスが 該当のIPになるので、ここでは「192.168.0.13」となる。

SSHポートを開放する

外部のPCからWSL2のSSHサーバーにアクセスする場合、windows10のSSHポートを開放する必要がある。色々な解説が、ネット上、見つかるが、代表的なものとして以下を挙げる:
Windows10で特定のポートを開放する
または、管理者権限でPowerShellで以下を実行する:
PowerShell

New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort 22 -Action Allow -Protocol TCP

GUIアプリ

XフォーワードでGUIアプリを動かすときに必要となるDISPLAY変数は以下を設定する。

export DISPLAY=<windowsの外部から見えるIP>:0.0 #上の例では以下のようになる: export DISPLAY=192.168.0.13:0.0

この設定をWSL2の~/.profileと~/.bashrcの末尾に登録すると
自動化できる。
なお、
~/.profileは、ログイン・シェル用の起動スクリプト、
~/.bashrcは、インタラクティブ・シェル用のスクリプトになる。

Xサーバーを内蔵している以下のMobaXtermを使用すれば特別にXサーバーを用意しなくてもWSL2のGUIアプリが使用できる。

SSHで外部からアクセスする場合、
「ssh -Y user@hostname.local」などで起動すれば、
GUIアプリも動作するが、DISPLAY変数を以下に設定する必要がある:

export DISPLAY=localhost:10.0

なお、内部のWSL2のログインでも上の設定でGUIアプリが動くようだが 遅いようなので、内部の使用では、もとの設定のほうが良いようだ。

MobaXterm - Enhanced terminal for Windows with X11 server, tabbed SSH client, network tools and much more
設定は、SSHはデフォルトで、
WSL2ログインの場合は「Run method: Native connector」に
する必要がある。

VScode in WSL2

WSL2にVScodeをインストールして実行すると以下のようなメッセージが出る:

To use Visual Studio Code with the Windows Subsystem for Linux, please install Visual Studio Code in Windows and uninstall the Linux version in WSL. You can then use the `code` command in a WSL terminal just as you would in a normal command prompt. Do you want to continue anyway? [y/N] y To no longer see this prompt, start Visual Studio Code with the environment variable DONT_PROMPT_WSL_INSTALL defined.

ようするに、WSL2ではlinux版ではなくてwindows版を使えと言ってくる。 たぶん以下のような機能があるのでwindows版で十分ということらしい。

VSCodeでWSL2のLinux上のファイルをリモート操作する

とは言え、普通の使い方がしたい場合、linux版のほうが良いと感じると思うので そのまま、このメッセージを無視しても構わない。このメッセージが頻繁にでて鬱陶しいので以下を実行すると出なくなる:

export DONT_PROMPT_WSL_INSTALL=1

永続的に有効にする場合は、~/.profile,~/.bashrcに登録する必要がある。

参考:VScodeのインストール方法

wget http://deb.rug.nl/ppa/mirror/packages.microsoft.com/repos/vscode/pool/main/c/code/code_1.54.2-1615424848_amd64.deb sudo dpkg -i code_1.54.2-1615424848_amd64.deb

エラー解消

GUIアプリを起動する際、動作に実害はないが、エラーメッセージが出ているので、その解消方法について述べる:

(1)「G_IS_DBUS_CONNECTION」

GLib-GIO-CRITICAL **: 21:22:13.063: g_dbus_proxy_new: assertion 'G_IS_DBUS_CONNECTION (connection)' failed

上のようなエラーが出ている場合、以下を実行すると解消する:

sudo apt purge fcitx-module-dbus

参考:Lubuntu - G_Is_Dbus_Connection

(2)「icon text-x-generic」

Could not load theme icon text-x-generic: ...

上のようなエラーが出ている場合、以下を実行すると解消する:

sudo apt install gnome-icon-theme

PowerShell.exeを動作させる(2021/3/18)

SSHログイン環境ではPATHの問題か「PowerShell.exe」が動作しない。 そこで以下のようにシンボリック・リンクを張り、SSHログイン環境下でも 「PowerShell.exe」が動作するようにする。

bash

sudo ln -s /mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0//PowerShell.exe /usr/bin/PowerShell.exe #確認 which PowerShell.exe #出力 /usr/bin/PowerShell.exe #シンボリック・リンクの確認 ls -l /usr/bin/PowerShell.exe lrwxrwxrwx 1 root root 62 3月 18 18:02 /usr/bin/PowerShell.exe -> /mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0//PowerShell.exe

参考情報

WSL2のUbuntuにsshできるようにする
Windows10で特定のポートを開放する
WSL2 に外部からアクセスする
MobaXterm - Enhanced terminal for Windows with X11 server, tabbed SSH client, network tools and much more

以上

» 続きを読む

| | コメント (0)

2021年3月10日 (水)

platfomioを使ってnaitive(linux/windows)のプログラムをビルドする方法

2021/3/10
初版

platformio naitive build

platformio naitive build

概要

platfomioを使ってnaitive(linux/windows)のプログラムをビルドする方法について述べる。
ここでは、platformioがインストール済みを前提とする。
実行環境はubuntuとwindows10を前提にする。

windows10の場合

ここでは既にscoopなどでplatformioがインストール済みとする。
以下の2つのファイルをプロジェクト・デレクトリに用意する:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter, extra scripting ; Upload options: custom port, speed and extra flags ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html [env:windows_x86] # Stable version #platform = windows_x86 # Development version platform = https://github.com/platformio/platform-windows_x86.git

src/main.c

#include <stdio.h> int main() { printf("Hello World from PlatformIO!\n"); return 0; }

ビルド/実行の例:
PowerShell

mkdir win cd win notepad platformio.ini #上の内容になるように編集する。 mkdir src notepad src/main.c #上の内容になるように編集する。 pio run -t clean #必要なツールのダウンロードとインストールが行われる。 # ビルド pio run # 実行 .\.pio\build\windows_x86\program.exe #(実行・出力例) Hello World from PlatformIO!

ubuntuの場合

ここでは既にplatformioがインストール済みとする。
以下の2つのファイルをプロジェクト・デレクトリに用意する:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter, extra scripting ; Upload options: custom port, speed and extra flags ; Library options: dependencies, extra library storages ; ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html [env:linux_x86_64] # Stable version #platform = linux_x86_64 # Development version platform = https://github.com/platformio/platform-linux_x86_64.git

src/main.c

#include <stdio.h> int main() { printf("Hello World from PlatformIO!\n"); return 0; }

ビルド/実行の例:
bash

mkdir pc cd pc gedit platformio.ini #上の内容になるように編集する。 mkdir src gedit src/main.c #上の内容になるように編集する。 pio run -t clean #必要なツールのダウンロードとインストールが行われる。 # ビルド pio run # 実行 ./.pio/build/linux_x86_64/program #(実行・出力例) Hello World from PlatformIO!

参考情報

platformio関連:
windows10にplatformioをインストールする(scoop版)
arduinoフレームワーク用platformio.ini集(linux版PlatformIOのインストール方法)

PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
ubuntu20.04をインストールする

以上

» 続きを読む

| | コメント (0)

2021年3月 7日 (日)

platformioのプログラムをArduino-IDEにインポートする方法

2021/3/6
初版

import platformio to Arduino-IDE

import platformio to Arduino-IDE

概要

platformioのプログラムをArduino-IDEにインポートする方法について述べる。
以下を前提とする:
(1)platformioのframeworkとして、arduinoに設定している
(2)Arduino-IDEは、インストール済みで使用するボードのボードマネージャーでの設定が完了している
(3)Arduino-IDEのディレクトリ構成はデフォルトのままとする
(4)ホストPCのOSとしてubuntuを使用している

インポート作業の流れとしては以下になる:
(1)platformioのプログラムをArduinoのディレクトリにコピーする
(2)platformioで使用しているライブラリをArduino/librariesにコピーする

実際の手順

ここでは例として、platformioのwiot-nixie-NTP(ディレクトリ)のプログラムを Arduino-IDEにインポートすることにする。

cd pio_ws # プログラムをコピーする cp -r wiot-nixie-NTP/src ~/Arduino/wiot-nixie-NTP mv ~/Arduino/wiot-nixie-NTP/*.ino ~/Arduino/wiot-nixie-NTP/wiot-nixie-NTP.ino cd wiot-nixie-NTP # ライブラリをダウンロードする # (以前、ビルドしたことがあれば不要) pio run # ライブラリをコピーする cp -r .pio/libdeps/seeed_wio_terminal/* ~/Arduino/libraries/

ここで「seeed_wio_terminal」は、ボード名称になるので、自分の状況にあわせて変更すること。

参考情報

スケッチ関連:
nixieクロックにNTPクライアントの機能を追加する(V2)
Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(NTP-CLIENT編)

PlatformIO関連:
arduinoフレームワーク用platformio.ini集
windows10にplatformioをインストールする(scoop版)
WSL2でのplatformioやPico-SDKの利用方法
PlatformIO Core (CLI)

Arduino-IDE関連:
Arduino IDEをUbuntu 20.04にインストールする
How to add boards in the board manager
Customizing the Arduino IDE
Arduino IDEライブラリのインストールとディレクトリ(フォルダ)構成 (Windows, Mac, Linux対応)
A Tour Inside Arduino Core: Source Files, How to Make A New Core and Arduino Building Steps

以上

» 続きを読む

| | コメント (0)

2021年3月 1日 (月)

windows10にplatformioをインストールする(scoop版)

2021/3/1

platformio windows10

platformio windows10

概要

windows10にplatformioをインストールする(scoop版)
windows10にscoopでplatformioをインストールする方法について述べる。

platformioをインストールする

PowerShell

# scoopをインストール Set-ExecutionPolicy RemoteSigned -scope CurrentUser iwr -useb get.scoop.sh | iex # pythonをインストールする scoop install python pip3 install platformio # (必要があれば)windows用VScodeをインストールする scoop bucket add extras scoop install vscode # 別の機能が割り当てられているaliasを削除する del alias:curl del alias:wget # curl, wgetをインストールする scoop install curl scoop install wget # その他の必要となるツールをインストールする scoop install git

scoopの簡単な説明:

# xxxxをインストール scoop install xxxx # Scoop自身とローカル内にあるアプリの更新情報を更新 scoop update # 最新バージョンでないアプリがあるかをチェック scoop status # xxxxを更新 scoop update xxxx # すべてのアプリを更新 scoop update * # xxxxをアンインストール scoop uninstall xxxx

platformioの使い方

# プロジェクトのディレクトリを作る # (一つのスケッチごとに一つのディレクトリ) mkdir proj cd proj # ソースを置くディレクトリsrcを作る mkdir src # スケッチを作成する # (テスト・スケッチとして以降にASCIITable.inoがある) notepad src/main.ino # 使うボードに対応したplatformio.iniを作る # (内容については以降を参照のこと) notepad platformio.ini # スケッチをビルドする # (最初の1回はライブラリ・ツールを自動的にダウンロードする) pio run # ボードをUSB接続して書き込む pio run -t upload

platformio.iniの具体的な内容は「arduinoフレームワーク用platformio.ini集」を参照のこと

その他の使い方

# build結果をクリアする pio run -t clean # キャッシュをクリアする # (ツールやライブラリがダウンロードし直しになるので注意のこと) rm -r .pio # 環境を切り替えて書き込む pio run -e f303 -t upload pio run -e f103 -t upload

環境を切り替えて書き込む場合のplatformio.iniは
以下のように複数の環境[env:xxx]を持っていること:
platformio.ini

[env:f103] platform = ststm32 board = nucleo_f103rb framework = arduino build_flags = -DNUCLEO_F103RB monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps = [env:f303] platform = ststm32 board = nucleo_f303k8 framework = arduino build_flags = -DNUCLEO_F303K8 monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

[env:xxxx]のxxxxの部分は環境名にあたり、 ダブらない任意の名前であること。

テスト用スケッチ

src/ASCIItable.ino

/* ASCII table Prints out byte values in all possible formats: - as raw binary values - as ASCII-encoded decimal, hex, octal, and binary values For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII The circuit: No external hardware needed. created 2006 by Nicholas Zambetti <http://www.zambetti.com> modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/ASCIITable */ void setup() { //Initialize serial and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // prints title with ending line break Serial.println("ASCII Table ~ Character Map"); } // first visible ASCIIcharacter '!' is number 33: int thisByte = 33; // you can also write ASCII characters in single quotes. // for example, '!' is the same as 33, so you could also use this: // int thisByte = '!'; void loop() { // prints value unaltered, i.e. the raw binary version of the byte. // The Serial Monitor interprets all bytes as ASCII, so 33, the first number, // will show up as '!' Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). // Decimal is the default format for Serial.print() and Serial.println(), // so no modifier is needed: Serial.print(thisByte); // But you can declare the modifier for decimal if you want to. // this also works if you uncomment it: // Serial.print(thisByte, DEC); Serial.print(", hex: "); // prints value as string in hexadecimal (base 16): Serial.print(thisByte, HEX); Serial.print(", oct: "); // prints value as string in octal (base 8); Serial.print(thisByte, OCT); Serial.print(", bin: "); // prints value as string in binary (base 2) also prints ending line break: Serial.println(thisByte, BIN); // if printed last visible character '~' or 126, stop: if (thisByte == 126) { // you could also use if (thisByte == '~') { // This loop loops forever and does nothing while (true) { continue; } } // go on to the next character thisByte++; }

本スケッチはarduinoのサンプルそのもの(bpsのみ変更)である。

alias削除の永続化

インストール時に以下でalias削除したものは、PowerShellのセッションを閉じると無効になり復活する。

# 別の機能が割り当てられているaliasを削除する del alias:curl del alias:wget

したがって、削除を永続化するためにセッション起動時に自動実行されるPowerShellのスクリプト(Microsoft.PowerShell_profile.ps1)の 末尾に以下を追加する: Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
(存在しない場合、新規に作成する)

del alias:curl del alias:wget

ビルド・エラー

Arduino-IDEのコンパイラと異なり、platformioのコンパイラは、関数定義の後方参照を許さないので、 この場合、関数の未定義エラーになる。したがって、Arduino-IDEでビルドできているソースでもエラーになることがある。このときの対応方法は、未定義エラーになる関数定義をプロトタイプ宣言としてソースの先頭に置き、後方参照を解消する。(関数定義の本体の位置はそのままで移動させる必要はない)

参考情報

WindowsコマンドラインツールScoopのすすめ(基礎編)
Windowsでパッケージ管理したいなら、先ずScoopより始めよ
PowerShell コンソール内で curl や wget が実行できないとお嘆きのあなたへ

PlatformIO M5ATOM on Windows10
TinyGO Install XIAO on Windows10

M5Stack関連:
PlatformIO M5Stack開発の現状
・https://github.com/m5stack/M5StickC-Plus.git
・https://github.com/m5stack/M5StickC.git
・https://github.com/m5stack/M5Stack.git

micro:bit関連:
micro:bit Arduino/MBED開発ツール(v2)(micro:bit-v2対応,linux版)
micro:bit v2 で遊ぶ

platformio関連:

https://docs.platformio.org/en/latest/platforms/creating_board.html Installation 1.Create boards directory in core_dir if it doesn’t exist. 2.Create myboard.json file in this boards directory. 3.Search available boards via pio boards command. You should see myboard board.

PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
ubuntu20.04をインストールする
Advanced Scripting - Before/Pre and After/Post actions

以上

» 続きを読む

| | コメント (0)

2021年2月27日 (土)

WSL2でのplatformioやPico-SDKの利用方法

2021/4/20++
arduinoボードにリセットをかけて書き込み用ストレージを出現させるスクリプトを追加した。

2021/4/12
uf2やmbedの書き込みのドライブを自動検出に改良した。

2021/3/10
さらにextra_script.pyを改良して mbed,uf2のファイルによる書き込みも自動化した。

2021/3/8+
さらにextra_script.pyを改良して XIAO,wio-terminalの書き込みをサポートした。

2021/3/4
さらにextra_script.pyを改良して 書き込み用ストレージがないボード(UNO,M5ATOMなど)でも プログラムが書き込めるようにした。

2021/3/1
extra_script.pyを改良して uf2まで自動生成するようにした。

2021/2/27
初版

WSL2 platformio Pico-SDK

WSL2 platformio Pico-SDK

概要

WSL2(Windows Subsystem for Linux version2)でのplatformioやPico-SDKの利用方法
WSL2でplatformioやPico-SDKを利用した場合、WSL2はUSBデバイスをサポートしていないので、そのままでは、ビルドまではできるが、書き込みができない。本記事では、その解決方法について述べる。
(ホストはubuntu20.04を想定している)

基本的な考え方は、書き込み用ストレージが現れるボードに限定されるが、 書き込み用ストレージのためのファイル(.uf2または.hex)を作成して、 それをWSL2側からPowerShellを使って該当ストレージにコピーすることで 書き込みを行う。

したがって、書き込みストレージがないボード(Arduno-UNOやESP32ボードなど)は書き込めないが、 それ以外のボード(XIAO,Wio-Terminal,Nucleo,micro:bitなど)は書き込みが可能となる。

追記1:
書き込みストレージがないボード(Arduno-UNO、M5ATOM(ESP32ボード))でも、windows側の書き込みツールを利用することでプログラムが書き込めるよう extra_script.pyを改良した。(2021/3/4)

追記2:
XIAO、wio-terminalにおいて、 windows側の書き込みツール(bossac)を利用することでプログラムが書き込めるよう extra_script.pyを改良した。(2021/3/8)

追記3:
mbedボードとuf2ファイルによる書き込みをサポートしているボードにおいて 自動的に書き込むように extra_script.pyを改良した。(2021/3/10)

準備(インストール)

platformioやPico-SDKのインストールについては 以下の記事がほとんどそのまま参考になる。 (ただし、udev登録などUSB関連は除く)

arduinoフレームワーク用platformio.ini集
PicoボードにPico_SDKでC言語をビルドする

platformioの場合

ビルド時にhexファイルが必要となるので platformio.iniに以下の行を追加する:
# 任意の位置で良いが、例えば「board=」の次の行に追加する

extra_scripts = post:extra_script.py

実行するスクリプトをカレントディレクトリに 以下の内容で作成する:
extra_script.py

Import("env") # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", "$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "Building $BUILD_DIR/${PROGNAME}.hex") )

参照:Add a new option which could generate .hex file in platformio.ini #240

ここで「pio run」の実行すると、.hexが生成される。

mbed系ボード(nucleo,micro:bitなど)は、書き込むファイルのフォーマットが.hexなので、
以下の手順で書き込みができる:

PowerShell.exe copy .pio/build/*/firmware.hex e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

Microchip(Almel)SAMD21/SAMD51ボード(XIAO,Wio-Terminalなど)の場合、書き込むフォーマットは、.uf2なので変換する必要がある。

このため以下の手順でツールをインストールする:

wget https://raw.githubusercontent.com/microsoft/uf2/master/utils/uf2conv.py chmod +x uf2conv.py

参照:
uf2conv -- Packing and unpacking UF2 files

XIOA(SAMD21)ボードの場合、以下のコマンドで.uf2に変換する:

./uf2conv.py .pio/build/*/firmware.hex -f 0x68ed2b88 -c -o hex2.uf2

Wio-Termial(SAMD51)ボードの場合、以下のコマンドで.uf2に変換する:

./uf2conv.py .pio/build/*/firmware.hex -f 0x55114460 -c -o hex2.uf2

他のチップに対応する場合、「-f xxxxx」のxxxxxがfamilyID(=ChipID)なので、その部分を該当IDに置き換える。
familyIDは以下を参照のこと:
Family list vs familyID

.uf2に変換後、以下の手順で書き込む:

PowerShell.exe copy hex2.uf2 e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

なお、以下のスクリプトで書き込みを自動化できる:
cp_wiot.sh
# SAMD51用

#!/bin/bash ./uf2conv.py .pio/build/*/firmware.hex -f 0x55114460 -c -o hex2.uf2 PowerShell.exe copy hex2.uf2 e:

注意:familyIDがチップごとに異なることに注意のこと。

Pico-SDKの場合

ビルドすると、自動的に.uf2まで作成するので、以下の手順で書き込むことができる:

PowerShell.exe copy xxxx.uf2 e:

ただし、「e:」は書き込みストレージのドライブ・レターなので環境に依存するので自分の環境でのドライブ・レターに置き換える。
(windows側のエクスプローラーなどで該当のドライブ・レターを確認できる)

extra_script.pyの改良

以下のように改良して、uf2生成までを自動化した:
extra_script.py

Import("env") board = env.GetProjectOption("board") #print("board:"+board) # set familyID(chip ID) familyID = 'undefined!' if "seeed_wio_terminal" == board: familyID = "0x55114460" if "adafruit_feather_m4" == board: familyID = "0x55114460" if "adafruit_grandcentral_m4" == board: familyID = "0x55114460" if "seeed_xiao" == board: familyID = "0x68ed2b88" if "adafruit_circuitplayground_m0" == board: familyID = "0x68ed2b88" if "nucleo_f103rb" == board: familyID = "mbed" if "nucleo_f303k8" == board: familyID = "mbed" if 'mbed' == familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) elif 'undefined!' != familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) # uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "python3 uf2conv.py $BUILD_DIR/${PROGNAME}.hex -f ", familyID, " -c -o $BUILD_DIR/${PROGNAME}.uf2" ]), "(2)Converting $BUILD_DIR/${PROGNAME}.uf2") ) # copy uf2 to current dir env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "cp $BUILD_DIR/${PROGNAME}.uf2 ." ]), "(3)Copying ${PROGNAME}.uf2 in current dir") )

以下が改良点になる:
(1)boardチェック
boardをチェックして自動的にfamilyIDを設定する。
# 定義がないboardの場合、追加する必要あり。
(2)mbed対応
boardをチェックしてmbed系ボードの場合、自動的にhexを生成する。
(2)uf2をカレントディレクトリにコピーする
書き込みドライブにコピーする際の利便性の向上

プログラミング・ヒント:
以下の部分において「 "$BUILD_DIR/${PROGNAME}.elf",」は、
「 "$BUILD_DIR/${PROGNAME}.hex",」にしたくなるが、
通常のビルド・プロセスで生成したファイルである必要がある。

# uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf",

extra_script.pyの改良(2021/3/4,2021/3/8,2021/3/10)

以下のように、さら改良して、UNO,M5ATOM,XIAO,wio-terminal,mbedボートやuf2ファイルでの書き込みするボードを書き込めるようにした:
extra_script.py

Import("env", "projenv") # access to global construction environment #print("env:") #print(dir(env)) # access to project construction environment #print("projenv:") #print(dir(projenv)) board = env.GetProjectOption("board") #print("board:"+board) ext = env.GetProjectOption("ext") print("ext:"+ext) # set familyID(chip ID) familyID = 'undefined!' if "seeed_wio_terminal" == board: familyID = "0x55114460" if "adafruit_feather_m4" == board: familyID = "0x55114460" if "adafruit_grandcentral_m4" == board: familyID = "0x55114460" if "seeed_xiao" == board: familyID = "0x68ed2b88" if "adafruit_circuitplayground_m0" == board: familyID = "0x68ed2b88" if "nucleo_f103rb" == board: familyID = "mbed" if "nucleo_f303k8" == board: familyID = "mbed" if "bbcmicrobit" == board: familyID = "mbed" if 'esp32dev' == board: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "esptool.py --chip esp32 elf2image $BUILD_DIR/${PROGNAME}.elf" ]), "(1)Building $BUILD_DIR/${PROGNAME}.bin") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for ESP32 board") ) elif 'm5stick-c' == board: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "esptool.py --chip esp32 elf2image $BUILD_DIR/${PROGNAME}.elf" ]), "(1)Building $BUILD_DIR/${PROGNAME}.bin") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for m5Stick-c/M5Atom board") ) if 'uno' == board: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for UNO board") ) # check familyID(include mbed) if 'mbed' == familyID: # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(2)Doing something for mbed board") ) elif 'undefined!' != familyID: # Custom BIN from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "binary", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.bin" ]), "(0)Building $BUILD_DIR/${PROGNAME}.bin") ) # Custom HEX from ELF env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "$OBJCOPY", "-O", "ihex", "-R", ".eeprom", " $BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex" ]), "(1)Building $BUILD_DIR/${PROGNAME}.hex") ) # uf2 from HEX env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", # "$BUILD_DIR/${PROGNAME}.hex", env.VerboseAction(" ".join([ "python3 uf2conv.py $BUILD_DIR/${PROGNAME}.hex -f ", familyID, " -c -o $BUILD_DIR/${PROGNAME}.uf2" ]), "(2)Converting $BUILD_DIR/${PROGNAME}.uf2") ) # copy uf2 to current dir env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "cp $BUILD_DIR/${PROGNAME}.uf2 ." ]), "(3)Copying ${PROGNAME}.uf2 in current dir") ) if '' != ext: env.AddPostAction( "$BUILD_DIR/${PROGNAME}.elf", env.VerboseAction(" ".join([ "./"+ext ]), "(4)Doing something for uf2 board") )

動作原理:
WSL2側で書き込みに必要なファイルを作成したあと、 windows10側のc:/tempのデイレクトリに、そのファイルをコピーして PowerShell経由でwindows側の書き込みツールを起動して ボードにプログラムを書き込む。

準備として以下を実行しておく:

#WSL2側 #ファイルをwindows10側に引き渡すディレクトリを作成する mkdir /mnt/c/temp #windows10側(PowerShell側) #windows10側の書き込みツールをインストールする scoop install avrdude pio install esptool # bossacをインストールする cd $HOME mkdir msi cd msi wget https://github.com/shumatech/BOSSA/releases/download/1.9.1/bossa-x64-1.9.1.msi Start-Process -filepath "$HOME\msi\bossa-x64-1.9.1.msi" # 実行パスを設定する $Env:Path += ";C:\Program Files (x86)\BOSSA\" # 別の機能が割り当てられているaliasを削除する del alias:curl del alias:wget # curl, wgetをインストールする scoop install curl scoop install wget # その他の必要となるツールをインストールする scoop install git

・参照:WindowsコマンドラインツールScoopのすすめ(基礎編)
・注意:設定した実行パスやalias削除は、セッションが閉じると無効になるので
PowerScriptの以下の起動スクリプト

$HOME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

の末尾に次の行を追加する。(スクリプトファイルがない場合、新規作成する)

del alias:curl del alias:wget $Env:Path += ";C:\Program Files (x86)\BOSSA\"


UNOの場合、以下のファイルをWSL2側に用意する:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:uno] platform = atmelavr board = uno extra_scripts = post:extra_script.py ext = f_UNO.sh framework = arduino #build_flags = -Dxxxx upload_protocol = arduino monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

f_UNO.sh

#!/bin/bash # Arduino UNO flash writing # for debug #ls .pio/build/uno/ rm /mnt/c/temp/* cp $HOME/.platformio/packages/tool-avrdude/avrdude.conf /mnt/c/temp/ cp .pio/build/uno/firmware.hex /mnt/c/temp/ PowerShell.exe avrdude -v -p atmega328p -C c:/temp/avrdude.conf -c arduino -b 115200 -D -P COM14 -U flash:w:c:/temp/firmware.hex:i exit 0

・COM14は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。


M5ATOMの場合:
platformio.ini

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 board = m5stick-c extra_scripts = post:extra_script.py ext = f_M5ATOM.sh framework = arduino build_flags = -DM5ATOM monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # use M5Atom lib 3113 # use "FastLED" 126

f_M5ATOM.sh

#!/bin/bash # M5ATOM flash writing # for debug #ls .pio/build/uno/ rm /mnt/c/temp/* cp $HOME/.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin /mnt/c/temp/ cp .pio/build/esp32dev/partitions.bin /mnt/c/temp/ cp $HOME/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /mnt/c/temp/ cp .pio/build/esp32dev/firmware.bin /mnt/c/temp/ PowerShell.exe esptool.py --chip esp32 --baud 1500000 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 c:/temp/bootloader_dio_40m.bin 0x8000 c:/temp/partitions.bin 0xe000 c:/temp/boot_app0.bin 0x10000 c:/temp/firmware.bin exit 0

・自動検出になっているので通信ポートの設定はない。
・実行属性を与えること。

XIAOの場合:
platformio.ini

<ヘッダー省略> [env:seeed_xiao] platform = atmelsam board = seeed_xiao extra_scripts = post:extra_script.py ext = f_XIAO.sh framework = arduino build_flags = -DXIAO upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # Accept new functionality in a backwards compatible manner and patches olikraus/U8g2 @ ^2.28.7

f_XIAO.sh

#!/bin/bash # XIAO flash writing # for debug #ls .pio/build/seeed_xiao/ rm /mnt/c/temp/* cp .pio/build/seeed_xiao/firmware.bin /mnt/c/temp/ PowerShell.exe bossac -p COM18 -i -e -w -v -R -o 0x2000 c:/temp/firmware.bin exit 0

・COM18は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。

wio-terminalの場合:
platformio.ini

<ヘッダー省略> [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal extra_scripts = post:extra_script.py ext = f.WIOT.sh framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = <以下、省略>

f_WIOT.sh

#!/bin/bash # wio-terminal flash writing # for debug #ls .pio/build/seeed_wio_terminal/ rm /mnt/c/temp/* cp .pio/build/seeed_wio_terminal/firmware.bin /mnt/c/temp/ PowerShell.exe bossac -p COM15 -i -e -w -v -R -o 0x4000 c:/temp/firmware.bin exit 0

・COM15は(window10側の)通信ポートになるが環境依存なので、自分の環境での通信ポートに変更すること。
・実行属性を与えること。

wio-terminalの場合(ファイルコピーによる書き込み):
platformio.ini

<ヘッダー省略> [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal extra_scripts = post:extra_script.py ext = f_UF2.sh framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = <以下、省略>

/***** 書き込みドライブを自動検出にしたので、以下、廃止 *****

f_UF2.sh

#!/bin/bash rm /mnt/c/temp/* cp firmware.uf2 /mnt/c/temp/ PowerShell.exe copy c:/temp/firmware.uf2 e: exit 0

・「e:」はドライブ・レターになるが環境依存なので、自分の環境のものに変更すること。
・実行属性を与えること。
***********************************************************/

// 改良版(2021/4/12)
f_UF2.sh

#!/bin/bash rm /mnt/c/temp/* cp firmware.uf2 /mnt/c/temp/ DRIVE=`PowerShell.exe get-volume|grep FAT|awk '{print $1}'` if [ "${DRIVE}" = "" ]; then echo "bootloader-mode is not activated!" exit 1 fi PowerShell.exe copy c:/temp/firmware.uf2 ${DRIVE}: exit 0

・書き込みのドライブを自動検出に改良した。
 (ただし、接続しているドライブとしてFATタイプが1台である前提)
・実行属性を与えること。

F103RBの場合(ファイルコピーによる書き込み):
platformio.ini

<ヘッダー省略> [env:nucleo_f103rb] platform = ststm32 board = nucleo_f103rb extra_scripts = post:extra_script.py ext = f_MBED.sh framework = arduino build_flags = -DNUCLEO_F103RB monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

/***** 書き込みドライブを自動検出にしたので、以下、廃止 *****

f_MBED.sh

#!/bin/bash rm /mnt/c/temp/* cp .pio/build/*/firmware.hex /mnt/c/temp/ PowerShell.exe copy c:/temp/firmware.hex e: exit 0

・「e:」はドライブ・レターになるが環境依存なので、自分の環境のものに変更すること。
・実行属性を与えること。
***********************************************************/

// 改良版(2021/4/12)
f_MBED.sh

#!/bin/bash rm /mnt/c/temp/* cp .pio/build/*/firmware.hex /mnt/c/temp/ DRIVE=`PowerShell.exe get-volume|grep FAT|awk '{print $1}'` if [ "${DRIVE}" = "" ]; then echo "MBED board is not connected!" exit 1 fi PowerShell.exe copy c:/temp/firmware.hex ${DRIVE}: exit 0

・書き込みのドライブを自動検出に改良した。
 (ただし、接続しているドライブとしてFATタイプが1台である前提)
・実行属性を与えること。

ビルド/書き込み
以下を実行する:

pio run -t clean pio run # extra_script.py(とf_xxxx.sh)のほうで書き込みを行うので「-t upload」は不要となる

対応ボードの追加:
現状は、UNO,M5ATOM,XIAO,wio-terminal,mbedボードになるが
対応ボードを追加する場合、 「extra_script.py」の変更と、実際の書き込みを実行する「f_xxxx.sh」を追加することになる。 「f_xxxx.sh」には実際の書き込みツールのコマンドラインの記述が必要となるが、 それを知るには、[pio run -v -t upload]を実行すると実際のコマンドラインが表示されるので それを参考に「f_xxxx.sh」に記述することになる。(当然のことながら、windows10側にインストールされていないツールであれば、windows10側に、そのツールをインストールする必要がある)

(参考)PowerShell.exe get-volume の出力例

raspberry-pi-picoを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- E RPI-RP2 FAT Removable Healthy OK D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK micro:bitを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK E MICROBIT FAT Removable Healthy OK wio-terminalを接続した場合: $ PowerShell.exe get-volume DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus ----------- ------------ -------------- --------- ------------ ---------------- D Volume NTFS Fixed Healthy OK NTFS Fixed Healthy OK System NTFS Fixed Healthy OK C Windows NTFS Fixed Healthy OK E Arduino FAT Removable Healthy OK

arduinoボードをリセットするスクリプト(2021/4/20)

USBシリアルが有効のボードでシリアル経由でリセットをかけて、書き込み用ストレージを出現させるスクリプトを紹介する。(raspberry-pi-picoボードでも有効)

windows側の準備:

.wslconfigを以下のように設定する:
C:\Users\USER\.wslconfig

[wsl2] localhostForwarding=true

以下を実行する:

#以下をインストールする(scoopがインストールされている前提) scoop install python scoop install grep scoop install gawk pip install pyserial # スクリプトを置くディレクトリを作成する mkdir ¥py

以下のスクリプトを用意する:

C:¥py¥reset_arduino.py

#!/usr/bin/env python3 import sys args = sys.argv # reset arduino board via serial import serial try: arduino = serial.Serial(args[1], baudrate=1200) arduino.close() except serial.SerialException as e: #if e.errno == 13: # raise e pass

C:¥py¥reset_arduino.ps1

$env:COMPORT=(Get-WMIObject Win32_SerialPort | Select-Object DeviceID | grep COM | gawk 'END{print}') python.exe c:\py\reset_arduino.py $env:COMPORT

・複数のシリアルが接続されている場合、一番最近接続されたものが選ばれる。
状況を単純化するためにも書き込みするボードのみを接続することを進める。

WSL側:

wsl.confは以下のように設定する:
/etc/wsl.conf

[automount] enabled=true mountFsTab=true root="/mnt/" options="" crossDistro=true [network] generateHosts=true generateResolvConf=true [interop] enabled=true appendWindowsPath=true

reset_arduino.sh

#!/bin/bash PowerShell.exe C:/py/reset_arduino.ps1

・実行属性を与えること

実行例
以下を実行するとボードにリセットがかかり書き込み用ストレージが出現する。

# ボードをホストとUSBで接続する ./reset_arduino.sh # この時点で接続されているボードがリセットされ書き込み用ストレージが出現する

参考情報

WSL関連:
wsl.conf と .wslconfig
WSLのアーキテクチャ

scoop関連:
scoopインストール方法(windows10にplatformioをインストールする(scoop版))
WindowsコマンドラインツールScoopのすすめ(基礎編)
Windowsでパッケージ管理したいなら、先ずScoopより始めよ
PowerShell コンソール内で curl や wget が実行できないとお嘆きのあなたへ

書き込みツール関連:
BOSSA
AVRDUDE - AVR Downloader/UploaDEr
esptool.py
Open source version of the STMicroelectronics STlink Tools
stlink Tools Tutorial

micro:bit関連:
micro:bit Arduino/MBED開発ツール(v2)(micro:bit-v2対応,linux版)
micro:bit v2 で遊ぶ

platformio関連:

https://docs.platformio.org/en/latest/platforms/creating_board.html Installation 1.Create boards directory in core_dir if it doesn’t exist. 2.Create myboard.json file in this boards directory. 3.Search available boards via pio boards command. You should see myboard board.

PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
ubuntu20.04をインストールする
【小ネタ】WSL利用時のRaspberry Pi Picoへの書き込みをコマンドラインから行う

Advanced Scripting - Before/Pre and After/Post actions

以上

» 続きを読む

| | コメント (0)

2021年2月21日 (日)

arduinoフレームワーク用platformio.ini集

2021/2/21+
初版

platformio.ini for arduino

platformio.ini for arduino

概要

arduinoフレームワーク用platformio.ini集
本記事は。各ボード用のplatformio.iniを集め、platformioの使い方を説明したものである。
(ホストはubuntu20.04を想定している)

準備

開発ツールをインストールする前に 必要なものをインストールする:

sudo apt update sudo apt install net-tools sudo apt install git curl sudo apt install gcc-arm-none-eabi build-essential sudo apt install cmake sudo apt install libusb-dev sudo apt install libusb-1.0-0-dev sudo apt install picocom sudo apt install python3-distutils sudo apt install python3-venv # lib for Arduino IDE for microbit sudo apt install libudev1:i386 # for Arduino IDE for ESP32/ESP8266 sudo apt install python-is-python3 pip install pyserial pip uninstall serial

bt(bootterm)のインストール

git clone https://github.com/wtarreau/bootterm cd bootterm make sudo make install

本ツールは、コマンドとして「bt」と入力すると最近有効になった「/dev/ttyACMx または /dev/ttyUSBx」に接続する。
参照:Bootterm – a developer-friendly serial terminal program

PlatformIOのインストール

python3 -m venv pio_env source pio_env/bin/activate pip install platformio インストール後も、このツールを使用する場合 同じディレクトリで以下を実行する: source pio_env/bin/activate # 「source」は、「.」でも良い

udev登録

以下を実行して、udevのrulesを登録する:

curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/master/scripts/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules sudo udevadm control --reload-rules sudo usermod -a -G dialout $USER sudo usermod -a -G plugdev $USER

platformioの使い方

# プロジェクトのディレクトリを作る # (一つのスケッチごとに一つのディレクトリ) mkdir proj cd proj # ソースを置くディレクトリsrcを作る mkdir src # スケッチを作成する # (テスト用には以降に出てくるsrc/ASCIItable.inoを使用する) gedit src/xxxx.ino # 使うボードに対応したplatformio.iniを作る # (内容は以降に出てくるplatform.iniをそのままコピーする) gedit platformio.ini # スケッチをビルドする # (最初の1回はライブラリ・ツールを自動的にダウンロードする) pio run # ボードをUSB接続して書き込む pio run -t upload # USBシリアルを使っているスケッチならば # 以下のコマンドでシリアル接続して出力を表示させる bt # または picocom -b115200 /dev/ttyACM0 (または/dev/ttyUSB0)

その他の使い方

# build結果をクリアする pio run -t clean # キャッシュをクリアする # (ツールやライブラリがダウンロードし直しになるので注意のこと) sudo rm -r .pio # 環境を切り替えて書き込む pio run -e f303 -t upload pio run -e f103 -t upload

環境を切り替えて書き込む場合のplatformio.iniは
以下のように複数の環境[env:xxx]を持っていること:
platformio.ini

[env:f103] platform = ststm32 board = nucleo_f103rb framework = arduino build_flags = -DNUCLEO_F103RB monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps = [env:f303] platform = ststm32 board = nucleo_f303k8 framework = arduino build_flags = -DNUCLEO_F303K8 monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

[env:xxxx]のxxxxの部分は環境名にあたり、 ダブらない任意の名前であること。

テスト用スケッチ

src/ASCIItable.ino

/* ASCII table Prints out byte values in all possible formats: - as raw binary values - as ASCII-encoded decimal, hex, octal, and binary values For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII The circuit: No external hardware needed. created 2006 by Nicholas Zambetti <http://www.zambetti.com> modified 9 Apr 2012 by Tom Igoe This example code is in the public domain. http://www.arduino.cc/en/Tutorial/ASCIITable */ void setup() { //Initialize serial and wait for port to open: Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // prints title with ending line break Serial.println("ASCII Table ~ Character Map"); } // first visible ASCIIcharacter '!' is number 33: int thisByte = 33; // you can also write ASCII characters in single quotes. // for example, '!' is the same as 33, so you could also use this: // int thisByte = '!'; void loop() { // prints value unaltered, i.e. the raw binary version of the byte. // The Serial Monitor interprets all bytes as ASCII, so 33, the first number, // will show up as '!' Serial.write(thisByte); Serial.print(", dec: "); // prints value as string as an ASCII-encoded decimal (base 10). // Decimal is the default format for Serial.print() and Serial.println(), // so no modifier is needed: Serial.print(thisByte); // But you can declare the modifier for decimal if you want to. // this also works if you uncomment it: // Serial.print(thisByte, DEC); Serial.print(", hex: "); // prints value as string in hexadecimal (base 16): Serial.print(thisByte, HEX); Serial.print(", oct: "); // prints value as string in octal (base 8); Serial.print(thisByte, OCT); Serial.print(", bin: "); // prints value as string in binary (base 2) also prints ending line break: Serial.println(thisByte, BIN); // if printed last visible character '~' or 126, stop: if (thisByte == 126) { // you could also use if (thisByte == '~') { // This loop loops forever and does nothing while (true) { continue; } } // go on to the next character thisByte++; }

本スケッチはarduinoのサンプルそのもの(bpsのみ変更)である。

plaformio.ini

(1)platformio.iniの先頭にあたる以下はコメントにあたるので省略している:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html

(2)追加するライブラリがある場合は以下のように 「lib_dep= 」以降にライブラリのurlなどを追加する:

lib_deps = #https://github.com/arduino-libraries/NTPClient.git arduino-libraries/NTPClient@^3.1.0

(3)以下、各ボード用のplatformio.iniになる。

Arduino Uno

[env:uno] platform = atmelavr board = uno framework = arduino #build_flags = -Dxxxx upload_protocol = arduino monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

wio-temirnal

[env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = https://github.com/Seeed-Studio/Seeed_Arduino_mbedtls/archive/dev.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcUnified/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcBLE/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FreeRTOS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_SFUD/archive/master.zip # https://github.com/Seeed-Studio/Seeed_Arduino_LCD/archive/master.zip # 551 #https://github.com/arduino-libraries/NTPClient.git arduino-libraries/NTPClient@^3.1.0

XIAO

[env:seeed_xiao] platform = atmelsam board = seeed_xiao framework = arduino build_flags = -DXIAO upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = olikraus/U8g2 @ ^2.28.7

Feather M4

[env:adafruit_feather_m4] platform = atmelsam board = adafruit_feather_m4 framework = arduino build_flags = -DFEATHER_M4 upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

Grand Central M4

[env:adafruit_grandcentral_m4] platform = atmelsam board = adafruit_grandcentral_m4 framework = arduino build_flags = -DGRANDCENTRAL_M4 upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

M5Atom

[env:esp32dev] platform = espressif32 #board = esp32dev board = m5stick-c framework = arduino build_flags = -DM5ATOM monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # use M5Atom lib 3113 # use "FastLED" 126

M5StickC

[env:esp32dev] platform = espressif32 board = m5stick-c framework = arduino build_flags = -DM5STICK_C monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = m5stack/M5StickC @ ^0.2.0

リセット方法:
(1)「M5」と書かれたボタンを正面に見て左側にあるボタンを6秒長押して電源を切る。
(2)そのボタンを再度、2秒長押しをして電源を入れる。(リセットになる)



M5StickCPlus

[env:esp32dev] platform = espressif32 board = m5stick-c framework = arduino build_flags = -DM5STICK_CP monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = m5stack/M5StickCPlus @ ^0.0.1

リセット方法:
(1)「M5」と書かれたボタンを正面に見て左側にあるボタンを6秒長押して電源を切る。
(2)そのボタンを再度、2秒長押しをして電源を入れる。(リセットになる)



M5Stack Fire

[env:esp32dev] platform = espressif32 board = m5stack-fire framework = arduino build_flags = -DM5STACK_FIRE monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = m5stack/M5Stack https://github.com/lovyan03/LovyanGFX.git

Power on/off:
・Power on: click the red power button on the left
・Power off: Quickly double-click the red power button on the left



ESP32

[env:esp32dev] platform = espressif32 board = esp32dev framework = arduino build_flags = -DESP32 monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

ESP8266

[env:huzzah] platform = espressif8266 board = esp_wroom_02 framework = arduino build_flags = -DESP8266 monitor_speed = 115200 lib_ldf_mode = deep+ #lib_deps =

micro:bit

[env:bbcmicrobit] platform = nordicnrf51 board = bbcmicrobit framework = arduino build_flags = -DMICROBIT -DNRF51_S110 monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = cmsis-dap lib_deps = https://github.com/adafruit/Adafruit_BusIO/archive/master.zip https://github.com/sparkfun/SparkFun_MAG3110_Breakout_Board_Arduino_Library/archive/master.zip https://cdn-learn.adafruit.com/assets/assets/000/046/217/original/MMA8653.zip https://github.com/stm32duino/LSM303AGR/archive/master.zip https://github.com/adafruit/Adafruit-GFX-Library/archive/master.zip # https://github.com/sandeepmistry/arduino-BLEPeripheral/archive/master.zip https://github.com/adafruit/Adafruit_Microbit/archive/master.zip # https://github.com/ht-deko/microbit_Screen/archive/master.zip

Nucleo STM32F103RB

[env:nucleo_f103rb] platform = ststm32 board = nucleo_f103rb framework = arduino build_flags = -DNUCLEO_F103RB monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

Nucleo STM32F303K8

[env:nucleo_f303k8] platform = ststm32 board = nucleo_f303k8 framework = arduino build_flags = -DNUCLEO_F303K8 monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = stlink #lib_deps =

TeensyLC

[env:teensylc] platform = teensy board = teensylc framework = arduino #build_flags = -Dxxxx monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = teensy-cli #lib_deps =

Teensy3.6

[env:teensy36] platform = teensy board = teensy36 framework = arduino #build_flags = -Dxxxx monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = teensy-cli #lib_deps =

Teensy4.0

[env:teensy40] platform = teensy board = teensy40 framework = arduino #build_flags = -Dxxxx monitor_speed = 115200 lib_ldf_mode = deep+ upload_protocol = teensy-cli #lib_deps =

ビルド・エラー

Arduino-IDEのコンパイラと異なり、platformioのコンパイラは、関数定義の後方参照を許さないので、 この場合、関数の未定義エラーになる。したがって、Arduino-IDEでビルドできているソースでもエラーになることがある。このときの対応方法は、未定義エラーになる関数定義をプロトタイプ宣言としてソースの先頭に置き、後方参照を解消する。(関数定義の本体の位置はそのままで移動させる必要はない)

参考情報

M5Stack関連:
PlatformIO M5Stack開発の現状
・https://github.com/m5stack/M5StickC-Plus.git
・https://github.com/m5stack/M5StickC.git
・https://github.com/m5stack/M5Stack.git

micro:bit関連:
micro:bit Arduino/MBED開発ツール(v2)(micro:bit-v2対応,linux版)
micro:bit v2 で遊ぶ

platformio関連:

https://docs.platformio.org/en/latest/platforms/creating_board.html Installation 1.Create boards directory in core_dir if it doesn’t exist. 2.Create myboard.json file in this boards directory. 3.Search available boards via pio boards command. You should see myboard board.

PlatformIO Core (CLI)
Arduino-IDEとPlatformioのコンパイラーの挙動の違いについて
ubuntu20.04をインストールする

以上

» 続きを読む

| | コメント (0)

2021年2月18日 (木)

nixieクロックにNTPクライアントの機能を追加する(V2)

2021/2/18:
第2版

pio nixie NTP Client v2

pio nixie NTP Client v2

概要

以下のnixieクロックにNTPクライアントの機能を追加する(V2)

Wio nixie tube clock

本記事は「 nixieクロックにNTPクライアントの機能を追加する 」の第2版にあたる。 これは、wio-terminalのWiFiファームウェアのアップグレードに対する対応になる。(wio-terminalのファームウェア・アップデートについて(v2)(linux版))

NTPクライアントの機能を追加しているので、RTCのハードを追加する必要はない。 (ホストPCとしてはubuntuを想定している)

プロジェクト wiot-nixie-NTP のディレクトリを作成する

mkdir wiot-nixie-NTP cd wiot-nixie-NTP # 以下を実行して必要なファイルを作成する pio init --board seeed_wio_terminal # platformをupdateする pio platform update nano platformio.ini 以下にように編集する:
; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = https://github.com/Seeed-Studio/Seeed_Arduino_mbedtls/archive/dev.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcUnified/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcBLE/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FreeRTOS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_SFUD/archive/master.zip # https://github.com/Seeed-Studio/Seeed_Arduino_LCD/archive/master.zip # 551 #https://github.com/arduino-libraries/NTPClient.git arduino-libraries/NTPClient@^3.1.0

該当スケッチのダウンロード

cd wiot-nixie-NTP wget https://macsbug.files.wordpress.com/2020/05/wio_nixie_tube_clock.zip_-4.pdf mv wio_nixie_tube_clock.zip_-4.pdf wio_nixie_tube_clock.zip unzip wio_nixie_tube_clock.zip cp Wio_nixie_tube_clock/*.* src/

デモ・スケッチ

上でダウンロートしたスケッチにNTPクライアント機能を追加して以下のようなソースに編集する:

src/Wio_nixie_tube_clock_NTP.ino

// NTP Client part added on 2020/08/01 by xshige //#include <AtWiFi.h> #include <rpcWiFi.h> #include <NTPClient.h> #include <WiFiUdp.h> const char *ssid = "your_ssid"; const char *password = "your_passwd"; //<---------------------------------------------------------- // derived/forked from http://mrkk.ciao.jp/memorandom/unixtime/unixtime.html #define ARRAYSIZE(_arr) (sizeof(_arr) / sizeof(_arr[0])) #define TIME_OFFSET 0 #define SECONDS_IN_A_DAY (24*60*60) #define EPOCH_DAY (1969*365L + 1969/4 - 1969/100 + 1969/400 + 306) // days from 0000/03/01 to 1970/01/01 #define UNIX_EPOCH_DAY EPOCH_DAY #define YEAR_ONE 365 #define YEAR_FOUR (YEAR_ONE * 4 + 1) // it is YEAR_ONE*4+1 so the maximum reminder of day / YEAR_FOUR is YEAR_ONE * 4 and it occurs only on 2/29 #define YEAR_100 (YEAR_FOUR * 25 - 1) #define YEAR_400 (YEAR_100*4 + 1) // it is YEAR_100*4+1 so the maximum reminder of day / YEAR_400 is YEAR_100 * 4 and it occurs only on 2/29 void ConvertUnixTimeToLocalTime(uint64_t unixtime, uint32_t *pyear, uint8_t *pmonth, uint8_t *pday, uint8_t *phour, uint8_t *pminute, uint8_t *psecond) { uint32_t unixday; uint16_t year = 0; uint8_t leap = 0; uint32_t n; uint8_t month, day, weekday; uint8_t hour, minute, second; static const uint16_t monthday[] = { 0,31,61,92,122,153,184,214,245,275,306,337 }; unixtime += TIME_OFFSET; second = unixtime % 60; minute = (unixtime / 60) % 60; hour = (unixtime / 3600) % 24; unixday = (uint32_t)(unixtime / SECONDS_IN_A_DAY); weekday = (uint8_t)((unixday + 3) % 7); // because the unix epoch day is thursday unixday += UNIX_EPOCH_DAY; // days from 0000/03/01 to 1970/01/01 year += 400 * (unixday / YEAR_400); unixday %= YEAR_400; n = unixday / YEAR_100; year += n * 100; unixday %= YEAR_100; if (n == 4){ leap = 1; } else { year += 4 * (unixday / YEAR_FOUR); unixday %= YEAR_FOUR; n = unixday / YEAR_ONE; year += n; unixday %= YEAR_ONE; if (n == 4) { leap = 1; } } if (leap != 0) { month = 2; day = 29; } else { month = (unixday * 5 + 2) / 153; day = unixday - monthday[month] + 1; // month += 3; if (month > 12) { ++year; month -= 12; } } *psecond = second; *pminute = minute; *phour = hour; *pyear = year; *pmonth = month; *pday = day; } //>---------------------------------------------------------- char *weekday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; uint32_t year; uint8_t month, day, hour, minu, sec; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "ntp.nict.jp", 3600*9, 60000); // set JST // You can specify the time server pool and the offset, (in seconds) // additionaly you can specify the update interval (in milliseconds). // NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); //================================================================ // added NTP Client feature: 2020.08.01 xshige // Woi Terminal nixie tube clock : 2020.05.25 macsbug // https://macsbug.wordpress.com/2020/05/25/wio-nixie-tube-clock/ // M5Stack nixie tube clock : 2019.06.16 macsbug // https://macsbug.wordpress.com/2019/06/16/m5stack-nixie-tube-clock/ // M5StickC Nixie tube Clock : 2019.06.06 macsbug // https://macsbug.wordpress.com/2019/06/06/m5stickc-nixie-tube-clock/ // RTC DS3231 : https://wiki.52pi.com/index.php/Raspberry_Pi_Super_Capacitor_RTC(English) // RTClib : https://www.arduinolibraries.info/libraries/rt-clib // mode controll : 5 way switch // mode 1 : yyyy_mmdd_hhmmss // mode 2 : mmdd_hh_mmss // mode 3 : mmdd_ss_hhmm // rtc : DS3231, SDA1 = 2, SCL1= 3; #include <SPI.h> #include <TFT_eSPI.h> TFT_eSPI tft = TFT_eSPI(); #include <Wire.h> //#include "RTClib.h" //RTC_DS3231 rtc; #include "vfd_18x34.c" // font 18px34 #include "vfd_35x67.c" // font 35x67 #include "vfd_70x134.c" // font 70px134 #include "apple_35x41.c" // icon 35px41 uint32_t targetTime = 0; // for next 1 second timeout const uint8_t*n[] = { // vfd font 18x34 vfd_18x34_0,vfd_18x34_1,vfd_18x34_2,vfd_18x34_3,vfd_18x34_4, vfd_18x34_5,vfd_18x34_6,vfd_18x34_7,vfd_18x34_8,vfd_18x34_9 }; const uint8_t*m[] = { // vfd font 35x67 vfd_35x67_0,vfd_35x67_1,vfd_35x67_2,vfd_35x67_3,vfd_35x67_4, vfd_35x67_5,vfd_35x67_6,vfd_35x67_7,vfd_35x67_8,vfd_35x67_9, vfd_35x67_q,vfd_35x67_n }; const uint8_t*b[] = { // vfd font 70x134 vfd_70x134_0,vfd_70x134_1,vfd_70x134_2,vfd_70x134_3,vfd_70x134_4, vfd_70x134_5,vfd_70x134_6,vfd_70x134_7,vfd_70x134_8,vfd_70x134_9, vfd_70x134_q,vfd_70x134_n }; const char *monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; uint16_t yy; uint8_t mn, dd, hh, mm, ss; uint8_t md = 2; // mode 1, 2, 3 void setup() { // Serial.begin(115200); WiFi.begin(ssid, password); while ( WiFi.status() != WL_CONNECTED ) { delay ( 500 ); Serial.print ( "." ); } timeClient.begin(); //--------------------- tft.init(); tft.setRotation(3); tft.fillScreen(TFT_BLACK); pinMode(WIO_5S_PRESS, INPUT_PULLUP); /**** Wire.begin(SDA1,SCL1); delay(10); rtc.begin(); rtc.adjust(DateTime(__DATE__, __TIME__)); // Set the PC time // esp_timer_init(); // wifi_setup(); rtc_setup(); // Read the value of RTC ****/ } void loop() { timeClient.update(); // if (targetTime < esp_timer_get_time()/1000 ){ // display current clock on serial port ConvertUnixTimeToLocalTime(timeClient.getEpochTime(), &year, &month, &day, &hour, &minu, &sec); Serial.printf("%4d/%02d/%02d(%s): %02d:%02d:%02d\r\n", year, month, day, weekday[timeClient.getDay()], hour, minu, sec); /**** DateTime now = rtc.now(); yy = now.year(); mn = now.month(); dd = now.day(); hh = now.hour(); mm = now.minute(); ss = now.second(); ****/ yy = year; mn = month; dd = day; hh = hour; mm = minu; ss = sec; if(digitalRead(WIO_5S_PRESS) == LOW){ // mode change if (md == 3){md = 1;tft.fillRect(1,1,317,236,TFT_BLACK);return;} if (md == 2){md = 3;tft.fillRect(1,1,317,236,TFT_BLACK);return;} if (md == 1){md = 2;tft.fillRect(1,1,317,236,TFT_BLACK);return;} } if ( md == 3 ){ hhmm();} // yyyy,mm,dd,ss,hh,mm if ( md == 2 ){ yyyy_mmdd_hhmmss();} // yyyy,mm,dd,hh,mm,ss if ( md == 1 ){ mmss();} // mm,ss // periodic_ntp(); delay(500); } /**** void rtc_setup(){ DateTime now = rtc.now(); // time geting from RTC if (now.year() == 2165){ // rtc check tft.setCursor(20,200);tft.setTextColor(TFT_RED); tft.print("RTC not installed");delay(2000); tft.fillRect(1, 1, 317, 236, TFT_BLACK); }else{ yy = now.year(); mn = now.month(); dd = now.day(); hh = now.hour(); mm = now.minute(); ss = now.second(); //Serial.printf("%d %d %d %d %d %d\n",yy,mn,dd,hh,mm,ss); tft.setCursor(20,200);tft.setTextColor(TFT_BLUE); tft.print("SET UP RTC");delay(2000); tft.fillRect(1, 1, 317, 236, TFT_BLACK); } } ****/ void yyyy_mmdd_hhmmss(){ int y1 = (yy / 1000) % 10; int y2 = (yy / 100) % 10; int y3 = (yy / 10) % 10; int y4 = yy % 10; int ma = (mn / 10) % 10; int mb = mn % 10; int d1 = (dd / 10) % 10; int d2 = dd % 10; int h1 = (hh / 10) % 10; int h2 = hh % 10; int m1 = (mm / 10) % 10; int m2 = mm % 10; int s1 = (ss / 10) % 10; int s2 = ss % 10; //int p0 = 8; int x0 = 40; int t0 = 22; // icon //tft.pushImage( p0 + 0*x0, t0, 35,41, (uint16_t *)apple_35x41); int p1 = 80; int px1 = 40; int py1 = 5; tft.pushImage( p1 + 0*px1, py1, 35,67, (uint16_t *)m[y1]); tft.pushImage( p1 + 1*px1, py1, 35,67, (uint16_t *)m[y2]); tft.pushImage( p1 + 2*px1, py1, 35,67, (uint16_t *)m[y3]); tft.pushImage( p1 + 3*px1, py1, 35,67, (uint16_t *)m[y4]); int p2 = 80; int px2 = 40; int py2 = 76; tft.pushImage( p2 + 0*px2, py2, 35,67, (uint16_t *)m[ma]); tft.pushImage( p2 + 1*px2, py2, 35,67, (uint16_t *)m[mb]); //tft.drawPixel(118,13, ORANGE); tft.drawPixel(119,23,ORANGE); tft.pushImage( p2 + 2*px2, py2, 35,67, (uint16_t *)m[d1]); tft.pushImage( p2 + 3*px2, py2, 35,67, (uint16_t *)m[d2]); int p3 = 2; int px3 = 40; int py3 = 150; tft.pushImage( p3 + 0*px3, py3, 35,67, (uint16_t *)m[h1]); tft.pushImage( p3 + 1*px3, py3, 35,67, (uint16_t *)m[h2]); tft.pushImage( p3 + 2*px3, py3, 35,67, (uint16_t *)m[10]); tft.pushImage( p3 + 3*px3, py3, 35,67, (uint16_t *)m[m1]); tft.pushImage( p3 + 4*px3, py3, 35,67, (uint16_t *)m[m2]); tft.pushImage( p3 + 5*px3, py3, 35,67, (uint16_t *)m[10]); tft.pushImage( p3 + 6*px3, py3, 35,67, (uint16_t *)m[s1]); tft.pushImage( p3 + 7*px3, py3, 35,67, (uint16_t *)m[s2]); if ( s1 == 0 && s2 == 0 ){ fade1();} } void mmss(){ int ma = (mn / 10) % 10; int mb = mn % 10; int d1 = (dd / 10) % 10; int d2 = dd % 10; int h1 = (hh / 10) % 10; int h2 = hh % 10; int m1 = (mm / 10) % 10; int m2 = mm % 10; int s1 = (ss / 10) % 10; int s2 = ss % 10; int p0 = 8; int x0 = 40; int t0 = 22; // icon tft.pushImage( p0 + 0*x0, t0, 35,41, (uint16_t *)apple_35x41); int p2 = 65; int px2 = 40; int py2 = 10; tft.pushImage( p2 + 0*px2, py2, 35,67, (uint16_t *)m[ma]); tft.pushImage( p2 + 1*px2, py2, 35,67, (uint16_t *)m[mb]); //tft.drawPixel(118,13, ORANGE); tft.drawPixel(119,23,ORANGE); tft.pushImage( p2 + 2*px2, py2, 35,67, (uint16_t *)m[d1]); tft.pushImage( p2 + 3*px2, py2, 35,67, (uint16_t *)m[d2]); int p3 = 240; int px3 = 40; int py3 = 10; tft.pushImage( p3 + 0*px3, py3, 35,67, (uint16_t *)m[h1]); tft.pushImage( p3 + 1*px3, py3, 35,67, (uint16_t *)m[h2]); int p4 = 2; int px4 = 80; int py4 = 100; tft.pushImage( p4 + 0*px4 , py4, 70,134, (uint16_t *)b[m1]); tft.pushImage( p4 + 1*px4 -4, py4, 70,134, (uint16_t *)b[m2]); //tft.drawPixel(155,150, ORANGE); tft.drawPixel(155,190,ORANGE); tft.fillCircle(156,151,3,TFT_ORANGE);tft.fillCircle(156,191,3,TFT_ORANGE); tft.fillCircle(156,151,1,TFT_YELLOW);tft.fillCircle(156,191,1,TFT_YELLOW); tft.pushImage( p4 + 2*px4 +4, py4, 70,134, (uint16_t *)b[s1]); tft.pushImage( p4 + 3*px4 , py4, 70,134, (uint16_t *)b[s2]); if ( m1 == 0 && m2 == 0 ){ fade2();} } void hhmm(){ int ma = (mn / 10) % 10; int mb = mn % 10; int d1 = (dd / 10) % 10; int d2 = dd % 10; int h1 = (hh / 10) % 10; int h2 = hh % 10; int m1 = (mm / 10) % 10; int m2 = mm % 10; int s1 = (ss / 10) % 10; int s2 = ss % 10; //int p0 = 8; int x0 = 40; int t0 = 22; // icon //tft.pushImage( p0 + 0*x0, t0, 35,41, (uint16_t *)apple_35x41); int p2 = 65; int px2 = 40; int py2 = 10; tft.pushImage( p2 + 0*px2, py2, 35,67, (uint16_t *)m[ma]); tft.pushImage( p2 + 1*px2, py2, 35,67, (uint16_t *)m[mb]); //tft.drawPixel(118,13, ORANGE); tft.drawPixel(119,23,ORANGE); tft.pushImage( p2 + 2*px2, py2, 35,67, (uint16_t *)m[d1]); tft.pushImage( p2 + 3*px2, py2, 35,67, (uint16_t *)m[d2]); int p3 = 240; int px3 = 40; int py3 = 10; tft.pushImage( p3 + 0*px3, py3, 35,67, (uint16_t *)m[s1]); tft.pushImage( p3 + 1*px3, py3, 35,67, (uint16_t *)m[s2]); int p4 = 2; int px4 = 80; int py4 = 100; tft.pushImage( p4 + 0*px4 , py4, 70,134, (uint16_t *)b[h1]); tft.pushImage( p4 + 1*px4 -4, py4, 70,134, (uint16_t *)b[h2]); //tft.drawPixel( 155,150, ORANGE); tft.drawPixel(155,190,ORANGE); tft.fillCircle(156,151,3,TFT_ORANGE);tft.fillCircle(156,191,3,TFT_ORANGE); tft.fillCircle(156,151,1,TFT_YELLOW);tft.fillCircle(156,191,1,TFT_YELLOW); tft.pushImage( p4 + 2*px4 +4, py4, 70,134, (uint16_t *)b[m1]); tft.pushImage( p4 + 3*px4 , py4, 70,134, (uint16_t *)b[m2]); if ( h1 == 0 && h2 == 0 ){ fade2();} } void fade1(){ int p3 = 2; int px3 = 40; int py3 = 150; for ( int i = 0; i < 2; i++ ){ tft.pushImage( p3 + 2*px3, py3, 35,67, (uint16_t *)m[11]); tft.pushImage( p3 + 5*px3, py3, 35,67, (uint16_t *)m[11]); delay(25); tft.pushImage( p3 + 2*px3, py3, 35,67, (uint16_t *)m[10]); tft.pushImage( p3 + 5*px3, py3, 35,67, (uint16_t *)m[10]); delay(25); } } void fade2(){ int p3 = 2; int px3 = 40; int py3 = 150; for ( int i = 0; i < 2; i++ ){ tft.fillCircle(156,151,3,TFT_BLACK);tft.fillCircle(156,191,3,TFT_BLACK); delay(25); tft.fillCircle(156,151,3,TFT_ORANGE);tft.fillCircle(156,191,3,TFT_ORANGE); delay(25); } }

以下の変更がWiFiファームウェア・アップグレードの対応にあたる:

//#include <AtWiFi.h> #include <rpcWiFi.h>

以下については、自分の環境に合わせて変更すること:

const char *ssid = "your_ssid"; const char *password = "your_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 Terminal ready 2020/08/01(Sat): 22:44:44 2020/08/01(Sat): 22:44:44 2020/08/01(Sat): 22:44:45 2020/08/01(Sat): 22:44:46 2020/08/01(Sat): 22:44:46 2020/08/01(Sat): 22:44:47 2020/08/01(Sat): 22:44:48 2020/08/01(Sat): 22:44:48 2020/08/01(Sat): 22:44:49 2020/08/01(Sat): 22:44:49 2020/08/01(Sat): 22:44:50 2020/08/01(Sat): 22:44:50 2020/08/01(Sat): 22:44:51 2020/08/01(Sat): 22:44:51 2020/08/01(Sat): 22:44:52 2020/08/01(Sat): 22:44:53 2020/08/01(Sat): 22:44:53 2020/08/01(Sat): 22:44:54

また、起動後、ニキシー管の時計が表示され、ボタンで表示画面を切り換えられる。

参考情報

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(NTP-CLIENT編)

PlatformIO Core (CLI)

以上

» 続きを読む

| | コメント (0)

«PicoボードのMicroPythonをVS_CodeのextensionのPico-Goでプログラミングする