# Question for someone better at maths than me :-)

Hi all.
I have a question that is doing my head in trying to figure it out.
Heres the scenario. I have a GPS unit and I have a color LCD that I am displaying the heading on....using TinyGPS library for this.

What I want to do is, I have a circle showing N E S W on it, like a compass, but what I want to do is show an indicator on the circle to show the course, i.e. 45 deg,145deg etc.

What I am having trouble with is how to work out where to put a colored pixel to show what way I am heading.

I am also using the GLCDI2C library for the LCD.

So I draw the circle as below:
maxX=160
MaxY=128
45 = the radius

lcd.circle(maxX >> 1, (maxY-15) >> 1, 45);

If I wanted to put a colored pixcel to show 25deg for example, what is the math calculation I need to used to work out where to draw the pixcel?

I hope I have provided enough info Thanks, Jeremy

You will probably need trig for that, unless you use a lookup table.
Convert the degrees to radians, then use sin and cos to get the x/y offsets from center circle.
http://arduino.cc/en/Reference/Sin
http://arduino.cc/en/Reference/Cos

Actually its easy.
You just have to know how to plot a circle in the first place. You just plot sin(a) against cos(a) over 360 degrees or 2PI radians depending on your trig functions.

try

plot(x_center_offset + R * sin(a), y_center_offset + R * cos(a));
or draw a line from xCenter, yCenter to the above 2

dont know if its plot(), havent look at your lib, but the principle is correct.
you may have to play with the + or - and swap the sin and cos depending on where your origin is.
Top left, bottom left etc

.... Simon

remember that when you plot a point you should remember the previous value to clear stuf.

so the function to plot a pixel should look something like .. (code is partial/not tested)

``````do_plot(int degrees)
{
x = midX + cos(degrees) * radius;
y = midY + sin(degrees) * radius;
plot(x,y, color);
if (prevX != x || prevY != y)
{
plox(prevX, prevY, 0); // clear
prevX = x; // remember current point
prevY = y;
}
}
``````

Thanks heaps for that. I managed to get is SORT of working by that I mean, I see pixels now, but not quit going in the right direction But I can figure that one out :*

Jeremy

please post your final code if things work for future reference

The sin and cos parameter is radians, not degrees. You must convert from degrees to radians.

edit: Using an array to store the sin/cos values (lookup table) has proven to be much faster and simpler to use for me. It works well when accuracy required is a degree or two. A second hand on an analog clock moves 6 degrees per second. Last I checked, that is 16 entries in a lookup table.

Last I checked, that is 16 entries in a lookup table

with some folding yes.
Instead of the sin/cos values in the lookup table you could put the (delta XY) coordinates in it.

e.g for a radius of 25 pixels it would be (according to excel int offsets = {0, 2, 5, 7, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 24, 25}

Nice, Rob! Now all you would need to do is compute the quadrant to tell whether to add or subtract each value. That is the sine table, and "backwards" is the cosine. I see a division and a modulus to get the quadrant and the offsets for that quadrant.

precisely, should be really fast.

I had a little spare time and curiosity. Here is a sketch that prints all the important stuff for a clock. For heading, divide degrees by 6. It is a 25 pixel radius centered at 25,25.

``````int offsets[] = {0, 2, 5, 7, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 24, 25};
int newPos;
int newSeconds=0;
int xOff;
int yOff;

void setup() {
Serial.begin(9600);
}

void loop() {
Serial.print("Seconds: ");
Serial.print(newSeconds);

newPos = newSeconds%15;

Serial.print("  Position: ");
Serial.print(newPos);

case 0:  xOff = 25 + offsets[newPos];
yOff = 25 - offsets[15 - newPos];
break;
case 1:  xOff = 25 + offsets[15 - newPos];
yOff = 25 + offsets[newPos];
break;
case 2:  xOff = 25 - offsets[newPos];
yOff = 25 + offsets[15 - newPos];
break;
case 3:  xOff = 25 - offsets[15 - newPos];
yOff = 25 - offsets[newPos];
break;
}

Serial.print(" LCD X: ");
Serial.print(xOff);
Serial.print("  Y: ");
Serial.println(yOff);

newSeconds++;

if(newSeconds > 59) newSeconds = 0;
delay(1000);
}
``````

that's what I call co-development code proofs the concept quite well.

SurferTim:
edit: Using an array to store the sin/cos values (lookup table) has proven to be much faster and simpler to use for me. It works well when accuracy required is a degree or two.

Funny I did something like that few days ago, unfortunately it's slower than calling sin/cos directly, because I put that array in progmem... If array is in ram of course it's much faster guix:
Funny I did something like that few days ago, unfortunately it's slower than calling sin/cos directly, because I put that array in progmem... If array is in ram of course it's much faster There is no way those sin/cos functions are faster than a lookup table. It had to have been your coding.

No try it guix:
No try it I have, many times. You may think you are talking to an amateur, but that assumption would be incorrect.

Funny I did something like that few days ago, unfortunately it's slower than calling sin/cos directly, because I put that array in progmem... If array is in ram of course it's much faster

You can check my sin/cos lookup table [182 bytes] + code here - Arduino Forum -
factor 2.5 faster, and without interpolation even more. Sorry, I was wrong (and that’s cool!) I don’t know what I did wrong in my previous test but I remember using an array in progmem was a little slower than using sin directly :S

Now…

``````Chrono 01 - { for (float j = 0.0; j < 360.0; j+=0.1) x = sinDegree1(j); } - 10 calls...
Average (microseconds) :   43075.20

Chrono 02 - { for (float j = 0.0; j < 360.0; j+=0.1) x = sinDegree2(j); } - 10 calls...
Average (microseconds) :   43074.80

Chrono 03 - { for (float j = 0.0; j < 360.0; j+=0.1) x = sinDegree3(j); } - 10 calls...
Average (microseconds) :  589187.63

0.84
0.84
0.83
``````

I’m surprised progmem is as fast as ram Oh and good code Rob’, I will try it test_sin_array.ino (9.26 KB)

I learn more from being wrong than being right. 