The mouse and keyboard are the basic input devices of a computer which can be connected with using PS2 protocol and nowadays with the help of the USB. The PS2 protocol is a simple two wire synchronous protocol which makes it possible for the simple microcontroller board to interface the standard PS2 mouse or keyboard with it. The PS2 mouse can continuously generate output data which contains the details of the movement in the X-Y plane and also the status of the buttons on it.
This particular project demonstrates how to find use the standard PS2 mouse as an accelerometer with the help of an Arduino board. The acceleration generated is indicated with the help of an LED and the corresponding value is displayed on the Serial Monitor window.
The AVR microcontroller boards which are provided with all the basic circuitry for the operation of the microcontroller which has been flashed with the Arduino boot-loader are called Arduino boards. The Arduino can communicate with the other devices using its digital I/O, serial port, I2C port, SPI port etc.The Arduino IDE is so simple to use that anyone who has basic knowledge of c programming can quickly get started with it. The project on how to get started with the Arduino explains about the steps required to get start with an Arduino board.
Fig. 2: Typical Arduino Pro-Mini Board
Fig. 3: Arduino IDE Software Window
Since the Arduino pro-mini board has no circuitary for interfacing it with the serial port or the USB port of the PC, an external USB to TTL converter board is required to connect it with the PC. This hardware helps in programming the Arduino board and also helps in the serial communication with the USB port of the PC.
Fig. 4: External USB to TTL converter board for programming Arduino and serial communication
It is assumed that the reader has gone through the project how to get started with the Arduino and tried out all the things discussed there.
The PS2 mouse uses a synchronous communication with the PC which is very much similar to the Two Wire Interface protocol. The PS2 connector has a pin for Data and another pin for Clock and using only these two pins the mouse communicate with the host device. The mouse always has 6 pin mini-DIN male connector for PS2 interface and the host device always has the corresponding female pin. The images and the pin-outs of the PS2 male and female connectors are shown in the following image;
The image of the PS2 male pin
Fig. 5: 6 pin mini-DIN Male connector for PS2 interface
The image of the PS2 female pin
Fig. 6: 6 Pin Mini DIN Female Connector Plug for PS2 interface
The pin-out of the PS2 male and female connectors
Fig. 7: Pin-Out Of PS2 Male and Female Connectors
When it comes to connecting the female connector with the circuit board one should be able to identify the pins at the bottom of the PS2 connector and the following image will be helpful.
Fig. 8: Bottom of Mini DIN Female Connector Plug for PS2 interface
The code reads the X and Y values from the PS2 mouse and it will take the difference between the present value and the previous values. The code takes average of the 10 such difference and hence get the average acceleration in both X and Y directions.
The value obtained is used to glow an LED with corresponding brightness using the functions analogWrite() which is explained in the previous projects on how to use analog input and analog output of Arduino board, how to use Arduino to display sensor values, how to make dynamic sensor display using Arduino.
The acceleration values are displayed on the Serial monitor window with the help of the functions Serial.begin(),Serial.print() and Serial.println() which are already discussed in previous projects on how to do serial communication with the Arduino, how to send and receive serial data using arduino and how to do serial debugging with the Arduino.
Make sure that the files “PS2Mouse.h” and “PS2Mouse.cpp” are kept in the same folder where the .pde file has been saved. When the coding is finished one can verify and upload the code to the Arduino board as explained in the project how to get started with the Arduino and can observe the variations in the X and Y acceleration values as the mouse moves and also can find the corresponding brightness indication in an LED.
Project Source Code
### /*============================ EG LABS ===================================// Demonstration on how to use PS2 MOUSE as an accelerometer with an arduino board The circuit: LCD: * LCD RS pin to digital pin 12 * LCD Enable pin to digital pin 11 * LCD D4 pin to digital pin 7 * LCD D5 pin to digital pin 6 * LCD D6 pin to digital pin 5 * LCD D7 pin to digital pin 4 * LCD R/W pin to ground * 10K resistor: * ends to +5V and ground * wiper to LCD pin 3 * LED anode attached to digital output 9 * LED cathode attached to ground through a 1K resistor MOUSE: DATA PIN TO PIN NUMBER 8 CLOCK PIN TO PIN NUMBER 3 ============================== EG LABS ===================================*/ #include "PS2Mouse.h" #define MOUSE_DATA 8 #define MOUSE_CLOCK 3 // include the library code: #include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins LiquidCrystal lcd(12, 11, 7, 6, 5, 4); // initialize the mouse library PS2Mouse mouse(MOUSE_CLOCK, MOUSE_DATA, STREAM); int i; int x_cur = 0; int y_cur = 0; int x_prv = 0; int y_prv = 0; int x_sum = 0; int y_sum = 0; const int analogOutPin = 9; int data[2]; void setup() { lcd.begin(16, 2); lcd.print("ENGINEERS GARAGE"); lcd.setCursor(0, 1); lcd.print(" PS2 MOUSE "); Serial.begin(38400); delay(2000); mouse.initialize(); // initialize the PS2 mouse connected with the ARDUINO board } void loop() { for( i = 0; i < 10; i ++) { mouse.report(data); // get data from the mouse x_cur = data[1]; // change in X position y_cur = data[2]; // chnage in Y position // ======== finding the acceleration ======== // x_sum += (x_cur - x_prv); y_sum += (y_cur - y_prv); x_prv = x_cur; y_prv = y_cur; } analogWrite(analogOutPin, (x_sum / 10)); // ======== finding the acceleration ======== // if((x_sum / 10) || (y_sum / 10)) { Serial.print("X_ACC = "); Serial.print((x_sum / 10)); // X acceleration Serial.print(", Y_ACC = "); Serial.print((y_sum / 10)); // Y acceleration Serial.println(); }else; x_sum = 0; y_sum = 0; } //*************PS2.h*************//
//#include "WConstants.h" #include "HardwareSerial.h" #include "PS2Mouse.h" #include "Arduino.h" PS2Mouse::PS2Mouse(int clock_pin, int data_pin, int mode) { _clock_pin = clock_pin; _data_pin = data_pin; _mode = mode; _initialized = false; _disabled = true; _enabled = false; } int PS2Mouse::clock_pin() { return _clock_pin; } int PS2Mouse::data_pin() { return _data_pin; } void PS2Mouse::initialize() { pull_high(_clock_pin); pull_high(_data_pin); delay(20); write(0xff); // Send Reset to the mouse read_byte(); // Read ack byte delay(20); // Not sure why this needs the delay read_byte(); // blank read_byte(); // blank delay(20); // Not sure why this needs the delay if (_mode == REMOTE) { set_remote_mode(); } else { enable_data_reporting(); // Tell the mouse to start sending data again } delayMicroseconds(100); _initialized = 1; } void PS2Mouse::set_mode(int data) { if (_mode == STREAM) { disable_data_reporting(); // Tell the mouse to stop sending data. } write(data); // Send Set Mode read_byte(); // Read Ack byte if (_mode == STREAM) { enable_data_reporting(); // Tell the mouse to start sending data again } if (_initialized) { delayMicroseconds(100); } } void PS2Mouse::set_remote_mode() { set_mode(0xf0); _mode = REMOTE; } void PS2Mouse::set_stream_mode() { set_mode(0xea); _mode = STREAM; } void PS2Mouse::set_sample_rate(int rate) { if (_mode == STREAM) { disable_data_reporting(); // Tell the mouse to stop sending data. } write(0xf3); // Tell the mouse we are going to set the sample rate. read_byte(); // Read Ack Byte write(rate); // Send Set Sample Rate read_byte(); // Read ack byte if (_mode == STREAM) { enable_data_reporting(); // Tell the mouse to start sending data again } delayMicroseconds(100); } void PS2Mouse::set_scaling_2_1() { set_mode(0xe7); // Set the scaling to 2:1 } void PS2Mouse::set_scaling_1_1() { set_mode(0xe6); // set the scaling to 1:1 } // This only effects data reporting in Stream mode. void PS2Mouse::enable_data_reporting() { if (!_enabled) { write(0xf4); // Send enable data reporting read_byte(); // Read Ack Byte _enabled = true; } } // Disabling data reporting in Stream Mode will make it behave like Remote Mode void PS2Mouse::disable_data_reporting() { if (!_disabled) { write(0xf5); // Send disable data reporting read_byte(); // Read Ack Byte _disabled = true; } } void PS2Mouse::set_resolution(int resolution) { if (_mode == STREAM) { enable_data_reporting(); } write(0xe8); // Send Set Resolution read_byte(); // Read ack Byte write(resolution); // Send resolution setting read_byte(); // Read ack Byte if (_mode == STREAM) { disable_data_reporting(); } delayMicroseconds(100); } void PS2Mouse::write(int data) { char i; char parity = 1; pull_high(_data_pin); pull_high(_clock_pin); delayMicroseconds(300); pull_low(_clock_pin); delayMicroseconds(300); pull_low(_data_pin); delayMicroseconds(10); pull_high(_clock_pin); // Start Bit while (digitalRead(_clock_pin)) {;} // wait for mouse to take control of clock) // clock is low, and we are clear to send data for (i=0; i < 8; i++) { if (data & 0x01) { pull_high(_data_pin); } else { pull_low(_data_pin); } // wait for clock cycle while (!digitalRead(_clock_pin)) {;} while (digitalRead(_clock_pin)) {;} parity = parity ^ (data & 0x01); data = data >> 1; } // parity if (parity) { pull_high(_data_pin); } else { pull_low(_data_pin); } while (!digitalRead(_clock_pin)) {;} while (digitalRead(_clock_pin)) {;} pull_high(_data_pin); delayMicroseconds(50); while (digitalRead(_clock_pin)) {;} while ((!digitalRead(_clock_pin)) || (!digitalRead(_data_pin))) {;} // wait for mouse to switch modes pull_low(_clock_pin); // put a hold on the incoming data. } int * PS2Mouse::report(int data[]) { write(0xeb); // Send Read Data read_byte(); // Read Ack Byte data[0] = read(); // Status bit data[1] = read_movement_x(data[0]); // X Movement Packet data[2] = read_movement_y(data[0]); // Y Movement Packet return data; } int PS2Mouse::read() { return read_byte(); } int PS2Mouse::read_byte() { int data = 0; pull_high(_clock_pin); pull_high(_data_pin); delayMicroseconds(50); while (digitalRead(_clock_pin)) {;} delayMicroseconds(5); // not sure why. while (!digitalRead(_clock_pin)) {;} // eat start bit for (int i = 0; i < 8; i++) { bitWrite(data, i, read_bit()); } read_bit(); // Partiy Bit read_bit(); // Stop bit should be 1 pull_low(_clock_pin); return data; } int PS2Mouse::read_bit() { while (digitalRead(_clock_pin)) {;} int bit = digitalRead(_data_pin); while (!digitalRead(_clock_pin)) {;} return bit; } int PS2Mouse::read_movement_x(int status) { int x = read(); if (bitRead(status, 4)) { for(int i = 8; i < 16; ++i) { x |= (1<<i); } } return x; } int PS2Mouse::read_movement_y(int status) { int y = read(); if (bitRead(status, 5)) { for(int i = 8; i < 16; ++i) { y |= (1<<i); } } return y; } void PS2Mouse::pull_low(int pin) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); } void PS2Mouse::pull_high(int pin) { pinMode(pin, INPUT); digitalWrite(pin, HIGH); }
###
Project Source Code
### #ifndef PS2Mouse_h #define PS2Mouse_h #define REMOTE 1 #define STREAM 2 class PS2Mouse { private: int _clock_pin; int _data_pin; int _mode; int _initialized; int _enabled; int _disabled; int read_byte(); int read_bit(); int read_movement_x(int); int read_movement_y(int); void pull_high(int); void pull_low(int); void set_mode(int); public: PS2Mouse(int, int, int mode = REMOTE); void initialize(); int clock_pin(); int data_pin(); int read(); int* report(int data[]); void write(int); void enable_data_reporting(); void disable_data_reporting(); void set_remote_mode(); void set_stream_mode(); void set_resolution(int); void set_scaling_2_1(); void set_scaling_1_1(); void set_sample_rate(int); }; #endif ###
Circuit Diagrams
Project Components
Project Video
Filed Under: Arduino Projects
Filed Under: Arduino Projects
Questions related to this article?
👉Ask and discuss on EDAboard.com and Electro-Tech-Online.com forums.
Tell Us What You Think!!
You must be logged in to post a comment.