**Tags**

arduino, astronomy, coding, math, programming, taylor series

I’ve been thinking of writing an astronomical toolkit for Arduino, to help users build their own go-to telescope mounts, satellite trackers, heliostats, and other cool amateur astronomy equipment. As anyone who has ever worked with astronomical coordinate systems know, since astronomers treat the sky as a 2 dimensional spherical surface, most calculations involving positions on this surface involve a good deal of trigonometry. While the Arduino library includes built-in functions for sine and cosine, it lacked the inverse trigonometric functions arcsine and arccosine. These are necessary if you ever need to convert a length ratio into an angle. It is impossible to convert between different sky coordinate systems (like Horizontal and Equatorial, the two most common) without access to these functions. In today’s post, I’ll show you how I wrote my own arcsin() and arccos() functions using Taylor polynomials.

### Computing Strange Functions

Calculating the value of functions like the trigonometric identities, logarithms, and exponentials have been a historical challenge for physicists and engineers. Before the advent of mechanical and electronic calculators, many people would spend most of their lives calculating by hand the values of common functions for ranges of numbers and tabulating them in books of tables. This is in fact still done digitally, by storing lookup tables in memory, and then recalling them when a function is called. I’m going to be working on a platform that only has 2kB of memory, so I want to avoid using this solution.

### Taylor Polynomials

Instead, I will be using a trick of calculus developed by Brook Taylor in the early 18th century. Taylor found that any continuously differentiable function f(x) could be expressed as an infinite power series of that function evaluated at some point a:

If we choose a=0, this gives us a nice simple sum called the Maclaurin series:

So, to figure out a series for calculating arcsin, I simply use it’s derivative:

This is a nice and easy derivative to work with, and, since I will be using a Maclaurin series, it gives some nice clean coefficients. However, I can’t just compute an infinite number of terms, as that would take just a bit longer than I can tolerate. So instead, I will calculate the first, let’s say, 7 derivatives of arcsine, and I can begin to write a function to calculate its value, with some small error associated!

Naturally, the first derivative, evaluated at 0 is just 1! The second term is 0, third is 1 again, fourth is 0, fifth is 9, sixth is 0, seventh is 225. There we go! So, my function for calculating arcsin is:

In Arduino wiring, the function is just:

float arcsin(angle) { return angle + (pow(angle, 3.0) / 6.0) + (pow(angle, 5.0) * 0.075) + (pow(angle, 7.0) * 0.0446429) }

### Bounding Error

So, I’ve obviously truncated a huge amount (an infinite amount in fact!) of terms from my Taylor series. This will certainly result in an error for my results. I need to bound that error, so I can know it is acceptable. The error term will be bounded by the next non-zero term of the Taylor series, the 9th derivative term. The 9th term will be:

The maximum error I will encounter will therefore occur when the ratio is 1 (as arcsin is defined over the range from 0 to 1). I can improve my results by adding more and more terms to my series. Ultimately, how many terms you add depends on how much performance you are willing to sacrifice. For low angles, the deviation between the true value and the Taylor series is quite low. You can see in the following figure that for most values, 7 terms are sufficient to closely match the real value, and adding the 9th term improves things even further, but with diminishing returns.

You can use Taylor series for nearly any function you can figure out the derivative for! Thanks, Brook.

H.Davies

said:This I found very helpful.

I think, though, Arduino does have arctan and that arcos and arcsine are easily derived from it

bwkeller

said:I don’t think it did back when I wrote this post, but I might have just missed something obvious!

H.Davies

said:It’s possible.I’ll remember your method and that pow() takes fractional exponents

Hassaan

said:Hey

its interesting to read and take benefit of this post. I am wondering how one can implement differential functions i.e., df/dx on arduino?

H.Davies

said:If the function is given analytically, just differentiate, then evaluate it.

If it is numerically specified, evaluate the derivative approximately, by dividing the difference between neighbouring values of the function by the difference between the corresponding arguments.

Extend, if needed, for functions of several variables