I am currently working on a Azimuth and Elevation controller to accept the output from the Linux program "Predict" by KD2BD. I have got a working system but I am sure it needs some tweaking to make it more efficient.
A couple of problems that I seem to have is: Sometimes the rate exceeds that "decoding" process. Meaning the servos move to a random position then back again. Also I need to figure out how to make the AZ 360 degrees with a modified servo.
Some tweaking that it needs is: The code is probably an inefficient way to capture and determine the AZ/EL. Problem is "Predict" shifts the bytes when the AZ drops below 100 degrees. That causes the array to shift one byte which throws off the EL reading. The code I wrote works, but I am sure there is a better way to do it.
Sample "Predict" on the serial line: AZ351.0 EL103.0
When this project is compete it will be a benefit to all amateurs that are looking to EME (Earth Moon Earth), and Satellite tracking. Any help would be greatly appreciated!
#include <Servo.h>
#include <stdlib.h>
int pinArray[2] = {2, 3}; // digital pins for the servos
int minPulse = 600; // minimum servo position
int maxPulse = 2400; // maximum servo position
int refreshTime = 20; // time (ms) between pulses (50Hz)
int i; // iterator
int s; //SERIAL byte data
int servoPin; // control pin for current servo
int predictInput[12]; // raw input from serial buffer, min 12 bytes
int pulseWidth; // servo pulse width
int azpulseWidth; //Azimuth pulse width
int elpulseWidth; //Elevation pulse width
int servoPosition; // commanded servo position, 0-180 degrees
int pulseRange; // maxPulse - minPulse
int centerServo; // servo starting point
long lastPulse = 0; // recorded time (ms) of the last pulse
int servo; // which servo to pulse? 1-2
int servo1[2]; // servo #1 array{pin, pulsewidth}
int servo2[2]; // servo #2 array{pin, pulsewidth}
int pin; // digital pin for pulse() function
int puls; // pulsewidth for pulse() function
int startbyte; // start byte, begin reading input
void setup() {
// loop through both servo pins
// and set them as OUTPUT
for (i=0;i<2;i++) {
pinMode(pinArray[i], OUTPUT);
}
// servo starting point (center)
pulseRange = maxPulse - minPulse;
centerServo = maxPulse - ((pulseRange)/2);
pulseWidth = centerServo;
// map pins to servos
servo1[0] = pinArray[0]; // servo #1 is pin 2
servo2[0] = pinArray[1]; // servo #2 is pin 3
// center all servos
servo1[1] = centerServo;
servo2[1] = centerServo;
// open serial connection
Serial.begin(9600); //Predicts default serial baud rate
Serial.flush(); //Flush extraneous serial data
}
void loop() {
// wait for serial input full serial line data (min 12 bytes in buffer)
if (Serial.available() > 12) {
//read the first byte
startbyte = Serial.read();
// check for the start of the serial string (65) ASCII (A)
if (startbyte == 65) {
// then get the whole line serial input line
for (s=0;s<12;s++) {
predictInput[s] = Serial.read();
}
char az[4] = { predictInput[1], predictInput[2], predictInput[3] };
char el[3] = { predictInput[9], predictInput[10] };
char els[3] = { predictInput[8], predictInput[9] };
int az_i = atoi(az); //Convert azimuth char string to integer
int el_i = atoi(el); //Convert elevation char string to integer
int els_i = atoi(els);
if (els_i > el_i ) {
elpulseWidth = minPulse + (els_i * (pulseRange/180));
elpulseWidth = minPulse + (els_i * (pulseRange/180));
} else {
elpulseWidth = minPulse + (el_i * (pulseRange/180));
elpulseWidth = minPulse + (el_i * (pulseRange/180));
}
// compute pulseWidth from Predict Input for Azimuth
azpulseWidth = minPulse + (az_i * (pulseRange/180));
azpulseWidth = minPulse + (az_i * (pulseRange/180));
if (pulseWidth > maxPulse) {
pulseWidth = maxPulse;
}
if (pulseWidth < minPulse) {
pulseWidth = minPulse;
}
// assign new pulsewidth to appropriate servo
servo1[1] = azpulseWidth;
servo2[1] = elpulseWidth;
}
}
// pulse each servo
if (millis() - lastPulse >= refreshTime) {
pulse(servo1[0], servo1[1]);
pulse(servo2[0], servo2[1]);
// save the time of the last pulse
lastPulse = millis();
}
}
void pulse(int pin, int puls) {
digitalWrite(pin, HIGH); // start the pulse
delayMicroseconds(puls); // pulse width
digitalWrite(pin, LOW); // stop the pulse
delay(30);
Serial.flush();
}