The project is to have two laser pointers mounted on two servos. Originally I left the whole range of compass degrees available to the servos, but after some experimentation I discovered that I can only count on having about 170 useable degrees of travel. 5-175 is what I'm using. The mounting and housing of my project also started to interfere so I had to exclude from 155 degrees to 200 degrees, this allows for an overlap in the front from 345 to 015 degrees and it was this overlapping parts of the compass in the servo arcs that broke my math. I kept trying to figure out a mathematical way to rotate the servo arcs so that they both cover the transition from 359 degrees to 0 (or 360) degrees. After beating my head on this for a week, I decided to cheat and bit-banged the code below. The code below does work but its huge, 15,892 bytes for the complete version of what I've shared below.
This section gets passed a Compass Bearing and needs to return a LEFT and RIGHT value for the servos. LEFT arc starts at 200 degrees (writing 5 to the servo) and ends at 015 (writing 175 to the servo). Right arc starts at 345 degrees (writing 5 to the servo) and ends at 155 (writing 175 to the servo). After writing to the servo(s) this code waits five seconds, generates a random new bearing for the next loop.
Just a note, the servos I'm testing my code with have very low power requirements (15-25mA @ 5VDC) so I've powered them through the surrounding pins. I've got a separate 6VDC source for the final build.
#define MAXANGLE 90
#define MINANGLE -90
#include <Servo.h>
int Bearing = 0; // Compass Bearing (0-359 degrees)
int BearingL = 0; // Heading to be sent to the LEFT servo
int BearingR = 0; // Heading to be sent to the RIGHT servo
Servo Left;
Servo Right;
void setup() {
Serial.begin(115200);
pinMode(8, OUTPUT); // Ground
pinMode(9, OUTPUT); // 5VDC
pinMode(10, OUTPUT); // Signal Left Servo
pinMode(11, OUTPUT); // Signal Right Servo
pinMode(12, OUTPUT); // 5VDC
pinMode(13, OUTPUT); // Ground
digitalWrite(8, LOW); // Set pin 8 to act as a ground
digitalWrite(9, HIGH); // Set pin 9 to provide 5VDC
digitalWrite(12, HIGH); // Set pin 12 to provide 5VDC
digitalWrite(13, LOW); // Set pin 13 to act as a ground
Left.attach(10);
Right.attach(11);
delay(50);
}
void loop() {
switch (Bearing) {
case 0:
BearingL = 160;
BearingR = 20;
break;
case 1:
BearingL = 161;
BearingR = 21;
break;
case 2:
BearingL = 162;
BearingR = 22;
break;
case 3:
BearingL = 163;
BearingR = 23;
break;
case 4:
BearingL = 164;
BearingR = 24;
break;
case 5:
BearingL = 165;
BearingR = 25;
break;
/// Bearings 006 thru 355 deleted for brevity, format is consistent. If the Bearing is out of a servo's range (less than 5 or more than 175) value is set to '999'.
case 356:
BearingL = 161;
BearingR = 16;
break;
case 357:
BearingL = 162;
BearingR = 17;
break;
case 358:
BearingL = 163;
BearingR = 18;
break;
case 359:
BearingL = 164;
BearingR = 19;
break;
case 360:
BearingL = 165;
BearingR = 20;
break;
default:
BearingL = 160;
BearingR = 25;
break;
}
Serial.println();
Serial.println();
Serial.println("**********");
Serial.println("**********");
Serial.print("Bearing: ");
Serial.println(Bearing);
Serial.println("**********");
Serial.println("**********");
Serial.print("LEFT: ");
Serial.println(BearingL);
Serial.println("**********");
Serial.println("**********");
Serial.print("RIGHT: ");
Serial.println(BearingR);
Serial.println("**********");
Serial.println("**********");
if (BearingL != 999) {
Serial.println(" Left Servo in Arc");
Left.write(BearingL);
delay(500);
}
if (BearingR != 999) {
Serial.println(" Right Servo in Arc");
Right.write(BearingR);
delay(500);
}
delay(5000);
Bearing = random(0, 360);
}
I'm having difficulty visualizing what you are doing, and correlating the bearing with the desired positions of the dervos. Let me just throw out a few things here...
lar3ry:
I'm having difficulty visualizing what you are doing, and correlating the bearing with the desired positions of the dervos. Let me just throw out a few things here...
I'm trying to remember why I quit doing something like that. I think I ended up with a confused servo (high current draw and a little binding noise). I'll play with this a try and see if I can replicate why I quit doing it. I did have a translation step in a previous version that allowed me to use a variable rather than a hard-coded figure for the range overlap. The huge Switch-Case makes a variable defined overlap impossible anyway.
And dummy here just spotted an error. If I'm limiting to 170 degrees, the LEFT Servo needs to start at 205 not 200 or else I run out of degrees before the end of the overlap range with the RIGHT Servo. 345-015 True = 145-175 LEFT = 005-035 RIGHT.
UKHeliBob:
It looks like there is a relationship between the case number and the bearings
There is. The Bearing is a Compass heading. The arc of the LEFT servo starts at 205 degrees True and sweeps clockwise through to 015 degrees True. The arc of the RIGHT servo starts at 345 degrees True and sweeps clockwise through to 150 degrees True. Neither servo is in arc between 150 and 205 degrees. BOTH servos have their arcs overlap between 345 True and 015 True.
Therefor BearingL and BearingR will be constrained to a min of 5 and a max of 175 and will not apply outside of their arcs.
lar3ry:
I'm having difficulty visualizing what you are doing, and correlating the bearing with the desired positions of the dervos. Let me just throw out a few things here...
I'm trying to remember why I quit doing something like that. I think I ended up with a confused servo (high current draw and a little binding noise). I'll play with this a try and see if I can replicate why I quit doing it. I did have a translation step in a previous version that allowed me to use a variable rather than a hard-coded figure for the range overlap. The huge Switch-Case makes a variable defined overlap impossible anyway.
Perhaps you didn't constrain the mapping with the if statements. There is also a 'constrain' function related to map().
And dummy here just spotted an error. If I'm limiting to 170 degrees, the LEFT Servo needs to start at 205 not 200 or else I run out of degrees before the end of the overlap range with the RIGHT Servo. 345-015 True = 145-175 LEFT = 005-035 RIGHT.
No matter. The idea is the same. an if/else if to do servo movements only between specific bearings, divided at 360/0 into two ranges.