From 9d54ac09ec81abd2c2605d3986ed85c320a2b17d Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Tue, 11 Jul 2023 11:18:30 +0200 Subject: [PATCH] gipy: fiddling with powersaving --- apps/gipy/README.md | 6 ++- apps/gipy/TODO | 38 +++++++++++++++++++ apps/gipy/app.js | 86 +++++++++++++++++++++++++++++-------------- apps/gipy/settings.js | 18 +++++++-- 4 files changed, 116 insertions(+), 32 deletions(-) diff --git a/apps/gipy/README.md b/apps/gipy/README.md index d75cd5d6f..fceff20c8 100644 --- a/apps/gipy/README.md +++ b/apps/gipy/README.md @@ -93,7 +93,7 @@ The distance to next point displayed corresponds to the length of the black segm ### Menu If you click the button you'll reach a menu where you can currently zoom out to see more of the map -(with a slower refresh rate) and reverse the path direction. +(with a slower refresh rate), reverse the path direction and disable power saving (keeping backlight on). ### Settings @@ -102,7 +102,8 @@ Few settings for now (feel free to suggest me more) : - lost distance : at which distance from path are you considered to be lost ? - buzz on turns : should the watch buzz when reaching a waypoint ? - disable bluetooth : turn bluetooth off completely to try to save some power. -- power lcd off : turn lcd off after 30 seconds to save power. the watch will wake up when reaching waypoints +- brightness : how bright should screen be ? (by default 0.5, again saving power) +- power lcd off (disabled by default): turn lcd off when inactive to save power. the watch will wake up when reaching points and when you touch the screen. ### Caveats @@ -111,6 +112,7 @@ It is good to use but you should know : - the gps might take a long time to start initially (see the assisted gps update app). - gps signal is noisy : there is therefore a small delay for instant speed. sometimes you may jump somewhere else. +- if you adventure in gorges the gps signal will become garbage. - your gpx trace has been decimated and approximated : the **REAL PATH** might be **A FEW METERS AWAY** - sometimes the watch will tell you that you are lost but you are in fact on the path. It usually figures again the real gps position after a few minutes. It usually happens when the signal is acquired very fast. diff --git a/apps/gipy/TODO b/apps/gipy/TODO index 0c25f7d0b..93f241e44 100644 --- a/apps/gipy/TODO +++ b/apps/gipy/TODO @@ -1,3 +1,41 @@ +*** thoughts on lcd power *** + +so, i tried experimenting with turning the lcd off in order to save power. + +the good news: this saves a lot. i did a 3h ride which usually depletes the battery and I still had +around two more hours to go. + +now the bad news: + +- i had to de-activate the twist detection : you cannot raise your watch to the eyes to turn it on. +that's because with twist detection on all road bumps turn the watch on constantly. +- i tried manual detection like : + +Bangle.on('accel', function(xyz) { + + if (xyz.diff > 0.4 && xyz.mag > 1 && xyz.z < -1.4) { + Bangle.setLCDPower(true); + Bangle.setLocked(false); + } + +}); + +this works nicely when you sit on a chair with a simulated gps signal but does not work so nicely when on the bike. +sometimes it is ok, sometimes you can try 10 times with no success. + +- instead i use screen touch to turn it on. that's a bother since you need two hands but well it could be worth it. +the problem is in the delay: between 1 and 5 seconds before the screen comes back on. + + +my conclusion is that: + +* we should not turn screen off unless we agree to have an unresponsive ui +* we should maybe autowake near segments ends and when lost +* we should play with backlight instead + + +************************** + + put back foot only ways + try fiddling with jit diff --git a/apps/gipy/app.js b/apps/gipy/app.js index a39062aa9..718a2c6f5 100644 --- a/apps/gipy/app.js +++ b/apps/gipy/app.js @@ -3,6 +3,7 @@ let displaying = false; let in_menu = false; let go_backwards = false; let zoomed = true; +let powersaving = true; let status; let interests_colors = [ @@ -18,9 +19,10 @@ let s = require("Storage"); var settings = Object.assign({ lost_distance: 50, + brightness: 0.5, buzz_on_turns: false, disable_bluetooth: true, - power_lcd_off: true, + power_lcd_off: false, }, s.readJSON("gipy.json", true) || {} ); @@ -606,6 +608,8 @@ class Interests { class Status { constructor(path, maps, interests) { this.path = path; + this.active = false; // should we have screen on + this.last_activity = getTime(); this.maps = maps; this.interests = interests; let half_screen_width = g.getWidth() / 2; @@ -644,6 +648,32 @@ class Status { this.old_points = []; // record previous points but only when enough distance between them this.old_times = []; // the corresponding times } + activate() { + this.last_activity = getTime(); + if (this.active) { + return; + } else { + this.active = true; + Bangle.setLCDBrightness(settings.brightness); + Bangle.setLocked(false); + if (settings.power_lcd_off) { + Bangle.setLCDPower(true); + } + } + } + check_activity() { + if (!this.active || !powersaving) { + return; + } + if (getTime() - this.last_activity > 30) { + this.active = false; + Bangle.setLCDBrightness(0); + Bangle.setLocked(true); + if (settings.power_lcd_off) { + Bangle.setLCDPower(false); + } + } + } invalidate_caches() { for (let i = 0; i < this.maps.length; i++) { this.maps[i].invalidate_caches(); @@ -713,6 +743,7 @@ class Status { if (in_menu) { return; } + this.check_activity(); // if we don't move or are in menu we should stay on this.adjusted_cos_direction = Math.cos(-direction - Math.PI / 2.0); this.adjusted_sin_direction = Math.sin(-direction - Math.PI / 2.0); @@ -768,6 +799,7 @@ class Status { // now check if we strayed away from path or back to it let lost = this.is_lost(next_segment); if (this.on_path == lost) { + this.activate(); // if status changes if (lost) { Bangle.buzz(); // we lost path @@ -798,6 +830,7 @@ class Status { // } // } if (this.reaching != next_point && this.distance_to_next_point <= 100) { + this.activate(); this.reaching = next_point; let reaching_waypoint = this.path.is_waypoint(next_point); if (reaching_waypoint) { @@ -807,16 +840,12 @@ class Status { setTimeout(() => Bangle.buzz(), 1000); setTimeout(() => Bangle.buzz(), 1500); } - if (!Bangle.isLCDOn()) { - Bangle.setLCDPower(true); - Bangle.setLocked(false); - } } } } - // abort most frames if locked - if (!Bangle.isLocked() && this.gps_coordinates_counter % 5 != 0) { + // abort most frames if inactive + if (!this.active && this.gps_coordinates_counter % 5 != 0) { return; } @@ -1353,9 +1382,9 @@ function simulate_gps(status) { let pos = p1.times(1 - alpha).plus(p2.times(alpha)); if (go_backwards) { - fake_gps_point -= 0.05; // advance simulation + fake_gps_point -= 0.01; // advance simulation } else { - fake_gps_point += 0.05; // advance simulation + fake_gps_point += 0.01; // advance simulation } status.update_position(pos, null, null); } @@ -1387,17 +1416,18 @@ function start(fn) { function start_gipy(path, maps, interests) { console.log("starting"); - if (settings.power_lcd_off) { - Bangle.setOptions({ - lockTimeout: 10000, - backlightTimeout: 20000, - lcdPowerTimeout: 30000, - hrmSportMode: 2, - wakeOnTwist: false, // if true watch will never sleep due to speed and road bumps. tried several tresholds. - wakeOnFaceUp: false, - wakeOnTouch: true, - }); - } + // we handle manually the backlight + Bangle.setOptions({ + lockTimeout: 0, + backlightTimeout: 0, + lcdPowerTimeout: 0, + hrmSportMode: 2, + wakeOnTwist: false, // if true watch will never sleep due to speed and road bumps. tried several tresholds. + wakeOnFaceUp: false, + wakeOnTouch: false, + powerSave: false, + }); + Bangle.setPollInterval(4000); // disable accelerometer as much as we can if (!simulated && settings.disable_bluetooth) { NRF.sleep(); // disable bluetooth completely } @@ -1406,6 +1436,7 @@ function start_gipy(path, maps, interests) { setWatch( function() { + status.activate(); if (in_menu) { return; } @@ -1429,6 +1460,12 @@ function start_gipy(path, maps, interests) { zoomed = v; }, }, + /*LANG*/"powersaving": { + value: powersaving, + onchange: (v) => { + powersaving = v; + } + }, "back to map": function() { in_menu = false; E.showMenu(); @@ -1461,6 +1498,7 @@ function start_gipy(path, maps, interests) { status.display(); Bangle.on("stroke", (o) => { + status.activate(); if (in_menu) { return; } @@ -1488,7 +1526,7 @@ function start_gipy(path, maps, interests) { Bangle.setLCDPower(1); setInterval(simulate_gps, 500, status); } else { - Bangle.setLocked(false); + status.activate(); let frame = 0; let set_coordinates = function(data) { @@ -1519,15 +1557,9 @@ function start_gipy(path, maps, interests) { Bangle.setGPSPower(true, "gipy"); Bangle.on("GPS", set_coordinates); - Bangle.on("lock", function(on) { - if (!on) { - Bangle.setGPSPower(true, "gipy"); // activate gps when unlocking - } - }); } } - let files = s.list(".gps"); if (files.length <= 1) { if (files.length == 0) { diff --git a/apps/gipy/settings.js b/apps/gipy/settings.js index 9283f8ab9..395b1ac93 100644 --- a/apps/gipy/settings.js +++ b/apps/gipy/settings.js @@ -5,7 +5,8 @@ lost_distance: 50, buzz_on_turns: false, disable_bluetooth: true, - power_lcd_off: true, + brightness: 0.5, + power_lcd_off: false, }, require("Storage").readJSON(FILE, true) || {} ); @@ -35,14 +36,25 @@ } }, "lost distance": { - value: 50 | settings.lost_distance, // 0| converts undefined to 0 + value: settings.lost_distance, min: 10, max: 500, onchange: (v) => { - settings.max_speed = v; + settings.lost_distance = v; writeSettings(); }, }, + "brightness": { + value: settings.brightness, + min: 0, + max: 1, + step: 0.1, + onchange: (v) => { + settings.brightness = v; + writeSettings(); + }, + }, + /*LANG*/"power lcd off": { value: settings.power_lcd_off == true, onchange: (v) => {