Whandall:
You uses a signed 0, my code uses an unsigned zero.
Had no idea this was a thing....
Thank you, I got it.
Whandall:
You uses a signed 0, my code uses an unsigned zero.
Had no idea this was a thing....
Thank you, I got it.
So, still something does not add up to me here.
everything seems to work fine up to a point.
here is what I tried:
void setup() {
Serial.begin(250000);
uint16_t a = 100;
uint16_t b = 102;
uint16_t x = (a - b) % 359;
Serial.println(x);
}
void loop() {}
returns
196
I expected 358... This reasoning around a circle is getting harder then I thought...
tomy983:
I expected 358...
The cycle length is 216 which is not divisible by 359,
so why would you expect something near the modulus for a value that corresponds to -2 ?
Whandall:
The cycle length is 216 which is not divisible by 359,
so why would you expect something near the modulus for a value that corresponds to -2 ?
I obviously have no idea about how this modulus works..
what I thought is that the modulus could constrain the result to setted value, let's say 0 to 360 and if outside this range it would just wrap around... I tried different input values and got different results, none of which made sense to me.
I don't know what you are referring to with "the circle length". I did look for modulo elsewhere and found that different languages give different output.
Would you mind explaining how the modulo works in arduino? The reference page doesn't really make it clear (to me).
The modulo in C/C++ is the remainder after successively subtracting full values of the modulus. If easier, think in terms of a float and use the decimal part of the result.
Example modulo 24, values 23, 24, 25.
In the first case you cannot subtract 24 from 23 so the remainder is 23. From 24 you can subtract once with remainder 0, 25 once, remainder 1.
As a decimal, 23/24=0.9583, .9583 multiplied by 24 is 23. 24/24=1.000, .000 multiplied by 24 is 0. 25/24 = 1.04167, .04167 multiplied by 24 is 1.
The result of a%b is simply the remainder from the integer division of a by b.
3 % 4 = 3 (result of the integer division is zero with a remainder of 3)
17 % 5 = 2 (result of division is 3 with a remainder of 2)
The % ignores the quotient and keeps the remainder.
Pete
ok, right. It is actually what I thought it was reading the reference.
I made myself the wrong idea when I read
DKWatson:
The most common way of doing 'circular' math is by using the modulo operator (%) where 'n' would be the rollover value so your statement would be,x = (x +1) % n;
This would then count from 0 to n-1 and the restart from 0.
[EDIT]from 0 to n-1 - see post #10
This was a pointer to the actual solution and not the solution itself. I wet to read the reference but somehow still thought that was a supernice constrain operator
. It is not. it's just the remainder.
Thank you guys.
It's good that u now understand the concept of using modulo but if I may ask how do you plan to use that again?
from your post #13:
tomy983:
- second axis
rotation of head around wire. one stepper and one angle sensor read via I2c. full 360 rotation allowed. no endstops.
so the angle sensor will be giving you an ADC value based on its position (0 - 65,535 unsigned). why are you then looking for a rollover function since the sensor should do that for you as it passes it 0deg position?
sherzaad:
It's good that u now understand the concept of using modulo but if I may ask how do you plan to use that again?from your post #13:
so the angle sensor will be giving you an ADC value based on its position (0 - 65,535 unsigned). why are you then looking for a rollover function since the sensor should do that for you as it passes it 0deg position?
I need the rollover function (so I believe at the moment) for two reasons:
first one is to calculate the distance from the target position in order to feed it to the pid function and so get the speed I should run the motor at.
The second reason is to properly manage the point "around" the sensor zero, while moving or while holding.
If I tell the controller to hold at 0 and it moves just a little it will see full scale rather than 0. pid will output high speed and things probably will oscillate quite a lot.
I think the best way to manage both situation is reasoning in distance from target in a circular way. Do you know of any simpler or possibly better way?
Meanwhile, this is what I collected. This is not my work, they are pieces of code I found either here or on stackexchange. I just modified them to work with arduino (ABS function for instance), and put them together.
Is a very small collection that might be useful to anyone looking to calculate things around a compass or in a circular way. I would have loved to find something like this, maybe in a library!! It would have spared me a lot of work (but also prevented me from learning quite a bit) so I would like to post it here.
void setup() {
Serial.begin(250000);
uint16_t a = 40; // angle a from
uint16_t b = 100; // angle b to
int mod = 360; // modulo
Serial.print("angle a (from): ");Serial.println(a);
Serial.print("angle b (to): ");Serial.println(b);
Serial.print("a+b: ");
Serial.println(SumSubtraction((a+b),mod)); // sum between angles
Serial.print("distance anticlockwise or a-b: ");
Serial.println(SumSubtraction((a-b),mod)); // subtraction between angles
Serial.print("distance clockwise or b-a: ");
Serial.println(SumSubtraction((b-a),mod)); // subtraction between angles
Serial.print("Shorter distance a_b: ");
Serial.println(ShorterDistance(a,b)); // shorter distance between angles
Serial.print("direction for Shorter distance from a to b (1 clockwise, 0 anticlockwise): ");
Serial.println(FindTurnSide(a, b)); // shorter distance between angles
}
void loop() {}
uint16_t SumSubtraction(int x, int m) {
int r = x%m;
return r<0 ? r+m : r;
}
int ShorterDistance(int x, int y) {
int z = x-y;
int a = abs(z);
int b = a-180;
return 180-abs(b);
}
bool FindTurnSide(int current, int target)
{
int diff = target - current;
if(diff < 0)
diff += 360;
if(diff > 180)
return 0;
else
return 1;
}
tomy983:
I was thinking about mapping the values to an uint_16 and letting it overflow either way, but here int - Arduino Reference I read that it might give unpredictable results.
Overflow will be well defined on all modern hardware, it wraps round.
So mapping 0..5V to 0x8000 .. 0x7fff was a good idea, then the error between two angles is always constrained
to be 180 degrees or less (google binary radians)
MarkT:
Overflow will be well defined on all modern hardware, it wraps round.So mapping 0..5V to 0x8000 .. 0x7fff was a good idea, then the error between two angles is always constrained
to be 180 degrees or less (google binary radians)
D'HO!! ![]()
nearly finished now... Tomorrow I will test the code for this axis... Well, will keep this in mind though!
Will have a look at google. Thanks.