Improve handling of low battery and init error condition for GPS.

pull/4/head
bob 2018-06-28 21:50:43 +10:00
rodzic 2f30a0a2c1
commit 11cd5a4849
6 zmienionych plików z 130 dodań i 56 usunięć

Wyświetl plik

@ -14,7 +14,7 @@
bool gps_enabled = false;
int8_t gps_model = GPS_MODEL_UNSET;
#if defined(UBLOX_USE_UART)
#if defined(UBLOX_UART_CONNECTED)
// Serial driver configuration for GPS
const SerialConfig gps_config =
{
@ -49,10 +49,12 @@ bool gps_receive_byte(uint8_t *data) {
I2C_read8(UBLOX_MAX_ADDRESS, 0xFF, data);
return true;
}
return false;
#else
#elif defined(UBLOX_USE_UART)
return sdReadTimeout(&SD5, data, 1, TIME_IMMEDIATE);
#else
(void) data;
#endif
return false;
}
/**
@ -580,7 +582,7 @@ bool GPS_Init() {
palSetLineMode(LINE_GPS_EN, PAL_MODE_OUTPUT_PUSHPULL); // GPS off
// Init UART
#if defined(UBLOX_USE_UART)
#if defined(UBLOX_UART_CONNECTED)
palSetLineMode(LINE_GPS_RXD, PAL_MODE_ALTERNATE(11)); // UART RXD
palSetLineMode(LINE_GPS_TXD, PAL_MODE_ALTERNATE(11)); // UART TXD
TRACE_INFO("GPS > Init GPS UART");

Wyświetl plik

@ -37,9 +37,13 @@ typedef enum {
#define UBLOX_MAX_ADDRESS 0x42
// You can either use I2C (TRUE) or UART (FALSE)
// You can either use I2C (TRUE) or UART if available (FALSE)
#define UBLOX_USE_I2C FALSE
#define UBLOX_USE_UART TRUE
#define UBLOX_UART_CONNECTED
#if UBLOX_USE_I2C == FALSE && !defined(UBLOX_UART_CONNECTED)
#warning "UBLOX has no I2C or UART communications enabled"
#endif
#define isGPSLocked(pos) ((pos)->type == 3 && (pos)->num_svs >= 4 && (pos)->fixOK == true)

Wyświetl plik

@ -865,10 +865,13 @@ msg_t aprs_send_telemetry_response(aprs_identity_t *id,
aprsd = *id->beacon;
aprsd.run_once = true;
aprsd.beacon.init_delay = 0;
thread_t * th = start_beacon_thread(&aprsd, "APRSD");
thread_t *th = start_beacon_thread(&aprsd, "APRSD");
if(th == NULL)
return MSG_ERROR;
return chThdWait(th);
if(chThdWait(th) == MSG_TIMEOUT)
/* GPS acquisition timeout in beacon (no fix or battery insufficient). */
return MSG_ERROR;
return MSG_OK;
/* //========================================================
// Encode and transmit telemetry config first

Wyświetl plik

@ -72,7 +72,7 @@ static void getPositionFallback(dataPoint_t* tp,
tp->gps_lat = 0;
tp->gps_lon = 0;
tp->gps_alt = 0;
if(isPositionValid(ltp)) {
if(isPositionFromSV(ltp)) {
tp->gps_lat = ltp->gps_lat;
tp->gps_lon = ltp->gps_lon;
tp->gps_alt = ltp->gps_alt;
@ -388,7 +388,7 @@ void setSystemStatus(dataPoint_t* tp) {
*
*/
THD_FUNCTION(collectorThread, arg) {
(void)arg;
thread_t *caller = (thread_t *)arg;
uint32_t id = 0;
@ -437,42 +437,38 @@ THD_FUNCTION(collectorThread, arg) {
} else {
TRACE_INFO("COLL > No data point found in flash memory");
/* State indicates that no valid stored position is available. */
lastDataPoint->gps_lat = 0;
lastDataPoint->gps_lon = 0;
lastDataPoint->gps_alt = 0;
lastDataPoint->gps_ttff = 0;
lastDataPoint->gps_pdop = 0;
lastDataPoint->gps_sats = 0;
lastDataPoint->gps_state = GPS_OFF;
// Measure telemetry
measureVoltage(lastDataPoint);
getSensors(lastDataPoint);
getGPIO(lastDataPoint);
setSystemStatus(lastDataPoint);
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
}
// Measure telemetry
measureVoltage(lastDataPoint);
getSensors(lastDataPoint);
getGPIO(lastDataPoint);
setSystemStatus(lastDataPoint);
// Write data point to Flash memory
flash_writeLogDataPoint(lastDataPoint);
sysinterval_t gps_wait_time;
/* Now check if the controller has been reset (RTC not set). */
getTime(&time);
if(time.year == RTC_BASE_YEAR) {
/*
* The RTC is not set.
* Enable the GPS and attempt a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Acquire time using GPS");
if(aquirePosition(newDataPoint, lastDataPoint, gps_wait_time - TIME_S2I(3))) {
/* Acquisition succeeded. */
TRACE_INFO("COLL > Time update acquired from GPS");
/* Update with freshly acquired data. */
lastDataPoint = newDataPoint;
GPS_Deinit();
} else {
/* Time is stale record. */
TRACE_INFO("COLL > Time update not acquired from GPS");
}
}
if(time.year == RTC_BASE_YEAR)
/* Let initializer know this is a cold start (power loss). */
(void)chMsgSend(caller, MSG_RESET);
else
(void)chMsgSend(caller, MSG_OK);
/*
* Done with initialization now.
* lastDataPoint becomes the first history entry for the loop.
*/
while(true) { /* Primary loop. */
/* Wait for a request from a client. */
thread_t *caller = chMsgWait();
caller = chMsgWait();
/* Fetch the message. */
bcn_app_conf_t *config;
config = (bcn_app_conf_t *)chMsgGet(caller);
@ -488,6 +484,25 @@ THD_FUNCTION(collectorThread, arg) {
getGPIO(tp);
setSystemStatus(tp);
getTime(&time);
if(time.year == RTC_BASE_YEAR) {
/*
* The RTC is not set.
* Enable the GPS and attempt a lock which results in setting the RTC.
*/
TRACE_INFO("COLL > Acquire time using GPS");
if(aquirePosition(newDataPoint, lastDataPoint, TIME_S2I(600))) {
/* Acquisition succeeded. */
TRACE_INFO("COLL > Time update acquired from GPS");
/* Update with freshly acquired data. */
lastDataPoint = newDataPoint;
GPS_Deinit();
} else {
/* Time is stale record. */
TRACE_INFO("COLL > Time update not acquired from GPS");
}
}
if(config->beacon.fixed) {
/*
* Use fixed position data.
@ -505,12 +520,14 @@ THD_FUNCTION(collectorThread, arg) {
getTime(&time);
tp->gps_time = date2UnixTimestamp(&time);
} else {
/*
* Try GPS lock to get data.
* If lock not attained fallback data is set.
*/
TRACE_INFO("COLL > Acquire position using GPS");
// Determine timeout waiting for lock.
sysinterval_t gps_wait_time;
if(config->beacon.gps_wait > TIME_S2I(63)) // Minimum 1M + 3S
gps_wait_time = config->beacon.gps_wait;
else
@ -566,14 +583,23 @@ void init_data_collector() {
thread_t *th = chThdCreateFromHeap(NULL,
THD_WORKING_AREA_SIZE(10*1024),
"COL", LOWPRIO,
collectorThread, NULL);
collectorThread, chThdGetSelfX());
collector_thd = th;
if(!th) {
// Print startup error, do not start watchdog for this thread
TRACE_ERROR("COLL > Could not start"
" thread (not enough memory available)");
} else {
chThdSleep(TIME_MS2I(300)); // Wait a little bit until data collector has initialized first dataset
/* Wait for collector to start. */
thread_t *tp = chMsgWait();
msg_t msg = chMsgGet(tp);
if(msg == MSG_RESET) {
TRACE_INFO("COLL > Executed cold start");
}
else {
TRACE_INFO("COLL > Executed warm start");
}
chMsgRelease(tp, MSG_OK);
}
}
}

Wyświetl plik

@ -135,15 +135,46 @@ void init_data_collector(void);
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if position data is valid
* @retval false if position not valid
* @retval true if position data is from satellite or fixed.
* @retval false if position not valid.
*
* @api
*/
#define isPositionValid(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_LOG)
#define isPositionValid(dp) (dp->gps_state == GPS_LOCKED1 \
|| dp->gps_state == GPS_LOCKED2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_LOG)
/**
* @brief Is position from a satellite.
* @notes This is an alias for hasGPSacquiredLock
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if position data is from satellite
* @retval false if position not satellite
*
* @api
*/
#define isPositionFromSV(dp) hasGPSacquiredLock(dp)
/**
* @brief Is GPS able to operate on battery.
*
* @param[in] pointer to data point
*
* @returns result of check
* @retval true if battery operable
* @retval false if not battery operable
*
* @api
*/
#define isGPSbatteryOperable(dp) (!(dp->gps_state == GPS_LOWBATT1 \
|| dp->gps_state == GPS_LOWBATT2 \
|| dp->gps_state == GPS_FIXED \
|| dp->gps_state == GPS_ERROR \
|| dp->gps_state == GPS_OFF))
#endif /* __COLLECTOR_H__ */

