WiiMouse
The WiiMouse
Introduction
Components
Circuit Diagram
PIC Code
MATLAB Code
The initialization code opens up a graphical user interface with a single button, allowing the user to turn on and off mouse control. The figure that is called can be found here.
function varargout = wiimouse(varargin) gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... 'gui_OpeningFcn', @wiimouse_OpeningFcn, ... 'gui_OutputFcn', @wiimouse_OutputFcn, ... 'gui_LayoutFcn', [] , ... 'gui_Callback', []); if nargin && ischar(varargin{1}) gui_State.gui_Callback = str2func(varargin{1}); end if nargout [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); else gui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT % --- Executes just before wiimouse is made visible. function wiimouse_OpeningFcn(hObject, eventdata, handles, varargin) handles.output = hObject; guidata(hObject, handles); delete(instrfind) % --- Outputs from this function are returned to the command line. function varargout = wiimouse_OutputFcn(hObject, eventdata, handles) varargout{1} = handles.output; % --- Executes on button press in pushbutton1. function pushbutton1_Callback(hObject, eventdata, handles) %When button is clicked, do the following: delete(instrfind) if get(hObject, 'Value') %If button was toggled on: import java.awt.*; %Java bot that simulates mouse clicks import java.awt.event.*; %Java bot that simulates mouse clicks rob=Robot; %Assign Java bot functions to variable Rob s = serial('COM7','BAUD',9600); %Pick serial port sets fopen(s) %Open Serial port set(hObject, 'String', 'Stop Mouse control') %Change text in button to "Stop Mouse Control" hold_but = [0 0]; %Initialize with no buttons being held down screen_res = get(0, 'ScreenSize'); %Get screen resolution origin = [51 35]; %Pick mouse origin (when accx and accy produce min position) buffx = []; %Initialize position buffer in x direction buffy = []; %Initialize position buffer in y direction end %~~~Main Loop of Program~~~ while 1 %Keep running indefinitely if ~get(handles.pushbutton1, 'Value'); %If the button is toggled to off: set(hObject, 'String', 'Start Mouse control') %Change button text bacl to "Start Mouse Control" s = serial('COM7','BAUD',9600); %Get serial port settings fclose(instrfind); %Close the serial port delete(instrfind); %Delete the serial port break; %End While loop end %~~~Get Serial Data~~~ serial_data = fscanf(s); %Import serial data in the format 'Xdata Ydata LeftClick RightClick MouseMove' serial_data = str2num(serial_data); %Turn the serial data into numbers, a 5 x 1 matrix if length(serial_data) ~=5 %If bad data comes in. serial_data = fscanf(s); %Rescan serial_data = str2num(serial_data); %Turn into number array end pause(0.02) %Pause to allow time to loop through %~~~Move Mouse~~~ if length(serial_data)~=5 %If good data is still didn't come through serial_data(5) = 0; %Make all missing values zero end if ~serial_data(5) %If the side toggle button is not pressed if length(buffx) <10 %If the buffer has not been filled yet buffx = [buffx serial_data(1)]; %Add the new serial x value to the buffer buffy = [buffy serial_data(2)]; %Add the new serial y value to the buffer else %If the buffer has been filled buffx = [buffx(2:10) serial_data(1)]; %Delete the first point, add a new point to the end buffy = [buffy(2:10) serial_data(2)]; %Delete the first point, add a new point to the end end accx = mean(buffx); %Get the average of all buffered values accy = mean(buffy); %Get the average of all buffered values lastpt = get(0, 'PointerLocation'); %Get te previous cursor position posx = 5*(accx) + origin(1); %Scaling factor for x, and translation posy = 5*(accy) + origin(2); %Scaling factor for y, and translation diffx = posx - lastpt(1); %Get difference between last point and new point in x diffy = posy - lastpt(2); %Get difference between last point and new point in y nx=0; %Reset x movement step size ny=0; %Reset y movement step size if abs(diffx)> 15 %If the change in x position is large enough if lastpt(1) > posx %If the movement is negative nx = -1; %Make the x step size -1 else nx = 1; %If movement is positive, make x step size + 1 end end if abs(diffy)> 15 %If the change in y position is large enough if lastpt(2) > posy %If the movement is negative ny = -1; %Make the y step size -1 else ny = 1; %If movement is positive, make y step size + 1 end end for i= lastpt(2):ny:posy set(0, 'PointerLocation', [lastpt(1) i]) %This interpolates and moves cursor between actual acquired data end for i= lastpt(1):nx:posx set(0, 'PointerLocation', [i posy]) %This interpolates and moves cursor between actual acquired data end else %If the red side button is pressed accx = serial_data(1); %Still save acceleration data in x accy = serial_data(2); %Still save acceleration data in y origin(1) = posx - 5*accx; %Set the new origin based on new position, and current acceleration value origin(2) = posy - 5*accy; %Set new origin in y direction buffx = []; %Reset the buffer buffy = []; %Reset the buffer end %~~~Handle Left and Right Mouse Clicks~~~ if serial_data(3) && ~hold_but(1) %If a left click is detected, and the left button is not already down rob.mousePress(InputEvent.BUTTON1_MASK); %Using Java bot, left click down hold_but(1) = 1; %Remember that the left click is down elseif ~serial_data(3) && hold_but(1) %If the left click is not detected, and the left button was previously down rob.mouseRelease(InputEvent.BUTTON1_MASK); %Using Java bot, left click up hold_but(1) = 0; %Remember that the left click is up elseif serial_data(4) && ~hold_but(2) %If the right click is detected, and it is not already down rob.mousePress(InputEvent.BUTTON3_MASK); %Using Java bot, right click down hold_but(2) = 1; %Remember that the right click is down elseif serial_data(4) && hold_but(2) %If the right click is no longer detected, and the button was previously down rob.mouseRelease(InputEvent.BUTTON3_MASK); %Using Java bot, right click up hold_but(3) = 0; %Remember that the right click is up end end
Challenges
Wireless Communication
Initially, we sought out to use a bluetooth transmitter to interface with the computer. We discovered that bluetooth modules can be extremely expensive, compounded by the fact that we were not buying them by the thousands. The less expensive modules are extremely difficult to solder, as they are surface mount. The module we purchase had grooves on the side that fit wires nicely, however would not stick when soldered. This was part #497-5791-ND on the Digikey website. Thus, our experience with bluetooth was shortlived, and was limited to hardware only.
Xbee ended up being a very straightforward way of transmitting data by using the printf function discussed in this wiki page. Coupled with the the ttl232r USB to Serial cable, this provided an elegant way of displaying information from a COM port in windows.
Mouse Control in Windows
For the most robust mouse control, writing a driver is your best bet, however this can be very challenging. We found that there was not enough time, or resources to be able to write a device driver.
We also attempted to create an executible in Visual C++. In this case, we were able to achieve mouse control using the function SendInput to mimick mouse movement and clicks. Read about SendInput more in the msdn guide.