Raspberry Pi用MGC3130搭載 3Dジェスチャー・トラッキングモジュールを使用する

この記事はSeeedUG アドベントカレンダー2021の23日目のエントリになります。

今年のエントリはかなり内容を悩みました。比較的通常時にデバイス関連なども書いていましたが、このタイミングで書くネタがなく、改めてネタを探していました。

そんな中で思いついた内容は以下のものとなります。

  • Seeeduino XIAOを使ってUSBホスト機能 … 安心な配線方法に自信がなかったのでボツ。そのうちチャレンジするとは思う。
  • Grove Uart Wifi v2を使ってみる … 存在しない機能であるネットワーク機能をアドオンできるのは魅力的だけど、そもそもそんな需要のあるはmicro:bitぐらい?ってことでボツ。
  • reTerminalを使ってみる … 少し時間が経ったこともあり割と情報が出てきているので目新しさがないのでボツ。

こんな感じで考えたのですが、どうもいい内容が思いつかない、既に同じないようを書いている人もいたりする。

考えを変えてみようと部屋の掃除をしてみたところ、以前に購入したRaspberry Pi用MGC3130搭載 3Dジェスチャー・トラッキングモジュールをまだ使っていないことに気が付きました。ネットでの検索でもあまり多くの情報がなかったということもあり、こちらを使ってみる内容にしようと思います。

jp.seeedstudio.comwww.switch-science.com

このデバイスMicrochip MGC3130チップを搭載し、測定面の磁場の変化をもとに手の動きを読み取るモジュールとなります。

https://www.microchip.com/en-us/product/MGC3130

測定可能な空間上の位置情報キャプチャ、近接検知、タッチ検知を行うことができます。天面のタップやダブルクリックも検知できます。

こちらの動画で説明が行われています。

youtu.be

この動画でタッチパッドと空間位置の検知ができるデバイスであることは想像できたかなと思います。

バイスI2Cインターフェイスを介して通信が行われRaspberryPiGPIOヘッダーに差し込んで接続するHATと呼ばれるような形になっています。RaspberryPi以外のデバイスに接続できるようにGroveコネクタもついています。

f:id:ueponx:20211221231345j:plain

今回はこのデバイスの動作テスト(C言語からの使用)やPythonからの使用を行ってみたいと思います。流石にRaspberry Pi用MGC3130搭載 3Dジェスチャー・トラッキングモジュールという名前では長すぎるので以降はMGC3130センサーシールドと呼ぶことにします。

使用した機材および環境

  • RaspberryPi2B
  • 最新のRaspberryPi OS(Bullseye)

後述しますが、RaspberryPi2Bではリアルタイム処理のパワーが足りないかもしれません。3B、3B+あたりがおすすめかなと思います。(4Bは発熱が凄いので、HATスタイルの接続は微妙かも?)

f:id:ueponx:20211221231055p:plain

動作テストを行う

動作テストは以下のサイトに詳細が書かれています。

wiki.seeedstudio.com

作業の手順としては以下のようになります。

  • I2Cを有効化
  • ncursesをインストール
  • テスト用のソースを入手して動作を確認

では順番に行っていきます。

RaspberryPiのI2C機能を有効化

I2Cの機能を有効化するにはおなじみのraspi-configを実行していくことになります。

$ sudo raspi-config

実行するとメニューが表示されるのでカーソルを操作し、 3 Interface Optionsを選択し、

f:id:ueponx:20211220222807p:plain

続いて、P5 I2Cを選択

f:id:ueponx:20211220222811p:plain

I2Cインターフェースを有効にするかを尋ねられるのでYesを選択

f:id:ueponx:20211220222822p:plain

I2Cが有効化されたことが表示されるのでOkを押す。

f:id:ueponx:20211220222826p:plain

初期メニューに戻るのでカーソルを移動し、Finishを選択します。

f:id:ueponx:20211220222835p:plain

念の為、RaspberryPiを再起動しておきましょう。

$ sudo reboot

再起動したら、以下のコマンドを実行し、

$ i2cdetect -y 1

I2Cアドレスが0x42にデータがあればOKです(デフォルト値)。

f:id:ueponx:20211220231451p:plain

ncursesをインストール

ncursesWikipediaによれば

ncurses は、端末に依存しない形式でテキストユーザインタフェース (TUI) を作成するためのAPIを提供するライブラリ。

