NRL Satellite (ARDUINO IN SAPCE!)

Ah yea, the code I wrote eliminates the need for typing :3
Everything is passed as an argument when starting.

I swear I will post both codes this week.

Well, the only typing commands I would have is to change satellite/frequency, though thats not a G-1000 thing, and probably a recalibration button just in case, since I don't know if it loses accuracy over time or not.

What happens now, and I don't know if Ivan told you or not, is that you would start predict, start the radio server, type in the satellite info, start radio, and then let it go. The only parameters are for radio.c and that is to define the usb port being used for the G-1000, since linux sometimes likes to change usb numbers.

Also, small nitpick, but on your next G-1000 board, can you make the led's a different color that doesn't blind the eyes? Its kinda bright right now that we had to hide it.

Do you have the numbers for a free satellite tracking program ? Which do you recommend ? I am N8TV

Yes, the LEDs are extremely bright, on the new board there is only one LED, that's a power/ready indicator. There is no reason for anymore LEDs. Ill make sure to order some dimmer ones.

uphiearl:
For tracking software there are are plenty.
Predict is a popular one.
There is also
Gpredict
PreviSat
JSatTrack
JOSAST
Well... here

I prefer Gpredict and Predict.

BIG NEWS!
TLE data is now available!

http://celestrak.com/NORAD/elements/tle-new.txt

35691 ANDE DEB [POLLUX CYL]
35692 ANDE DEB [CASTOR CYL]

35693 ANDE POLLUX SPHERE
35694 ANDE CASTOR SPHERE

Also as promised the code to the g-1000. I... I can't find my Pollux code right now.

#include "EEPROM.h"
#include <avr/io.h>
#include <avr/interrupt.h>

#define LED_ONE     7
#define LED_TWO     6
#define MOTOR_UP    18 
#define MOTOR_DOWN  19
#define MOTOR_LEFT  16
#define MOTOR_RIGHT 17
#define ADC_EL      0
#define ADC_AZ      1

#define RX_BUFFER  256

#define CMD_SEND_POS  'C'
#define CMD_MOVE_ROT  'W'
#define CMD_CANCEL    'S'
#define CMD_RESET     'R'
#define CMD_CAL       'K'

#define CAL_DELAY   2000 //Delay in ms       

byte buff[RX_BUFFER];

typedef struct Cords{
  int az;
  int el;
};

typedef struct Rotor{
  boolean adj;
  Cords pos;
};

Rotor RotorCtrl;

struct AnalogCal { 
  float EL;
  float AZ;
  char   minAz;
  char   minEl;
};

AnalogCal CalConf = {0,0,0,0};
//interrupt stuff
#define MAX_TIMEOUT 17 //About 1 millsecond, enough for 10 bits to be transmited @ 9600 baud 
boolean TIMEOUT = false;
int TIMECOUNT = 0;

boolean valMove() {
 if (buff[1] <= '9' && buff[1] >= '0' && buff[2] <= '9' && buff[2] >= '0' && buff[3] <= '9' && buff[3] >= '0' && buff[5] <= '9' && buff[5] >= '0' && buff[6] <= '9' && buff[6] >= '0' && buff[7] <= '9' && buff[7] >= '0') 
   return true;
  else {
     error("Invalid Move Rotor Command. Syntax: Waaa eee\\r\\n Where aaa is Azimuth 000-450 and eee is Elevation 000-180");
     return false;
  }
} 

void getMovPos(byte *buff, struct Cords *position) {
    position->az = (buff[0]-'0')*100 + (buff[1]-'0')*10 + (buff[2]-'0');
    position->el = (buff[4]-'0')*100 + (buff[5]-'0')*10 + (buff[6]-'0');
}

