UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


communication:protocol

This is an old revision of the document!


Communications Protocol

This is the typical protocol used by UKHAS members to transmit GPS data balloon to ground on the unlicensed bands, although any custom data may be tacked onto the end of the string.

This doesn't have to be strictly adhered to, since we can easily set up different rules via dl-fldigi's ability to automatically configure itself (upon request).

 $$<CALL SIGN>,<COUNTER D>,<TIME HH:MM:SS>,<LATITUDE DD.DDDDDD>,<LONGITUDE DD.DDDDDD>,<ALTITUDE METRES MMMMM>,<O SPEED KM/H DDDD.DD>,<O BEARING DDD.DD>,<O TEMPERATURE INTERNAL C D.DD>,<O TEMPERATURE EXTERNAL C D.DD>,<O TEMPERATURE CAMERA C D.DD>,<O BAROMETRIC PRESSURE hPa(millibars)>,<O CUSTOM DATA>*<CHECKSUM><NEWLINE> 
  • The individual fields can be of variable length, the minimum and maximum can be set in the payloads XML file.
  • <CALL SIGN> simply identifies your balloon - doesn't have to be a real, licensed callsign.
  • <INCREMENTAL COUNTER ID> also helps people receiving many transmissions at once. This should go up for each new transmission. It can go up 1, 2, 3, or be the milliseconds since poweron, or whatever you want. It just has to increase each time a new string is sent.
  • <LATITUDE> and <LONGITUDE> can either be in decimal degrees (DD.dddd) or the NMEA format (DDMM.mmmm). If using decimal degrees take care that your conversion code does not break if it crosses the meridian. While the NMEA format is accepted you will still need to parse whether it its NSEW and use +/- appropriately.
  • After “<ALTITUDE>,” the distributed tracker or anyone else not prepared for your custom data will not plot your data however the DL system will log the data for review. If you want to send anything else down, you can do so in that space.
  • The checksum is optional, but strongly recommended. It must either be the NMEA XOR format or the CRC16_CITT
  • The newline at the end IS required. It does make the protocol much more easier to human-read, and dl-fldigi looks for that character to terminate the string.
  • The minimum recommended strings consists of
    $$<CALL SIGN>,<COUNTER D>,<TIME HH:MM:SS>,<LATITUDE DD.DDDDDD>,<LONGITUDE DD.DDDDDD>,<ALTITUDE METRES MMMMM>*<CHECKSUM><NEWLINE>
  • Here are example strings:
XOR Checksum'd string:
$$A1,15254,15:36:34,52.145255,000.542061,00118,0000,03,3F4D3F2F,45*62
Example of a CRC16_CCITT'd string:
$$hadie,181,10:42:10,54.422829,-6.741293,27799.3,1:10*002A
Demonstration of the fact that the custom data can be anything:
$$icarus,12342,12:34:17,52.345645,-1.02342,10232,21.35,192.3,15.4,-22.34,-18.27,1232,Blah;Blah;Blah*0C

Usage example for the below two functions

#include <stdio.h>
#include <stdint.h>
#include <string.h>
 
char s[100];
 
void make_string(struct information i)
{
	char checksum[10];
 
	snprintf(s, sizeof(s), "$$MYPAYLOAD,%i,%s,%s", i->num, i->gps.lat, i->gps.lon);
 
	snprintf(checksum, sizeof(checksum), "*%04X\n", gps_CRC16_checksum(s));
	// or 	snprintf(checksum, sizeof(checksum), "*%02X\n", gps_xor_checksum(s));
 
	// It would be much more efficient to use the return value of snprintf here, rather than strlen
 
	if (strlen(s) > sizeof(s) - 4 - 1)
	{
		// Don't overflow the buffer. You should have made it bigger.
		return;
	}
 
	// Also copy checksum's terminating \0 (hence the +1).
	memcpy(s + strlen(s), checksum, strlen(checksum) + 1);
}

Useful code to calculate NMEA xor checksum

#include <stdio.h>
#include <stdint.h>
#include <string.h>
 
uint8_t gps_xor_checksum(char *string)
{
	size_t i;
	uint8_t XOR;
	uint8_t c;
 
	XOR = 0;
 
	// Calculate checksum ignoring the first two $s
	for (i = 2; i < strlen(string); i++)
	{
		c = string[i];
		XOR ^= c;
	}
 
	return XOR;
}

Useful code to calculate CRC16_CCITT checksum on the AVR

#include <stdio.h>
#include <stdint.h>
#include <util/crc16.h>
#include <string.h>
 
uint16_t gps_CRC16_checksum (char *string)
{
	size_t i;
	uint16_t crc;
	uint8_t c;
 
	crc = 0xFFFF;
 
	// Calculate checksum ignoring the first two $s
	for (i = 2; i < strlen(string); i++)
	{
		c = string[i];
		crc = _crc_xmodem_update (crc, c);
	}
 
	return crc;
}
communication/protocol.1275916105.txt.gz · Last modified: 2010/06/07 13:08 by jcoxon