CUI形式の画面でもメニューの可能にするようなライブラリといえばいいのかもしれません。動作テストを行うプログラムでこちらのライブラリを使用しているのでインストールを行います。

参考にしたサイトでncursesのバージョンは6.1となっていましたが、6.3があったのでそちらを使用しました。パッケージがあればそれを使用してaptコマンドでインストールしてもいいと思います。

$ cd ~
$ wget https://invisible-mirror.net/archives/ncurses/ncurses-6.3.tar.gz
$ tar -xvf ncurses-6.3.tar.gz 
$ cd ncurses-6.3/
$ ./configure 
$ make
$ sudo make install

ここまで終ればncursesのインストールは無事に終了しています。あとはインストールされたncursesを動作させてバージョンを確認してみます。

$ ncurses6-config --version
6.3.20211021

などという風に表示されていれば大丈夫です。

テスト用のソースを入手して動作を確認

あとは動作確認を行います。テスト用のソースは以下のGitHubにあるのでクローンをして入手していきます。

github.com

もし、必要があればWiringPiを以下のようにインストールしておきます。

$ cd ~
$ git clone https://github.com/WiringPi/WiringPi.git
$ cd wiringPi
$ ./build

あとはクローンを行って、ソースファイルのmakeを行います。

$ cd ~
$ git clone https://github.com/Seeed-Studio/Seeed_mgc3x30.git
$ cd Seeed_mgc3x30/
$ make clean && make

makeが成功したら実際に動作させてみます。

$ ./mgc3130 

すると以下のような情報が得られます。

  • x,y,z軸の各座標
  • ジェスチャー
  • AirWheelの状態(指でくるくる円を書くことで回転の状態を知ることができますが、結構操作に癖があり)
  • タッチやタップの状況

f:id:ueponx:20211220230626p:plain

測定範囲内で指を動かすなどを行って数値などの情報が表示されれば、動作確認は成功になります。

このソースはC言語で記載されているのですが、 ~/Seeed_mgc3x30/src/Seeed_3D_touch_mgc3030.c内のint32_t mg3030_read_data(void *data)処理でデータの取得を行っています。 データのブロックで計測データを取得しているので、取得後もデータを分解し、処理を行います。そのため、サンプリング的に取得することになるのでパワーが必要になってしまいます。今回はRaspberryPi 2Bでテストしてみましたが、処理が追い付かないこともあるようです。

pythonで動作させてみる

C言語での動作は確認できましたが、できればpythonからでも使用可能になると、使用用途がかなり広がるのはないかと思います。

GitHubをみてみると以下の2つが該当するようです。

GitHub - linux-downey/seeed_mgc3x30_python: A library for 3D Gesture.

GitHub - open-electronics/GestIC: Interface the electrode board for gesture recognition to Arduino and to Raspberry Pi

今回はうまくいったこちらを使用してみることにしました。

github.com

以下のようにクローンして動作させるのですが、一筋縄ではうまくいきませんw またか!!

$ git clone https://github.com/open-electronics/GestIC.git
$ cd GestIC/AppRaspberry/Librerie/MGC3130_Lib/V1_1_0_0/MGC3130
$ sudo python setup.py install

実はBullseyeベースのRaspberryPiではpython2系がインストールされておらず、デフォルトのpythonコマンドも3.9系になっています。

f:id:ueponx:20211221231253p:plain

そのため、上記のようにインストール作業を行うと、インストール先がpython2系とは別となり、/usr/local/lib/python2.7/dist-packages/MGC3130にインストールされます。

GitHubでクローンした動作環境がpython2系のままなのが問題の様です。あとスペルミスもあったり…。

オリジナルのファイルを使うと以下のようなエラーが出ます。

ライブラリ側のエラー

  • print文のカッコを補う
  • ctypeのスペルミス修正

動作デモファイル側のエラー

  • importするライブラリのパスが通っていない

以下に修正したファイルを置いておきます。

ライブラリファイル /usr/local/lib/python3.9/dist-packages/MGC3130/MGC3130.py

