My Pi Description

My Experiences With the Raspberry Pi -- Tracking My Learning -- My Pi Projects

Tuesday, March 18, 2014

Writing An Arduino Library

My last post included a script for controlling the angle of rotation of a small dc servo. That script expects the user to input a floating point number from the terminal. I wanted that script to concentrate on the servo code, so to avoid encumbering the script with the process of handling the user's input, I put the input handling code into a library. Never having created a library, I wanted to learn how that is done. I read several tutorials but they all seemed rather simplistic. One of my concerns was how to pass values between the code that uses the library and the library functions themselves. I started with simple functions and built on those until I arrived at the function I needed for the servo
When you use the Arduino "Serial.read()" function to read from your terminal, you get only one character from each call. If you need more than one character, you need successive reads and a way to put those characters together into something meaningful. You also need to know when the last character was entered and some way to deal with characters entered in error. My servo script wants the user to input positive or negative floating point numbers of indeterminate length.
Note added June 22, 2014 concerning the last paragraph. If you use an Arduino instead of the Gertboard, you can use the serial monitor provided by the Arduino IDE. This serial monitor works quite differently. Rather than only returning one character for each call, it buffers your key presses and returns all of the characters when you hit "enter". In switching my next project from the Gertboard to the Arduino I had to modify the library created below to accommodate this change. See my post of June 15, 2014.

Final Script

Figure 1 below is my final script to control the servo. This is the same as in my previous post. The leading comments in that script were all about making the servo work so I removed them here. This script uses the library I wrote. You cannot see any of the details associated with inputting the floating point number. Only two lines, 2, 4, and 26 deal with the library:
FIGURE 1: Final Script - Without Leading Comments

Getting Started Making A Library

First, you develop the code, as usual, in a script using the Arduino IDE. Identify the parts of the code that will eventually be part of your library: functions, commands, and variables. Make sure there is test code that thoroughly tests the soon-to-be library. Compile and upload this script to make certain it will run properly. Try to break the code by changing conditions.
My test code is the code to control the servo. Figure 2 is my script. I call it my all inclusive script because it contains everything, in one script: the code to input numbers and code to control the servo:
Figure 2: Original All Inclusive Script - No Leading Comments
Most of the code (lines 3 to 68) deals with inputting the floating point number and just a few lines with the servo control.
The code to handle inputting the number accepts any digit, accepts a minus sign only if it is the first character, accepts one, and only one, decimal point, and accepts the backspace key to make a correction. All other characters are ignored. The function returns the floating point number to the calling code. This is not a perfect solution. I don't have a way to correct individual characters. When the backspace key is pressed, a space prints on the terminal after the last character, and the entire number must be entered from scratch.
I think it is pretty clear how the code works so I won't dwell on the details. We have two functions "termNumb()" and "clearVars()", and several variables. "clearVars()" is only called from "termNumb(). "termNumb()" is called from the program in line 91. The variables (lines 3 - 5), one int, three floats, and three boolean are needed by both functions so are global.

Now We Give The Code Some Class