boolean getPos(struct Cords *position) {
   if (CalConf.AZ == 0 || CalConf.EL == 0) {
      error("Could Not Get Current Rotor Position! Device is not calibrated. Please calibrate.");
      return false;
   }
   unsigned int samples = 0;
   unsigned long az = 0;
   unsigned long el = 0;
   for (samples = 0; samples < 1024; samples++) {
      az +=  analogRead(ADC_AZ);
      el +=  analogRead(ADC_EL);
   }
    position->az = (int)(((az>>10)-CalConf.minAz)*CalConf.AZ);
    position->el = (int)(((el>>10)-CalConf.minEl)*CalConf.EL);
  return true;    
}

void sendPos(){
 Cords pos;
if (getPos(&pos)){
 Serial.print("+0");
 if (pos.az/100 > 0) {
    Serial.print(pos.az,DEC);
 } else if (pos.az/10 > 0) {
    Serial.print("0");
    Serial.print(pos.az,DEC);
 } else {
    Serial.print("00");
    Serial.print(pos.az,DEC); 
 }
 Serial.print("+0");
 if (pos.el/100 > 0) {
    Serial.print(pos.el,DEC);
 } else if (pos.el/10 > 0) {
    Serial.print("0");
    Serial.print(pos.el,DEC);
 } else {
    Serial.print("00");
    Serial.print(pos.el,DEC); 
 }
 Serial.print("\r\n");
} else {
  error("Send Pos: Could not get position info! Is the device Calibrated?");
 }
}


ISR(TIMER2_OVF_vect) {
    if (++TIMECOUNT == MAX_TIMEOUT) { 
      TIMSK2 = 0x00;
      TIMEOUT = true;
      TIMECOUNT = 0;
    }
}

int readSerial(void) {
    //start time out interrupt  
    TIMEOUT = false;
    TIMECOUNT = 0;
    TIMSK2 = _BV(TOIE2);
   
    int count = 0;
    if (Serial.available() > 1) {
       byte newByte = 0;   
       byte oldByte = 0;
       newByte = (char)Serial.read();
       buff[count++] = newByte;
     do {
       if (Serial.available() > 0) {
         oldByte = newByte;
         newByte = (char)Serial.read();
         buff[count++] = newByte;
         TIMECOUNT=0; //reset count for timeout
       }
     }  while (!TIMEOUT && count < RX_BUFFER && !(newByte == '\n' && oldByte == '\r')); 
      if (TIMEOUT || count >= RX_BUFFER) {
         count = 0;
         TIMEOUT = false;
       }
     Serial.flush();
   }
  return count;
}


void error(char *Str) {  
  Serial.print("?>");
  Serial.print(Str);
  Serial.print("\r\n");
}

int oneSample (int pin) {
      int i = 0;
      unsigned long int sample = 0;
      for (i = 0; i < 512; i++) 
            sample += analogRead(pin);
      return sample >> 9;
}

void calibrate(struct AnalogCal * cal) {
      char adjustAz = 2;
      char adjustEl = 2;
      int AzPrev = oneSample(ADC_AZ);
      int ElPrev = oneSample(ADC_EL);
      int Az = -1;
      int El = -1;      
      int Azmin;
        int Elmin;
      //Moving to max range
      while (adjustAz > 0 | adjustEl > 0) {
            if (abs(Az - AzPrev) < 2) { 
                    if (adjustAz == 2) { 
                          Azmin = Az; 
                          adjustAz = 1;
                    } else if (adjustAz == 1) adjustAz = 0;
            } else 
                  AzPrev = Az;

            if (abs(El - ElPrev) < 2) {
                    if (adjustEl == 2) { 
                          Elmin = El; 
                          adjustEl = 1;
                    } else if (adjustEl == 1) adjustEl = 0;
            } else 
                  ElPrev = El;
                  
            //Update motors State :D
                                               
            digitalWrite(MOTOR_RIGHT,adjustAz == 1);
            digitalWrite(MOTOR_UP,adjustEl == 1);
                digitalWrite(MOTOR_LEFT,adjustAz == 2);
            digitalWrite(MOTOR_DOWN,adjustEl == 2);            

            delay(CAL_DELAY); //give some time for the motor to move ^_^
            El = oneSample(ADC_EL);
            Az = oneSample(ADC_AZ);
      }

        if ((El-Elmin) > 180 && (Az-Azmin) > 450) {
          Serial.print("\r"); 
        cal->EL = (float)(180.000/(El-Elmin)); //Our multiplyer to convert sample to angel
        cal->AZ = (float)(450.000/(Az-Azmin)); //Our multiplyer to convert sample to angel
          cal->minEl = Elmin;
          cal->minAz = Azmin;
          save();
        } else {
          error("The Voltage Range On the g-5500 is way too low! Please read the manual to learn how to adjust the Output Voltage.");
          cal->EL = 0;
          cal->AZ = 0;
          save();
        }
    }