#===========================================================================
#  This is the library for MGC3130. 
#  
#  MGC3130 is a device that lets you control your hardware projects in a whole new way.  
#  MGC3130 detects hands movements and converts these  in gestures. These gestures
#  permit to manage a device without touch it. 
#
#  Written by Matteo Destro for Futura Group srl
#  www.Futurashop.it
#  www.open-electronics.org
#
#  BSD license, all text above must be included in any redistribution
#  ===========================================================================
#
#       REVISION        1.0.0   30/06/2015
#
#  ===========================================================================
#
#       REVISION        1.1.0   13/03/2016
#
#       - Fixed Bug print North to South gestic and South to North gestic
#
#       - Added new gesture recognitions:
#               *       Gesture Wave X
#               *       Gesture Wave Y
#               *       Gesture Hold
#               *       Gesture Presence
#               *       Gesture Double West To East 
#               *       Gesture Double East To Weast 
#               *       Gesture Double North To South 
#               *       Gesture Double South To North 
#
#  ===========================================================================
#
#  SUPPORT
#
#  info@open-electronics.org
#
#===========================================================================

from ctypes import *
from MGC3130_DefVar import *

import smbus
import time
import sys

#I2Cbus = smbus.SMBus(0)
I2Cbus = smbus.SMBus(1)

_Data          = c_ubyte * 256
_i2caddr       = 0x42
_Counter       = 0
_FirstTelegram = False
_GestInfo      = GestureInfo()
_TouchInfo     = TouchInfo()
_xyz           = Coordinates()
_GestOutput    = Gesture()

#===================================================================
#       Enable/Disable code to debug
EnablePrintMGC3130RawFirmwareInfo = True
EnablePrintMGC3130RawData         = True
EnablePrintMGC3130Gesture         = True
EnablePrintMGC3130xyz             = False
#===================================================================

#===================================================================
def MGC3130_SetAdd(Addr):
        global _Data
        _i2caddr = Addr
#===================================================================

#===================================================================
def MGC3130_Begin(GPIO, Ts, Rst):
        global _FirstTelegram
        print("MGC3130 initialization in progress...wait")
        GPIO.setup(Ts, GPIO.IN, pull_up_down=GPIO.PUD_UP)       # MGC3130 TS Line. Input mode
        #GPIO.add_event_detect(Ts, GPIO.FALLING, bouncetime=100)
        GPIO.setup(Rst, GPIO.OUT, initial=GPIO.HIGH)            # MGC3130 RESET Line
        GPIO.output(Rst, GPIO.LOW)                                                      # Reset MGC3130 Device
        time.sleep(0.250)                                                                   # Delay 250mSec
        GPIO.output(Rst, GPIO.HIGH)                                                     # Remove Reset MGC3130 Device                 
        #time.sleep(0.250)                                                                  # Delay 250mSec
        #_FirstTelegram = True
 
        time.sleep(0.500)                                                                   # Delay 500mSec
        _FirstTelegram = False
        print("MGC3130 device is ready")
#===================================================================

#===================================================================
def MGC3130_ResetDevice(GPIO, Rst):
        GPIO.setup(Rst, GPIO.OUT, initial=GPIO.HIGH)            # MGC3130 RESET Line
        GPIO.output(Rst, GPIO.LOW)
#===================================================================

#===================================================================
def MGC3130_ExitResetDevice(GPIO, Rst):
        GPIO.setup(Rst, GPIO.OUT, initial=GPIO.HIGH)            # MGC3130 RESET Line
        GPIO.output(Rst, GPIO.HIGH)
#===================================================================
 
#===================================================================
def MGC3130_ReleaseTsLine(GPIO, Ts):
        #print("Release TS Line")
        GPIO.output(Ts, GPIO.HIGH)
        time.sleep(0.050)
        GPIO.setup(Ts, GPIO.IN, pull_up_down=GPIO.PUD_UP)       # MGC3130 TS Line. Input mode
#===================================================================

#=================================================================== 
def MGC3130_GetTsLineStatus(GPIO, Ts):
        if (GPIO.input(Ts) == GPIO.LOW):
                #print("Get TS Line")
                time.sleep(0.050)
                GPIO.setup(Ts, GPIO.OUT)        # MGC3130 TS Line. Output mode
                GPIO.output(Ts, GPIO.LOW)
                return True
        else:
                return False
#===================================================================

