Teensy4.0

2020年4月25日 (土)

Grove-OLED-i2cにFramebufferモジュールを使ってイメージを表示する

2020/4/25+

MCP2221A adafruit_blinka Framebuffer Image

MCP2221A adafruit_blinka Framebuffer Image

概要

MCP2221Aボードで以下のGrove-OLED-i2cにFramebufferモジュールを使ってイメージを表示する. 本記事は「Grove-OLED-i2cをFramebufferモジュールで機能拡張する」の続きになる。

Grove - OLED Display 1.12"

本ボードは、ボードのバージョンによって、解像度が96x96または128x128であり、それぞれでコントローラも異なる。 入手したボードは、v1.1で解像度は128x128でコントローラはSH1107Gであった。(Vdd:3.3V/5V両用対応)

接続

MCP2221Aボードのi2cに本件のOLEDを接続する。(Vdd=3.3V)

該当モジュールのインストール

cd ~/mcp2221a_ws # 仮想環境に切り替える source blinka/bin/activate # sh1107g_cpy.pyをダウンロードする wget https://beta-notes.way-nifty.com/blog/files/sh1107g_cpy.py # adafruit_framebufをインストールする pip3 install adafruit-circuitpython-framebuf # framebufで使用するフォントをダウンロードする wget https://github.com/adafruit/Adafruit_CircuitPython_framebuf/blob/master/examples/font5x8.bin # python3のimageライブラリーをインストールする pip3 install Pillow # adafruit_imageloadモジュールをダウンロードする(CircuitPython用) git clone https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad.git cp -r Adafruit_CircuitPython_ImageLoad/adafruit_imageload . # テスト用画像をダウンロードする(これは任意の画像で良い) wget https://upload.wikimedia.org/wikipedia/en/5/58/Blinka.png

テスト用画像をビットマップ画像に変換する

以下のスクリプトを実行してテスト用ビットマップ画像を作る:
mk_b1image.py

#!/usr/bin/python3 from PIL import Image im = Image.open('Blinka.png') resized_im = im.resize((128,128)) gray_im = resized_im.convert("L") # 以下の「x < 90」の「90」の画像によって調整すること tmp_im = gray_im.point(lambda x: 0 if x < 90 else 255) b1_im = tmp_im.convert('1') b1_im.save('blinka_b1.bmp') # inverted image # 以下の「x < 90」の「90」の画像によって調整すること tmp_im = gray_im.point(lambda x: 255 if x < 90 else 0) inv_b1_im = tmp_im.convert('1') inv_b1_im.save('blinka_inv_b1.bmp')

これにより以下の2つのファイルが作られる。
blinka_b1.bmp
blinka_inv_b1.bmp

デモ・スクリプト(python3/circuitpython兼用)

test_fb1_sh1107g.py

#CIRCUITPY = True CIRCUITPY = False # import image related module if CIRCUITPY: import displayio import adafruit_imageload else: from PIL import Image # for CircuitPython/blinka import time import busio import board i2c = busio.I2C(board.SCL, board.SDA) i2c.try_lock() from sh1107g_cpy import SH1107G oled = SH1107G(i2c) oled.clear() #----------------------------- # framebuffer related import adafruit_framebuf # pixel size for display WIDTH = 128 HEIGHT = 128 fbuf = bytearray(round(WIDTH * HEIGHT / 8)) fb = adafruit_framebuf.FrameBuffer(fbuf, WIDTH, HEIGHT, buf_format=adafruit_framebuf.MVLSB) #------------------------------ # write image into framebuffer def fb_image(fb,img): # Iterate through the pixels for x in range(img.width): for y in range(img.height): if img.getpixel((x, y)): fb.pixel(x, y, 1) else: fb.pixel(x, y, 0) # for circuitpython def fb_image_cpy(fb,img): # Iterate through the pixels for x in range(img.width): for y in range(img.height): if img[x, y]: fb.pixel(x, y, 1) else: fb.pixel(x, y, 0) # (for debug) Ascii printer for very small framebufs! def print_buffer(the_fb): print("." * (the_fb.width+2)) for y in range(the_fb.height): print(".", end='') for x in range(the_fb.width): if fb.pixel(x, y): print("*", end='') else: print(" ", end='') print(".") print("." * (the_fb.width+2)) # clear framebuffer def clear_fbuf(): for i, _ in enumerate(fbuf): fbuf[i] = 0 #---------------------------------- print("image test1: ") clear_fbuf() if CIRCUITPY: im, pal = adafruit_imageload.load( "blinka_b1.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette) fb_image_cpy(fb, im) else: im = Image.open('blinka_b1.bmp') im.show() fb_image(fb, im) # show display oled.draw(fbuf, len(fbuf)) time.sleep(4) print("image test2: ") clear_fbuf() if CIRCUITPY: im, pal = adafruit_imageload.load( "blinka_inv_b1.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette) fb_image_cpy(fb, im) else: im = Image.open('blinka_inv_b1.bmp') im.show() fb_image(fb, im) # show display oled.draw(fbuf, len(fbuf)) time.sleep(4)

