M5Stackから、新製品の M5StickV が発売されました。今回はESP32ではなくて、K210 RISC-V搭載です。顔検出などが高速にできるプロセッサとのこと。無線機能はついてないので、技適は必要なし!よって日本でも即発売となりました!
発売当初品薄だったのですが、運よく初回販売で入手することができました。
M5StickV きたー! pic.twitter.com/0Bj60L4IEU
— Nochi (@shikarunochi) 2019年7月13日
初期プログラムとして、顔認識するプログラムが入っています。起動すると即、顔認識起動!すごい!
顔認識してもらうために、ムックに偽装する PLEN:bit pic.twitter.com/9ceP907hRl
— Nochi (@shikarunochi) 2019年7月13日
M5StickVについては、さいとてつやさんのサイトが情報満載です。
さいとてつやさんのM5StickVまとめ
https://scrapbox.io/saitotetsuya/M5StickV
起動時には、本体内フラッシュの boot.py が自動的に起動されます。boot.py消すと、標準のboot.py が自動的に作成されてそれが起動されるみたいです。microSDカードのルートにboot.pyというファイル名で入れておけば、そちらを起動してくれます。これは便利!とはいえ、自動的に起動されてしまうので、止めたい時のために「起動時にボタンを押すとプログラム終了する」ような仕掛けを入れておく必要がありますね。
プログラムは、基本的には MaixPy (MicroPython) で行います。
こちらで紹介されている、20種類の物を認識するプログラムを動かしてみました。
MaixPy Run 20-classes object detection based on tiny-yolov2 in 30 lines~
https://bbs.sipeed.com/t/topic/683
20-classes object detection、SDカードからの起動で動きました!https://t.co/M3R73gJQDc
SDカードにファイル一式コピーして、https://t.co/OS0ZHDk6Iv を https://t.co/shwtPRNvvt にリネーム、kmodelをsdカードから読み込むように変更、でOKです!
task = kpu.load(“/sd/20class.kmodel”) pic.twitter.com/BDUS2YpIwE— Nochi (@shikarunochi) 2019年7月13日
データの読み元を、フラッシュメモリアドレス指定からSDカード指定に変更して動作しました。
せっかくなので、判別した結果によって、何かアクションを起こしてみたいですね。
ということで、PLEN:bit と通信して動かしてみました。
通信はGPIO。コード2本を使って2種類の信号を通信してみます。シンプルで、贅沢な方法ですw
M5StickV のピン番号は、ケースのフタ裏側に書いてあります。
これによれば、GROVE端子には、GND / Vout / G35 / G34 が接続されてます。
MaixPyでのG34へのGPIO送信はこれでできました。
from Maix import GPIO from fpioa_manager import fm fm.register(34, fm.fpioa.GPIOHS0, force=True) pinout34 = GPIO(GPIO.GPIOHS0, GPIO.OUT) pinout34.value(0)
あまり資料見つけられなくて、いろいろ試行錯誤しました。(ファームウェアバージョンによっては force=True つけなくていいかも?)
任意のピンに任意の機能を割り振る、FPIOA という仕掛けがあるみたいです。
FPIOA (Field Programmable Input and Output Array)
https://maixpy.sipeed.com/en/libs/Maix/fpioa.html
こちらの公式のサンプルが参考になりました。
MaixPy_scripts/hardware/demo_gpio.py
https://github.com/sipeed/MaixPy_scripts/blob/master/hardware/demo_gpio.py
ソース全体はこういう感じ。
import sensor,image,lcd,time
import KPU as kpu
from Maix import GPIO
from fpioa_manager import fm
lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)
sensor.run(1)
fm.register(34, fm.fpioa.GPIOHS0, force=True)
fm.register(35, fm.fpioa.GPIOHS1, force=True)
pinout34 = GPIO(GPIO.GPIOHS0, GPIO.OUT)
pinout34.value(0)
pinout35 = GPIO(GPIO.GPIOHS1, GPIO.OUT)
pinout35.value(0)
clock = time.clock()
classes = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']
# task = kpu.load(0x500000)
task = kpu.load("/sd/20class.kmodel")
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):
clock.tick()
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
print(clock.fps())
if code:
for i in code:
a=img.draw_rectangle(i.rect())
a = lcd.display(img)
for i in code:
#lcd.draw_string(i.x(), i.y(), classes[i.classid()], lcd.RED, lcd.WHITE)
#lcd.draw_string(i.x(), i.y()+12, '%f1.3'%i.value(), lcd.RED, lcd.WHITE)
if classes[i.classid()] == 'cat':
lcd.draw_string(0,0,'neko!',lcd.RED, lcd.WHITE)
print('cat')
pinout34.value(1)
time.sleep_ms(1000)
pinout34.value(0)
if classes[i.classid()] == 'car':
lcd.draw_string(0,0,'kuruma!',lcd.RED, lcd.WHITE)
print('car')
pinout35.value(1)
time.sleep_ms(1000)
pinout35.value(0)
else:
a = lcd.display(img)
a = kpu.deinit(task)
20-classes object detectionに処理追加して、”cat” の場合、34ピンに 1 を出力、”car”の場合、35ピンに 1 を出力するようにしました。
PLEN:bit 側は MicrosoftCode でプログラム作成。
plenbit.servoInitialSet()
basic.forever(function () {
basic.showLeds(`
# # # # #
# . . . #
. . # # #
. . . . .
. . # . .
`)
if (pins.digitalReadPin(DigitalPin.P0) == 1) {
basic.showIcon(IconNames.Happy)
plenbit.eyeLed(plenbit.LedOnOff.On)
plenbit.servoWrite(4, 120)
basic.pause(2000)
plenbit.servoWrite(4, 20)
plenbit.eyeLed(plenbit.LedOnOff.Off)
basic.pause(1000)
} else {
if (pins.digitalReadPin(DigitalPin.P2) == 1) {
basic.showIcon(IconNames.Happy)
plenbit.eyeLed(plenbit.LedOnOff.On)
plenbit.servoWrite(0, 20)
basic.pause(2000)
plenbit.servoWrite(0, 100)
plenbit.eyeLed(plenbit.LedOnOff.Off)
basic.pause(1000)
}
}
})
センサー0 が ON になれば右手を挙げて、センサー2 が ON になれば左手を挙げるだけです。
せっかくなので認識に合わせて胸のLED表示も変更。
PLEN:bitに、ネコと車の旗を持ってもらいました。G34 / G35 と GND を PLEN:bit の端子に接続しています。
PLEN:bit に、ネコか車かの判定をしてもらいました!#M5StackV #plenbit pic.twitter.com/MtlxcjqLHm
— Nochi (@shikarunochi) 2019年7月14日
シリアルでつないで、文字列をそのまま送信するのもやってみました。
UARTでの送信こういう感じ。
from machine import UART
from fpioa_manager import fm
fm.register(34, fm.fpioa.UART1_TX, force=True)
fm.register(35, fm.fpioa.UART1_RX, force=True)
uart_A = UART(UART.UART1, 115200,8,0,0, timeout=1000, read_buf_len=4096)
uart_A.write("string"+"\r\n")
改行文字は受け手に合わせて。
GROVE端子からのUART接続テストです。
UARTシリアル接続して、検出したものを文字列で送信してみました。
誤検知とバッファ溜まりもそのまま表示してます。
PLEN:bit の動きを入れてないので動画的には地味ですねw pic.twitter.com/qYjxXjntrl— Nochi (@shikarunochi) 2019年7月15日

