mirror of https://github.com/espruino/BangleApps
added gpssetup app
parent
754826a3a3
commit
68252a0c5e
|
@ -0,0 +1 @@
|
|||
0.01: First version of GPS Setup app
|
|
@ -0,0 +1,64 @@
|
|||
# GPS Setup
|
||||
|
||||
An App to enable the GPS to be configured into low power mode.
|
||||
|
||||
## Goals
|
||||
|
||||
To develop app that sets the GPS up to run with the lowest possible
|
||||
power consumption.
|
||||
|
||||
|
||||
* An app that turns on the GPS and constantly displays the screen
|
||||
will use around 75mA, the battery will last between 3-4 hours.
|
||||
|
||||
* Using the GPS in a Widget in Super-E Power Saving Mode (PSM) with
|
||||
the screen off most of the time, will consume around 35mA and you
|
||||
might get 10hrs before a recharge.
|
||||
|
||||
* Using the GPS in Power Saving Mode On/Off (PSMOO) with suitable
|
||||
settings can reduce the average consumption to around 15mA. A
|
||||
simple test using a 120s update period, 6s search period was still
|
||||
running with 45% battery 20 hours after it started.
|
||||
|
||||
|
||||
## Settings
|
||||
|
||||
The Settings App enables you set the options below for the GPS.
|
||||
Either start the App from the launcher or go to Settings, select
|
||||
App/Widgets and then 'GPS Setup'.
|
||||
|
||||
When you exit the setup App the settings will be stored in the
|
||||
gpssetup.settings.json file; the GPS will be switched on and the
|
||||
necessary commands sent to the GPS to configure it. The GPS is then
|
||||
powered off. The GPS configuration is stored in the GPS non-volatile
|
||||
memory so that next time the GPS is powered on they are used. These
|
||||
settings will remain and impact every app that uses the GPS.
|
||||
|
||||
|
||||
- Power Mode:
|
||||
|
||||
- SuperE - the factory default setup for the GPS. The recommended
|
||||
power saving mode.
|
||||
|
||||
- PSMOO - On/Off power saving mode. Configured by interval and
|
||||
search time. Choose this mode if you are happy to get a GPS
|
||||
position update less often (say every 1 or 2 minutes). The longer
|
||||
the interval the more time the GPS will spend sleeping in low
|
||||
power mode (7mA) between obtaining fixes (35mA). For walking in
|
||||
open country an update once every 60 seconds is adequate to put
|
||||
you within a 6 digit grid refernce sqaure.
|
||||
|
||||
- update - the time between two position fix attempts.
|
||||
|
||||
- search - the time between two acquisition attempts if the receiver
|
||||
is unable to get a position fix.
|
||||
|
||||
## References
|
||||
|
||||
* [UBLOX M8 Receiver Data Sheet](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29.pdf)
|
||||
|
||||
* [UBLOX Power Management App Note](https://www.u-blox.com/sites/default/files/products/documents/PowerManagement_AppNote_%28UBX-13005162%29.pdf)
|
||||
|
||||
* Some useful code on Github and be found [here](https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control)
|
||||
and [here](https://github.com/thasti/utrak/blob/master/gps.c)
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
const SETTINGS_FILE = "gpssetup.settings.json";
|
||||
let settings = undefined;
|
||||
let settings_changed = false;
|
||||
|
||||
function updateSettings() {
|
||||
require("Storage").write(SETTINGS_FILE, settings);
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
log_debug("loadSettings()");
|
||||
settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
|
||||
settings.update = settings.update||120;
|
||||
settings.search = settings.search||5;
|
||||
settings.power_mode = settings.power_mode||"SuperE";
|
||||
log_debug(settings);
|
||||
}
|
||||
|
||||
/*********** GPS Power and Setup Functions ******************/
|
||||
|
||||
function log_debug(o) {
|
||||
//console.log(o);
|
||||
}
|
||||
|
||||
// quick hack
|
||||
function wait(ms){
|
||||
var start = new Date().getTime();
|
||||
var end = start;
|
||||
while(end < start + ms) {
|
||||
end = new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
function setupGPS() {
|
||||
Bangle.setGPSPower(1);
|
||||
if (settings.power_mode === "PSMOO") {
|
||||
setupPSMOO();
|
||||
} else {
|
||||
setupSuperE();
|
||||
}
|
||||
|
||||
log_debug("Powering GPS Off");
|
||||
Bangle.setGPSPower(0);
|
||||
}
|
||||
|
||||
function setupPSMOO() {
|
||||
log_debug("setupGPS() PSMOO");
|
||||
UBX_CFG_RESET();
|
||||
wait(100);
|
||||
|
||||
UBX_CFG_PM2(settings.update, settings.search);
|
||||
wait(20);
|
||||
|
||||
UBX_CFG_RXM();
|
||||
wait(20);
|
||||
|
||||
UBX_CFG_SAVE();
|
||||
wait(20);
|
||||
}
|
||||
|
||||
function setupSuperE() {
|
||||
log_debug("setupGPS() Super-E");
|
||||
UBX_CFG_RESET();
|
||||
wait(100);
|
||||
|
||||
UBX_CFG_PMS();
|
||||
wait(20);
|
||||
|
||||
UBX_CFG_SAVE();
|
||||
wait(20);
|
||||
}
|
||||
|
||||
function writeGPScmd(cmd) {
|
||||
var d = [0xB5,0x62]; // sync chars
|
||||
d = d.concat(cmd);
|
||||
var a=0,b=0;
|
||||
for (var i=2;i<d.length;i++) {
|
||||
a += d[i];
|
||||
b += a;
|
||||
}
|
||||
d.push(a&255,b&255);
|
||||
Serial1.write(d);
|
||||
}
|
||||
|
||||
// UBX-CFG-PMS - enable power management - Super-E
|
||||
function UBX_CFG_PMS() {
|
||||
writeGPScmd([0x06,0x86, // msg class + type
|
||||
8,0,//length
|
||||
0x00,0x03, 0,0, 0,0, 0,0]);
|
||||
}
|
||||
|
||||
// convert an integer to an array of bytes
|
||||
function int_2_bytes( x ){
|
||||
var bytes = [];
|
||||
var i = 4;
|
||||
do {
|
||||
bytes[--i] = x & (255);
|
||||
x = x>>8;
|
||||
} while (i);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extended Power Management
|
||||
* update and search are in milli seconds
|
||||
* settings are loaded little endian, lsb first
|
||||
*
|
||||
* https://github.com/thasti/utrak/blob/master/gps.c
|
||||
*/
|
||||
function UBX_CFG_PM2(update,search) {
|
||||
|
||||
var u = int_2_bytes(update*1000);
|
||||
var s = int_2_bytes(search*1000);
|
||||
|
||||
writeGPScmd([0x06, 0x3B, /* class id */
|
||||
44, 0, /* length */
|
||||
0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */
|
||||
0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */
|
||||
u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
|
||||
s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
|
||||
0x00, 0x00, 0x00, 0x00, /* grid offset */
|
||||
0x00, 0x00, /* on-time after first fix */
|
||||
0x01, 0x00, /* minimum acquisition time */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 6 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 7 */
|
||||
0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */
|
||||
0x00, 0x00, 0x00, 0x00]); /* reserved 11 */
|
||||
}
|
||||
|
||||
// enable power saving mode, after configured with PM2
|
||||
function UBX_CFG_RXM() {
|
||||
writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */
|
||||
2, 0, /* length */
|
||||
0x08, 0x01]); /* reserved, enable power save mode */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save configuration otherwise it will reset when the GPS wakes up
|
||||
*
|
||||
*/
|
||||
function UBX_CFG_SAVE() {
|
||||
writeGPScmd([0x06, 0x09, // class id
|
||||
0x0D, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, // clear mask
|
||||
0xFF, 0xFF, 0x00, 0x00, // save mask
|
||||
0x00, 0x00, 0x00, 0x00, // load mask
|
||||
0x07]); // b2=eeprom b1=flash b0=bat backed ram
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset to factory settings using clear mask in UBX_CFG_CFG
|
||||
* https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control
|
||||
*/
|
||||
function UBX_CFG_RESET() {
|
||||
writeGPScmd([0x06, 0x09, // class id
|
||||
0x0D, 0x00,
|
||||
0xFF, 0xFB, 0x00, 0x00, // clear mask
|
||||
0x00, 0x00, 0x00, 0x00, // save mask
|
||||
0xFF, 0xFF, 0x00, 0x00, // load mask
|
||||
0x17]);
|
||||
}
|
||||
|
||||
|
||||
/*********** GPS Setup Menu App *****************************/
|
||||
|
||||
function showMainMenu() {
|
||||
var power_options = ["SuperE","PSMOO"];
|
||||
|
||||
const mainmenu = {
|
||||
'': { 'title': 'GPS Setup' },
|
||||
'< Back': ()=>{exitSetup();},
|
||||
'Power Mode': {
|
||||
value: 0 | power_options.indexOf(settings.power_mode),
|
||||
min: 0, max: 1,
|
||||
format: v => power_options[v],
|
||||
onchange: v => {
|
||||
settings.power_mode = power_options[v];
|
||||
updateSettings();
|
||||
},
|
||||
},
|
||||
|
||||
'Update (s)': {
|
||||
value: settings.update,
|
||||
min: 10,
|
||||
max: 1800,
|
||||
step: 10,
|
||||
onchange: v => {
|
||||
settings.update =v;
|
||||
updateSettings();
|
||||
}
|
||||
},
|
||||
'Search (s)': {
|
||||
value: settings.search,
|
||||
min: 1,
|
||||
max: 65,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
settings.search = v;
|
||||
updateSettings();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return E.showMenu(mainmenu);
|
||||
}
|
||||
|
||||
/*
|
||||
function exitSetup() {
|
||||
log_debug("exitSetup()");
|
||||
if (settings_changed) {
|
||||
log_debug(settings);
|
||||
E.showMessage("Configuring GPS");
|
||||
setupGPS();
|
||||
}
|
||||
load();
|
||||
}
|
||||
*/
|
||||
|
||||
function exitSetup() {
|
||||
log_debug("exitSetup()");
|
||||
if (settings_changed) {
|
||||
log_debug(settings);
|
||||
E.showMessage("Configuring GPS");
|
||||
setTimeout(function() {
|
||||
setupGPS();
|
||||
setTimeout(function() { load() }, 750);
|
||||
}, 500);
|
||||
} else {
|
||||
load();
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
function exitSetup() {
|
||||
log_debug("exitSetup()");
|
||||
if (settings_changed) {
|
||||
log_debug(settings);
|
||||
g.clear();
|
||||
g.setFontAlign(0,0);
|
||||
g.setColor(3);
|
||||
g.setFontVector(25);
|
||||
g.drawString("Configuring GPS",120,120);
|
||||
setTimeout(function() {
|
||||
setupGPS();
|
||||
setTimeout(function() { load() }, 500);
|
||||
}, 500);
|
||||
} else load();
|
||||
}
|
||||
*/
|
||||
|
||||
loadSettings();
|
||||
showMainMenu();
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
(function(back) {
|
||||
// just go right to our app
|
||||
load("gpssetup.app.js");
|
||||
})();
|
|
@ -0,0 +1 @@
|
|||
{"power_mode":"SuperE", "update":120, "search":6}
|
Loading…
Reference in New Issue