Файл: Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 14.06.2025
Просмотров: 3629
Скачиваний: 1
248 8 DRIVING MOTORS - DC & STEPPER
Switching[2] = 0x66;
Switching[3] = 0x96; break;
case BPHS: MaxIndex = 8; Switching[0] = 0x99; Switching[1] = 0x09; Switching[2] = 0x69; Switching[3] = 0x60; Switching[4] = 0x66; Switching[5] = 0x06; Switching[6] = 0x96; Switching[7] = 0x90;
}
}
void StepperMotor::Forward()
{
if(++CycleIndex == MaxIndex) CycleIndex = 0; WritePort0(Switching[CycleIndex]); delay(259-GetSpeed());
}
void StepperMotor::Reverse()
{
if(--CycleIndex == -1) CycleIndex = MaxIndex -1; WritePort0(Switching[CycleIndex]); delay(259-GetSpeed());
}
void StepperMotor::Brake()
{
switch(MotorType)
{
case UPFS: case UPHS: WritePort0(0x11); break;
case BPFS: case BPHS: WritePort0(0x99);
}
}
void main()
{
Motor *MotorPtr; int Selection;
8 DRIVING MOTORS - DC & STEPPER 249
clrscr(); |
|||
cout << endl << " |
MOTOR MENU"; |
||
cout << endl << " |
~~~~~~~~~~" << endl; |
||
cout << " |
1 |
DC Motor" << endl; |
|
cout << " |
2 |
UPFS" << endl; |
|
cout << " |
3 |
UPHS" << endl; |
|
cout << " |
4 |
BPFS" << endl; |
|
cout << " |
5 |
BPHS" << endl; |
|
cout << " |
6 |
QUIT" << endl; |
|
cout << endl; |
|||
cout << " |
Select the MOTOR Number: "; |
||
cin >> Selection;
switch(Selection)
{
case 1: MotorPtr = new DCMotor; break;
case 2: MotorPtr = new StepperMotor(UPFS); break;
case 3: MotorPtr = new StepperMotor(UPHS); break;
case 4: MotorPtr = new StepperMotor(BPFS); break;
case 5: MotorPtr = new StepperMotor(BPHS); break;
case 6: return;
default: cout << endl;
cout << " Unspecified Motor type...."; cout << " PRESS a key to END Program!"; getch();
exit(1); // Exits the program
}
if(MotorPtr == NULL)
{
cout << "Memory allocation failed " << endl; getch();
exit(1);
}
cout << "**********************************" << endl; cout << "* CONNECT BOARD POWER SUPPLY NOW *" << endl;
250 8 DRIVING MOTORS - DC & STEPPER
cout << "**********************************" << endl; cout << endl;
cout << " After connecting power,”;
cout << “ press a key to continue " << endl; getch();
cout << endl;
cout << " Keypress changes Speed/Rotation”; cout << “ (& Braking)." << endl;
//..... Motor control part starts here .....
MotorPtr->SetSpeed(150); while(!kbhit()) MotorPtr->Forward(); getch(); // clear keyboard buffer
MotorPtr->SetSpeed(220); while(!kbhit()) MotorPtr->Forward(); getch();
MotorPtr->SetSpeed(250); while(!kbhit()) MotorPtr->Reverse(); getch();
MotorPtr->SetSpeed(255); while(!kbhit()) MotorPtr->Reverse(); getch();
cout << endl << " Braking Applied!" << endl; while(!kbhit()) MotorPtr->Brake();
getch();
MotorPtr->Off();
//..... Motor control part ends here .....
// Free the memory occupied by the 'Motor' object delete MotorPtr;
}
Don’t be overwhelmed by the length of this program. In general, programmers create header files and library files to hide all the code that is shown ahead of the main() function. Had we done the same, the program to control any of the motors in our list would be the size of the main function.
Observe the motor’s behaviour without the effect of dynamic braking by commenting out the call to the Brake() function in Listing 8-19. This is best seen if the motor shaft has some inertial load connected to it.
If we did NOT use virtual functions, then the code to control the motors (shown in
8 DRIVING MOTORS - DC & STEPPER 251
Listing 8-10) will need to be included within each case of the switch statement in the main() function of Listing 8-13. The pointer used within each case will need to be declared to point specifically to an object for that particular case, and all functions will be linked at programming time (early binding). A main() function equivalent to that of Listing 8-13, but without the use of virtual functions is given in Listing 8-20.
Listing 8-20 main() function WITHOUT using virtual functions.
void main()
{
int Selection; DCMotor* DCMotorPtr;
StepperMotor* UPFSStepperMotorPtr; StepperMotor* UPHSStepperMotorPtr; StepperMotor* BPFSStepperMotorPtr; StepperMotor* BPHSStepperMotorPtr;
clrscr(); |
|||
cout << endl << " |
MOTOR MENU"; |
||
cout << endl << " |
~~~~~~~~~~" << endl; |
||
cout << " |
1 |
DC Motor" << endl; |
|
cout << " |
2 |
UPFS" << endl; |
|
cout << " |
3 |
UPHS" << endl; |
|
cout << " |
4 |
BPFS" << endl; |
|
cout << " |
5 |
BPHS" << endl; |
|
cout << " |
6 |
QUIT" << endl; |
|
cout << endl; |
|||
cout << " |
Select the MOTOR Number: "; |
||
cin >> Selection; cout << endl;
switch(Selection)
{
case 1: DCMotorPtr = new DCMotor; if(DCMotorPtr == NULL)
{
cout << "Memory allocation failed " << endl; exit(1);
}
cout << "**********************************" <<
endl;
252 8 DRIVING MOTORS - DC & STEPPER
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;
// DCMotor control part starts here DCMotorPtr->SetSpeed(150); while(!kbhit()) DCMotorPtr->Forward(); getch(); // clear keyboard buffer
DCMotorPtr->SetSpeed(255); while(!kbhit()) DCMotorPtr->Forward(); getch();
DCMotorPtr->SetSpeed(150); while(!kbhit()) DCMotorPtr->Reverse(); getch();
DCMotorPtr->SetSpeed(255); while(!kbhit()) DCMotorPtr->Reverse(); getch();
while(!kbhit()) DCMotorPtr->Brake();
DCMotorPtr->Off();
//DCMotor control part ends here
//Release memory occupied by the DCMotor object delete DCMotorPtr;
break;
case 2: UPFSStepperMotorPtr = new StepperMotor(UPFS); if(UPFSStepperMotorPtr == NULL)
{
cout << "Memory allocation failed " << endl; exit(1);
}
cout << "**********************************" <<
endl;
cout << "* CONNECT BOARD POWER SUPPLY NOW *" <<
endl;
cout << "**********************************" <<
8 DRIVING MOTORS - DC & STEPPER 253
endl; cout << endl;
cout << " After connecting power,”;
cout << “ press a key to continue " << endl; getch();
cout << " KEYPRESS changes SPEED/ROTATION (& Braking)." << endl;
// UPFS Motor control part starts here UPFSStepperMotorPtr->SetSpeed(150); while(!kbhit()) UPFSStepperMotorPtr->Forward(); getch(); // clear keyboard buffer
UPFSStepperMotorPtr->SetSpeed(220); while(!kbhit()) UPFSStepperMotorPtr->Forward(); getch();
UPFSStepperMotorPtr->SetSpeed(250); while(!kbhit()) UPFSStepperMotorPtr->Reverse(); getch();
UPFSStepperMotorPtr->SetSpeed(255); while(!kbhit()) UPFSStepperMotorPtr->Reverse(); getch();
while(!kbhit()) UPFSStepperMotorPtr->Brake();
UPFSStepperMotorPtr->Off();
//UPFS Motor control part ends here
//Release memory occupied by the DCMotor object delete UPFSStepperMotorPtr;
break;
case 3: UPHSStepperMotorPtr = new StepperMotor(UPHS); if(UPHSStepperMotorPtr == 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;
254 8 DRIVING MOTORS - DC & STEPPER
getch();
cout << " KEYPRESS changes SPEED/ROTATION (& Braking)." << endl;
// UPHS Motor control part starts here UPHSStepperMotorPtr->SetSpeed(150); while(!kbhit()) UPHSStepperMotorPtr->Forward(); getch(); // clear keyboard buffer
UPHSStepperMotorPtr->SetSpeed(220); while(!kbhit()) UPHSStepperMotorPtr->Forward(); getch();
UPHSStepperMotorPtr->SetSpeed(250); while(!kbhit()) UPHSStepperMotorPtr->Reverse(); getch();
UPHSStepperMotorPtr->SetSpeed(255); while(!kbhit()) UPHSStepperMotorPtr->Reverse(); getch();
while(!kbhit()) UPHSStepperMotorPtr->Brake();
UPHSStepperMotorPtr->Off();
//UPHS Motor control part ends here
//Release memory occupied by the DCMotor object delete UPHSStepperMotorPtr;
break;
case 4: BPFSStepperMotorPtr = new StepperMotor(BPFS); if(BPFSStepperMotorPtr == 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(); |
" |
KEYPRESS changes SPEED/ROTATION (& |
cout << |
||
Braking)." << endl; |
||
// BPFS |
Motor control part starts here |
|
8 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