I always wanted antenna tracker. There are many commercial ones integrated to their OSD’s and transmitting location info back by audio channel or sometimes video. Not the way I wanted and pretty expensive.
After switching to my version of OpenLRS I searched for antenna tracker project (source code) suitable for use with OpenLRSng’s transparent telemetry. Then I found Ghettostation by KipK. It is running on arduino, has display and buttons and is open source. I havent had Arduino Mega nor Teensy, so I modified source code to run on atmega328. For now I am running it on OpenLRS receiver without RF module. When my Teensy arrive, I will switch it.
Simplified schematic:
Ghettostation understands several protocols natively, like Mavlink or UAVtalk. This is great, but in some of my planes, there is no autopilot. Just GPS and OSD. Also, using Mavlink directly needs to have full featured serial telemetry to plane with XBEE or 3DR modems. To address this, GS has it’s own protocol called LightTelemetry (LTM). It is optimized for very low baudrate and one way communication only. This was meant to be used with FSK audio modems. But it is great for OpenLRSng as well! Kipk included support for LTM in TauLabs and Multiwii, so if you have one of these, load modified firmware and connect it with receiver and you are done. But if you have other flight control or none, I made simple arduino program for parsing NMEA crap and encoding it in LTM packets. I used TinyGPS++ library for parsing NMEA and few lines from TauLabs code.
Antenna tracker hardware is still under development, I had to find a good way to do panning. I used what I had around and recycled most of the stuff. Pan servo is modified to 360 degreed by replacing potentiometer with external one geared from servo output. Tilt servo is direct drive.
Today I made first field test, walking around with big breadboard and great wire mess. Whole setup worked, tracker was pointing at me all the time! There is still issue with pan servo precision and ancient Garmin GPS is not very accurate, but still big success for me.
Can’t wait to finish this and fly with tracker on regular basis.
As a future feature, my plan is to add piece of code into GS to reconstruct NMEA sentences from LTM to use Oziexplorer (or any other desktop map software – no google maps) on PC to see my plane on map.
Code for protocol translating Arduino:
[cpp]
/**
*****************************************************************************
* NMEA to LightTelemetry protocol translator, for use in UAV
* to be used with ghettostation https://code.google.com/p/ghettostation/
* requires TinyGPS++ library
*
* using only one serial port: GPS output to RX pin, TX pin to datalink input.
* GPS > LTM encoder > wireless datalink in air >>> wireless datalink on earth > ghettostation
* (c) kolin 2014
*****************************************************************************
*
* #################################################################################################################
* LightTelemetry protocol (LTM)
*
* Ghettostation one way telemetry protocol for really low bitrates (1200/2400 bauds).
*
* Protocol details: 3 different frames, little endian.
* G Frame (GPS position) (2hz @ 1200 bauds , 5hz >= 2400 bauds): 18BYTES
* 0x24 0x54 0x47 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xC0
* $ T G ——–LAT——– ——-LON——— SPD ——–ALT——– SAT/FIX CRC
*
* A Frame (Attitude) (5hz @ 1200bauds , 10hz >= 2400bauds): 10BYTES
* 0x24 0x54 0x41 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xC0
* $ T A –PITCH– –ROLL— -HEADING- CRC
*
* S Frame (Sensors) (2hz @ 1200bauds, 5hz >= 2400bauds): 11BYTES
* 0x24 0x54 0x53 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xC0
* $ T S VBAT(mv) Current(ma) RSSI AIRSPEED ARM/FS/FMOD CRC
* #################################################################################################################
*/
#include <TinyGPS++.h>
#define BAUDRATE 4800
#define LTM_GFRAME_SIZE 18
TinyGPSPlus gps; //define TinyGPS++ object
TinyGPSCustom fixtype(gps, "GPGSA",2); //extract for fix type (no,2D,3D..) $GPGSA sentence, 2nd element
long previousMillis = 0;
long interval = 200; //5Hz telemetry send rate
bool newdata = false;
void setup()
{
Serial.begin(BAUDRATE);
}
void loop()
{
unsigned long currentMillis = millis();
if (Serial.available() > 0) //check serial line for new data
{
if (gps.encode(Serial.read())) //while feeding tinyGPS with new data, check if it has new sentence parsed
{
newdata=true;
}
}
if(currentMillis – previousMillis > interval && newdata == true) //do this part only in interval
{
previousMillis = currentMillis; // save the last time you passed
newdata=false;
uint8_t* LTM_Packet = encode_LTM_Packet(); //prepare the packet
Serial.write(LTM_Packet, LTM_GFRAME_SIZE); //send the packet
}
}
static uint8_t* encode_LTM_Packet()
{
int32_t lt_latitude = 10000000 * gps.location.lat(); //Latitude in degrees (double)
int32_t lt_longitude = 10000000 * gps.location.lng(); // Longitude in degrees (double)
uint8_t lt_groundspeed = (uint8_t) round(gps.speed.mps()); //Speed in meters per second (double)
int32_t lt_altitude = gps.altitude.value(); // Raw altitude in centimeters (i32)
uint8_t lt_gpssats = (uint8_t) round(gps.satellites.value()); // Number of satellites in use (u32)
uint8_t lt_gpsfix = atoi(fixtype.value()); //type of GPS fix, returns string, so the conversion
//code copied from TauLabs with LTM support
uint8_t LTBuff[LTM_GFRAME_SIZE];
//G Frame: $T(2 bytes)G(1byte)LAT(cm,4 bytes)LON(cm,4bytes)SPEED(m/s,1bytes)ALT(cm,4bytes)SATS(6bits)FIX(2bits)CRC(xor,1byte)
//START
LTBuff[0]=0x24; //$
LTBuff[1]=0x54; //T
//FRAMEID
LTBuff[2]=0x47; //G
//PAYLOAD
LTBuff[3]=(lt_latitude >> 8*0) & 0xFF;
LTBuff[4]=(lt_latitude >> 8*1) & 0xFF;
LTBuff[5]=(lt_latitude >> 8*2) & 0xFF;
LTBuff[6]=(lt_latitude >> 8*3) & 0xFF;
LTBuff[7]=(lt_longitude >> 8*0) & 0xFF;
LTBuff[8]=(lt_longitude >> 8*1) & 0xFF;
LTBuff[9]=(lt_longitude >> 8*2) & 0xFF;
LTBuff[10]=(lt_longitude >> 8*3) & 0xFF;
LTBuff[11]=(lt_groundspeed >> 8*0) & 0xFF;
LTBuff[12]=(lt_altitude >> 8*0) & 0xFF;
LTBuff[13]=(lt_altitude >> 8*1) & 0xFF;
LTBuff[14]=(lt_altitude >> 8*2) & 0xFF;
LTBuff[15]=(lt_altitude >> 8*3) & 0xFF;
LTBuff[16]= ((lt_gpssats << 2)& 0xFF ) | (lt_gpsfix & 0b00000011) ; // last 6 bits: sats number, first 2:fix type (0,1,2,3)
uint8_t LTCrc = 0x00;
for (int i = 3; i < LTM_GFRAME_SIZE-1; i++) {
LTCrc ^= LTBuff[i];
}
LTBuff[LTM_GFRAME_SIZE-1]=LTCrc;
return LTBuff;
}
[/cpp]
Sorry, I’m using a translator ..
I cannot contact the author of the original so I am writing here – could you please change the tracker code to use endless servos?