user23232: I'm trying to determine what is the best way to scale a magnometer to a servo, I am using the BNO055 from Bosch I get a heading say 50 degrees, and I want to be able to input 45 degrees and have the servo motor move accordingly. I am using a 180 degree motor. I would like to be able to input 45 degrees, and then the motor if 50 degrees was 95, would decrease in value step by step until the magnometer read 45; I'm having difficulty creating the logic to do this.
Bosch output is between 0 and 360; so I could end up with servo 0 is 120; and servo 180 is 300. Meaning the values are 300 - 360, 0 - 120 making the full 180, so I am not sure how I could use something like map in arduino to solve this issue.

user23788: Okay, lets say the output of your BNO055 is called x and the value for your servo is y. We need to translate x to y and you are correct to use the map() function. But what you are forgetting is that you do not need to map all the values of x to all the values of y. You can split it up.
In your example the values of the BNO055 relate to the servo as follows:
x   | y   
0   | 0
120 | 0
300 | 180
360 | 180

The servo only rotates from 0 degrees to 180 degrees between the BNO055 sensor values of 120 and 300. So you only need to map those values, while all values below should result in 0 and all values above should result in 180 degrees for the servo.
This translates into the following code:
//x is the output of BNO055 sensor
if(x < 120){
  servo.write(0);
}
if(x > 300){
  servo.write(180);
}
if(x > 120 && x < 300){
  y = map(x, 120, 300, 0, 180);
  servo.write(y);
}

Another way of coding this is:
if(x < 120){
  servo.write(0);
}
else if(x > 300){
  servo.write(180);
}
else{
  y = map(x, 120, 300, 0, 180);
  servo.write(y);
}


user4143: You need to remember that you are working with a circle. You have degrees 0 to 360, but only if counting clockwise. If you work anticlockwise you also have degrees 0 to -360.
So your angles of interest are, clockwise from 0, 0-120, and anti-clockwise from 0, 0 to -60
To make things easier on you you need to create a range that is wrapped around so that anything in the "left" half of the circle is counted as anticlockwise from 0 and anything in the "right" half of the circle is counted clockwise from 0.
So values 0-180 are 0-180, but values of 180 to 360 are -128 to 0.  Then your entire range spreads from -180 to +180 instead of 0-360 (if that makes sense).
It's simple enough:
if (angle > 180) angle = 0 - (360 - angle);

So if angle is 300 you get:
0 - (360 - 300) = 0 - 60 = -60

If angle is 330 you get:
0 - (360 - 330) = 0 - 30 = -30

Now you can map the new values using the map function @Len has detailed above:
servo = map(angle, -60, 120, 0, 180);

It is also possible to combine it all into one line should you wish, using the C "inline if" format:
servo = map((angle > 180 ? (0 - (360 - angle)) : angle), -60, 120, 0, 180);

But that is kind of cryptic :)

23232: <p>I'm trying to determine what is the best way to scale a magnometer to a servo, I am using the BNO055 from Bosch I get a heading say 50 degrees, and I want to be able to input 45 degrees and have the servo motor move accordingly. I am using a 180 degree motor. I would like to be able to input 45 degrees, and then the motor if 50 degrees was 95, would decrease in value step by step until the magnometer read 45; I'm having difficulty creating the logic to do this.</p>

<p>Bosch output is between 0 and 360; so I could end up with servo 0 is 120; and servo 180 is 300. Meaning the values are 300 - 360, 0 - 120 making the full 180, so I am not sure how I could use something like map in arduino to solve this issue.</p>
 23788: <p>Okay, lets say the output of your BNO055 is called <code>x</code> and the value for your servo is <code>y</code>. We need to translate <code>x</code> to <code>y</code> and you are correct to use the <code>map()</code> function. But what you are forgetting is that you do not need to map all the values of <code>x</code> to all the values of <code>y</code>. You can split it up.</p>

<p>In your example the values of the BNO055 relate to the servo as follows:</p>

<pre><code>x   | y   
0   | 0
120 | 0
300 | 180
360 | 180
</code></pre>

<p>The servo only rotates from 0 degrees to 180 degrees between the BNO055 sensor values of 120 and 300. So you only need to map those values, while all values below should result in 0 and all values above should result in 180 degrees for the servo.</p>

<p>This translates into the following code:</p>

<pre><code>//x is the output of BNO055 sensor
if(x &lt; 120){
  servo.write(0);
}
if(x &gt; 300){
  servo.write(180);
}
if(x &gt; 120 &amp;&amp; x &lt; 300){
  y = map(x, 120, 300, 0, 180);
  servo.write(y);
}
</code></pre>

<p>Another way of coding this is:</p>

<pre><code>if(x &lt; 120){
  servo.write(0);
}
else if(x &gt; 300){
  servo.write(180);
}
else{
  y = map(x, 120, 300, 0, 180);
  servo.write(y);
}
</code></pre>
 4143: <p>You need to remember that you are working with a circle. You have degrees 0 to 360, but only if counting clockwise. If you work anticlockwise you also have degrees 0 to -360.</p>

<p>So your angles of interest are, clockwise from 0, 0-120, and anti-clockwise from 0, 0 to -60</p>

<p>To make things easier on you you need to create a range that is wrapped around so that anything in the "left" half of the circle is counted as anticlockwise from 0 and anything in the "right" half of the circle is counted clockwise from 0.</p>

<p>So values 0-180 are 0-180, but values of 180 to 360 are -128 to 0.  Then your entire range spreads from -180 to +180 instead of 0-360 (if that makes sense).</p>

<p>It's simple enough:</p>

<pre><code>if (angle &gt; 180) angle = 0 - (360 - angle);
</code></pre>

<p>So if <code>angle</code> is 300 you get:</p>

<pre><code>0 - (360 - 300) = 0 - 60 = -60
</code></pre>

<p>If <code>angle</code> is 330 you get:</p>

<pre><code>0 - (360 - 330) = 0 - 30 = -30
</code></pre>

<p>Now you can map the new values using the <code>map</code> function @Len has detailed above:</p>

<pre><code>servo = map(angle, -60, 120, 0, 180);
</code></pre>

<p>It is also possible to combine it all into one line should you wish, using the C "inline if" format:</p>

<pre><code>servo = map((angle &gt; 180 ? (0 - (360 - angle)) : angle), -60, 120, 0, 180);
</code></pre>

<p>But that is kind of cryptic :)</p>
