Go Down

Topic: NRL Satellite (ARDUINO IN SAPCE!) (Read 12 times) previous topic - next topic

Shutter

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.

Code: [Select]
#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

Shutter

#76
Aug 19, 2009, 05:12 pm Last Edit: Aug 19, 2009, 05:15 pm by Shutter Reason: 1
So anyone able to track castor or pollux yet?

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

armadillo

btw shutter, i just found this:

http://www.uk.amsat.org/index.php?option=com_content&task=view&id=254&Itemid=86

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

Shutter

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?

armadillo

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

Go Up