Skip to content

Instantly share code, notes, and snippets.

@xkrishnam
Last active December 8, 2024 16:27
Show Gist options
  • Save xkrishnam/d50cd48ebcf07427d0475a32ae922113 to your computer and use it in GitHub Desktop.
Save xkrishnam/d50cd48ebcf07427d0475a32ae922113 to your computer and use it in GitHub Desktop.
experiment with mouse optical sensor

Using the ADNS-5090 Optical Mouse Sensor for Motion Tracking and Image Capture

Introduction

In this project, we explored the capabilities of the ADNS-5090 optical mouse sensor. From capturing image data to tracking motion in real-time, this versatile sensor offers a wealth of possibilities. Here's a detailed account of how we got it all working, with Arduino and Python.


Materials Needed

  • Arduino Uno
  • ADNS-5090 Optical Mouse Sensor
  • Breadboard and Jumper Wires
  • Computer with Arduino IDE and Python

Setting Up the Hardware

Begin by connecting the ADNS-5090 sensor to the Arduino Uno. Ensure all connections are secure, following this pin configuration:

ADNS-5090 Pin Arduino Uno Pin Notes
MISO 12 (MISO) SPI data output
MOSI 11 (MOSI) SPI data input
SCLK 13 (SCK) SPI clock
NCS 10 (CS) Chip Select
VDD 3.3V Power supply
GND GND Ground

Initializing the Sensor

First, we need to initialize the sensor. The Arduino sketch below does this by setting up SPI communication and initializing the ADNS-5090:

#include <SPI.h>

#define CS_PIN 10

void setup() {
  Serial.begin(115200);
  while (!Serial); // Wait for the Serial to initialize
  Serial.println("Initializing...");
  
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH); // Ensure CS is high
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV16); // Set SPI clock speed
  SPI.setDataMode(SPI_MODE3); // Set SPI mode
  
  // Initialize the sensor
  digitalWrite(CS_PIN, LOW);
  delay(100); // Hold reset low longer
  writeRegister(0x00, 0x80); // Reset command
  delay(100);
  writeRegister(0x00, 0x00); // End reset
  digitalWrite(CS_PIN, HIGH);
  delay(1000); // Extended delay for sensor initialization
  
  Serial.println("Sensor initialized");
}

void loop() {
  // Your main code here
}

byte readRegister(byte reg) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg);
  byte value = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  return value;
}

void writeRegister(byte reg, byte value) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x80); // Set MSB for write operation
  SPI.transfer(value);
  digitalWrite(CS_PIN, HIGH);
}

Capturing Image Data

Next, we set up the sensor to capture image data. Here’s how we read pixel values from the sensor:

#include <SPI.h>

#define CS_PIN 10
#define PIXEL_REGISTER 0x0b // Register for pixel data
#define IMAGE_WIDTH 19
#define IMAGE_HEIGHT 19

void loop() {
  byte image[IMAGE_HEIGHT][IMAGE_WIDTH];
  
  // Capture image data
  Serial.println("Reading pixel data:");
  for (int i = 0; i < IMAGE_HEIGHT; i++) {
    for (int j = 0; j < IMAGE_WIDTH; j++) {
      byte pixelValue = readRegister(PIXEL_REGISTER);
      if (pixelValue & 0x80) { // Check if pixel data is valid
        byte pixelData = pixelValue & 0x7F; // Mask out PG_VALID bit
        image[i][j] = pixelData;
      } else {
        image[i][j] = 0; // Mark invalid pixel as 0
      }
      writeRegister(PIXEL_REGISTER, 0x00); // Reset the grabber to origin
    }
  }
  
  // Print image data
  for (int i = 0; i < IMAGE_HEIGHT; i++) {
    for (int j = 0; j < IMAGE_WIDTH; j++) {
      Serial.print(image[i][j]);
      Serial.print("\t"); // Print with tab space
    }
    Serial.println(); // New line after each row
  }
  
  delay(5000); // Capture image every 5 seconds
}

Real-Time Motion Tracking

For real-time motion tracking, we read the motion data (dx, dy) and plot it using Python and matplotlib. Update your Arduino code to output motion data:

#include <SPI.h>

#define CS_PIN 10
#define MOTION_REGISTER 0x02
#define DELTA_X_REGISTER 0x03
#define DELTA_Y_REGISTER 0x04

void loop() {
  byte motion = readRegister(MOTION_REGISTER); // Read motion register
  if (motion & 0x80) { // Check if there is movement
    int dx = (int8_t)readRegister(DELTA_X_REGISTER); // Read delta X
    int dy = (int8_t)readRegister(DELTA_Y_REGISTER); // Read delta Y
    Serial.print(dx);
    Serial.print(",");
    Serial.println(dy);
  }
  delay(100); // Short delay between readings
}

Plotting Motion Data in Real-Time

Using Python, we can plot the motion data in real-time. Here's the Python script:

import serial
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Set up the serial connection (adjust the port and baud rate as needed)
ser = serial.Serial('COM3', 115200)  # Replace 'COM3' with your port

# Initialize the position of the point
current_x = 0
current_y = 0

fig, ax = plt.subplots()
point, = ax.plot([], [], 'ro')

def init():
    ax.set_xlim(-100, 100)  # Adjust limits based on expected motion range
    ax.set_ylim(-100, 100)
    return point,

def update(frame):
    global current_x, current_y
    if ser.in_waiting > 0:
        data = ser.readline().decode('utf-8').strip()
        if ',' in data:  # Check if the line contains motion data
            try:
                dx, dy = map(int, data.split(','))
                current_x += dx
                current_y += dy

                # Update the point's position
                point.set_data(current_x, current_y)
                
                # Update plot limits if necessary
                ax.set_xlim(current_x - 100, current_x + 100)
                ax.set_ylim(current_y - 100, current_y + 100)
            except ValueError:
                pass  # Skip lines that can't be parsed
    return point,  # Return a sequence of Artist objects

ani = FuncAnimation(fig, update, init_func=init, blit=True)
plt.show()

Conclusion

This project demonstrates how to leverage the ADNS-5090 sensor for capturing images and tracking motion. Whether for educational purposes or prototyping, the ADNS-5090 offers a versatile tool for exploring sensor technology.

Feel free to leave comments or reach out if you have any questions or suggestions. Happy tinkering!


I hope this helps! You can expand upon each section with more details or personal insights to make it even more engaging. Let me know if there's anything else you'd like to add or change!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment