Longan Nanoの開発環境をLinux環境にインストール

秋月にLongan Nanoというボードが入荷していたので買ってきました。簡単に言うと、俗に(かな?)BluePillというSTM32F103C8が載った格安のボード(AliExpressで2ドル以下)がありますが、このボードのCPUをGD32VF103というGigaDeviceという会社のRISC-Vチップに置き換えて、小型のカラーIPS液晶(見た目の雰囲気はOLEDっぽいのですが???)と(写真にはありませんが)MicroSDスロットを追加した感じの仕様のものです。USBのコネクタは今時らしくType-Cになっています。
そして、嬉しいことに、これだけの仕様で秋月で830円という激安価格で売っています。

で、写真は公式サイトにあるBadAppleのデモを動かしたものです。(残念ながら、Linux環境ではDFUでのダウンロードがうまく行かず、こちらの記事に従ってWindows環境でファーム書き込みしました)

引き続き、開発環境を構築してみます。環境はいつものLinuxMintです。

公式サイトの製品Wikiによると、longan nanoの開発はPlatformIO IDEで行います。

ここでは公式サイト内のGETTING STARTEDにある手順に沿って開発環境を整えてみます。

幸い、以前、PlatformIOは試してみているので、VScodeのインストールや、PlatformIO(PIOと略されている)のインストールは省いて、GD32Vのplatformの定義のインストールから行います。作業は現時点ではコマンドラインとGUIと両方必要なようです。

一番左のPlatformIOのロゴ(宇宙人みたいなやつ)をクリックして表示されるQUICK ACCRESSの中の「New Terminal」をクリックします。
すると、新しいターミナルのペインが開くので、そこで。

$ platformio platform install gd32v

と入力してインストールします。