#===================================================================
def MGC3130_GetEvent():
        global EnablePrintMGC3130RawFirmwareInfo
        global _Counter
        global _Data
        global _FirstTelegram
        global _GestInfo
        global _TouchInfo
        global _xyz
 
        _Counter = 0
         
        if (_FirstTelegram == True):
                _FirstTelegram = False
                _Data = I2Cbus.read_i2c_block_data(_i2caddr, 0x00, 0x20)
        else:
                _Data = I2Cbus.read_i2c_block_data(_i2caddr, 0x00, 0x1A)

        if (_Data[3] == ID_FW_VERSION):
                if (_Data[4] == 0xAA):
                        if (EnablePrintMGC3130RawFirmwareInfo == True):
                                MGC3130_PrintMGC3130RawFirmwareInfo()

                        print("###################################################")
                        print("Valid Library detected")
                        # 以下2行修正
                        print('Hardware Rev: {}.{}' .format(_Data[5], _Data[6]))
                        print('Library Loader Version: {}.{}' .format(_Data[9], _Data[8]))
                        #===========================================
                        sys.stdout.write("Gestic Library Version: ")
                        TempStr = ""
                        for i in range(12, 17):
                                if (i < len(_Data)):
                                        TempStr = TempStr + chr(_Data[i])
                        sys.stdout.write(TempStr + "\n")
                        #===========================================
                 
                        #===========================================
                        sys.stdout.write("Platform: ")
                        TempStr = ""
                        for i in range(20, 31):
                                if (i < len(_Data)):
                                        TempStr = TempStr + chr(_Data[i])
                        sys.stdout.write(TempStr +"\n")
                        #===========================================
                        print("###################################################")
                        print("\n")
                 
                else:
                        print("Invalid Library detected")
                 
        elif (_Data[3] == ID_DATA_OUTPUT):
                #===========================================
                # Save Data into internal array
                for i in range(4):
                        _GestInfo.GestInfoArray[i]   = _Data[i + 10]
                        _TouchInfo.TouchInfoArray[i] = _Data[i + 14]
                         
                _GestInfo.GestureInfoLong &= MASK_GESTURE_RAW
                _TouchInfo.TouchInfoLong  &= MASK_TOUCH_RAW 
                AirWheelInfo = _Data[18]
                for i in range(6):
                        if (i < len(_Data)):
                                _xyz.xyzArray[i] = _Data[i + 20]
                #===========================================
        else:
                print("Telegram not managed")
#=================================================================== 

