Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)
.pdf8 DRIVING MOTORS - DC & STEPPER 255
BPFSStepperMotorPtr->SetSpeed(150); while(!kbhit()) BPFSStepperMotorPtr->Forward(); getch(); // clear keyboard buffer
BPFSStepperMotorPtr->SetSpeed(220); while(!kbhit()) BPFSStepperMotorPtr->Forward(); getch();
BPFSStepperMotorPtr->SetSpeed(250); while(!kbhit()) BPFSStepperMotorPtr->Reverse(); getch();
BPFSStepperMotorPtr->SetSpeed(255); while(!kbhit()) BPFSStepperMotorPtr->Reverse(); getch();
while(!kbhit()) BPFSStepperMotorPtr->Brake();
BPFSStepperMotorPtr->Off();
//BPFS Motor control part ends here
//Release memory occupied by the DCMotor object delete BPFSStepperMotorPtr;
break;
case 5: BPHSStepperMotorPtr = new StepperMotor(BPHS); if(BPHSStepperMotorPtr == NULL)
{
cout << "Memory allocation failed " << endl; exit(1);
}
cout << "**********************************" <<
endl;
cout << "* CONNECT BOARD POWER SUPPLY NOW *" <<
endl;
cout << "**********************************" << endl; cout << endl;
cout << " After connecting power,”;
cout << “ press a key to continue " << endl; getch();
cout << " KEYPRESS changes SPEED/ROTATION (& Braking)." << endl;
// BPHS Motor control part starts here BPHSStepperMotorPtr->SetSpeed(150); while(!kbhit()) BPHSStepperMotorPtr->Forward(); getch(); // clear keyboard buffer
256 8 DRIVING MOTORS - DC & STEPPER
BPHSStepperMotorPtr->SetSpeed(220); while(!kbhit()) BPHSStepperMotorPtr->Forward(); getch();
BPHSStepperMotorPtr->SetSpeed(250); while(!kbhit()) BPHSStepperMotorPtr->Reverse(); getch();
BPHSStepperMotorPtr->SetSpeed(255); while(!kbhit()) BPHSStepperMotorPtr->Reverse(); getch();
while(!kbhit()) BPHSStepperMotorPtr->Brake();
BPHSStepperMotorPtr->Off();
//BPHS Motor control part ends here
//Release memory occupied by the DCMotor object delete BPHSStepperMotorPtr;
break;
case 6: return;
default: cout << endl;
cout << " Unspecified Motor type...."; cout << " PRESS a key to END Program!"; getch();
exit(1); // Exits the program
}
}
As you can see, coding without the use of virtual functions can be quite inefficient. Note: the delete operator was used in Listing 8-10, Listing 8-13, and Listing 8-20 to relinquish the dynamically allocated memory that stored the ‘motor’ object.
8.7 Keyboard Controls
We can enhance control of the motor by making use of the PC keyboard. To do this the program must be able to detect each press of the keys used for motor control purposes. These key presses can be detected using several methods. The easiest method is to use the getch() or the getche() functions. Another option is to use the library function kbhit().
8 DRIVING MOTORS - DC & STEPPER 257
The functions getch() and getche() as their names imply, can be used to read the character corresponding to the key pressed. The function getche() has the extra capability of being able to display the character on-screen as it is read. This is known as echoing to the screen (the added ‘e’ stands for ‘echo’). However, there is a disadvantage to using these two functions being that they wait for a key press. Execution of a getch() function will not allow following statements to be executed until a key is pressed. This delay will prevent us from generating the fast changing signals needed for motor control.
The kbhit() function operates differently. It does not wait for a key press. It checks if a key has been pressed. If a key has been pressed, the function will return true, if not it will return 0, meaning false. Because it does not wait for a key press, the program will execute continuously as intended. Note that kbhit() does not clear the keyboard buffer (ready for the next time it needs to be used).
The built-in library also provides another function named bioskey() used to detect normal keys with an ASCII code (see Appendix B) or extended keys such as function keys, INS, DEL keys etc. Extended keys are identified by a two-byte key code whereas normal keys are identified by a one-byte key code.
The function bioskey() can operate in different modes depending on the parameter passed to it. It uses one integer parameter whose value determines if it will detect a key press like the kbhit() function or read the pressed key. Note that this function does clear the keyboard buffer when used to read a key.
We can read a special location in memory using the peekb() function to detect keys including Right Shift, Left Shift, Ctrl, Alt, Caps lock, Scroll lock, etc. Note that the peekb() function cannot detect some keys such as the arrow keys.
The byte read from this memory location has flags (bits, shown in Figure 8-27) that are used to indicate which keys are pressed at any given time. The peekb() function is the fastest to execute and will generate minimum disruption to the continuous execution of the program. Therefore, using peekb() will enable smooth operation of the motors. If slower functions were used to read the keyboard, motor control could be erratic.
We will use the peekb() function to add keyboard control to our program using the following combinations of keys:
ξ |
Pressing the Ctrl key will drive the motor forward. |
ξ |
Pressing the Alt key will drive the motor in reverse. |
ξ |
Pressing the Right Shift key will increase speed. |
ξ |
Pressing the Left Shift key will decrease speed. |
ξ |
Pressing both Left Shift and Right Shift keys brakes the motor. |
ξ |
Pressing No keys will switch motor power off. |
ξ |
Pressing the Insert key will end the program. |
The status of the Shift keys, Control key, Alt key and the Insert key can be determined by reading a special memory location using peekb(). This 8-bit
258 8 DRIVING MOTORS - DC & STEPPER
memory location is at the segment:offset address of 0x40:0x17. When the respective key is pressed, its bit will be 1. For an explanation of segment:offset addressing, see Technical Reference: Personal Computer AT by IBM Corporation.
Byte at 0x40:0x17
|
7 |
6 |
5 |
|
4 |
3 |
2 |
1 |
0 |
|
Insert |
|
|
|
|
|
|
|
|
Right shift |
|
Caps lock |
|
|
|
|
|
|
|
|
Left shift |
|
Num lock |
|
|
|
|
|
|
|
|
Ctrl |
|
|
|
Scroll lock |
|
|
Alt |
|
|
|
Figure 8-27 Memory byte at 0x40:0x17 used to store key status.
A while loop is implemented in the program segment shown in Listing 8-21 which will run continuously provided the variable Quit is 0. This listing can be viewed as a replacement for Listing 8-10.
Listing 8-21 Motor control using a keyboard.
Motor *MotorPtr;
int Quit = 0;
unsigned char key = 0; int SpeedLock = 1;
while(!Quit)
{
key = peekb(0x40,0x17); // Read control key byte. if(key & 0x80) // Test Insert key ON (MSBit '1').
Quit = 1; // Exit the program.
else
{
//If both shift keys are released SpeedLock is
//released
if(!(key & 0x01) && !(key & 0x02)) SpeedLock = 0;
key &= 0x0F; // Filter out bits corresponding to
8 DRIVING MOTORS - DC & STEPPER 259
// just SHIFT, ALT & CTRL keys.
switch(key)
{
case 0x04 : MotorPtr->Forward(); break;
case 0x08 : MotorPtr->Reverse(); break;
case 0x01 : if(!SpeedLock)
{
MotorPtr->SetSpeed(MotorPtr->GetSpeed()+4); SpeedLock = 1;
}
break;
case 0x02 : if(!SpeedLock)
{
MotorPtr->SetSpeed(MotorPtr->GetSpeed()-4); SpeedLock = 1;
}
break;
case 0x03 : MotorPtr->Brake(); break;
case 0x05 : if(!SpeedLock)
{
MotorPtr->SetSpeed(MotorPtr->GetSpeed()+4); SpeedLock = 1;
}
MotorPtr->Forward(); break;
case 0x06 : if(!SpeedLock)
{
MotorPtr->SetSpeed(MotorPtr->GetSpeed()-4);