Now that the code is working and tested as thoroughly as possible, it is time to define a class. We will tie those soon-to-be library functions to that class as well as those global variables we spoke about above. This script still contains the test code for controlling the servo. Figure 3 is the new script:
Figure 3: The Script With Class
At the top we create a class called "TERMNUMB". A class defines a data type (like an int or float). Elements you give that class are available to use when you use this class in other code. The elements of our data type, "TERMNUMB", are three functions (or methods): "TERMNUMB()", "termNumb()" and "clearVars()" and seven variables. The first two functions are declared as "Public" meaning they can be accessed by other code outside of the code that implements the class. The function "clearVars()" and the seven variables are declared as "Private" which means they are not known to code that call this class, but are seen by the functions declared in the class. There is no need for "clearVars()" to be public since it is only called from "termNumb()"
The functions "termNumb()" and "clearVars()" are the same as seen in the original, all inclusive, script as seen in Figure 2. "TERMNUMB() is new and is a special type of function called a constructor. Notice it has no return type and its name is exactly the same as the name of the class. The constructor is the first thing you see in the code below the class creation.
Note the function "termNumb()" has a float return type. When called, the function will return a floating point number to the calling program.
"TERMNUMB" class also declares seven variables and these variables, as indicated above, are declared as private. Notice these are the same variables declared in Figure 2, the all inclusive script above. I have added an underscore to the names of these variables. This differentiates them from variables that are declared within the functions themselves (like inChar).
Now that the class is created we define the three functions referenced in the class. The first function to be defined (line 14) is the constructor introduced above. Notice, in this example, there is no code associated with this function. The purpose of this function is to create an instance of the class "TERMNUMB". The way we associate "TERMNUMB()" to our class "TERMNUMB" is to use this strange syntax "::". The structure "::" is called the scope resolution operator and it says that "TERMNUMB()" is within the scope of class "TERMNUMB". The same must be done for our two other functions. "clearVars()" in the all inclusive script (Figure 2) becomes "TERMNUMB::clearVars()". "termNumb()" becomes "TERMNUMB::termNumb()".
The code from lines 17 through 78 define the implementation of our two functions "TERMNUMB::clearVars()" and "TERMNUMB::termNumb()". The code is nearly identical to the code in the all inclusive script (Figure 2) lines 7 - 68. The only differences are in the function names, just discussed, and the underscore attached to the names of the private variables.
We have created a class and defined the workings of the functions in that class. Now it's time to use it in our code to control our servo. Like declaring any type of variable, such as an int or float, we declare our class. This is done in line 80. We are declaring "inFromTerm" to be of type "TERMNUMB". One of the elements in "inFromTerm" is the function "termNumb()". That is exactly what we need to get the floating point number that becomes the angle our servo is to steer to. All of the work we have done culminates in line 102. The variable "angle" will be the return value from member "termNumb()" of data type "inFromTerm".
Make sure you compile and upload this code. Test it to make sure it works as desired.

Making the Library Files

The hard work is done. What remains is to create two files. These two files will constitute the library. Essentially, they will be cut-and-pasted from file in Figure 3 above. The first file is the header file with a .h extension. The second is the object file that has a .cpp extension.
Unfortunately, you can not make these files from the Arduino IDE because it only allows you to save a file with an .ino extension. You will have to use one of the text editors available with your Linux distribution like nano, vi, or leafpad to create, edit, and save the two files.

Header File

Figure 4, below, is the header file:
Figure 4: Header File InputNumbFromTerminal.h
As you can see, lines 22 - 31, in the header file, are exactly the same as lines 3 - 12 in Figure 3 above. Note we have added some comments to describe how the class will function.
Lines 17, 18, and 33 prevent "TERMNUMB" from defining multiple times and from creating duplication in the final binary file. Those lines assure that the class will only be created if it had not been created before. This is standard practice when creating header files.
Line 20 is absolutely necessary if your object code uses any of the special Arduino functions available from the Arduino IDE. In our case, that includes "Serial.read()" and "Serial.print()". If you have a pre Arduino 1.0 IDE you would use WProgram.h instead of Arduino.h.

Object File

The object file follows:
Figure 5: Object File InputNumbFromTerminal.cpp
The object file,Figure 5, "InputNumbFromTerminal.cpp" is the implementation of the class "TERMNUMB". Lines 4 - 68 are exactly the same as lines 14 - 78 in Figure 3 above. In lines 1 and 2, we include the two header files: Arduino.h (WProgram.h for pre Arduino 1.0 IDE), and the header file we just created, InputNumbFromTerminal.h.
Notice that the variables declared in lines 3 - 5 in the original, all inclusive, script (Figure 2) are not declared in the object file. Instead, these are the private variables declared in the header file. In the object file, they appear with the same names except they include the underscore as their last character.
None of the code to control the servo can be found in either the header or object files. No test software is included. That is why the testing is done before making the library files.

The Header and Object Files Are Now Created - What's Next

The library, consisting of the header and object files, must be placed in the correct location in your file structure. For the RaspberryPi, all user libraries must go into the "/home/pi/Sketchbook/libraries/" directory or a subdirectory of "home/pi/Sketchbook/libraries/".
VERY IMPORTANT:Once your files are located within the proper directory structure, you must close your Arduino IDE and any files open in the Arduino IDE. Only then, when you reopen the Arduino IDE, can your library be accessed by other code.

Putting It All Together - Revisiting The Final Sketch