#===================================================================
def MGC3130_DecodeGesture():
        global EnablePrintMGC3130RawData
        global EnablePrintMGC3130Gesture
        global EnablePrintMGC3130xyz
        global _GestInfo
        global _TouchInfo
        global _GestOutput
        global LastTouch
        global LastGesture
 
        Mask = 0x00000001
        if (((_TouchInfo.TouchInfoLong ^ LastTouch) > 0) or ((_GestInfo.GestureInfoLong ^ LastGesture) > 0)):
                if (EnablePrintMGC3130RawData == True):
                        MGC3130_PrintMGC3130RawData()
                _GestOutput.GestureLong = 0x00000000
                if ((_TouchInfo.TouchInfoLong ^ LastTouch) > 0):
                        LastTouch = _TouchInfo.TouchInfoLong
                        for i in range (15):
                                if ((_TouchInfo.TouchInfoLong & Mask) > 0):
                                        _GestOutput.GestureLong |= Mask
                                Mask = Mask << 1
                elif ((_GestInfo.GestureInfoLong ^ LastGesture) > 0):
                        LastGesture = _GestInfo.GestureInfoLong
                        if (_GestInfo.GestureInfo32Bit.GestureCode == NO_GESTURE):
                                print("No Gesture")
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_GARBAGE):
                                print("Garbage Gesture")
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_EDGE_WEST_EAST):
                                _GestOutput.GestureLong |= GESTURE_MASK_EDGE_WEST_EAST
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_EDGE_EAST_WEST):
                                _GestOutput.GestureLong |= GESTURE_MASK_EDGE_EAST_WEST
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_EDGE_SOUTH_NORTH):
                                _GestOutput.GestureLong |= GESTURE_MASK_EDGE_SOUTH_NORTH
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_EDGE_NORTH_SOUTH):
                                _GestOutput.GestureLong |= GESTURE_MASK_EDGE_NORTH_SOUTH
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_WEST_EAST):
                                if (_GestInfo.GestureInfo32Bit.Edgeflick == 0):
                                        _GestOutput.GestureLong |= GESTURE_MASK_WEST_EAST
                                else:
                                        _GestOutput.GestureLong |= GESTURE_MASK_EDGE_WEST_EAST
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_EAST_WEST):
                                if (_GestInfo.GestureInfo32Bit.Edgeflick == 0):
                                        _GestOutput.GestureLong |= GESTURE_MASK_EAST_WEST
                                else:
                                        _GestOutput.GestureLong |= GESTURE_MASK_EDGE_EAST_WEST
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_SOUTH_NORTH):
                                if (_GestInfo.GestureInfo32Bit.Edgeflick == 0):
                                        _GestOutput.GestureLong |= GESTURE_MASK_SOUTH_NORTH
                                else:
                                        _GestOutput.GestureLong |= GESTURE_MASK_EDGE_SOUTH_NORTH
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_NORTH_SOUTH):
                                if (_GestInfo.GestureInfo32Bit.Edgeflick == 0):
                                        _GestOutput.GestureLong |= GESTURE_MASK_NORTH_SOUTH
                                else:
                                        _GestOutput.GestureLong |= GESTURE_MASK_EDGE_NORTH_SOUTH
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_CLOCK_WISE):
                                _GestOutput.GestureLong |= GESTURE_MASK_CLOCK_WISE
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_COUNTER_CLOCK_WISE):
                                _GestOutput.GestureLong |= GESTURE_MASK_COUNTER_CLOCK_WISE
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_WAVE_X):
                                _GestOutput.GestureLong |= GESTURE_MASK_WAVE_X
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_WAVE_Y):
                                _GestOutput.GestureLong |= GESTURE_MASK_WAVE_Y
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_HOLD):
                                _GestOutput.GestureLong |= GESTURE_MASK_HOLD
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_PRESENCE):
                                _GestOutput.GestureLong |= GESTURE_MASK_PRESENCE
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_DOUBLE_WEST_EAST):
                                _GestOutput.GestureLong |= GESTURE_MASK_DOUBLE_WEST_EAST 
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_DOUBLE_EAST_WEST):
                                _GestOutput.GestureLong |= GESTURE_MASK_DOUBLE_EAST_WEST 
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_DOUBLE_SOUTH_NORTH):
                                _GestOutput.GestureLong |= GESTURE_MASK_DOUBLE_SOUTH_NORTH 
                        elif (_GestInfo.GestureInfo32Bit.GestureCode == GESTURE_DOUBLE_NORTH_SOUTH): 
                                _GestOutput.GestureLong |= GESTURE_MASK_DOUBLE_NORTH_SOUTH
                 
                _GestOutput.GestureLong &= ~(MASK_FILTER_GESTURE)
         
                if (EnablePrintMGC3130Gesture == True):
                        MGC3130_PrintMGC3130Gesture()
                if (EnablePrintMGC3130xyz == True):
                        MGC3130_PrintMGC3130xyz()
#===================================================================

#===================================================================
def MGC3130_PrintMGC3130RawFirmwareInfo():
        global _Data
 
        RawInfoIndent      = "#####################################################################################\nRow Firmware Info from MGC3130 \n"
        HeaderInfo         = "Header: "
        PayloadInfo        = "Payload: "
        RawInfoCloseIndent ="\n#####################################################################################\n\n";
 
        if (_Data[3] == ID_FW_VERSION):
                sys.stdout.write(RawInfoIndent)
                #===========================================
                #       Header   
                sys.stdout.write(HeaderInfo)
                for i in range(4):
                        MGC3130_SetHexPrintOutput(_Data[i])
                print("\n")
                #===========================================
 
                #===========================================
                #       Payload
                sys.stdout.write(PayloadInfo)
                MGC3130_SetHexPrintOutput(_Data[4])
                sys.stdout.write(" | ")
                #===========================================
         
                #===========================================
                #       HwRev
                for i in range(5, 7):
                        MGC3130_SetHexPrintOutput(_Data[i]) 
                sys.stdout.write(" | ")
                #===========================================
                 
                #===========================================
                #       ParameterStartAddr
                MGC3130_SetHexPrintOutput(_Data[7])
                sys.stdout.write(" | ")
                #===========================================             
         
                #===========================================
                #       LibraryLoaderVersion
                for i in range(8, 11):
                        MGC3130_SetHexPrintOutput(_Data[i]) 
                sys.stdout.write(" | ")
                #===========================================     
         
                #===========================================
                #       FwStartAddr
                MGC3130_SetHexPrintOutput(_Data[11])
                sys.stdout.write(" | ")
                #===========================================
         
                #===========================================
                #       LibraryLoaderVersion
                for i in range(12, len(_Data)):
                        MGC3130_SetHexPrintOutput(_Data[i]) 
                sys.stdout.write(RawInfoCloseIndent)
                #===========================================             
                                 
