Here is some of my first "proof of concept" code to use a PS/2 mouse to control two motors with PID.
Description of system Velleman K8000 I2C I/O board for D/A converters. Generic roller ball PS/2 mouse all hacked. Two kids ride-around toy motors. Mini-ATX (now called ITX) EPIA motherboard. Mandrake Linux 9.2
The code as follows:
i2cdev.cpp and i2cdev.h, I2C bus interface class k8000.cpp and k8000.h, k8000 inteface class. mouse.cpp and mouse.h, PS/2 mouse interface class mousecode.h, ps/2 mouse protocol codes.
mpwm.cpp, a hacked disaster of test code.
http://64.46.156.80/robot/mousrobot-050412.tar.gz You will not be able to compile this code "as is" because it is being built within a much larger code framework, but it shouldn't take much work, and the mouse, i2c, and velleman classes should require almost nothing. Feel free to post questions if you want to try it and get stuck.
The one interesting class is the "kbd" class used in mpwm.cpp, on Linux it wraps code for testing for a key present on the console and reading it. The important aspect of that code is:
Boolean MFKbd::iskey() { #ifdef Linux
int n; char ch; int result = FALSE;
TRACE_FUNCT("iskey");
if(m_waiting != EOF) result = TRUE; else { m_ionew.c_cc[VMIN]=0; tcsetattr(0,TCSANOW,&m_ionew); n = read(0,&ch,1); m_ionew.c_cc[VMIN]=1; tcsetattr(0,TCSANOW,&m_ionew);
if(n == 1) { m_waiting = ch; result = TRUE; } }
return result;
#elif defined( WIN32 ) return _kbhit(); #else return 0; #endif }
Theory of operation: (in mpwm.cpp)
Encoder is a virtual class to define a set of encoders. Ps2Encoder is an implementation of Encoder that uses the PS2 mouse interface class, Mouse. PIDControl is a class that implements PID control. In the function: CalcPID: PID stands for: Proportional, Integral, Derivitive error is the difference between target and actual. Propotional comes from the current error times a "gain" value. Integral comes from an accumulated error times a "gain" value. Derivitive comes from the difference between the previous error and current error times a "gain" value.
Loop operation:
Check if a key is hit, if so, read it and act on it. (Allows to play with the various gains and speed.) get current time of day. Update the encoder values. Calculate elapsed time from start Get the current encoder values. Scale them for elapsed time. calculate the PID. If a second has passed, print a report. (Test code, will not be there later.) Calculate the proper values for the motor control. Send them out if they are different than the last time. Save the current time as start. loop.