void moveTo(struct Rotor *rotor) {
  digitalWrite(13,HIGH);
   Cords pos;
   if (getPos(&pos)) {
     digitalWrite(MOTOR_UP, (pos.el < rotor->pos.el && abs(pos.el-rotor->pos.el) > 1 && rotor->pos.el > -1));
     digitalWrite(MOTOR_DOWN, (pos.el > rotor->pos.el && abs(pos.el-rotor->pos.el) > 1 && rotor->pos.el > -1));
     digitalWrite(MOTOR_LEFT, (pos.az > rotor->pos.az && abs(pos.az-rotor->pos.az) > 1 && rotor->pos.az > -1));
     digitalWrite(MOTOR_RIGHT, (pos.az < rotor->pos.az && abs(pos.az-rotor->pos.az) > 1 &&rotor->pos.az > -1));
     digitalWrite(LED_ONE,rotor->pos.el>-1); 
     digitalWrite(LED_TWO,rotor->pos.az>-1);
   
     if (pos.el == rotor->pos.el)
           rotor->pos.el = -1;
     if (pos.az == rotor->pos.az)
           rotor->pos.az = -1;
     if (rotor->pos.az < 0 && rotor->pos.el < 0) {
        rotor->adj = false;
     }
   } else {
      error("Move Rotors: Can not Get Current Position! Is the device calibrated?");
      rotor->adj = false;
   }
}


void load() {
  byte *ptr;
  ptr = (byte*)(void*) &CalConf;
  int i = 0;
  for (i = 0; i < sizeof(CalConf); i++) 
     ptr[i] = EEPROM.read(i);

}

void save() {
  byte *ptr;
  ptr = (byte*)(void*) &CalConf;
  int i = 0;
  for (i = 0; i < sizeof(CalConf); i++) {
     EEPROM.write(i,ptr[i]);
   } 
}


void setup() {
 Serial.begin(9600);
 pinMode(LED_ONE,OUTPUT);
 pinMode(LED_TWO,OUTPUT);
 pinMode(MOTOR_UP,OUTPUT);
 pinMode(MOTOR_DOWN,OUTPUT);
 pinMode(MOTOR_LEFT,OUTPUT);
 pinMode(MOTOR_RIGHT,OUTPUT);
 //setup interupts
 TCCR2A = 0x00;
 TCCR2B = (_BV(CS22) | _BV(CS20));
 load();
 }

int read = 0;