def MGC3130_SetHexPrintOutput(Data):
        if (Data < 0x10):
                sys.stdout.write("0x" + format(Data, "02x") + " ")
        else:
                sys.stdout.write(hex(Data) + " ")

#===================================================================

#===================================================================
def MGC3130_PrintMGC3130RawData():
        global _Data
 
        RawDataIndent      = "#####################################################################################\nRow data from MGC3130 \n"
        HeaderRawData      = "Header: "
        PayloadRawData     = "Payload: "
        RawDataCloseIndent ="\n#####################################################################################\n\n";
 
        if (_Data[3] == ID_DATA_OUTPUT):
                sys.stdout.write(RawDataIndent)
                #===========================================
                #       Header   
                sys.stdout.write(HeaderRawData)
                for i in range(4):
                        MGC3130_SetHexPrintOutput(_Data[i])
                print("\n")
                #===========================================
         
                #===========================================
                #       Payload
                #       DataOutputConfigMask
                sys.stdout.write(PayloadRawData)
                for i in range(4, 6):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #===========================================     
 
                #===========================================
                #       TimeStamp
                MGC3130_SetHexPrintOutput(_Data[6])
                sys.stdout.write(" | ")
                #===========================================     
         
                #===========================================
                #       SystemInfo
                MGC3130_SetHexPrintOutput(_Data[7])
                sys.stdout.write(" | ")
                #===========================================     
         
                #===========================================
                #       DSPStatus
                for i in range(8, 10):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #===========================================     
         
                #===========================================
                #       GestureInfo
                for i in range(10, 14):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #=========================================== 
         
                #===========================================
                #       TouchInfo
                for i in range(14, 18):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #===========================================
         
                #===========================================
                #       AirWheelInfo
                for i in range(18, 20):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #===========================================
         
                #===========================================
                #       xyzPosition
                for i in range(20, 26):
                        MGC3130_SetHexPrintOutput(_Data[i])
                sys.stdout.write(" | ")
                #===========================================
         
                sys.stdout.write(RawDataCloseIndent)                     
#===================================================================

#===================================================================
def MGC3130_PrintMGC3130Gesture():
        global _GestOutput
 
        if (_GestOutput.Gesture64Bit.TouchSouth):
                print ("Touch South")
                print("\n")
        if (_GestOutput.Gesture64Bit.TouchWest):
                print ("Touch West")
                print("\n")
        if (_GestOutput.Gesture64Bit.TouchNorth):
                print ("Touch North")
                print("\n")
        if (_GestOutput.Gesture64Bit.TouchEast):
                print ("Touch East")     
                print("\n")
        if (_GestOutput.Gesture64Bit.TouchCentre):                       
                print ("Touch Centre")
                print("\n")
         
        if (_GestOutput.Gesture64Bit.TapSouth):
                print ("Tap South")
                print("\n")
        if (_GestOutput.Gesture64Bit.TapWest):
                print ("Tap West")
                print("\n")
        if (_GestOutput.Gesture64Bit.TapNorth):
                print ("Tap North")
                print("\n")
        if (_GestOutput.Gesture64Bit.TapEast):
                print ("Tap East")       
                print("\n")
        if (_GestOutput.Gesture64Bit.TapCentre):                         
                print ("Tap Centre")     
                print("\n")
         
        if (_GestOutput.Gesture64Bit.DoubleTapSouth):
                print ("Double Tap South")
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleTapWest):
                print ("Double Tap West")
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleTapNorth):
                print ("Double Tap North")
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleTapEast):
                print ("Double Tap East")        
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleTapCentre):                   
                print ("Double Tap Centre") 
                print("\n")
         
        if (_GestOutput.Gesture64Bit.GestWestEast):
                print ("Gesture Flick West to East")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestEastWest):
                print ("Gesture Flick East to West")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestSouthNorth):
                print ("Gesture Flick South to North")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestNorthSouth):
                print ("Gesture Flick North to South")           
                print("\n")
         
        if (_GestOutput.Gesture64Bit.EdgeGestWestEast):
                print ("Gesture Flick Edge West to East")
                print("\n")
        if (_GestOutput.Gesture64Bit.EdgeGestEastWest):
                print ("Gesture Flick Edge East to West")
                print("\n")
        if (_GestOutput.Gesture64Bit.EdgeGestSouthNorth):
                print ("Gesture Flick Edge South to North")
                print("\n")
        if (_GestOutput.Gesture64Bit.EdgeGestNorthSouth):
                print ("Gesture Flick Edge North to South")
                print("\n")
         
        if (_GestOutput.Gesture64Bit.GestClockWise):
                print ("Gesture Clock Wise")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestCounterClockWise):
                print ("Gesture Counter Clock Wise")     
                print("\n")
         
        if (_GestOutput.Gesture64Bit.GestWaveX):
                print ("Gesture Wave X")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestWaveY):
                print ("Gesture Wave Y")         
                print("\n")
        if (_GestOutput.Gesture64Bit.GestHold):
                print ("Gesture Hold")
                print("\n")
        if (_GestOutput.Gesture64Bit.GestPresence):
                print ("Gesture Presence")       
                print("\n")
         
        if (_GestOutput.Gesture64Bit.DoubleGestWestEast):
                print ("Gesture Double West to East")
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleGestEastWest):
                print ("Gesture Double East to West")    
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleSouthNorth):
                print ("Gesture Double South to North")
                print("\n")
        if (_GestOutput.Gesture64Bit.DoubleGestNorthSouth):
                print ("Gesture Double North to South")  
                print("\n")
                         