変数CIRCUITPYのTrue/Falseでcircuitpython/python3用を切り換えている。

実行

PC(python3)の場合

# 仮想環境を有効化する source blinka/bin/activate # 実行する export BLINKA_MCP2221=1 python3 test_fb1_sh1107g.py

注意:変数CIRCUITPYをFalseにすること。

CircuitPythonの場合

REPL: import test_fb1_sh1107g

注意:変数CIRCUITPYをTrueにすること。

なお、CircuitPythonで実行する場合、 以下のファイル/ディレクトリをCIRCUITPYにコピーする:

(1)sh1107g_cpy.py (2)blinka/lib/python3.6/site-packages/adafruit_framebuf.py # 「python3.6」の部分は、ホストPCの状況に合わせる (3)test_fb1_sh1107g.py (4)blinka_b1.bmp (5)blinka_inv_b1.bmp (6)adafruit_imageload(デレクトリ) これは、CIRCUITPY/lib以下にコピーする

動作実績

(1)MCP2221Aボード
正常に動作した(Vdd=3.3V)
(2)CircutPython Teensy4.0
正常に動作した(Vdd=3.3V)
(3)FT232Hボード
i2c.scan()でデバイス・アドレスが返ってこない。(動作せず)(Vdd=5V)
デバイスの仕様としては、5V/3.3V両用対応になっているが本ボードでは動作しないようだ。

参照情報

PIL/Pillow チートシート

Framebuffer API
Famebuffer docs (MicroPython-based)

Python library for Seeedstudio Grove devices
Arduino Library for this Grove - OLED Display 1.12inch
download datasheet SH1107_v2.1.pdf

USB-I2CブリッジボードV2(GROVE対応ボード)【MR-GROVE-B】
USB-I2CブリッジボードV2(GROVE対応ブレッドボード版)【MR-GROVE-BB】
MCP2221 Blinka Pinout

CircuitPython Libraries on any Computer with MCP2221

CircuitPython on Linux and Raspberry Pi
CircuitPython 5.0.x - I2C

PCのpython3でCircuitPythonのAPIを使用する(FT232H版)
PCのpython3でCircuitPythonのAPIを使用する(MCP2221A版)

以上

続きを読む "Grove-OLED-i2cにFramebufferモジュールを使ってイメージを表示する"

| | コメント (0)

2020年4月 5日 (日)

FT232Hボード用ならびにCircuitPython用にJupyter-Notebookをインストールする

2020/4/5

FT232H Jupyter Notebook

FT232H Jupyter Notebook

概要

以下のFT232Hボード用ならびにCircuitPython用にJupyter-Notebookをインストールする。

FT232H使用USB⇔GPIO+SPI+I2C変換モジュール
Adafruit FT232H Breakout
PCのpython3でCircuitPythonのAPIを使用する

インストール方法

FT232Hボードを動かすために、python3の仮想環境blinkaの中で必要なインストールを行なう。

cd ft232h_ws # activate venv blinka source blinka/bin/activate export BLINKA_FT232H=1 # Install the Jupyter_Notebook & related module pip3 install matplotlib pip3 install pandas pip3 install jupyter pip3 install jupyterlab # Installing the CircuitPython Kernel git clone https://github.com/adafruit/circuitpython_kernel.git cd circuitpython_kernel/ python3 setup.py install python3 -m circuitpython_kernel.install # chcek circuitpython kernel jupyter kernelspec list # 以下のようにcircuitpythonが見えればOK Available kernels: circuitpython /home/xxxxx/.local/share/jupyter/kernels/circuitpython python3 /home/xxxxx/.local/share/jupyter/kernels/python3

Jupyter-notebookの起動

# start jupyter notebook cd ~/ft232h_ws # 仮想環境blinkaが無効になっている場合、以下を実行する: # activate venv blinka source blinka/bin/activate export BLINKA_FT232H=1 # FT232Hボードは、この時点でPCに接続する # または、CircuitPythonボードを接続する # jupyter notebook を起動する場合、以下を実行する jupyter notebook # jupyter lab を起動する場合、以下を実行する jupyter lab

起動するとブラウザーが自動的に起動して、notebookの画面が現れる。

notebookの新規作成

# create new book メニューから以下を選択する: FT232Hボード(python3)の場合 New -> Notebook -> Python3 CircuitPythonボードの場合: New -> Notebook -> CircuitPython

留意事項

notebookの使い方については、ここでは、説明しないが 以下に留意すること:

FT232H(python3)を使用している場合: ・実行を止める場合、kernel/interrupt を実行する。 このままだと出力が残るので、消したい場合は、Cell/Current Output/Clear を実行する。 ・「File/Download as」で保存した場合、デフォルトのDownloadsディレクトリに保存される。 ・スクリプトのprintなどの出力は、そのままnotebookの出力になる。 CircuitPythonを使用している場合: ・(/dev/ttyACM0が/dev/ttyACM1に変わったりするので、あまり、勧めないが) kernel/interruptなどでは(boardの)実行が止まらないようなので、その場合、USBの接続をいったん切ってから再接続する。(jupyter notebookから抜ける必要なし) /dev/ttyACM1などになった場合、ホストPC自身を再起動すると解消する。 ・スクリプトのprintなどの出力は、実行が正常終了後に、notebookに出力される。 (python3と異なり、「while True:」などの無限ループ中はprintなどは出力されない)

Notebook例

FT232H(Python3)のnotebook:
FT232H-notebook
注意:強制終了したので、そのメッセージが出力されているが、異常ではない。

CircuitPythonのnotebook:
CircuitPython(Teensy4.0)-notebook

参照情報

CircuitPython with Jupyter Notebooks

図解!Jupyter Notebookを徹底解説!(インストール・使い方・起動・終了方法)
図解!Jupyter Labを徹底解説!(インストール・使い方・拡張機能)

FT232H Blinka PINOUT

CircuitPython Libraries on any Computer with FT232H

FT232H使用USB⇔GPIO+SPI+I2C変換モジュール
Adafruit FT232H Breakout

CircuitPython on Linux and Raspberry Pi
CircuitPython 5.0.x - I2C

以上

続きを読む "FT232Hボード用ならびにCircuitPython用にJupyter-Notebookをインストールする"

| | コメント (0)

2020年4月 2日 (木)

FT232Hボードに気圧センサーMPL115A2(i2c)を接続する

2020/4/2

FT232H MPL115A2(i2c)

FT232H MPL115A2(i2c)

概要

以下のFT232Hボードに気圧センサーMPL115A2(i2c)を接続する。

FT232H使用USB⇔GPIO+SPI+I2C変換モジュール
Adafruit FT232H Breakout
PCのpython3でCircuitPythonのAPIを使用する

接続

Wiring:
CircuitPythonボードの場合の接続も一緒に載せている。

MPL115A2 FT232H CircuitPython(Teensy4.0)
1(VDD) 5V 3.3V
2(CAP) NC NC
3(GND) GND GND
4(SHDN) 5V 3.3V
MPL115A2 FT232H CircuitPython(Teensy4.0)
8(SCL) D0 D19
7(SDA) D1・D2 D18
6(NC) NC NC
5(RST) 5V 3.3V

2(CAP)は、1μFのコンデンサでGNDと接続する。
8(SCL),7(SDA)は、それぞれ4.7kΩでプルアップする。
VDDは、5V,3.3Vどちらでも、かまわない。
NC: None Connection

注意:ピンのレイアウトや機能はモジュール基板の配線によって変わるので 上の配線表は、あくまでも、手持ちのモジュールのものである。

該当モジュールのインストール

Module Install:

pip3 install adafruit-circuitpython-mpl115a2

デモ・スクリプト

Demo Script:

mpl115a2_test.py

from time import sleep import board import busio import adafruit_mpl115a2 i2c = busio.I2C(board.SCL, board.SDA) mpl = adafruit_mpl115a2.MPL115A2(i2c) while True: print("Pressure: {:0.2f} Temperature: {:0.1f}".format( mpl.pressure, mpl.temperature)) sleep(1)

Output:

$ export BLINKA_FT232H=1 $ python3 mpl115a2_test.py Pressure: 1002.50 Temperature: 28.4 Pressure: 1002.50 Temperature: 28.0 Pressure: 1002.50 Temperature: 28.2 Pressure: 1003.24 Temperature: 28.2 Pressure: 1002.12 Temperature: 28.4 Pressure: 1002.12 Temperature: 28.4 ...