I'm going to repeat the final sketch here in Figure 6 showing how we use the library to input the floating point number.
Figure 6: Final Script - Without Leading Comments
To access the library to input the floating point number we include the header file. This is done in line 2. Note we have declared "inFromTerm" to be of the data type "TERMNUMB". We also used "inFromTerm" in the code Figure 3. We did not have to use the same name. If we had called it something else in the final sketch we would need to match that name in line 26.

Quick Example Of Passing Values To A Library

Before I developed a library, I was not certain how you pass values to a library and how you pass a value from a library. The library above shows how the latter is done, but not the former. I have a really simple library that accepts two integers from a calling program, adds them together and prints the result to the terminal. The following are the header file, the object file, and the script using the library:
Figure 7: Header File
Figure 8: Object File
Figure 9: Script Calling The Library
Note, unlike in the library created above, we actually have some code within the constructor REALSIMPLE::REALSIMPLE().
I hope this tutorial has been helpful.

Thursday, March 6, 2014

Gertboard - Pulse Width Modulation - Servo Control

This is really a continuation of my last post. This post carries Pulse Width Modulation further by considering the control of a servo.
There are two types of small servos: a standard type and continuous type. This post describes the standard servo. This is the servo I purchased from Adafruit.
The standard servo has a shaft that rotates to a desired position and stops rotating once that position is attained. It can rotate 180°, or 90° in each direction from a neutral position.
It has a DC motor that connects through a series of gears to the shaft of a potentiometer, a device producing a variable electrical resistance. An extension of the potentiometer shaft is the output shaft of the servo. The set of gears between the motor and the potentiometer significantly reduces the speed of the motor and significantly increases its torque.
As the motor turns the potentiometer shaft, the resulting change in resistance produces a change in voltage. Let's call this voltage "A". Another voltage is produced that comes from translating the width of input pulses to voltage. The input pulses come from your ATmega microcontroller and represent the desired shaft position of the servo. Let's call this voltage "B". Voltages "A" and "B" are compared in a feedback circuit within the servo. As long as voltage "A" does not equal voltage "B", the feedback circuit produces a voltage to turn the motor either CW or CCW. When the motor has rotated the potentiometer to the point where the voltage "A" equals voltage "B", the control circuit stops the motor. As long as voltage "B" does not change, the output shaft will not rotate. A small servo usually can prevent a fair amount of external torque from turning the shaft.
Photo Found On Several Sites Servo As Found On Adafruit's Website
The other type is the continuous servo. This type turns continuously and the PWM controls the direction and speed of rotation. This may be a good alternative to a toy motor as it will be geared down for a more manageable speed range.
The ATmega328P will produce the pulses required by the servo using its Pulse Width Modulation features. In my last post, controlling a DC motor, the pulse repetition frequency was not very critical. This is not the case with the servo. The servo requires a pulse repetition frequency of 50Hz. We need a pulse every 20ms. The pulse duration is also specified and is in the range of 0.5ms. to 2.5ms. All the documentation I had seen for this type of servo specified the range to be 1.0ms. to 2.0ms. My particular servo, purchased from Adafruit, did not come with a data sheet, but apparently has better resolution than the typical unit. Programming from 1.0ms. to 2.0ms. did not turn the shaft 180°. Programming from 0.5ms. to 2.5ms. (confirmed by my oscilloscope) did produce 180° of rotation.
Forget about using the Arduino AnalogWrite() function. This function provides a fixed frequency of either 490Hz or 980Hz depending on the I/O pin. We need 50Hz. for servos.
The discussion below describes my system with a 12MHz clock frequency, and my servo that has a 0.5ms. to 2.5ms. pulse duration range. If your system is different you will have to make the appropriate adjustments.
The first decision we have to make is what timer/counter and prescaler value to use. The decision will be based on having adequate resolution of the angle of rotation. Since we know the frequency of pulse repetition we can rearrange the formula found in my last post. This gives us two unknowns: the maximum count and the prescaler value.
pulse repetition freq = clock speed / (2 * prescaler * max count)
Substituting the known values:
50 = 12,000,000 / (2 * prescaler * max count)
Rearranging and simplifying:
max count = 120,000 / prescaler
The range in pulse width is 2.0ms (2.5ms. at +90° minus 0.5ms. at -90°). This is one tenth of the 20ms. pulse repetition rate (1/50 x 1000). Therefore, the range of programmable count values is one tenth of the maximum count. The rotation resolution is the range of motion of the servo, 180°, divided by the count range. This is summarized below:
Prescaler Max Count Pulse Width Count Range Rotation Resolution
1 120,000 N/A N/A
8 15,000 1500 0.12°
64 1875 187.5 0.96°
256 468.8 46.8 3.84°
1024 117.2 11.7 15°
From the chart above we can eliminate the prescaler value of 1 because the ATmega328 does not provide a timer/counter that can count to 120,000 (65535 or 255). The only way to employ an eight bit timer/counter (timer/counter 0, or 2) is to use the prescaler value of 1024 - the only choice where the maximum count is under 255. However, the resolution of 15° is poor. This means that we will use timer/counter 1 because it can count to 65535. We should go for the best resolution which means that we will use the divide by 8 prescaler. This gives a resolution of 0.12° per count
Next we select the mode. We will select mode 8, the "Phase and Frequency Correct PWM" mode. The value of the maximum count will be programmed into register 1CR1.
The script I wrote is below and the details of register programming is included within the comments. The script requires you to open a terminal window on the host computer - the Raspberry Pi in my case. You are asked to input a floating point number which is the desired degrees of rotation from the middle position. The script accepts values from -90° to +90°. Once it rotates the servo shaft to the angle you requested, it will ask for your input, again.
Inputting a number from the terminal is not a trivial endeavor. The terminal handles one character at a time and it is up to the programmer to make sense of those characters. I did not want the script to be encumbered with the handling of the character inputs so I wrote a library to do that task. I wanted to learn how to do that, anyway, having not done that before. There are only three lines dealing with the character input: line 35 where we include the library dot h file, line 37 where we create an instance of the class created in the library, and line 59 where we call the function to get our number. My next post will report on creating that library function.
The servo has three pins, two go the battery to power the device, and provide a ground reference, and the third is the control pin which receives the output from the ATmega328. Don't forget to connect the ground pin from the battery to one of the grounds of the Gertboard.
The script:

