As a leader at the forefront of the manufacturing industry, we are all about discovering and utilizing the most efficient processes for everything we do. This, of course, does not exclude our programming. Our programmer, Jeremy, has taken the initiative to compose four terrific tips for writing more efficient C programming. In fact, he’s been working on developing our acceleration profiles to maximize efficiency for our HX Series CNC machines. So, without further ado, let’s jump in!
A Word from The Expert
Jeremy Says: “For the past several months, we have been working on a linear acceleration routine in Arduino for a stepper motor. For this program, timing is the key to everything working. As a result, I was forced to research several factors regarding programming efficiency.”
- Convert to a Switch Statement
‘Long if…else if…else if…else if…’ chains require lots of jumps for cases near the end of the chain in addition to testing each condition. If it’s possible, convert to a switch statement, which the compiler sometimes optimizes into a table lookup with a single jump. If a switch statement is not likely, put the most common clauses at the beginning of the ‘if’ chain. To learn more about this, check out this article that includes tips for optimizing the C/C++ code/.
The program that Jeremy initially began working with had multiple ‘if…else’ statements. After researching what takes more time to interpret, Jeremy modified the code into a switch statement. This made the code run much more efficiently, around ten times faster than the speed of the original code! Additionally, with the stepper motor, the pause between cases is much less than the pauses between ‘if…else’ statements.
So, why exactly does this matter? If you have ever worked with stepper motors, you probably realize timing is the critical component to success. When the stepper motor is at a reasonably fast speed any pause in the timing will bind the motor causing it to stop abruptly. Because of this issue, Jeremy had to change the logic of the code. He now uses a switch statement instead of ‘if…else’ statements.
- Use Shift Operations >> and << Instead of Integer Multiplications Wherever Possible
For the acceleration profile, our team uses the Taylor Series Approximation for determining the time delay between steps. With this profile, we have the following equation for ramping down the acceleration:
Time Delay = (Time Delay * ((stepCount<<2)+1) + 1) /((((stepCount<<2)+1)) + 1 – 2)));
As you can see, the bitwise operators are multiplying the variables by four instead of using the multiplication sign. This may not seem like a big deal, but when you are working with microseconds, it can make all the difference in the world. Be cognizant of this option, as it could become the difference between efficiency and inefficiency. For more information, reference the article from tip #1.
- Use the Smallest Possible Data Type
Next, for choosing data types, it is helpful to use the smallest possible type to get the job done and use an unsigned type whenever possible. This is because many 8-bit processors have no direct support for manipulating anything that is more complicated than an unassigned 8-bit value. Although, eight-bitters often offer direct support for the manipulation of bits, unlike larger computers. Reference this article written by the Barr Group for more information.
- A Variable Should Be Declared Volatile Whenever Its Value Could Change Unexpectedly
A variable should be declared volatile whenever its value could change unexpectedly. In practice, only three types of variables could change:
- Memory-mapped peripheral registers
- Global variables modified by an interrupt service routine
- Global variables accessed by multiple tasks within a multi-threaded application.
Reference this article written by the Barr Group to learn more about how to use C’s volatile keyword.
For the acceleration program, we use an interrupt service routine to control how often the motor moves. Every variable accessed within the service routine must be declared as volatile. The reason for this is because global variables may be shared between two different threads or tasks at the same time.
We hope this short guide can be of use to you in your endeavors! As always, please don’t hesitate to contact us with questions, we’d love to be of assistance!