・温度値は圧力補正に使用されるデータで、室温などの温度ではないようだ。

今回のスクリプトは、そのまま、CircuitPythonで動作する。 必要なモジュールは以下のディレクトリにあるので、CircuitPythonのフラッシュにコピーする。

仮想環境blinkaを使用している場合は、以下のようになる:

$ cd ~/ft232h_ws/blinka/lib/python3.6/site-packages $ ls a*.py adafruit_mpl115a2.py ... ...

参照情報

FT232H Blinka PINOUT

CircuitPython Libraries on any Computer with FT232H

FT232H使用USB⇔GPIO+SPI+I2C変換モジュール
Adafruit FT232H Breakout

CircuitPython on Linux and Raspberry Pi
CircuitPython 5.0.x - I2C

以上

続きを読む "FT232Hボードに気圧センサーMPL115A2(i2c)を接続する"

| | コメント (0)

2020年3月31日 (火)

CircuitPythonに温度センサーLM61CIZ(analog)を接続する

2020/3/31

CircuitPython LM61CIZ(analog)

CircuitPython LM61CIZ(analog)

概要

CircuitPythonに以下の温度センサーLM61CIZ(analog)を接続する。
(ホストPCとしてはubuntuを想定している)

高精度IC温度センサLM61CIZ

接続

以下のように接続する。

Wiring:

LM61 CircuitPython(Teensy4.0)
左(VCC) 3.3V
中央(Vout) A9(D23)
右(GND) GND

左/中央/右はマーキングが見える状態での位置関係。

Teensy4.0 Pinout
Teensy4.0 Back Side Pinout

該当モジュールのインストール

analogセンサーなので、特にインストールするモジュールはない。

Demo Script(動作確認)

LM61_tempe_test.py

# LM61 tempe sensor from time import sleep import board from analogio import AnalogIn # D23(A9) of Teensy4.0 lm61 = AnalogIn(board.A9) def get_voltage(raw): return (raw * 3.3) / 65536 def vo2tempe(vo): return (vo*1000-600)/10 # mV -> ℃ while True: raw = lm61.value vo = get_voltage(raw) tempe = vo2tempe(vo) print('tempe: {:0.2f}'.format(tempe)) sleep(1)

出力結果

Press any key to enter the REPL. Use CTRL-D to reload. Adafruit CircuitPython 5.0.0-87-g3a5f79a on 2020-03-16; Teensy 4.0 with IMXRT1062DVJ6A >>> import LM61_tempe_test tempe: 18.31 tempe: 18.31 tempe: 18.31 tempe: 18.31 ... ...

参照情報

高精度IC温度センサLM61CIZ

LM61 datasheet

Teensy4.0 Pinout
Teensy4.0 Back Side Pinout

Turtorial Examples for CircuitPython(Teensy4.0)
Teensy4.0にCircuitPythonをインストールする

Turtorial Examples for Nucleo-MicroPytho
NUCLEO-F446REにMicropythonをインストールする(v2)

CircuitPython 5.0.x - I2C

python3/micro:bit-micropython/CircuitPython用エディタ(mu-editor)をインストールする(linux版)

以上

続きを読む "CircuitPythonに温度センサーLM61CIZ(analog)を接続する"

| | コメント (0)

2020年3月24日 (火)

CircuitPython/MicroPythonに温度センサーTMP102(i2c)を接続する

2020/2/24

CircuitPython TMP102(i2c)

CircuitPython TMP102(i2c)

概要

CircuitPython/MicroPythonに以下の温度センサーTMP102(i2c)を接続する。
(ホストPCとしてはubuntuを想定している)

TMP102搭載 デジタル温度センサモジュール

接続

以下のように接続する。

Wiring:

TMP102 Teensy4.0(CircuitPython)
SCL D19(SCL0)
SDA D18(SDA0)
VCC 3.3V
GND GND

該当モジュールのインストール

Module Install:

git clone https://github.com/khoulihan/micropython-tmp102.git cd micropython-tmp102 cp _tmp102.py tmp102_cpy.py # Patch  次項目の内容のようにtmp102_cpy.pyにパッチする。 # copy related modules cp tmp102_cpy.py CIRCUTPY/lib/

tmp102_cpy.pyの内容:
「#m」を含む行が修正行になる。
(コメントアウト行も含む)

