ラズパイピコでマウスセンサーを使う。

ラズパイピコ

 Raspberry Pi Picoで、光学式マウスセンサー(MX8650A)を制御してみました。マウスのセンサーは秋月電子では見つけられず、aliexpressにはあるようですが、今回はダ○ソーの300円マウスから取り出して使っています(自作マウスを作るのにマウスを買ってきましたが、まぁ安いので)。

広告

使用する電子部品

 下記部品を使いました。

電子部品個数備考
1個Raspberry Pi Pico
1個光学式マウスセンサー
ダイ○ーで買ってきたマウスから取り出しました。センサ(MX8650)自体に加えて光学レンズ、10μF&100μFのコンデンサ、LED、抵抗も使われているものをそのまま使用。

 マウスから基板を取り出して、コントローラーを外して必要な部分を切り取りました。タクトスイッチもついてますが、それは使っていません。

配線・構成

 接続はMX8650のSDIOピン(Pin3)をRaspberry Pi PicoのGP18、SCLKピン(Pin4)をGP19、GNDピン(Pin6)をGND、VDDピン(Pin7)をGP17につないでいます。VDDピンはPicoの3V3(OUT)ピンでも良いです。コンデンサ、LED、抵抗は元の基板についていた物をそのまま使用。VDDAピン(Pin8)とGNDピンの間に10μF、VDDピンとGNDピンの間に100μF入っています。NCピン(Pin1)とMOTSWKピン(Pin2)は不使用です。

 3dプリンタで光学レンズと基板のホルダーを作りました。光学レンズとMX8650のクリアランス(隙間)によっては、カーソルの動きがガタついたりしたので何個かつくって微調整。

hdr

CircuitPythonのコード

 MX8650を動かすコードはこちらを参考にしました。
 readRegisterにアドレスを渡すと、MX8650からデータを読み出せます。またwriteRegisterにアドレスとデータを渡すことで、MX8650の設定を変更できます。アドレスやデータについてはMX8650のデータシートを参照しました。

#OptiMouse.py

import digitalio
from board import *
import time

class OptiMouse:
    
    sclkPin = digitalio.DigitalInOut(GP19)
    sdioPin = digitalio.DigitalInOut(GP18)
    
    #コンストラクタ
    def __init__(self):        
        self.sclkPin.direction = digitalio.Direction.OUTPUT
        self.sdioPin.direction = digitalio.Direction.INPUT
        self.sdioPin.pull = digitalio.Pull.DOWN
        
    #micro秒sleep
    def microsleep(self, microsec):
        now = time.monotonic_ns()
        flag=True
        while flag==True:
            if (now+microsec*1000) < time.monotonic_ns():
                flag=False
    
    #MX8650の開始
    def begin(self):
        self.sclkPin.direction = digitalio.Direction.OUTPUT        
        #センサを同期させる
        self.sclkPin.value=1
        self.microsleep(5)
        self.sclkPin.value=0
        self.microsleep(1)
        self.sclkPin.value=1
        self.microsleep(1000000)

    #MX8650からデータを読み込む
    def readRegister(self, address):
        self.sclkPin.direction = digitalio.Direction.OUTPUT        
        #アドレスを書き込む
        self.sdioPin.direction = digitalio.Direction.OUTPUT  
        for i in reversed(range(8)):
            self.sclkPin.value=0
            self.sdioPin.value=(address & (1 << i))
            self.sclkPin.value=1
        #データを読み出す
        self.sdioPin.direction = digitalio.Direction.INPUT
        self.sdioPin.pull = digitalio.Pull.DOWN
        #self.microsleep(0)
        r = 0
        for i in reversed(range(8)):
            self.sclkPin.value=0
            self.sclkPin.value=1
            r |= (self.sdioPin.value << i)
        self.microsleep(100)
        return r;

    #MX8650にデータを書き込む
    def writeRegister(self, address, data):
        self.sclkPin.direction = digitalio.Direction.OUTPUT  
        #MSB(最上位ビット)をhighにし書き込みモードにする
        address |= 0x80
        #アドレスを書き込む
        self.sdioPin.direction = digitalio.Direction.OUTPUT 
        for i in reversed(range(8)):
            self.sclkPin.value=0
            self.sdioPin.value=(address & (1 << i))
            self.sclkPin.value=1
        #データを書き込む
        for i in reversed(range(8)):
            self.sclkPin.value=0
            self.sdioPin.value=(data & (1 << i))
            self.sclkPin.value=1

上記のクラスを以下のように使用しました。

import usb_hid
from adafruit_hid.mouse import Mouse
import time
import math
import digitalio
from board import *
import OptiMouse

mouse = Mouse(usb_hid.devices)

#電源ON
vddPin = digitalio.DigitalInOut(GP17)
vddPin.direction = digitalio.Direction.OUTPUT
vddPin.value=True

#MX8650の準備
mx8650=OptiMouse.OptiMouse()
mx8650.begin()
#CPIを1200に変更
mx8650.writeRegister(0x06,6)

while True:  
    motionstatus=mx8650.readRegister(0x02)
    time.sleep(0.001)
    s8dx=mx8650.readRegister(0x03)
    s8dy=mx8650.readRegister(0x04)
    dx=-(s8dx & 0b10000000) | (s8dx & 0b01111111)
    dy=-(s8dy & 0b10000000) | (s8dy & 0b01111111)
    mouse.move(dx, -dy, 0)

#電源OFF
vddPin.value=False

動作の様子

コメント

タイトルとURLをコピーしました