Monday, March 3, 2014

Gertboard - Pulse Width Modulation - DC Motor Control

This post is about using the ATmega328P microcontroller for Pulse Width Modulation. While the subject is covered pretty well in the device's data sheet, some clarification and simplification is in order. This is my intention here. Please have the datasheet available. It can be found here. Select the first pdf file.

What is Pulse Width Modulation

If you landed on this page you probably know, so this explanation will be really short. While you can control a DC motor by controlling the voltage it is connected to, it is usually more precise and actually easier to control the motor by repeatedly turning it off and on. The motor responds to the average time the voltage is applied. You apply the motor voltage as a string of pulses with a defined frequency and a defined pulse width. If the duration of the pulse is half of the duration between pulses, the PWM will be 50% and the motor should turn at 1/2 speed.

To Drive A DC Motor

My last blog entry used Timer/Counter 1 in Normal mode to produce a timed delay. The timed delay function only had to use the timer/counter to do one thing: count up to a value and issue an interrupt. Pulse width modulation has two requirements. It must establish a frequency of pulse repetition and control the width of the pulses. While interrupts can be generated, PWM typically controls the logic level of a pin, or pins, that connect to external devices. Let's start with the dc motor being that external device.
We have plenty of options to consider. The first is whether we can use an eight bit timer/counter or do we need a 16 bit timer/counter. The answer is we probably don't need all of that resolution to control a dc motor. We can use ATmega's timer/counter 0 or 2 - both 8 bit circuits. Let's use timer/counter 0.
Next we need to decide between two major PWM modes. One mode gives twice the maximum frequency of pulse repetition as the other. This "Fast PWM Mode" operates by having the counter count up, and when it reaches its upper value, the counter starts over at zero. If you were to graph count against time, you would see a sawtooth wave. The other mode, "Phase Correct PWM Mode" has the counter count up, and when it reaches its upper value, count down at the same rate. When the count reaches 0 it counts up again. Graphing this looks like a triangular wave. See my graphic below.
Why are there two modes? If you never change the motor speed, either mode is fine. If you do change the motor speed, the Phase Correct PWM mode always has the center of the pulse at exactly the same place in time (if you keep the pulse repetition frequency the same and only change the pulse width). When changing the speed in Fast PWM the center of the pulse will move. Phase correct PWM results in a smooth transition in speed, while Fast PWM is more abrupt. Motors like the former over the latter. My example will use the Phase Correct PWM
With that settled, we have to deal with the frequency of pulse repetition. I don't know enough about DC motors to say what is the best frequency of pulse generation. I guess if the frequency is too low, the motor could lose speed between pulses. I don't know if there is a down side of too high a frequency. The higher frequency could limit the resolution of the speed differences we can program. This will be clear soon. The frequency of pulse repetition rate is determined as follows:
Pulse repetition frequency = clock speed divided by the prescaler and divided again by the maximum count set into the timer counter and finally divided by 2
My clock speed is 12MHz and the possible prescaler values are 1, 8, 64, 256, 1024 (allowable values for timer/counter 0). The lower the prescaler value the higher the frequency. The lower the count also gives you higher frequency. A little drawing is in order here:
The slope of the triangular waveform is determined by the clock frequency and the prescaler value. The clock frequency is your system clock so is not a variable. The prescaler value is, however, programmable. The horizontal line at the top, "Frequency" is controllable by your program and represents the maximum count in the timer/counter. It should be clear that changing the maximum count changes the pulse repetition. If you lower the count, the peaks of the triangles move to the left decreasing the time between pulses. Generally, when you decide on a pulse repetition rate, you would keep that constant.
The lower horizontal line, "Pulse Width", represents the width of the pulses. Typically, this value changes during your application. For example, if your project is a car with dc motors controlling two wheels, you frequently alter the speed of the car. And, you could steer the car by differentially changing the speed of each motor. Therefore, the width of the pulses frequently change. The graphic above should make it clear how the width of the pulses are changed. Lower the horizontal line and the width of each pulse decreases (assuming the we are talking about the positive going rectangle).
Note that the count for the "Pulse Width" must be less than the "Frequency" count. The "Frequency" count then determines the resolution of the pulse width modulation. If the "Frequency" count is the maximum allowed, which is 255 for timer/counter 0, each count will correspond to a pulse modulation increment of about 0.4%. If you lowered that "Frequency" count to 10, you would only be able to program PWM in 10% increments.
There is another programmable selection. The "Resulting Pulses" in the graphic are the result of selecting: clear (go low) on a compare match when counting up, and set (go high) on a compare match when counting down. The compare match value is represented in the above graphic by the line "Pulse Width". You can also program the opposite action: set on a compare match when counting up, and clear on a compare match when counting down. If you program that option, the "Resulting Pulses" waveform would be turned upside down.

