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日