kopia lustrzana https://github.com/DL7AD/pecanpico10
Improve handling of low battery and init error condition for GPS.
rodzic
2f30a0a2c1
commit
11cd5a4849
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Ładowanie…
Reference in New Issue