Wyświetl plik

@ -38,21 +38,29 @@ THD_FUNCTION(bcnThread, arg) {
char code_s[100];
pktDisplayFrequencyCode(conf->radio_conf.freq, code_s, sizeof(code_s));
TRACE_INFO("POS > Do module BEACON cycle for %s on %s",
conf->call, code_s);
TRACE_INFO("POS > Do module BEACON cycle for %s on %s%s",
conf->call, code_s, conf->run_once ? " (?aprsp response)" : "");
extern thread_t *collector_thd;
/*
* Pass pointer to beacon config to the collector thread.
*/
dataPoint_t *dataPoint =
(dataPoint_t *)chMsgSend(collector_thd, (msg_t)conf);
/* Continue here when collector responds. */
if(!p_sleep(&conf->beacon.sleep_conf)) {
if(!isPositionValid(dataPoint) || dataPoint == NULL) {
TRACE_INFO("BCN > Waiting for position data for"
" %s (GPS state=%d)", conf->call, dataPoint->gps_state);
chThdSleep(TIME_S2I(60));
continue;
TRACE_INFO("BCN > Waiting for position data for"
" %s (GPS state=%d)", conf->call, dataPoint->gps_state);
if(conf->run_once)
/* If this is run once don't retry. */
chThdExit(MSG_TIMEOUT);
if(isGPSbatteryOperable(dataPoint)) {
/* If the battery is good retry quickly.
* TODO: Rework and involve the p_sleep setting? */
chThdSleep(TIME_S2I(60));
continue;
}
/* Else battery weak so beacon fallback data (TX may fail). */
}
// Telemetry encoding parameter transmissions
@ -150,7 +158,7 @@ THD_FUNCTION(bcnThread, arg) {
}
}
/*
/**
*
*/
thread_t * start_beacon_thread(bcn_app_conf_t *conf, const char *name) {