#===================================================================

#===================================================================
def MGC3130_PrintMGC3130xyz():
        global _xyz
        global Last_X
        global Last_Y
        global Last_Z
 
        if (Last_X != _xyz.xyz.x):
                Last_X = _xyz.xyz.x
                sys.stdout.write("The X coordinate is: ")
                print(_xyz.xInt)
        if (Last_Y != _xyz.xyz.y):
                Last_Y = _xyz.xyz.y
                sys.stdout.write("The Y coordinate is: ")
                print(_xyz.yInt)
        if (Last_Z != _xyz.xyz.z):
                Last_Z = _xyz.xyz.z
                sys.stdout.write("The Z coordinate is: ")
                print(_xyz.zInt)
        print("\n")
#===================================================================

動作デモファイル Seeed_mgc3130.py

import sys
#修正点(ライブラリパスの修正)
sys.path.insert(0, "/usr/local/lib/python3.9/dist-packages/MGC3130")
import MGC3130
from MGC3130 import *
import RPi.GPIO as GPIO
import time

# 初期設定
MGC3130_SetAdd("/dev/i2c-1")
GPIO.setmode(GPIO.BCM)
MGC3130_Begin(GPIO, 8, 11)
# GPIO.cleanup()

while(True):
        # データ読取
        MGC3130_GetEvent()
        # rawデータから2byteずつ取出
        x = MGC3130._xyz.xyzArray[1] * 256 + MGC3130._xyz.xyzArray[0]
        y = MGC3130._xyz.xyzArray[3] * 256 + MGC3130._xyz.xyzArray[2]
        z = MGC3130._xyz.xyzArray[5] * 256 + MGC3130._xyz.xyzArray[4]
        print("{:>5},{:>5},{:>5}".format(x,y,z))
        time.sleep(0.01)

動作デモファイルを実行すると、取得したデータ表示されてスクロールされます。

f:id:ueponx:20211221234907p:plain

Telegram not managedという表示はジェスチャーがうまく認識できなかったことを指しています。表示がきれいでないのでpythonからもncursesを使用して整形するのが美しいでしょう。時間ができたらそのあたりにもチャレンジしたいです。

おわりに

Raspberry Pi用MGC3130搭載 3Dジェスチャー・トラッキングモジュールを使用してみたというエントリとなりました。このデバイスですが、使用には癖があるので操作インターフェースとしては少しむずかしい部類ではありますが、使えるようになれば色々な可能性がありそうです。トラックパッドのようにも使用可能ですし、入力した値やジェスチャーをプログラム側で変換することで、キーボードやマウスのようなデバイスの代わりにもできるかと思います。

ようやく、アドベントカレンダーのエントリを書き終えて安心しましたw

/* -----codeの行番号----- */