Putting It Together In a Script

I did a small sample project where I control a toy DC motor. Since my ATmega328P resides on my Gertboard, I connect the motor and a 6V battery (4 AA's) to the BD6222HFP H-Bridge motor controller. This isolates the motor and it's power source from the PI and the Gertboard. My project increases the motor speed from off to full on, decreases the speed to off, changes the direction of the motor, increases the speed to the max and reduces it to off again. This action is repeated continuously.
There are only two timer/counter 0 modes for Phase Correct PWM, mode 1 and mode 5. My project uses mode 5. Compare register OCR0A controls the "Frequency". If I use mode 1, the "Frequency" count would be fixed to 255. Using mode 5, I can select any value from 0 to 255. As it so happens, I chose 255 anyway. If I had two motors to control, I would choose mode 1. In that case, compare register OCR0A controls one motor and OCR0B controls the other. Pulse repetition frequency would be the same for both motors but each would have it's own PWM percentage. They could turn in the same or opposite direction from each other.
The pulse repetition frequency of this project is 12,000,000 / (2 * 64 * 255) = 368 repetitions per second.
The H-Bridge takes two inputs. One input gets the pulses from pin PD5 while the other input comes from pin PD7. PD7 will determine the direction of rotation just like reversing the leads to the motor. When PD7 is low, we will select clear on a compare match when counting up, and set on a compare match when counting down. When PD7 is high we select set on a compare match when counting up, and clear on a compare match when counting down. You can picture how this works by considering how you would stop the motor. The motor stops if both PD5 (PWM = 0%) and PD7 are the same polarity.
The script below has a lot of comments (more comments than code) so I think the details are well presented within the script.