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のクリアランス(隙間)によっては、カーソルの動きがガタついたりしたので何個かつくって微調整。


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
コメント