$ platformio platform install gd32v
PlatformManager: Installing gd32v
gd32v @ 1.1.0 has been successfully installed!
PackageManager: Installing toolchain-gd32v @ ~9.2.0
Downloading [####################################] 100% 
Unpacking [####################################] 100% 
toolchain-gd32v @ 9.2.0 has been successfully installed!
The platform 'gd32v' has been successfully installed!
The rest of packages will be installed automatically depending on your build environment.

完了したら、GUIでの作業です。

QUICK ACCRESSの中の「Open」をクリックします。
次にPIO HomeタブのPlatformsをクリック、開いたページの中の「Advanced Installation」をクリック、

開いたダイアログで

https://github.com/sipeed/platform-gd32v.git

を入力してインストールをクリックします。

こんな感じになれば成功です。

あと、USBデバイスとして認識できるようにしておきます。

$ 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 nano /etc/udev/rules.d/99-gigadevice-udev.rules

として、udevのルールを用意します。1つ目はPlatformIOの推奨のファイルをダウンロードしてきます。2つ目はGigaDevice GD32VF103用の内容を用意します。(PlatformIOには存在しないため)

# Longan Nano
ATTRS{idVendor}=="28e9", ATTRS{idProduct}=="0189", MODE="0666"

作成したら、認識させておきます。

$ sudo udevadm control --reload-rules
$ sudo udevadm trigger

つづく

GitHubを使ってみた

これまでソースコードは自宅内サーバ上に保管していたのですが、いつもぐちゃぐちゃでわけがわからなくなっているので、GitHubのプライベートリポジトリを利用してみることにしました。

公式のチュートリアルで理解できたことは以下の通り。

1.リポジトリを作る。masterブランチが神様

統合開発環境で最初にプロジェクトを作る、というのとほぼ同じ意味だろうか。
これまで「masterってなんだろう?」と思いながら git clone していたのが理解できた。

2.一時的なブランチを作る

一時的に改変して試す環境を作る、くらいの感じだろうか。ブランチを選択するドロップダウンメニュー(のようなもの)にある「Switch branches/tags」に新しいブランチの名称を入れる。

3.作成したブランチを編集してデバッグなどを行う

チュートリアルではブラウザ上で編集できるファイルを編集しているので、ローカルで編集・デバッグする必要のあるファイルの操作方法は別途調べないといけない。
編集したら、commt changesで改変内容を commit する。

4.Pull Requestを作成する

たぶん、「masterブランチにとりこんでね!」という要求。チュートリアルだとどちらも自分なのでわかりにくい概念だけど。

5.(masterブランチ宛ての)Pull Requestをマージする

Merge pull request ボタンを押して、変更点をmasterブランチに取り込む

6.一時的なブランチを削除する

 

こんな感じかな??

pyftdiでI2C通信

pyftdiでI2Cデバイスをつなげてみました。

接続したデバイスは昔秋月で買ったLPS331使用の大気圧センサモジュールです。

回路はこんな感じ。

右側のがLPS331使用の大気圧センサモジュール。真ん中のLEDは使用していません。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from os import environ
import sys
from pyftdi.i2c import I2cController
from time import sleep

class LPS331(object):
    """
    """

    def __init__(self):
        self._i2c = I2cController()

    def open(self):
        url = environ.get('FTDI_DEVICE', 'ftdi://ftdi:232h/1')
        self._i2c.configure(url,frequency=400000)
        self._port = self._i2c.get_port(0x5c)

    def close(self):
        pass

    def init(self):
        port = self._port
        port.write([0x10,0x6A])		# Pres Average 512 / Temp Average 64
        port.write([0x20,0xF4])		# ODR=25Hz、BDU=1
    
    def read(self):
        port = self._port
        out1 = port.exchange([0x08],1)
        out2 = port.exchange([0x09],1)
        out3 = port.exchange([0x0a],1)
        refp = (out1[0] + out2[0]*256 + out3[0]*65536)/4096.0
        out1 = port.exchange([0x28],1)
        out2 = port.exchange([0x29],1)
        out3 = port.exchange([0x2a],1)
        pres = (out1[0] + out2[0]*256 + out3[0]*65536)/4096.0
        out1 = port.exchange([0x2b],1)
        out2 = port.exchange([0x2c],1)
        out = (out1[0] + out2[0]*256) 
        if out >= 0x8000 : out -= 0x10000
        temp = 42.5 + out/480.0
        return(refp,pres,temp)
        
if __name__ == '__main__':
    lps331 = LPS331()
    lps331.open()
    lps331.init()
    while True:
        (refp,pres,temp) = lps331.read()
        print(refp,pres,temp)
        sleep(1)

実行すると

$ python ftdi-lps331.py 
0.0 1012.830078125 27.485416666666666
0.0 1012.68212890625 27.504166666666666
0.0 1012.84716796875 27.525
0.0 1012.838134765625 27.508333333333333
0.0 1012.654296875 27.541666666666664
0.0 1012.570556640625 27.53125

という感じで気圧と気温を取得できました。

これでデスクトップPCでもI2Cデバイスの評価などができて便利そうです。

pyftdiでLチカ

gpio.pyをベースにpyftdiでLチカしてみました。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from os import environ
import sys
from pyftdi.gpio import GpioController, GpioException
from time import sleep

class GpioTest(object):
    """
    """

    def __init__(self):
        self._gpio = GpioController()
        self._state = 0  # SW cache of the GPIO output lines

    def open(self, out_pins):
        """Open a GPIO connection, defining which pins are configured as
           output and input"""
        out_pins &= 0xFF
        url = environ.get('FTDI_DEVICE', 'ftdi://ftdi:232h/1')
        self._gpio.open_from_url(url, direction=out_pins)

    def close(self):
        """Close the GPIO connection"""
        self._gpio.close()

    def set_gpio(self, line, on):
        """Set the level of a GPIO ouput pin.

           :param line: specify which GPIO to madify.
           :param on: a boolean value, True for high-level, False for low-level
        """
        if on:
            state = self._state | (1 << line)
        else:
            state = self._state & ~(1 << line)
        self._commit_state(state)

    def get_gpio(self, line):
        """Retrieve the level of a GPIO input pin

           :param line: specify which GPIO to read out.
           :return: True for high-level, False for low-level
        """
        value = self._gpio.read_port()
        return bool(value & (1 << line))

    def _commit_state(self, state):
        """Update GPIO outputs
        """
        self._gpio.write_port(state)
        # do not update cache on error
        self._state = state


if __name__ == '__main__':
    gpio = GpioTest()
    mask = 0x80  # AD7=Out
    gpio.open(mask)
    while True:
        gpio.set_gpio(7, True)
        sleep(0.2)
        gpio.set_gpio(7, False)
        sleep(0.2)

pyftdiをテスト

pyftdiを動かしてみました。環境はいつもの LinuxMint19 64bit です。

pyftdiのインストール

まずは、インストールドキュメントをベースに進めます。

$ sudo apt-get install libusb-1.0

引き続き、/etc/udev/rules.d/11-ftdi.rules に udev ルールを追加します。

# /etc/udev/rules.d/11-ftdi.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6011", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", GROUP="plugdev", MODE="0666"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6015", GROUP="plugdev", MODE="0666"

以下の内容を実行して再認識させます・・・が、再認識したのかどうかよくわからなかったので、USBケーブルを抜き差ししました。

$ sudo udevadm control --reload-rules
$ sudo udevadm trigger

pyftdiを使うため、以下のコマンドを実行します。

$ sudo adduser $USER plugdev

・・・が、すでに、plugdevのメンバーになっている旨、表示されました。

テスト用環境の構築

以下のようにして Python3 の仮想環境を作ります。

$ mkdir ~/python3
$ cd ~/python3
$ sudo apt-get install python3-venv
$ python3 -m venv pyftdi-test
$ cd pyftdi-test
$ source ./bin/activate
(pyftdi-test) $ python -V
Python 3.6.8
(pyftdi-test) $ pip install --upgrade pip
(pyftdi-test) $ pip install pyusb pyserial pyftdi

GPIOテストの実施

テスト用のスクリプトがあったのでダウンロードしてきます。

$ wget https://github.com/eblot/pyftdi/raw/master/pyftdi/tests/gpio.py

107-108行目の以下の部分をコメントアウトします。
(コメントアウトしないと、ここで必ずテストエラーになるような気がするのですが??)

        else:
            self.assertTrue(bool((1 << gp) & mask))

で、

$ python gpio.y

としてテストを実行すると、AD7に接続したLEDが消灯⇒点灯しました。

UM232Hモジュール

PythonでFTDIのチップをUSB経由で制御するpyftdiというモジュールを見かけました。ドキュメントをみると、UARTだけではなく、GPIO、SPI(master)、I2C(master)、JTAG(master)としても動作しそうな感じです。

そこで、随分昔から積みボードになっていたUM232Hというモジュールで動かそうとしたところ、PWRのLEDすら点灯しません。dmesgを見ても、なんのログもでていません。USBケーブルを変えても、PCからRaspberry Piに変えても状況は同じです。これは使い物にならん、と捨てようかと思っていたところ・・・・、資料が見つかりました。(もっと早く見つけろよ^^;)

これをパラパラっと眺めていたところ、

という感じで、TXD/RXD、RTS/CTSの他に何やら配線が・・・しかも、電源っぽいのが・・・必要そうです。

さっそく、この通りに接続してみると、

[  507.979206] usb 1-1.5: new high-speed USB device number 5 using dwc_otg
[  508.112740] usb 1-1.5: New USB device found, idVendor=0403, idProduct=6014, bcdDevice= 9.00
[  508.112779] usb 1-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  508.112792] usb 1-1.5: Product: UM232H
[  508.112803] usb 1-1.5: Manufacturer: FTDI
[  508.112814] usb 1-1.5: SerialNumber: FTUBIAT4
[  508.183601] usbcore: registered new interface driver usbserial_generic
[  508.183714] usbserial: USB Serial support registered for generic
[  508.201021] usbcore: registered new interface driver ftdi_sio
[  508.201150] usbserial: USB Serial support registered for FTDI USB Serial Device
[  508.201531] ftdi_sio 1-1.5:1.0: FTDI USB Serial Device converter detected
[  508.201771] usb 1-1.5: Detected FT232H
[  508.203415] usb 1-1.5: FTDI USB Serial Device converter now attached to ttyUSB0

という感じで、無事に検出してくれました。

無事にLEDも点灯しています。

参考:データシート(DS_UM232H

台風19号

BME280+ESP32でAmbientに上げているデータによると、21:24頃の965.6hPaが気圧の底のようです。970hPaを切ったあたりからの風はものすごかった・・・。

その後、急速に気圧は回復してきていますが、雨の被害が大きくなってきているようで心配です。風は収まってきたかと思ったのですが、吹返しの風が吹き始めてきました。

約二日間の気圧変化の推移。

CO2センサをポチってみた

最近、眠気とCO2の濃度に関係があるというのを読んでCO2センサを物色しています。少し前までは少し大きめのセンサでそこそこ値段も張っていたのですが、最近はCCS811というMEMSタイプのセンサがでてきているようで、価格もこなれてきました。

そこで、CCS811について(いつもの)Aliexpressで物色して、ポチってみました。CCS811を搭載した基板は何種類かあるようなのですが、SI7021という湿度センサとBMP280(温湿度+気圧センサのBME280の湿度なしバージョン)を一緒に載せたもの、HD1080という温湿度センサを一緒に搭載したものがあるようです。もちろん、CCS811単品のものが一番安いです。

で、せっかくならCO2(の他にTVOCもCCS811は測定できます)だけではなく、温湿度・気圧も測れれば・・・と思ったのですが、意外に気になるのは温度は自己発熱の影響を受けることです。

で、ドキュメントを調べてみると、CCS811は内部にヒーターを持っているため結構消費電力が大きく、Idle Modeでは0.034mW@Vdd=1.8Vなのですが、1秒に1回測定するモードでは46mW、10秒に1回では7mW、60秒に1回では1.2mWの電力を消費します(Vdd=1.8V時)。

また、ENV_DATAレジスタというのがあり、温度・湿度を設定すると、それに応じて測定値を補正する機能があるようです。(スイッチサイエンスなどのサイトでは、オプションでNTCサーミスタでの温度補正ができるように書いてあるところがありますが、製品変更通知CN25-2017でサポートされない旨、記載されています)

したがって、一緒に搭載されている温湿度センサーは、CCS811の補正用ということだと思われます。補正用の温湿度センサーがない場合には、デフォルト値の25℃50%を前提にして動作するものと思われます。

データシート上の書き方としては「外部の温湿度センサが利用できる場合には補正に利用できる」という表現になっていますので、今回はCCS811が単独で載っているものをポチってみました。

BluePillボードへの書き込みアダプタ

少し前に試してみたSTM32F103C8にArduinoのスケッチを書き込む話ですが、USBだけ使いたいというケースがでてきたため、ヘッダピンを半田付けせずに書き込みができるような治具を作ってみました。

端子との接続はインサーキットテスタ用のテストピンを3Dプリンタで作ったホルダーに挿入して、基板にはんだ付けしたものを使っています。ピンの内部にバネが入っていて、端子が伸縮するので接触性は良好です。

実際に使う際には下の写真のようにランドに押し付けて接触させておいて、USBシリアル基板にUSBケーブルを接続します。しばらく押し付けたままにしておく必要があるのですが、基板を大きくせず(=端子を半田付けせず)に書き込みができるようになりました。

redisを触ってみた

key value型のデータベースとしてよく使われているらしいredisをちょっとだけ触ってみた。

ちょっとだけなので、dockerで動かしてみる。

~/docker$ mkdir redis
~/docker$ cd redis/
~/docker/redis$ docker run --name redis -d -p 6379:6379 redis redis-server --appendonly yes  
~/docker/redis$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
755385f9518d        redis               "docker-entrypoint.s…"   11 seconds ago      Up 8 seconds        0.0.0.0:6379->6379/tcp   redis
~/docker/redis$ docker exec -it redis /bin/sh
# redis-cli
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> set ABCDE 12345
OK
127.0.0.1:6379[1]> get ABCDE
"12345"
127.0.0.1:6379[1]> get CDEFG
(nil)
127.0.0.1:6379[1]> keys *
1) "ABCDE"
127.0.0.1:6379[1]> lpush LST 1
(integer) 1
127.0.0.1:6379[1]> lpush LST 2
(integer) 2
127.0.0.1:6379[1]> lpush LST 3
(integer) 3
127.0.0.1:6379[1]> lpush LST 4
(integer) 4
127.0.0.1:6379[1]> llen LST
(integer) 4
127.0.0.1:6379[1]> lrange LST 0 4
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379[1]> 

なるほど、簡単そうだ。