Line 82: | Line 82: | ||
<br> | <br> | ||
===Calling inner functions of a class (Methods)=== | ====Calling inner functions of a class (Methods)==== | ||
Imagine we want to drive the left motor with full throttle whereas the right motor should stop completely. | Imagine we want to drive the left motor with full throttle whereas the right motor should stop completely. | ||
Line 95: | Line 95: | ||
A positive side effect: your program gains readability by picking distinct names for your Objects and Methods. | A positive side effect: your program gains readability by picking distinct names for your Objects and Methods. | ||
====Classes can contain other variables that can only be accessed „internally“==== | |||
How do the Objects „leftMotor“ and „rightMotor“ know which pins they want to switch on and off? | |||
Until now our „Motor“ class is quite abstract since it does not contain this information. | |||
A class that should conduct practical actions needs further variables (concrete pin numbers) and lines of code that describe what to do exactly. | |||
We can simply include both things in the class definition: | |||
'' | |||
class MotoMamaMotor { | |||
... | |||
private: // the following definitions are only of „internal use“ for the class itself | |||
int forwardPin; // c | |||
int reversePin; | |||
int throttlePin; | |||
... | |||
}; | |||
'' | |||
How do we include the pin numbers into the Object if they are not visible from the outside? | |||
We simply write a „setup“ Function for the class: | |||
'' | |||
class MotoMamaMotor { | |||
private: | |||
... | |||
public: // we want the setup-function to be accessible from the outside. | |||
void setup (int newForwardPin, int newReversePin, int newThrottlePin){ | |||
// we remember the pins for future use | |||
forwardPin=newForwardPin; | |||
reversePin=newReversePin; | |||
throttlePin=newThrottlePin; | |||
// and at the same time we initialize the outputs ! | |||
digitalWrite(throttlePin,LOW); // so that the motors don’t spin directly from the beginning .. | |||
pinMode(forwardPin,OUTPUT); | |||
pinMode(reversePin,OUTPUT); | |||
pinMode(throttlePin,OUTPUT); | |||
} | |||
... | |||
}; | |||
'' | |||
====A complete example ==== | |||
In order to construct a complete example we only have to include the „speed“-Function (see description above): | |||
// Defining a class for motor control | |||
class MotoMamaMotor { | |||
private: // the following definitions are only of „internal use“ for the class itself | |||
int forwardPin; //Every MotoMamaMotor type Object has its own forwardPin | |||
int reversePin; | |||
int throttlePin; | |||
public: // the following qualities and methods are visible from the outside. | |||
// This setup-Function has to be called before using the motor control | |||
void setup(int newForwardPin, int newReversePin, int newThrottlePin){ | |||
// we remember the pins for future use | |||
forwardPin=newForwardPin; | |||
reversePin=newReversePin; | |||
throttlePin=newThrottlePin; | |||
// and at the same time we initialize the outputs ! | |||
digitalWrite(throttlePin,LOW); // so that the motors don’t spin directly from the beginning .. | |||
pinMode(forwardPin,OUTPUT); | |||
pinMode(reversePin,OUTPUT); | |||
pinMode(throttlePin,OUTPUT); | |||
} | |||
// this Function allows to control the motor speed | |||
void setThrottle (int newThrottle){ | |||
if (newThrottle>0){ // should it spin forwards or backwards? | |||
// spin forwards | |||
digitalWrite(reversePin,LOW); | |||
digitalWrite(forwardPin,HIGH); | |||
}else{ | |||
// spin backwards | |||
digitalWrite(forwardPin,LOW); | |||
digitalWrite(reversePin,HIGH); | |||
} | |||
// adjust the speed: | |||
analogWrite(throttlePin, newThrottle); | |||
} | |||
}; | |||
// create two separate MotoMamaMotor type Objects (leftMotor, rightMotor). They can be used as normal variables. | |||
MotoMamaMotor leftMotor; | |||
MotoMamaMotor rightMotor; | |||
void setup(){ // this is our „main“ setup Function | |||
leftMotor.setup(3,4,5); // assign the pin numbers for each motor in the setup Function: setup(int newForwardPin, int newReversePin, int newThrottlePin) | |||
rightMotor.setup(6,7,8); | |||
}; | |||
void loop(){ // this is our „main“ loop Function where concrete actions are executed. For example: | |||
// Start backwards, slow down and accelerate forwards | |||
for (int i =-255, i<=255;i++){ | |||
leftMotor.setThrottle(i); | |||
rightMotor.setThrottle(i); | |||
}; | |||
// Start forwards, slow down and accelerate backwards | |||
for (int i =255, i>=-255;i--){ | |||
leftMotor.setThrottle(i); | |||
rightMotor.setThrottle(i); | |||
}; | |||
}; | |||
Organizing classes in separate files | |||
We can improve our program structure by putting classes in separate files. | |||
1) | |||
Click on the arrow in the right corner in order to add a new file. | |||
Select „new Tab“. | |||
----BILD---- | |||
2) | |||
Enter a filename at the bottom of the window. | |||
It must end with .h ! | |||
In our case I suggest the name motorControl.h. | |||
3) | |||
Enter the first line: | |||
#include „Arduino.h“ | |||
This line „links“ the file to the Arduino-specific features. | |||
Now we can include the code of our class. | |||
4) | |||
Go back to your main file. | |||
Now you have to „link“ the new file to your main file in order to use the features of our class. | |||
Include the following line in the top of your main file | |||
#include „MotorControl.h“ | |||
and write the rest of your program as usual. | |||
More details on the concept | |||
Classes can build up on each other (inheritance) | |||
In the beginning we promised that it is possible to replace different motor drivers without changing the rest of the program. | |||
Classes can indeed include other Objects in the form of „member variables“. | |||
C++ allows class declarations and the code for included Functions to be be placed in different files. | |||
If you want to know more about that you can read this article about creating libraries in Arduino: [http://arduino.cc/en/Hacking/LibraryTutorial http://arduino.cc/en/Hacking/LibraryTutorial ] |