# tmp102_cpy.py # 2020/3/24 modification for CircutPython REGISTER_TEMP = 0 REGISTER_CONFIG = 1 EXTENDED_MODE_BIT = 0x10 def _set_bit(b, mask): return b | mask def _clear_bit(b, mask): return b & ~mask def _set_bit_for_boolean(b, mask, val): if val: return _set_bit(b, mask) else: return _clear_bit(b, mask) class Tmp102(object): def __init__(self, bus, address, temperature_convertor=None, **kwargs): # There doesn't seem to be a way to check this at present. The first # send or recv should throw an error instead if the mode is incorrect. #if not bus.in_master_mode(): # raise ValueError('bus must be in master mode') self.bus = bus self.address = address self.temperature_convertor = temperature_convertor # The register defaults to the temperature. self._last_write_register = REGISTER_TEMP self._extended_mode = False if len(kwargs) > 0: # Apply the passed in settings config = bytearray(self._get_config()) for key, value in kwargs.items(): applyfunc = '_apply_{}'.format(key) config = getattr(self, applyfunc)(config, value) self._set_config(config) if 'thermostat_high_temperature' in kwargs: self.thermostat_high_temperature = kwargs['thermostat_high_temperature'] if 'thermostat_low_temperature' in kwargs: self.thermostat_low_temperature = kwargs['thermostat_low_temperature'] def _read_register(self, register): val = bytearray(2) #m if register != self._last_write_register: # Reads come from the last register written. self._write_register(register) try: #m val = self.bus.readfrom(self.address, 2) self.bus.readfrom_into(self.address, val) except AttributeError: #m val = self.bus.recv(2, addr=self.address) self.bus.readfrom_into(self.address, val) return val def _write_register(self, register, value=None): bvals = bytearray() bvals.append(register) if value is not None: for val in value: bvals.append(val) try: self.bus.writeto(self.address, bvals) except AttributeError: self.bus.send(bvals, addr=self.address) self._last_write_register = register def _get_config(self): return self._read_register(REGISTER_CONFIG) def _set_config(self, config): self._write_register(REGISTER_CONFIG, config) self._extended_mode = config[1] & EXTENDED_MODE_BIT def _read_temperature_register(self, register): rt = self._read_register(register) lo = rt[1] hi = rt[0] negative = (hi >> 7) == 1 shift = 4 if self._extended_mode: shift = 3 if not negative: t = (((hi * 256) + lo) >> shift) * 0.0625 else: remove_bit = 0b011111111111 if self._extended_mode: remove_bit = 0b0111111111111 ti = (((hi * 256) + lo) >> shift) # Complement, but remove the first bit. ti = ~ti & remove_bit t = -(ti * 0.0625) if self.temperature_convertor is not None: t = self.temperature_convertor.convert_to(t) return rt, t @property def temperature(self): """ The most recently recorded temperature. """ rt, t = self._read_temperature_register(REGISTER_TEMP) return t

CircuitPythonとMicroPythonに共通してあるi2c.writeto,i2c.readfrom_intoを使用しているので、両方に対応できている。

Demo Script(動作確認)

import time import busio import board i2c = busio.I2C(board.SCL, board.SDA) i2c.try_lock() from tmp102_cpy import Tmp102 sensor = Tmp102(i2c, 0x48) while True: print('Temperature: {0:.1f}'.format(sensor.temperature)) time.sleep(2)

MicroPython(Nucleo)の場合

該当モジュールtmp102_cpy.pyが、CircuitPython/MicroPython両方に対応しているので そのまま/flashに書き込むだけでパッチなどは必要ない。

Demo Script:

import time from machine import Pin, I2C i2c = I2C(1) from tmp102_cpy import Tmp102 sensor = Tmp102(i2c, 0x48) while True: print('Temperature: {0:.1f}'.format(sensor.temperature)) time.sleep(2)

デバイスなどの初期化以外はCircuitPythonのものと全く同じ。

参照情報

TMP102搭載 デジタル温度センサモジュール

ESP8266のMicroPythonに温度センサーTMP102(i2c)を接続する

Turtorial Examples for CircuitPython(Teensy4.0)
Teensy4.0にCircuitPythonをインストールする

Turtorial Examples for Nucleo-MicroPytho
NUCLEO-F446REにMicropythonをインストールする(v2)

CircuitPython 5.0.x - I2C

以上

続きを読む "CircuitPython/MicroPythonに温度センサーTMP102(i2c)を接続する"

| | コメント (0)