void loop() {
  read = readSerial();


 if (read > 0 ) {
   switch (buff[0]) {
    case CMD_CAL:
        calibrate(&CalConf);
        break;
    case CMD_SEND_POS:
        sendPos();
        break;    
    case CMD_CANCEL:
        RotorCtrl.adj = false;
        break;    
    case CMD_RESET:
        load();
        RotorCtrl.adj = false;
        break;
    case CMD_MOVE_ROT:
        if (read == 10) {
           if (valMove()) {
             getMovPos(buff+1,&RotorCtrl.pos);
             if (RotorCtrl.pos.az > 450 || RotorCtrl.pos.el > 180) {
               error("Move Rotor Out Of Range! Azimuth is 0-450 and Elevation is 0-180");
             } else {
               Serial.print("\r");
               RotorCtrl.adj = true;
             }
           }
        } else {
           error("Invalid Move Rotor Command. Syntax: Waaa eee\\r\\n Where aaa is Azimuth 000-450 and eee is Elevation 000-180");
        }
        break;    
    default:
        error("No Such command!");
        break;
     } 
 }
 // End of Serial 
  if (RotorCtrl.adj) moveTo(&RotorCtrl);
  else {                        
    digitalWrite(13, LOW);          
    digitalWrite(MOTOR_UP, LOW);    
    digitalWrite(MOTOR_DOWN, LOW);  
    digitalWrite(MOTOR_LEFT, LOW);   
    digitalWrite(MOTOR_RIGHT, LOW);
    digitalWrite(LED_ONE, LOW);      
    digitalWrite(LED_TWO, LOW);
  } 
}

Feel free to critique the code

So anyone able to track castor or pollux yet?

the TLE is here:
http://celestrak.com/NORAD/elements/amateur.txt

btw shutter, i just found this:

while looking for rotators and interfaces.

you mention on a previous post that you where coding the software to control your design... or, am i wrong and you will simply use software like gpredict, WXtrack, etc... ?

regards,
/a

Well, yes i have seen that design before. In fact we own one. IT is big and kinda poorly designed.
My code for the g-1000 is done and posted, tough i need to add some safety code. We burnt out a motor when it got stuck so i need to add a time out.

We are about ready to release the g-1000, I can't wait

Anyone able to talk to castor or pollux here?

About Castor and Pollux..

Just tried with castor on this downlink 145.825 MHz but got nothing, im using a good LNA and a cross dipole turnstyle antenna with which i can get good signals from the NOAA's or the ISS.

I guess it will help if i use an arrow antenna and do some tracking.

I will like to get one of your g-1000, could you help me get one?

/a

We have been having problems with Castor, We will check it with our antenna on the next pass. It could be dead, but we also have had trouble with the antenna design. Instruments inside are messing up the signals.

We are going to do the production run for the g-1000 soon. Ill tell you when it is available.

For now you will have better luck with Pollux.

cool, put me on the list for the g-1000.

just had a second go to Castor and got nothing, im actually switching antennas trying to get some action on the support networks for sts-128, that is 259700.. but it was also silent.

will try pollux on the next pass, AOS in 65min.

We were setting up our ground station yesterday, and Pollux was the first satellite we heard (although we didn't have enough equipment hooked up to decode it).

-j

Thats Awesome!

Hey Guys! High Res Photos are available here!
https://goby.nrl.navy.mil/ANDE/Photos.html

firefox is showing up "untrusted link" at that address :s

http://goby.nrl.navy.mil/ANDE/Photos.html

Yea they don't have proper certificates. Don;t worry about it, your not sending any sensitive information are you?a
It is just not a properly signed cert.

GOOD NEWS![/b[
The Goldberg-1000 is ready to be produced!
We found one problem with the code and have fixed it, we forgot to add an auto-stop if the rotor gets caught!
With this added and our months of testing, we feel it is time to release it!
Here is the RTM board:


Thanks for all of those tracking Pollux and Castor!
If you have any questions please ask!
**I have some graphs of the data if you are interested. **

Are either of them still up and running?

EDIT:
Never mind. I answered my own question.
http://www.amsat.org/amsat-new/satellites/satInfo.php?satID=122&retURL=/satellites/status.php

Hi guys, sorry I'm late to the party...

Was anyone able to collect telemetry data from either satellite? How current are the TLE's? It looks like Pollux is decayed and Castor is still up...

Oops sorry looks like the TLE's for Castor are as recent as yesterday...

1 35694U 09038F 10134.16770768 .00062420 12905-4 14304-3 0 3723
2 35694 051.6379 021.6508 0003600 098.6805 261.4610 15.97612265 45617

But no more Pollux? :frowning: