I am plotting a circle using two stepper motors. The X axis is relatively simple, stepping one step at a time. Here is the code I use to plot the circle:
void circle(int r){
int r2 = sq(r);
for (int i=1;i<r;i++){
x.step(1);
curx+=1;
int yts = (sqrt(r2 - (curx * curx) ) );
y.step(yts);
cury += yts;
}
}
I am a novice at this, and I suspect my problem has to do with the data type of int, and the limitations thereof. I have also tried using both long and signed long. Either way, I keep getting strange numbers for sq(300), usually between 25,000 and 35,000.
I understand that there is a maximum value for ints, but what data type should I be using to store numbers like 300^2: five digits?
Your comment made me realize that I was declaring the radius as an integer (I didn't think it'd be a problem since the usable drawing area is only 1000 steps, so a theoretical maximum radius of 1000), but I assume that an operation between a long and an int returns an int.
Changing the data type for the radius to long fixed the issue, and everything is working as expected now.
You assume incorrectly. If you declare r2 as long, it will work out as well. The compiler uses the smallest available size so once you involve a long, it all turns into a long for the operator, then the sqrt returns a float and it gets truncated into an int to assign to yts. You did not specify what type curx is which could also impact the results. For example, if curx was uint8_t, then the
(curx * curx) portion could be done with 8 bit miltiplication which would be wrong and then the long result promoted to a long to subtract from r2...
I defined curx before setup as a long. I am, however, interested in what you said here:
sqrt returns a float and it gets truncated into an int to assign to yts.
Is this the nature of the sqrt() function? Is there a better way to go about this? Here is my updated code (although at the moment, it only draws 1/4 of a circle):
void circle(long r){
Serial.println("Starting the circle.");
long r2 = sq(r);
Serial.println("Radius squared: ");
Serial.println(r2);
for (int i=0;i<r;i++){
x.step(1);
curx+=1;
long expy = (sqrt(r2 - (sq(curx))))+1;
y.step(expy-cury);
cury = expy;
Serial.println();
Serial.print(" X: "+String(curx));
Serial.print(" Y: "+String(cury));
}
delay(10000);
}
Your code is stepping through values of X in a linear way. The Y values are not going to be linear, because the circumference of a circle is not a line.
So I'm not sure what you think is unexpected about this. What did you want to happen? What's the problem with the code you have?
Alright, I figured it out guys. TL;DR: I'm kind of an idiot.
PaulRB was mostly right, but to put it more simply: I'm generating this circle by stepping through values of X, one at a time. At x=0, y=radius of the circle, the Y values change very slowly, hence the smoothness. At x=radius, y=0, I'm still only stepping X by one value at a time, but Y changes more per value of X, giving it a choppier look.
The question I asked was essentially flawed from the start. Thanks everyone for the responses.