Python+Microcontroller=Mouse
After working with the IR tracking I remembered about an accelerometer I had laying around. i decided to map the mouse to it instead. This way is a lot more efficient. It doesn't really touch the CPU and with the throttling isn't noticeable. It uses PySerial to read the debugged data from the chip. Win32api/win32con is used for the clicks, and windll.user32 for the mouse movements.
I have a video demonstration the use, its on face book so you might have to be a member to view it. here's the link http://www.facebook.com/#!/video/video.php?v=1236239189937&ref=nf
I know I probably should have posted this in the code bank, but I never get any responses there, I wouldn't be surprised if no one looked in there.
Here is the code that's loaded onto the chip:
' {$STAMP BS2}
' {$PBASIC 2.5}
x VAR Word
y VAR Word
DO
PULSIN 8, 1, x
PULSIN 7, 1, y
DEBUG LF, ? x , ? y , ? IN9, ? IN10
LOOP
And now for the python code:
#Accelorometer mouse (Basic Stamp 2)
#3-12-10
#Tech B.
from ctypes import *
import serial
import win32api
import win32con
s = serial.Serial('COM5') #Will differ between systems. I use Serial to USB cable
user = windll.user32
#inital x,y values
x = 0
y = 0
speed = 10
def lUP():
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
def lDOWN():
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
def rUP():
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP, 0, 0)
def rDOWN():
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0)
c1 = 0
#Main Loop
while 1:
try:
d = s.readline()
d = d.split()
if int(d[2]) > 2700:
if x < 1400:
x += speed
elif int(d[2]) < 2400:
if x > 0:
x -= speed
if int(d[5]) > 2600:
if y > 0:
y -= speed
elif int(d[5]) < 2400:
if y < 900:
y += speed
if int(d[8]) == 1 and c1 == 0:
lDOWN()
c1 += 1
elif int(d[8]) == 0:
lUP()
c1 = 0
if int(d[11]) == 1:
rDOWN()
rUP()
user.SetCursorPos(x,y)
except:
pass
A video would be nice( just saw it I don't have facebook), whats an accerometer driven mouse like? It seems liek to use it you'd need to be jerky but also it could be used in 3d?
I have so many questions…
Most of my mouse movements is more of a glide with only acceration at the beginging and end. Does this mean you have to continually be accerating to move your mouse? Have you thought about integrating the acceration to get velocity?
What chip are you using? Looks like a basic stamp from code.
If you put this on a pen, then you could track the tip or the top with a IR LED( you'd need two really) like your last thing and use g for orientation. that could be very useful. Essentially wii mote with lower accuracy.
Keep up the awesome work :)
edit: video explains alot.
It is BasicStamp2 specifically the Homework Board. The mouse movements are more of a stepper motion. It reads the values from the accelerometer and if the value is above or below the given threshold, 10 pixels is added to the mouses current position.
I plan on making headgear, the parts are in the mail now, and am waiting for a patent on my design.
There is now a video demonstrating the use on photobucket for those who don't believe me.
Link: http://s880.photobucket.com/albums/ac6/Tech_B/?action=view¤t=te.flv&newest=1
The video is kinda glitchy, I am trying out windows encoder as the screen capturing method. I don't like it. I've used CamStudio but its not the quality I want. Any suggestions for free screen capturing?
If I don't get a patent I'm going to pitch it to the school board, and hopefully it can be at least in school for handicapped/disabled to use a computer since the schools around here are emphasizing use of technology. If anything maybe they can make an intro class to programming and microcontrollers for high schools or middle schools.
Have you tried the double integrating the acceleration? All you'd have to do is add up the values.
So, you total up the values in each direction. then do the same again.
so, say, x_v += x x_d += x_v and x_d would give you how much the mouse has moved in the x-axis from the start poisition. Not sure if I'm explaining myself properly, but I'd like to see how accurate it is if you'd oblige? :)
wolfmankurd wrote: Have you tried the double integrating the acceleration? All you'd have to do is add up the values.
So, you total up the values in each direction. then do the same again.
so, say, x_v += x x_d += x_v and x_d would give you how much the mouse has moved in the x-axis from the start poisition. Not sure if I'm explaining myself properly, but I'd like to see how accurate it is if you'd oblige? :)
Yeah, I'm game. I just don't quite understand what your talking about. you could PM me with more detailed explanation of what you mean.
Demons Halo wrote: correct me if I'm wrong but I think he means that the longer you hold the device in a non horizontal position, the faster the arrow moves toward that direction?
Or am I wrong once again? :P pm'd. kind of. the chip outputs acceleration( or well force) right? so if you use that output to fiond out it's speed, you can then use that to find out how far it's moved. withthe help of some fudge factors which you might be able to get from it's value for g???
So long as the value is proportional( and hopefully linear) to the force on the chip it should work. If 1000 is the lowest factor then divide all values by 1000?
Another option would be divding the value it gievs under for gravity by 9.98 (as this is g) which would give you a conversion factor from pulse rate to m/s/s. well I think at least. Or by 1000 then by 9.98 might even be best.
x_d( displacement) and x_v(velocity) should initially be zero as the mouse has not moved and is not moving. but if the mouse starts displaced (say at the center of the screen but the oftware takes the corner to be the starting point then an initial displacement may be convienient.)
If you don't buy the maths I can show you proof but it wouldn't be particulaly interesting.
But if ya can't get it to work you can't get it to work. Thanks for trying. tempted to get a chip from sparkfun and try it out for myself
update: I'm being stupid, I have a wiimote and a bluetooth laptop also I wrote a python script years a go to get the aceleration data… I'll let you guys know if I get it working.video of that script in action wonder if I still have it it was in 2007 :/
techb wrote: I was thinking more of software.
how about this?
I heard about it during a radio program on IT, and the dev was interviewed in person, it seems pretty impressive, and free as well.
wolfmankurd wrote: So long as the value is proportional( and hopefully linear) to the force on the chip it should work. If 1000 is the lowest factor then divide all values by 1000?
Another option would be divding the value it gievs under for gravity by 9.98 (as this is g) which would give you a conversion factor from pulse rate to m/s/s. well I think at least. Or by 1000 then by 9.98 might even be best.
x_d( displacement) and x_v(velocity) should initially be zero as the mouse has not moved and is not moving. but if the mouse starts displaced (say at the center of the screen but the oftware takes the corner to be the starting point then an initial displacement may be convienient.)
If you don't buy the maths I can show you proof but it wouldn't be particulaly interesting.
But if ya can't get it to work you can't get it to work. Thanks for trying. tempted to get a chip from sparkfun and try it out for myself
update: I'm being stupid, I have a wiimote and a bluetooth laptop also I wrote a python script years a go to get the aceleration data… I'll let you guys know if I get it working.video of that script in action wonder if I still have it it was in 2007 :/
I belive you 100% on the math. I also kinda understand how it works. I just can't figure out how to get the accelerometer data to mouse data. I'm going to ask my math teacher to explain in detail tomorrow(er.. well today). I really thank you for helping.
And can anyone see my signature? I can't….
I got it working with the physics. It cam it me in class today.
v = accelValue
Leftthreshold = 2700
Rightthreshold = 2400
BaseSpeed
if v > Leftthreshold:
x += (v-Leftthreshold)/BaseSpeed
if v < Rightthreshold:
x -= (Rightthreshold-v)/BaseSpeed
The actual code looks like:
...
if int(d[2]) > 2700:
if x < 1400:
x += (int(d[2])-2700)/10
elif int(d[2]) < 2400:
if x > 0:
x -= (2400-int(d[2]))/10
if int(d[5]) > 2600:
if y > 0:
y -= (int(d[5])-2600)/10
elif int(d[5]) < 2400:
if y < 900:
y += (2400-int(d[5]))/10
...
This gives me the desired effect.
People wouldn't learn if they didn't ask questions. I don't think you could learn much from me though lol.
Its more about angle than gravity I guess. This is the accelerometers data sheet. http://www.parallax.com/dl/docs/prod/acc/memsickit.pdf
But I don't calculate g's; instead I base my calculations off of the pulse rate of the accelerometers two out-put pins. If the pulse rate goes above a set threshold value, I take the deference of the value from the accelerometer and the threshold number value-threshold.
If the rate goes below a threshold, I take the deference between the threshold and the accelerometer value threshold-value. That way it stays positive.
I divide the deference by 10 because it gives me more reasonable speed values. Because 2937 - 2600 = 337(actual test values). If I added 337 pixel values to the mouse position it will move 1/4 across my screen. And even then, people could be running at lower resolutions as me too(mines 1440 x 900). So if I divide 337 by 10 in python I get 33. I know 337/10 really is 33.7, but I'm using integers not floats.
The higher the tilt, the higher the deference, the higher the speed at which the mouse moves.
Yeah thanks :) Though, it sounds like rather than moving the mouse you just tilt it? My not just move it? Unless you actually move it it seems pointless to bother to integrate the acceleration. My point wasthat you oculd then have it so if a mouse moved an inch the onscreen cursour would move similarly (though that'd be ineffecient).