Multiple changes.

- Update APRS position packet to include timestamp.
- Add ability to set air pressure level to control GPS airborne mode
- Add capability for time only acquisition from GPS when fixed coord set
- Revise GPIO naming to use IO1 - IO3 (2 & only if not external BME)
pull/4/head
CInsights 2018-04-28 01:05:57 +10:00
rodzic e56eca71e6
commit 061fc953ab
16 zmienionych plików z 616 dodań i 398 usunięć

Wyświetl plik

@ -247,6 +247,9 @@
#define LINE_GPIO_PIN PAL_LINE(GPIOA, 8U)
#define LINE_IO_TXD PAL_LINE(GPIOB, 10U)
#define LINE_IO_RXD PAL_LINE(GPIOC, 11U)
#define LINE_IO1 LINE_GPIO_PIN
#define LINE_IO2 LINE_IO_TXD
#define LINE_IO3 LINE_IO_RXD
// LED
#define LINE_IO_BLUE PAL_LINE(GPIOC, 1U)

Wyświetl plik

@ -131,7 +131,8 @@ const conf_t conf_flash_default = {
.rssi = 0x3F
},
// Node rx identity
.call = "VK2GJ-4"
.call = "VK2GJ-4",
.symbol = SYM_ANTENNA // Use this symbol in message responses
},
.tx = { // The transmit identity for digipeat transmit and messages responses
.radio_conf = {
@ -170,6 +171,7 @@ const conf_t conf_flash_default = {
.gps_on_vbat = 1000,
.gps_off_vbat = 1000,
.gps_onper_vbat = 1000,
.gps_airborne = 90000, // Enable airborne mode below this threshold (Pa)
.magic = CONFIG_MAGIC_DEFAULT // Do not remove. This is the activation bit.
};

Wyświetl plik

@ -395,7 +395,7 @@ uint8_t gps_power_save(int on) {
return gps_receive_ack(0x06, 0x11, 1000);
}
bool GPS_Init(void) {
bool GPS_Init(bool airborne) {
// Initialize pins
TRACE_INFO("GPS > Init pins");
palSetLineMode(LINE_GPS_RESET, PAL_MODE_OUTPUT_PUSHPULL); // GPS reset
@ -431,15 +431,16 @@ bool GPS_Init(void) {
return false;
}
cntr = 3;
while((status = gps_set_airborne_model()) == false && cntr--);
if(status) {
TRACE_INFO("GPS > ... Set airborne model OK");
} else {
TRACE_ERROR("GPS > Communication Error [set airborne]");
return false;
}
if(airborne) {
cntr = 3;
while((status = gps_set_airborne_model()) == false && cntr--);
if(status) {
TRACE_INFO("GPS > ... Set airborne model OK");
} else {
TRACE_ERROR("GPS > Communication Error [set airborne]");
return false;
}
}
return true;
}

Wyświetl plik

@ -36,7 +36,7 @@ uint8_t gps_power_save(int on);
//uint8_t gps_save_settings(void);
bool gps_get_fix(gpsFix_t *fix);
bool GPS_Init(void);
bool GPS_Init(bool airborne);
void GPS_Deinit(void);
uint32_t GPS_get_mcu_frequency(void);
bool gps_calc_ubx_csum(uint8_t *mbuf, uint16_t mlen);

Wyświetl plik

@ -12,45 +12,52 @@ dataPoint_t* flash_getLogBuffer(uint16_t id)
}
/**
* Returns next free log entry address in memory. Returns 0 if all cells are
* filled with data
* Returns next free log entry address in memory.
* Returns NULL if all entries are used.
*/
static dataPoint_t* flash_getNextFreeLogAddress(void)
{
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++)
if(LOG_IS_EMPTY(tp))
return tp;
return NULL;
static dataPoint_t* flash_getNextFreeLogAddress(void) {
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(LOG_IS_EMPTY(tp))
return tp;
}
return NULL;
}
dataPoint_t* flash_getNewestLogEntry(void)
{
dataPoint_t* last_tp = NULL;
uint64_t last_id = 0x0;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && last_id <= LOG_RSTandID(tp)) {
last_id = LOG_RSTandID(tp);
last_tp = tp;
}
}
return last_tp;
/*
*
*/
dataPoint_t* flash_getNewestLogEntry(void) {
dataPoint_t* last_tp = NULL;
uint64_t last_id = 0x0;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && last_id <= LOG_RSTandID(tp)) {
last_id = LOG_RSTandID(tp);
last_tp = tp;
} else {
break;
}
}
return last_tp;
}
dataPoint_t* flash_getOldestLogEntry(void)
{
dataPoint_t* first_tp = NULL;
uint64_t first_id = 0xFFFFFFFFFFFFFFFF;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && first_id >= LOG_RSTandID(tp)) {
first_id = LOG_RSTandID(tp);
first_tp = tp;
}
}
return first_tp;
/*
*
*/
dataPoint_t* flash_getOldestLogEntry(void) {
dataPoint_t* first_tp = NULL;
uint64_t first_id = 0xFFFFFFFFFFFFFFFF;
dataPoint_t* tp;
for(uint32_t i=0; (tp = flash_getLogBuffer(i)) != NULL; i++) {
if(!LOG_IS_EMPTY(tp) && first_id >= LOG_RSTandID(tp)) {
first_id = LOG_RSTandID(tp);
first_tp = tp;
} else {
break;
}
}
return first_tp;
}
/**
@ -77,7 +84,7 @@ void flash_writeLogDataPoint(dataPoint_t* tp)
flash_eraseOldestLogData();
address = flash_getNextFreeLogAddress();
}
if(address == NULL) // Something went wront at erasing the memory
if(address == NULL) // Something went wrong at erasing the memory
{
TRACE_ERROR("LOG > Erasing flash failed");
return;

Wyświetl plik

@ -70,7 +70,7 @@ void getTime(ptime_t *date) {
RTCDateTime timespec;
rtcGetTime(&RTCD1, &timespec);
date->year = timespec.year + 2000;
date->year = timespec.year + RTC_BASE_YEAR;
date->month = timespec.month;
date->day = timespec.day;
date->hour = timespec.millisecond / 3600000;
@ -85,7 +85,7 @@ void getTime(ptime_t *date) {
void setTime(ptime_t *date) {
TRACE_INFO("GPS > Calibrate RTC");
RTCDateTime timespec;
timespec.year = date->year - 2000;
timespec.year = date->year - RTC_BASE_YEAR;
timespec.month = date->month;
timespec.day = date->day;
timespec.millisecond = date->hour * 3600000 + date->minute * 60000 + date->second * 1000;

Wyświetl plik

@ -609,7 +609,7 @@ static bool Si446x_transmit(radio_unit_t radio,
chThdSleep(TIME_MS2I(1));
}
/* Clear channel timing. */
TRACE_INFO( "SI > CCA completed in %d milliseconds",
TRACE_INFO( "SI > CCA attained in %d milliseconds",
chTimeI2MS(chVTTimeElapsedSinceX(t0)));
}
@ -1298,7 +1298,7 @@ int16_t Si446x_getLastTemperature(radio_unit_t radio) {
pktAcquireRadio(radio, TIME_INFINITE);
// Temperature readout
lastTemp = Si446x_getTemperature(radio);
TRACE_INFO("SI > Transmitter temperature %d degC\r\n", lastTemp/100);
TRACE_INFO("SI > Transmitter temperature %d degC", lastTemp/100);
pktReleaseRadio(radio);
} else {
TRACE_INFO("SI > Transmitter temperature not available");

Wyświetl plik

@ -479,7 +479,7 @@ packet_t ax25_from_text (char *monitor, int strict)
if ( ! ax25_parse_addr (AX25_SOURCE, pa, strict, atemp, &ssid_temp, &heard_temp)) {
TRACE_ERROR("PKT > Bad source address in packet");
/* Only need single packet release here but linked probably better for consistency. */
/* Only need single packet release here but linked would be fine for consistency. */
pktReleasePacketBuffer(this_p);
return (NULL);
}
@ -2509,10 +2509,12 @@ unsigned short ax25_dedupe_crc (packet_t pp)
* There is a very very small probability that two unrelated
* packets will result in the same checksum, and the
* undesired dropping of the packet.
*
* TODO: Deprecate - not used
*
*------------------------------------------------------------------------------*/
unsigned short ax25_m_m_crc (packet_t pp)
/*unsigned short ax25_m_m_crc (packet_t pp)
{
unsigned short crc;
unsigned char fbuf[AX25_MAX_PACKET_LEN];
@ -2524,7 +2526,7 @@ unsigned short ax25_m_m_crc (packet_t pp)
crc = crc16(fbuf, flen, crc);
return (crc);
}
}*/
/*------------------------------------------------------------------

Wyświetl plik

@ -425,7 +425,7 @@ extern int ax25_get_pid (packet_t this_p);
extern unsigned short ax25_dedupe_crc (packet_t pp);
extern unsigned short ax25_m_m_crc (packet_t pp);
//extern unsigned short ax25_m_m_crc (packet_t pp);
extern void ax25_safe_print (char *, int, int ascii_only);

Wyświetl plik

@ -173,9 +173,8 @@ const conf_command_t command_list[] = {
const APRSCommand aprs_commands[] = {
{"?aprsd", aprs_send_aprsd_message},
{"?aprsh", aprs_send_aprsh_message},
{"?aprsp", aprs_send_position_beacon},
{"?aprsp", aprs_send_position_response},
{"?gpio", aprs_execute_gpio_command},
/* {"?gps", aprs_handle_gps_command},*/
{"?reset", aprs_execute_system_reset},
{"?save", aprs_execute_config_save},
{"?img", aprs_execute_img_command},
@ -270,6 +269,113 @@ void aprs_debug_getPacket(packet_t pp, char* buf, uint32_t len)
}
}
/**
* @brief Transmit APRS position packet.
*
* @param[in] callsign origination call sign
* @param[in] path path to use
* @param[in] symbol symbol for originator
* @param[in] dataPoint position data object
*
* @return encoded packet object pointer
* @retval NULL if encoding failed
*/
packet_t aprs_encode_position(const char *callsign,
const char *path, aprs_sym_t symbol,
dataPoint_t *dataPoint) {
ptime_t time;
unixTimestamp2Date(&time, dataPoint->gps_time);
// Latitude
uint32_t y = 380926 * (90 - dataPoint->gps_lat/10000000.0);
uint32_t y3 = y / 753571;
uint32_t y3r = y % 753571;
uint32_t y2 = y3r / 8281;
uint32_t y2r = y3r % 8281;
uint32_t y1 = y2r / 91;
uint32_t y1r = y2r % 91;
// Longitude
uint32_t x = 190463 * (180 + dataPoint->gps_lon/10000000.0);
uint32_t x3 = x / 753571;
uint32_t x3r = x % 753571;
uint32_t x2 = x3r / 8281;
uint32_t x2r = x3r % 8281;
uint32_t x1 = x2r / 91;
uint32_t x1r = x2r % 91;
// Altitude
uint32_t a = logf(METER_TO_FEET(dataPoint->gps_alt)) / logf(1.002f);
uint32_t a1 = a / 91;
uint32_t a1r = a % 91;
uint8_t gpsFix = dataPoint->gps_state == GPS_LOCKED1
|| dataPoint->gps_state == GPS_LOCKED2
|| dataPoint->gps_state == GPS_FIXED ? GSP_FIX_CURRENT : GSP_FIX_OLD;
uint8_t src = NMEA_SRC_GGA;
uint8_t origin = ORIGIN_PICO;
char xmit[256];
uint32_t len = chsnprintf(xmit, sizeof(xmit), "%s>%s,%s:@%02d%02d%02dz",
callsign,
APRS_DEVICE_CALLSIGN,
path,
time.hour,
time.minute,
time.second);
xmit[len+0] = (symbol >> 8) & 0xFF;
xmit[len+1] = y3+33;
xmit[len+2] = y2+33;
xmit[len+3] = y1+33;
xmit[len+4] = y1r+33;
xmit[len+5] = x3+33;
xmit[len+6] = x2+33;
xmit[len+7] = x1+33;
xmit[len+8] = x1r+33;
xmit[len+9] = symbol & 0xFF;
xmit[len+10] = a1+33;
xmit[len+11] = a1r+33;
xmit[len+12] = ((gpsFix << 5) | (src << 3) | origin) + 33;
// Comments
uint32_t len2 = base91_encode((uint8_t*)dataPoint,
(uint8_t*)&xmit[len+13],
sizeof(dataPoint_t));
xmit[len+len2+13] = '|';
/* APRS base91 encoded telemetry. */
// Sequence ID
uint32_t t = dataPoint->id & 0x1FFF;
xmit[len+len2+14] = t/91 + 33;
xmit[len+len2+15] = t%91 + 33;
// Telemetry analog parameters
for(uint8_t i=0; i<5; i++) {
switch(i) {
case 0: t = dataPoint->adc_vbat; break;
case 1: t = dataPoint->adc_vsol; break;
case 2: t = dataPoint->pac_pbat+4096; break;
case 3: t = dataPoint->sen_i1_temp/10 + 1000; break;
case 4: t = dataPoint->sen_i1_press/125 - 40; break;
}
xmit[len+len2+16+i*2] = t/91 + 33;
xmit[len+len2+16+i*2+1] = t%91 + 33;
}
// Telemetry digital parameter
xmit[len+len2+26] = dataPoint->gpio + 33;
/* Digital bits second byte - set zero. */
xmit[len+len2+27] = 33;
xmit[len+len2+28] = '|';
xmit[len+len2+29] = 0;
return ax25_from_text(xmit, true);
}
/**
* @brief Transmit APRS position and telemetry packet.
* @notes Base 91 telemetry encoding is used.
@ -291,8 +397,10 @@ void aprs_debug_getPacket(packet_t pp, char* buf, uint32_t len)
* @retval NULL if encoding failed
*/
packet_t aprs_encode_position_and_telemetry(const char *callsign,
const char *path, uint16_t symbol,
dataPoint_t *dataPoint) {
const char *path, aprs_sym_t symbol,
dataPoint_t *dataPoint,
bool extended) {
(void)extended;
// Latitude
uint32_t y = 380926 * (90 - dataPoint->gps_lat/10000000.0);
uint32_t y3 = y / 753571;
@ -316,15 +424,24 @@ packet_t aprs_encode_position_and_telemetry(const char *callsign,
uint32_t a1 = a / 91;
uint32_t a1r = a % 91;
uint8_t gpsFix = dataPoint->gps_state == GPS_LOCKED1
|| dataPoint->gps_state == GPS_LOCKED2
|| dataPoint->gps_state == GPS_FIXED ? GSP_FIX_CURRENT : GSP_FIX_OLD;
uint8_t src = NMEA_SRC_GGA;
uint8_t origin = ORIGIN_PICO;
ptime_t time;
unixTimestamp2Date(&time, dataPoint->gps_time);
char xmit[256];
uint32_t len = chsnprintf(xmit, sizeof(xmit), "%s>%s,%s:!",
callsign, APRS_DEVICE_CALLSIGN, path);
uint32_t len = chsnprintf(xmit, sizeof(xmit), "%s>%s,%s:@%02d%02d%02dz",
callsign,
APRS_DEVICE_CALLSIGN,
path,
time.hour,
time.minute,
time.second);
uint8_t gpsFix = dataPoint->gps_state == GPS_LOCKED1
|| dataPoint->gps_state == GPS_LOCKED2
|| dataPoint->gps_state == GPS_FIXED ? GSP_FIX_CURRENT : GSP_FIX_OLD;
uint8_t src = NMEA_SRC_GGA;
uint8_t origin = ORIGIN_PICO;
xmit[len+0] = (symbol >> 8) & 0xFF;
xmit[len+1] = y3+33;
@ -378,6 +495,9 @@ packet_t aprs_encode_position_and_telemetry(const char *callsign,
return ax25_from_text(xmit, true);
}
/*
*
*/
packet_t aprs_encode_data_packet(const char *callsign, const char *path,
char packetType, uint8_t *data)
{
@ -555,101 +675,120 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
if(argc != 1)
return MSG_ERROR;
if(!strcmp(argv[0], "pa8:1")) {
TRACE_INFO("RX > Message: GPIO query PA8 HIGH");
palSetPadMode(GPIOA, 8, PAL_MODE_OUTPUT_PUSHPULL);
palSetPad(GPIOA, 8);
return MSG_OK;
}
if(!strcmp(argv[0], "pa8:0")) {
TRACE_INFO("RX > Message: GPIO query PA8 LOW");
palSetPadMode(GPIOA, 8, PAL_MODE_OUTPUT_PUSHPULL);
palClearPad(GPIOA, 8);
return MSG_OK;
}
if(!strcmp(argv[0], "pa8:?")) {
char buf[AX25_MAX_APRS_MSG_LEN + 1];
/* TODO: Need to read mode and if not output then report as "input" etc. */
chsnprintf(buf, sizeof(buf),
"PA8 is %s ",
(palReadPad(GPIOA, 8) == PAL_HIGH) ? "HIGH" : "LOW");
packet_t pp = aprs_encode_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
}
if(!transmitOnRadio(pp,
id->freq,
0,
0,
id->pwr,
id->mod,
id->cca)) {
TRACE_ERROR("RX > Transmit of GPIO status failed");
return MSG_ERROR;
}
return MSG_OK;
}
return MSG_ERROR;
}
/*
* @brief Handle GPS command
*
* @param[in] id aprs node identity
* @param[in] argc number of parameters
* @param[in] argv array of pointers to parameter strings
*
* @return result of command
* @retval MSG_OK if the command completed.
* @retval MSG_ERROR if there was an error.
*/
/*msg_t aprs_handle_gps_command(aprs_identity_t *id,
int argc, char *argv[]) {
if(argc != 1)
char *tok = strtok(argv[0], ":");
if(tok == NULL)
return MSG_ERROR;
if(!strcmp(argv[0], "fixed")) {
TRACE_INFO("RX > Message: GPS set to fixed location");
test_gps_enabled = true;
/* TODO: WIP to generalize by parsing out the port # and operation. */
if(!strcmp(argv[0], "io1:1")) {
TRACE_INFO("RX > Message: GPIO set IO1 HIGH");
palSetLineMode(LINE_IO1, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_IO1);
return MSG_OK;
}
if(!strcmp(argv[0], "normal")) {
TRACE_INFO("RX > Message: GPS set to normal operation");
test_gps_enabled = false;
if(!strcmp(argv[0], "io1:0")) {
TRACE_INFO("RX > Message: GPIO set IO1 LOW");
palSetLineMode(LINE_IO1, PAL_MODE_OUTPUT_PUSHPULL);
palClearLine(LINE_IO1);
return MSG_OK;
}
if(!strcmp(argv[0], "status")) {
char buf[AX25_MAX_APRS_MSG_LEN + 1];
#if ENABLE_EXTERNAL_I2C != TRUE
chsnprintf(buf, sizeof(buf),
"GPS is %s",
test_gps_enabled ? "fixed" : "normal");
if(!strcmp(argv[0], "io2:1")) {
TRACE_INFO("RX > Message: GPIO set IO2 HIGH");
palSetLineMode(LINE_IO2, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_IO2);
return MSG_OK;
}
packet_t pp = aprs_encode_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
if(!strcmp(argv[0], "io2:0")) {
TRACE_INFO("RX > Message: GPIO set IO2 LOW");
palSetLineMode(LINE_IO2, PAL_MODE_OUTPUT_PUSHPULL);
palClearLine(LINE_IO2);
return MSG_OK;
}
if(!strcmp(argv[0], "io3:1")) {
TRACE_INFO("RX > Message: GPIO set IO3 HIGH");
palSetLineMode(LINE_IO3, PAL_MODE_OUTPUT_PUSHPULL);
palSetLine(LINE_IO3);
return MSG_OK;
}
if(!strcmp(argv[0], "io3:0")) {
TRACE_INFO("RX > Message: GPIO set IO3 LOW");
palSetLineMode(LINE_IO3, PAL_MODE_OUTPUT_PUSHPULL);
palClearLine(LINE_IO3);
return MSG_OK;
}
#endif
/* TODO: Parse out IO number and reduce above and below ugly DRY code. */
packet_t pp;
do {
if(!strcmp(argv[0], "io1:?")) {
char buf[AX25_MAX_APRS_MSG_LEN + 1];
/* TODO: Need to read mode and if not output then report as "input" etc. */
chsnprintf(buf, sizeof(buf),
"IO1 is %s ",
(palReadLine(LINE_IO1) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO1 is %s", (palReadLine(LINE_IO1) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_encode_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
}
break;
}
if(!transmitOnRadio(pp,
id->freq,
0,
0,
id->pwr,
id->mod,
id->rssi)) {
TRACE_ERROR("RX > Transmit of GPS status failed");
return MSG_ERROR;
#if ENABLE_EXTERNAL_I2C != TRUE
if(!strcmp(argv[0], "io2:?")) {
char buf[AX25_MAX_APRS_MSG_LEN + 1];
/* TODO: Need to read mode and if not output then report as "input" etc. */
chsnprintf(buf, sizeof(buf),
"IO2 is %s ",
(palReadLine(LINE_IO2) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO2 is %s", (palReadLine(LINE_IO2) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_encode_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
}
break;
}
return MSG_OK;
if(!strcmp(argv[0], "io3:?")) {
char buf[AX25_MAX_APRS_MSG_LEN + 1];
/* TODO: Need to read mode and if not output then report as "input" etc. */
chsnprintf(buf, sizeof(buf),
"IO3 is %s ",
(palReadLine(LINE_IO3) == PAL_HIGH) ? "HIGH" : "LOW");
TRACE_INFO("RX > Message: GPIO query IO3 is %s", (palReadLine(LINE_IO3) == PAL_HIGH) ? "HIGH" : "LOW");
pp = aprs_encode_message(id->call, id->path, id->src, buf, false);
if(pp == NULL) {
TRACE_WARN("RX > No free packet objects or badly formed message");
return MSG_ERROR;
}
break;
}
/* No known IO port found. */
return MSG_ERROR;
#endif
} while(true);
if(!transmitOnRadio(pp,
id->freq,
0,
0,
id->pwr,
id->mod,
id->cca)) {
TRACE_ERROR("RX > Transmit of GPIO status failed");
return MSG_ERROR;
}
return MSG_ERROR;
}*/
return MSG_OK;
}
/**
* @brief Request for position beacon to be sent
@ -662,16 +801,17 @@ msg_t aprs_execute_gpio_command(aprs_identity_t *id,
* @retval MSG_OK if the command completed.
* @retval MSG_ERROR if there was an error.
*/
msg_t aprs_send_position_beacon(aprs_identity_t *id,
msg_t aprs_send_position_response(aprs_identity_t *id,
int argc, char *argv[]) {
(void)argv;
if(argc != 0)
return MSG_ERROR;
/* TODO: Implement a simple (non base 91) position parameter. */
TRACE_INFO("RX > Message: Position query");
dataPoint_t* dataPoint = getLastDataPoint();
packet_t pp = aprs_encode_position_and_telemetry(id->call,
packet_t pp = aprs_encode_position(id->call,
id->path,
id->symbol,
dataPoint);
@ -686,7 +826,7 @@ msg_t aprs_send_position_beacon(aprs_identity_t *id,
id->pwr,
id->mod,
id->cca)) {
TRACE_ERROR("RX > Transmit of APRSD failed");
TRACE_ERROR("RX > Transmit of APRSP failed");
return MSG_ERROR;
}
return MSG_OK;
@ -951,6 +1091,7 @@ static bool aprs_decode_message(packet_t pp) {
&& (conf_sram.aprs.thread_conf.active);
if(aprs_rx) {
strcpy(identity.call, conf_sram.aprs.rx.call);
identity.symbol = conf_sram.aprs.rx.symbol;
/* Other parameters come from tx identity. */
}

Wyświetl plik

@ -87,8 +87,13 @@ extern bool test_gps_enabled;
extern "C" {
#endif
void aprs_debug_getPacket(packet_t pp, char* buf, uint32_t len);
packet_t aprs_encode_position_and_telemetry(const char *callsign, const char *path,
uint16_t symbol, dataPoint_t *dataPoint);
packet_t aprs_encode_position(const char *callsign,
const char *path, aprs_sym_t symbol,
dataPoint_t *dataPoint);
packet_t aprs_encode_position_and_telemetry(const char *callsign,
const char *path,
aprs_sym_t symbol,
dataPoint_t *dataPoint, bool extended);
packet_t aprs_encode_telemetry_configuration(const char *originator,
const char *path,
const char *destination,
@ -101,7 +106,7 @@ extern "C" {
packet_t aprs_compose_aprsd_message(const char *callsign, const char *path,
const char *receiver);
void aprs_decode_packet(packet_t pp);
msg_t aprs_send_position_beacon(aprs_identity_t *id,
msg_t aprs_send_position_response(aprs_identity_t *id,
int argc, char *argv[]);
msg_t aprs_send_aprsd_message(aprs_identity_t *id,
int argc, char *argv[]);

Wyświetl plik

@ -23,7 +23,7 @@
static dataPoint_t dataPoints[2];
static dataPoint_t* lastDataPoint;
static bool threadStarted = false;
static uint8_t attached = 0;
static uint8_t useGPS = 0;
/**
* Returns most recent data point which is complete.
@ -46,94 +46,99 @@ void waitForNewDataPoint(void) {
*/
static void aquirePosition(dataPoint_t* tp, dataPoint_t* ltp,
sysinterval_t timeout) {
sysinterval_t start = chVTGetSystemTime();
sysinterval_t start = chVTGetSystemTime();
gpsFix_t gpsFix;
memset(&gpsFix, 0, sizeof(gpsFix_t));
gpsFix_t gpsFix;
memset(&gpsFix, 0, sizeof(gpsFix_t));
// Switch on GPS if enough power is available and GPS is needed by any position thread
uint16_t batt = stm32_get_vbat();
if(batt < conf_sram.gps_on_vbat) {
tp->gps_state = GPS_LOWBATT1;
} else {
// Switch on GPS if enough power is available and GPS is needed by any position thread
uint16_t batt = stm32_get_vbat();
if(batt < conf_sram.gps_on_vbat) {
tp->gps_state = GPS_LOWBATT1;
} else {
// Switch on GPS
bool status = GPS_Init();
// Switch on GPS
bool airborne = ltp->sen_i1_press/10 < conf_sram.gps_airborne;
TRACE_INFO("COLL > GPS %s in airborne mode", airborne ? "is" : "is not");
bool status = GPS_Init(airborne);
if(status) {
// Search for lock as long as enough power is available
do {
batt = stm32_get_vbat();
gps_get_fix(&gpsFix);
} while(!isGPSLocked(&gpsFix)
&& batt >= conf_sram.gps_off_vbat
&& chVTIsSystemTimeWithin(start, start + timeout)); // Do as long no GPS lock and within timeout, timeout=cycle-1sec (-3sec in order to keep synchronization)
if(status) {
// Search for lock as long as enough power is available
do {
batt = stm32_get_vbat();
gps_get_fix(&gpsFix);
} while(!isGPSLocked(&gpsFix)
&& batt >= conf_sram.gps_off_vbat
&& chVTIsSystemTimeWithin(start, start + timeout)); // Do as long no GPS lock and within timeout, timeout=cycle-1sec (-3sec in order to keep synchronization)
if(batt < conf_sram.gps_off_vbat) { // GPS was switched on but prematurely switched off because the battery is low on power, switch off GPS
if(batt < conf_sram.gps_off_vbat) { // GPS was switched on but prematurely switched off because the battery is low on power, switch off GPS
GPS_Deinit();
TRACE_WARN("COLL > GPS sampling finished GPS LOW BATT");
tp->gps_state = GPS_LOWBATT2;
GPS_Deinit();
TRACE_WARN("COLL > GPS sampling finished GPS LOW BATT");
tp->gps_state = GPS_LOWBATT2;
} else if(!isGPSLocked(&gpsFix)) { // GPS was switched on but it failed to get a lock, keep GPS switched on
} else if(!isGPSLocked(&gpsFix)) { // GPS was switched on but it failed to get a lock, keep GPS switched on
TRACE_WARN("COLL > GPS sampling finished GPS LOSS");
tp->gps_state = GPS_LOSS;
TRACE_WARN("COLL > GPS sampling finished GPS LOSS");
tp->gps_state = GPS_LOSS;
} else { // GPS locked successfully, switch off GPS (unless cycle is less than 60 seconds)
} else { // GPS locked successfully, switch off GPS (unless cycle is less than 60 seconds)
// Switch off GPS (if cycle time is more than 60 seconds)
if(timeout < TIME_S2I(60)) {
TRACE_INFO("COLL > Keep GPS switched on because cycle < 60sec");
tp->gps_state = GPS_LOCKED2;
} else if(conf_sram.gps_onper_vbat != 0 && batt >= conf_sram.gps_onper_vbat) {
TRACE_INFO("COLL > Keep GPS switched on because VBAT >= %dmV", conf_sram.gps_onper_vbat);
tp->gps_state = GPS_LOCKED2;
} else {
TRACE_INFO("COLL > Switch off GPS");
GPS_Deinit();
tp->gps_state = GPS_LOCKED1;
}
// Switch off GPS (if cycle time is more than 60 seconds)
if(timeout < TIME_S2I(60)) {
TRACE_INFO("COLL > Keep GPS switched on because cycle < 60sec");
tp->gps_state = GPS_LOCKED2;
} else if(conf_sram.gps_onper_vbat != 0 && batt >= conf_sram.gps_onper_vbat) {
TRACE_INFO("COLL > Keep GPS switched on because VBAT >= %dmV", conf_sram.gps_onper_vbat);
tp->gps_state = GPS_LOCKED2;
} else {
TRACE_INFO("COLL > Switch off GPS");
GPS_Deinit();
tp->gps_state = GPS_LOCKED1;
}
// Debug
TRACE_INFO("COLL > GPS sampling finished GPS LOCK");
// Debug
TRACE_INFO("COLL > GPS sampling finished GPS LOCK");
// Calibrate RTC
setTime(&gpsFix.time);
// Calibrate RTC
setTime(&gpsFix.time);
// Take time from GPS
tp->gps_time = date2UnixTimestamp(&gpsFix.time);
// Take time from GPS
tp->gps_time = date2UnixTimestamp(&gpsFix.time);
// Set new GPS fix
tp->gps_lat = gpsFix.lat;
tp->gps_lon = gpsFix.lon;
tp->gps_alt = gpsFix.alt;
// Set new GPS fix
tp->gps_lat = gpsFix.lat;
tp->gps_lon = gpsFix.lon;
tp->gps_alt = gpsFix.alt;
tp->gps_sats = gpsFix.num_svs;
tp->gps_pdop = (gpsFix.pdop+3)/5;
}
tp->gps_sats = gpsFix.num_svs;
tp->gps_pdop = (gpsFix.pdop+3)/5;
}
} else { // GPS communication error
} else { // GPS communication error
GPS_Deinit();
tp->gps_state = GPS_ERROR;
GPS_Deinit();
tp->gps_state = GPS_ERROR;
}
}
}
}
tp->gps_ttff = TIME_I2S(chVTGetSystemTime() - start); // Time to first fix
tp->gps_ttff = TIME_I2S(chVTGetSystemTime() - start); // Time to first fix
if(tp->gps_state != GPS_LOCKED1 && tp->gps_state != GPS_LOCKED2) { // We have no valid GPS fix
// Take time from internal RTC
ptime_t time;
getTime(&time);
tp->gps_time = date2UnixTimestamp(&time);
if(tp->gps_state != GPS_LOCKED1 && tp->gps_state != GPS_LOCKED2) { // We have no valid GPS fix
// Take time from internal RTC
ptime_t time;
getTime(&time);
if(time.year != RTC_BASE_YEAR) {
/* RTC has been set so OK to use data. */
tp->gps_time = date2UnixTimestamp(&time);
// Take GPS fix from old lock
tp->gps_lat = ltp->gps_lat;
tp->gps_lon = ltp->gps_lon;
tp->gps_alt = ltp->gps_alt;
}
// Take GPS fix from old lock
tp->gps_lat = ltp->gps_lat;
tp->gps_lon = ltp->gps_lon;
tp->gps_alt = ltp->gps_alt;
} /* Else don't set tp data since RTC is not valid. */
}
}
/*
@ -259,132 +264,179 @@ static void setSystemStatus(dataPoint_t* tp) {
* Data Collector (Thread)
*/
THD_FUNCTION(collectorThread, arg) {
uint8_t *attached = arg;
uint8_t *useGPS = arg;
uint32_t id = 0;
lastDataPoint = &dataPoints[0];
uint32_t id = 0;
// Read time from RTC
ptime_t time;
getTime(&time);
lastDataPoint->gps_time = date2UnixTimestamp(&time);
// Read time from RTC
ptime_t time;
getTime(&time);
dataPoints[0].gps_time = date2UnixTimestamp(&time);
dataPoints[1].gps_time = date2UnixTimestamp(&time);
// Get last data point from memory
TRACE_INFO("COLL > Read last data point from flash memory");
dataPoint_t* lastLogPoint = flash_getNewestLogEntry();
lastDataPoint = &dataPoints[0];
if(lastLogPoint != NULL) { // If there is stored data point, then get the last know GPS fix
dataPoints[0].reset = lastLogPoint->reset+1;
dataPoints[1].reset = lastLogPoint->reset+1;
lastDataPoint->gps_lat = lastLogPoint->gps_lat;
lastDataPoint->gps_lon = lastLogPoint->gps_lon;
lastDataPoint->gps_alt = lastLogPoint->gps_alt;
lastDataPoint->gps_sats = lastLogPoint->gps_sats;
lastDataPoint->gps_ttff = lastLogPoint->gps_ttff;
// Get last data point from memory
TRACE_INFO("COLL > Read last data point from flash memory");
dataPoint_t* lastLogPoint = flash_getNewestLogEntry();
TRACE_INFO(
"COLL > Last data point (from memory)\r\n"
"%s Reset %d ID %d\r\n"
"%s Latitude: %d.%07ddeg\r\n"
"%s Longitude: %d.%07ddeg\r\n"
"%s Altitude: %d Meter",
TRACE_TAB, lastLogPoint->reset, lastLogPoint->id,
TRACE_TAB, lastDataPoint->gps_lat/10000000, (lastDataPoint->gps_lat > 0 ? 1:-1)*lastDataPoint->gps_lat%10000000,
TRACE_TAB, lastDataPoint->gps_lon/10000000, (lastDataPoint->gps_lon > 0 ? 1:-1)*lastDataPoint->gps_lon%10000000,
TRACE_TAB, lastDataPoint->gps_alt
);
} else {
TRACE_INFO("COLL > No data point found in flash memory");
}
if(lastLogPoint != NULL) { // If there is stored data point, then get it.
dataPoints[0].reset = lastLogPoint->reset+1;
dataPoints[1].reset = lastLogPoint->reset+1;
unixTimestamp2Date(&time, lastDataPoint->gps_time);
lastDataPoint->gps_lat = lastLogPoint->gps_lat;
lastDataPoint->gps_lon = lastLogPoint->gps_lon;
lastDataPoint->gps_alt = lastLogPoint->gps_alt;
lastDataPoint->gps_sats = lastLogPoint->gps_sats;
lastDataPoint->gps_ttff = lastLogPoint->gps_ttff;
lastDataPoint->gps_state = GPS_LOG; // Mark dataPoint as LOG packet
TRACE_INFO(
"COLL > Last data point (from memory)\r\n"
"%s Reset %d ID %d\r\n"
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
"%s Latitude: %d.%07ddeg\r\n"
"%s Longitude: %d.%07ddeg\r\n"
"%s Altitude: %d Meter",
TRACE_TAB, lastLogPoint->reset, lastLogPoint->id,
TRACE_TAB, time.year, time.month, time.day, time.hour,
time.minute, time.day,
TRACE_TAB, lastDataPoint->gps_lat/10000000,
(lastDataPoint->gps_lat > 0
? 1:-1)*lastDataPoint->gps_lat%10000000,
TRACE_TAB, lastDataPoint->gps_lon/10000000,
(lastDataPoint->gps_lon > 0
? 1:-1)*lastDataPoint->gps_lon%10000000,
TRACE_TAB, lastDataPoint->gps_alt
);
lastDataPoint->gps_state = GPS_LOG; // Mark dataPoint as LOG packet
} else {
TRACE_INFO("COLL > No data point found in flash memory");
lastDataPoint->gps_state = GPS_OFF; // Mark dataPoint unset
}
// Measure telemetry
measureVoltage(lastDataPoint);
getSensors(lastDataPoint);
getGPIO(lastDataPoint);
setSystemStatus(lastDataPoint);
// Measure telemetry
measureVoltage(lastDataPoint);
getSensors(lastDataPoint);
getGPIO(lastDataPoint);
setSystemStatus(lastDataPoint);
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
// Wait for position threads to start
chThdSleep(TIME_MS2I(500));
// Wait for position threads to start
chThdSleep(TIME_MS2I(500));
sysinterval_t cycle_time = chVTGetSystemTime();
while(true)
{
TRACE_INFO("COLL > Do module DATA COLLECTOR cycle");
sysinterval_t cycle_time = chVTGetSystemTime();
while(true)
{
TRACE_INFO("COLL > Do module DATA COLLECTOR cycle");
dataPoint_t* tp = &dataPoints[(id+1) % 2]; // Current data point (the one which is processed now)
dataPoint_t* ltp = &dataPoints[ id % 2]; // Last data point
dataPoint_t* tp = &dataPoints[(id+1) % 2]; // Current data point (the one which is processed now)
dataPoint_t* ltp = &dataPoints[ id % 2]; // Last data point
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600);
if(conf_sram.pos_pri.thread_conf.active && conf_sram.pos_sec.thread_conf.active) { // Both position threads are active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle < conf_sram.pos_sec.thread_conf.cycle ? conf_sram.pos_pri.thread_conf.cycle : conf_sram.pos_sec.thread_conf.cycle; // Choose the smallest cycle
(*attached)++;
} else if(conf_sram.pos_pri.thread_conf.active) { // Only primary position thread is active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle;
(*attached)++;
} else if(conf_sram.pos_sec.thread_conf.active) { // Only secondary position thread is active
data_cycle_time = conf_sram.pos_sec.thread_conf.cycle;
(*attached)++;
} else if(conf_sram.aprs.thread_conf.active && conf_sram.aprs.tx.beacon) { // APRS beacon is active
data_cycle_time = conf_sram.pos_sec.thread_conf.cycle;
if(conf_sram.aprs.tx.gps)
(*attached)++;
} else { // There must be an error
TRACE_ERROR("COLL > Data collector started but no position thread is active");
}
// Determine cycle time and if GPS should be used.
sysinterval_t data_cycle_time = TIME_S2I(600);
if(conf_sram.pos_pri.thread_conf.active && conf_sram.pos_sec.thread_conf.active) { // Both position threads are active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle < conf_sram.pos_sec.thread_conf.cycle ? conf_sram.pos_pri.thread_conf.cycle : conf_sram.pos_sec.thread_conf.cycle; // Choose the smallest cycle
(*useGPS)++;
} else if(conf_sram.pos_pri.thread_conf.active) { // Only primary position thread is active
data_cycle_time = conf_sram.pos_pri.thread_conf.cycle;
(*useGPS)++;
} else if(conf_sram.pos_sec.thread_conf.active) { // Only secondary position thread is active
data_cycle_time = conf_sram.pos_sec.thread_conf.cycle;
(*useGPS)++;
} else if(conf_sram.aprs.thread_conf.active && conf_sram.aprs.tx.beacon) { // APRS beacon is active
data_cycle_time = conf_sram.aprs.tx.cycle;
if(conf_sram.aprs.tx.gps) {
(*useGPS)++;
}
} else { // There must be an error
TRACE_ERROR("COLL > Data collector started but no position thread is active");
}
// Get GPS position
if(*attached) aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
// Gather telemetry and system status data
measureVoltage(tp);
getSensors(tp);
getGPIO(tp);
setSystemStatus(tp);
tp->id = ++id; // Serial ID
/*
* Enable GPS position acquisition if requested.
* a) If the RTC was not set then enable GPS temporarily to set it.
* b) If a thread is using GPS for position.
*/
unixTimestamp2Date(&time, ltp->gps_time);
if(*useGPS == 0 && time.year == RTC_BASE_YEAR) {
TRACE_INFO("COLL > Acquire time using GPS");
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
/* GPS done. */
if(!(tp->gps_state == GPS_LOCKED1
|| tp->gps_state == GPS_LOCKED2)) {
/* Acquisition failed. Wait and then try again. */
TRACE_INFO("COLL > Time acquisition from GPS failed");
chThdSleep(TIME_S2I(60));
continue;
}
TRACE_INFO("COLL > Time acquired from GPS");
/* Switch GPS off. */
GPS_Deinit();
} else if(*useGPS > 0) {
aquirePosition(tp, ltp, data_cycle_time - TIME_S2I(3));
} else {
/*
* No threads using GPS.
* RTC valid so set tp & ltp from fixed location data.
*/
tp->gps_alt = conf_sram.aprs.tx.alt;
tp->gps_lat = conf_sram.aprs.tx.lat;
tp->gps_lon = conf_sram.aprs.tx.lon;
tp->gps_state = GPS_FIXED;
// Measure telemetry
measureVoltage(tp);
getSensors(tp);
getGPIO(tp);
setSystemStatus(tp);
ltp->gps_time = tp->gps_time;
ltp->gps_alt = tp->gps_alt;
ltp->gps_lat = tp->gps_lat;
ltp->gps_lon = tp->gps_lon;
ltp->gps_state = GPS_FIXED;
}
// Trace data
unixTimestamp2Date(&time, tp->gps_time);
TRACE_INFO( "COLL > New data point available (ID=%d)\r\n"
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
"%s Pos %d.%05d %d.%05d Alt %dm\r\n"
"%s Sats %d TTFF %dsec\r\n"
"%s ADC Vbat=%d.%03dV Vsol=%d.%03dV Pbat=%dmW\r\n"
"%s AIR p=%d.%01dPa T=%d.%02ddegC phi=%d.%01d%%\r\n"
tp->id = ++id; // Serial ID
// Trace data
unixTimestamp2Date(&time, tp->gps_time);
TRACE_INFO( "COLL > New data point available (ID=%d)\r\n"
"%s Time %04d-%02d-%02d %02d:%02d:%02d\r\n"
"%s Pos %d.%05d %d.%05d Alt %dm\r\n"
"%s Sats %d TTFF %dsec\r\n"
"%s ADC Vbat=%d.%03dV Vsol=%d.%03dV Pbat=%dmW\r\n"
"%s AIR p=%d.%01dPa T=%d.%02ddegC phi=%d.%01d%%\r\n"
#if ENABLE_EXTERNAL_I2C == TRUE
"%s IO IO1=%d",
"%s IOP IO1=%d",
#else
"%s IO IO1=%d IO2=%d IO3=%d",
"%s IOP IO1=%d IO2=%d IO3=%d",
#endif
tp->id,
TRACE_TAB, time.year, time.month, time.day, time.hour, time.minute, time.day,
TRACE_TAB, tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
TRACE_TAB, tp->gps_sats, tp->gps_ttff,
TRACE_TAB, tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->pac_pbat,
TRACE_TAB, tp->sen_i1_press/10, tp->sen_i1_press%10, tp->sen_i1_temp/100, tp->sen_i1_temp%100, tp->sen_i1_hum/10, tp->sen_i1_hum%10,
tp->id,
TRACE_TAB, time.year, time.month, time.day, time.hour, time.minute, time.day,
TRACE_TAB, tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt,
TRACE_TAB, tp->gps_sats, tp->gps_ttff,
TRACE_TAB, tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->pac_pbat,
TRACE_TAB, tp->sen_i1_press/10, tp->sen_i1_press%10, tp->sen_i1_temp/100, tp->sen_i1_temp%100, tp->sen_i1_hum/10, tp->sen_i1_hum%10,
#if ENABLE_EXTERNAL_I2C == TRUE
TRACE_TAB, tp->gpio & 1
TRACE_TAB, tp->gpio & 1
#else
TRACE_TAB, tp->gpio & 1, (tp->gpio >> 1) & 1, (tp->gpio >> 2) & 1
TRACE_TAB, tp->gpio & 1, (tp->gpio >> 1) & 1, (tp->gpio >> 2) & 1
#endif
);
);
// Write data point to Flash memory
flash_writeLogDataPoint(tp);
// Write data point to Flash memory
flash_writeLogDataPoint(tp);
// Switch last data point
lastDataPoint = tp;
// Switch last data point
lastDataPoint = tp;
// Wait until cycle
cycle_time = chThdSleepUntilWindowed(cycle_time, cycle_time + data_cycle_time);
}
// Wait until cycle
cycle_time = chThdSleepUntilWindowed(cycle_time, cycle_time + data_cycle_time);
}
}
/*
@ -399,7 +451,7 @@ void init_data_collector() {
thread_t *th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(10*1024),
"TRA", LOWPRIO,
collectorThread, &attached);
collectorThread, &useGPS);
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("COLL > Could not start"

Wyświetl plik

@ -11,8 +11,8 @@ typedef enum {
GPS_LOSS, // The GPS was switched on all time but it couln't acquire a fix
GPS_LOWBATT1, // The GPS wasn't switched on because the battery has not enough energy
GPS_LOWBATT2, // The GPS was switched on but has been switched off prematurely while the battery has not enough energy (or is too cold)
GPS_LOG, // The tracker has been just switched on and the position has been taken from the log
GPS_OFF, // There is no active position thread so the GPS was never switched on (in oder to save power)
GPS_LOG, // The tracker has just been switched on and the position has been taken from the log
GPS_OFF, // There was no prior acquisition by GPS
GPS_ERROR, // The GPS has a communication error
GPS_FIXED // Fixed location data used from APRS location
} gpsState_t;
@ -32,19 +32,20 @@ typedef struct {
gpsState_t gps_state; // GPS state
uint8_t gps_sats; // Satellites used for solution
uint8_t gps_ttff; // Time to first fix in seconds
uint8_t gps_pdop; // Position DOP in 0.05 per unit (unitless)
uint8_t gps_pdop; // Position DOP in 0.05 per arbitrary unit
uint16_t gps_alt; // Altitude in meter
int32_t gps_lat; // Latitude in 10^(-7)° per unit
int32_t gps_lon; // Longitude in 10^(-7)° per unit
int32_t gps_lat; // Latitude in 10^(-7)° per unit
int32_t gps_lon; // Longitude in 10^(-7)° per unit
// BME280 (on board)
uint32_t sen_i1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e1_press; // Airpressure in Pa*10 (in 0.1Pa)
uint32_t sen_e2_press; // Airpressure in Pa*10 (in 0.1Pa)
int16_t sen_i1_temp; // Temperature in 0.01°C per unit
int16_t sen_e1_temp; // Temperature in 0.01°C per unit
int16_t sen_e2_temp; // Temperature in 0.01°C per unit
// BME280 (off board)
int16_t sen_i1_temp; // Temperature in 0.01°C per unit
int16_t sen_e1_temp; // Temperature in 0.01°C per unit
int16_t sen_e2_temp; // Temperature in 0.01°C per unit
uint8_t sen_i1_hum; // Rel. humidity in %
uint8_t sen_e1_hum; // Rel. humidity in %
@ -72,8 +73,8 @@ typedef struct {
* - 3:4 pac1720 status
* - 5:7 OV5640 status
* - 8:9 BMEi1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 9:10 BMEe1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 10:11 BMEe2 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 10:11 BMEe1 status (0 = OK, 1 = Fail, 2 = Not fitted)
* - 12:13 BMEe2 status (0 = OK, 1 = Fail, 2 = Not fitted)
*/
} dataPoint_t;
@ -82,5 +83,5 @@ dataPoint_t* getLastDataPoint(void);
void init_data_collector(void);
#endif
#endif /* __COLLECTOR_H__ */

Wyświetl plik

@ -36,16 +36,6 @@ THD_FUNCTION(bcnThread, arg) {
TRACE_INFO("BCN > Do module BEACON cycle");
dataPoint_t* dataPoint = getLastDataPoint();
if(dataPoint->gps_state != GPS_LOCKED1
|| dataPoint->gps_state != GPS_LOCKED2) {
TRACE_INFO("BCN > Set location from fixed location data");
dataPoint->gps_alt = conf->tx.alt;
dataPoint->gps_lat = conf->tx.lat;
dataPoint->gps_lon = conf->tx.lon;
dataPoint->gps_state = GPS_FIXED;
} else {
TRACE_INFO("BCN > Set location from GPS derived data");
}
if(!p_sleep(&conf->thread_conf.sleep_conf)) {
// Telemetry encoding parameter transmission
@ -63,7 +53,7 @@ THD_FUNCTION(bcnThread, arg) {
type);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects for"
" telemetry config transmission");
" telemetry config transmission");
} else {
if(!transmitOnRadio(packet,
conf->tx.radio_conf.freq,
@ -80,62 +70,73 @@ THD_FUNCTION(bcnThread, arg) {
last_conf_transmission += conf->tx.tel_enc_cycle;
}
TRACE_INFO("BCN > Transmit position beacon");
if(dataPoint->gps_state == GPS_FIXED
|| dataPoint->gps_state == GPS_LOCKED1
|| dataPoint->gps_state == GPS_LOCKED2) {
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->tx.call, conf->tx.path,
conf->tx.symbol, dataPoint);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->tx.radio_conf.freq,
0,
0,
conf->tx.radio_conf.pwr,
conf->tx.radio_conf.mod,
conf->tx.radio_conf.cca)) {
TRACE_ERROR("BCN > failed to transmit beacon data");
TRACE_INFO("BCN > Transmit position beacon");
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->tx.call,
conf->tx.path,
conf->tx.symbol,
dataPoint, true);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects"
" for position transmission");
} else {
if(!transmitOnRadio(packet,
conf->tx.radio_conf.freq,
0,
0,
conf->tx.radio_conf.pwr,
conf->tx.radio_conf.mod,
conf->tx.radio_conf.cca)) {
TRACE_ERROR("BCN > failed to transmit beacon data");
}
chThdSleep(TIME_S2I(5));
}
chThdSleep(TIME_S2I(5));
}
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be sent to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.aprs.base.enabled
? conf_sram.aprs.base.call : APRS_DEVICE_CALLSIGN;
/*
* Encode/Transmit APRSD packet.
* This is a tracker originated message (not a reply to a request).
* The message will be sent to the base station if set.
* Else send it to device identity.
*/
char *call = conf_sram.aprs.base.enabled
? conf_sram.aprs.base.call : APRS_DEVICE_CALLSIGN;
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf->tx.call,
conf->base.path,
call);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->tx.radio_conf.freq,
0,
0,
conf->tx.radio_conf.pwr,
conf->tx.radio_conf.mod,
conf->tx.radio_conf.cca
)) {
TRACE_ERROR("BCN > Failed to transmit APRSD data");
/*
* Send message from this device.
* Use call sign and path as specified in base config.
* There is no acknowledgment requested.
*/
packet = aprs_compose_aprsd_message(
conf->tx.call,
conf->base.path,
call);
if(packet == NULL) {
TRACE_WARN("BCN > No free packet objects "
"or badly formed APRSD message");
} else {
if(!transmitOnRadio(packet,
conf->tx.radio_conf.freq,
0,
0,
conf->tx.radio_conf.pwr,
conf->tx.radio_conf.mod,
conf->tx.radio_conf.cca
)) {
TRACE_ERROR("BCN > Failed to transmit APRSD data");
}
chThdSleep(TIME_S2I(5));
}
chThdSleep(TIME_S2I(5));
} else {
TRACE_INFO("BCN > No GPS data available for position beacon");
chThdSleep(TIME_S2I(60));
continue;
}
}
} /* psleep */
time = waitForTrigger(time, conf->tx.cycle);
}
}

Wyświetl plik

@ -77,7 +77,9 @@ THD_FUNCTION(posThread, arg)
// Encode/Transmit position packet
packet_t packet = aprs_encode_position_and_telemetry(conf->call,
conf->path,
conf->symbol, dataPoint);
conf->symbol,
dataPoint,
true);
if(packet == NULL) {
TRACE_WARN("POS > No free packet objects"
" for position transmission");

Wyświetl plik

@ -115,7 +115,7 @@ typedef struct {
typedef struct {
radio_rx_conf_t radio_conf;
aprs_sym_t symbol;
// Protocol
char call[AX25_MAX_ADDR_LEN];
} thd_rx_conf_t;
@ -165,6 +165,7 @@ typedef struct {
volt_level_t gps_off_vbat; // Battery voltage threshold at which GPS is switched off
volt_level_t gps_onper_vbat; // Battery voltage threshold at which GPS is kept switched on all time. This value must be larger
// When gps_on_vbat and gps_off_vbat otherwise this value has no effect. Value 0 disables this feature
uint32_t gps_airborne; // Air pressure below which GPS is switched to airborne mode
uint32_t magic; // Key that indicates if the flash is loaded or has been updated
uint16_t crc; // CRC to verify content
} conf_t;