Skip to content

Commit

Permalink
Major changes to support GPS-off sleep
Browse files Browse the repository at this point in the history
  • Loading branch information
Max-Plastix committed Jan 27, 2022
1 parent 44c03ed commit dab13d2
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 76 deletions.
69 changes: 40 additions & 29 deletions console-decoders/unified_decoder.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Decoder for CubeCell and Unified TTGO mappers, same as
// Decoder for MaxPlastix mappers, compatible with:
// https://github.com/hkicko/CubeCell-GPS-Helium-Mapper
// but without the Tracker payload.
//
Expand All @@ -8,31 +8,42 @@
// Battery is 1/100 of a volt, offset by 2v for a range of 2.00 to 4.56 volts.
//
function Decoder(bytes, port) {
var decoded = {};

var latitude = ((bytes[0]<<16)>>>0) + ((bytes[1]<<8)>>>0) + bytes[2];
latitude = (latitude / 16777215.0 * 180) - 90;

var longitude = ((bytes[3]<<16)>>>0) + ((bytes[4]<<8)>>>0) + bytes[5];
longitude = (longitude / 16777215.0 * 360) - 180;

switch (port)
{
case 2:
decoded.latitude = latitude;
decoded.longitude = longitude;

var altValue = ((bytes[6]<<8)>>>0) + bytes[7];
var sign = bytes[6] & (1 << 7);
if(sign) decoded.altitude = 0xFFFF0000 | altValue;
else decoded.altitude = altValue;

decoded.speed = parseFloat((((bytes[8]))/1.609).toFixed(2));
decoded.battery = parseFloat((bytes[9]/100 + 2).toFixed(2));
decoded.sats = bytes[10];
decoded.accuracy = 2.5; // Bogus Accuracy required by Cargo/Mapper integration
break;
}

return decoded;
}
var decoded = {};

var latitude = ((bytes[0] << 16) >>> 0) + ((bytes[1] << 8) >>> 0) + bytes[2];
latitude = (latitude / 16777215.0 * 180) - 90;

var longitude = ((bytes[3] << 16) >>> 0) + ((bytes[4] << 8) >>> 0) + bytes[5];
longitude = (longitude / 16777215.0 * 360) - 180;

switch (port) {
case 2: // Mapper! (Cargo and Heatmap too)
decoded.latitude = latitude;
decoded.longitude = longitude;

var altValue = ((bytes[6] << 8) >>> 0) + bytes[7];
var sign = bytes[6] & (1 << 7);
if (sign) decoded.altitude = 0xFFFF0000 | altValue;
else decoded.altitude = altValue;

decoded.speed = parseFloat((((bytes[8])) / 1.609).toFixed(2));
decoded.battery = parseFloat((bytes[9] / 100 + 2).toFixed(2));
decoded.sats = bytes[10];
decoded.accuracy = 2.5; // Bogus Accuracy required by Cargo/Mapper integration
break;
case 5: // System status
decoded.battery = parseFloat((bytes[6] / 100 + 2).toFixed(2));
decoded.status = bytes[7];
decoded.value = bytes[8];
break;
case 6: // Lost GPS
decoded.last_latitude = latitude;
decoded.last_longitude = longitude;
decoded.battery = parseFloat((bytes[6] / 100 + 2).toFixed(2));
decoded.sats = bytes[7];
decoded.minutes = ((bytes[8] << 8) >>> 0) + bytes[9];
break;
}

return decoded;
}
95 changes: 67 additions & 28 deletions main/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,72 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

// -----------------------------------------------------------------------------
// Version
// -----------------------------------------------------------------------------
#define APP_NAME "MaxP Mapper"
#define APP_VERSION "1.7.1"

// -----------------------------------------------------------------------------
// CONFIGURATION
// Stuff you might reasonably want to change is here:
// -----------------------------------------------------------------------------

// Select which T-Beam board is being used. Only uncomment one.
//#define T_BEAM_V07 // AKA Rev0 (first board released)
#define T_BEAM_V10 // AKA Rev1 (second board released), also for "v1.1"

#define MIN_DIST 68.0 // Minimum distance in meters from the last sent location before we can send again. A hex is about 340m.
#define STATIONARY_TX_INTERVAL ( 2 * 60) // If no minimum movement, the LoRa frame will still be sent once every N seconds

#define REST_WAIT (30 * 60) // If we still haven't moved in this many seconds, start sending even slower
#define REST_TX_INTERVAL (10 * 60) // Slow resting ping frequency in seconds

#define SCREEN_IDLE_OFF_S (30) // If there are no Uplinks sent for this long, turn the screen off.

#define BATTERY_LOW_VOLTAGE 3.4 // Below this voltage, power off until USB power allows charging

#define LORAWAN_PORT 2 // FPort for Uplink messages -- must match Helium Console Decoder script!
#define LORAWAN_CONFIRMED_EVERY 0 // Send confirmed message for ACK every N messages (0 means never, 1 means always, 2 every-other-one..)
#define LORAWAN_SF DR_SF7 // Spreading factor (recommended DR_SF7 for network map purposes, DR_SF10 is slower/more-reach)
// All time settings here are SECONDS

// Minimum Distance between Mapper reports. This is your MAIN knob to turn for more/fewer uplink packets.
// SMALLER distance: More packets, more dots on the map, more DC spent, more power consumed
// (If you set this to a very small value, it will still be rate-limited by how often your Region allows back-to-back Uplink packets.)
// LARGER distance: Fewer packets, might miss some hexes, conserves DC, battery might last longer
// Note that a hex is about 340m across. Ideally, you want at least two uplinks in each hex to map it.
#define MIN_DIST 70.0 // Minimum distance in meters from the last sent location before we send again.

// If we are not moving at least MIN_DIST meters away from the last uplink, when should we send a redundant
// Mapper Uplink from the same location? This Heartbeat or ping isn't all that important for mapping, but might be
// useful for time-at-location tracking or other monitoring. You can safely set this value very high.
#define STATIONARY_TX_INTERVAL ( 5 * 60) // Send one uplink at least once every N seconds
#define NEVER_REST 0 // Change to 1 if you want to always send at THIS rate, with no slowing or sleeping.

// After being stationary for a long while, we move to a slower heartbeat interval:
#define REST_WAIT (20 * 60) // If we still haven't moved in this many seconds, start sending even slower..
#define REST_TX_INTERVAL (30 * 60) // Slow resting ping frequency in seconds

// This last stage is a low-power sleep to conserve battery when the Mapper has not moved for a long time.
// This one is a difficult compromise: Waking up to boot & power on the GPS is not a fast operation,
// so we want to avoid it as much as possible. There is no other motion sensor, so if we make it too long,
// we miss the first minutes of each motion while sleeping.
// Note that USB Power will prevent this low-power sleep, and also wake us up from it.
// A button press will also wake from sleep, but takes some time to initialise and re-aquire
#define SLEEP_WAIT ( 2 * 60 * 60) // If we STILL haven't moved in this long, turn off the GPS to save power
// For a vehicle application where USB Power appears BEFORE motion, this can be set very high without missing anything:
#define SLEEP_TX_INTERVAL ( 1 * 60 * 60) // Wake up and check position every now and then to see if movement happened

// When searching for a GPS Fix, we may never find one due to obstruction, noise, or reduced availability.
// Note that GPS Lost also counts as no-movement, so the Sleep tier above still applies
#define GPS_LOST_WAIT ( 5 * 60) // How long to wait for a GPS fix before declaring failure
#define GPS_LOST_PING (15 * 60) // Without GPS reception, how often to send a non-mapper status packet

#define SCREEN_IDLE_OFF_S ( 2 * 60) // If there are no Uplinks or button presses sent for this long, turn the screen off.
#define MENU_TIMEOUT_S 5 // Seconds to wait before exiting the menu.

// Below this voltage, power off until USB power allows charging. The PMIC also has a (safety) turn-off much lower than this.
// We use a conservative 3.3v here since the battery will last longer.
#define BATTERY_LOW_VOLTAGE 3.3

// Confirmed packets (ACK request) conflict with the function of a Mapper and should not normally be enabled.
// In areas of reduced coverage, the Mapper will try to send each packet six or more times with different SF/DR.
// This causes irregular results and the location updates are infrequent, unpredictable, and out of date.
#define LORAWAN_CONFIRMED_EVERY 0 // Request Confirmation message every N Uplinks (0 means never, 1 means always, 2 every-other-one..)

// Spreading Factor (Data Rate) determines how long each 11-byte Mapper Uplink is on-air, and how observable it is.
// SF10 is about two seconds of transmission per packet, and the highest range, while SF7 is a good compromise
// for moving vehicles and reasonable mapping observations.
#define LORAWAN_SF DR_SF7 // Spreading factor (recommended DR_SF7 for network map purposes)

// Deadzone defines a circular area where no map packets will originate.
// Set Radius to zero to disable, or leave it enabled to select center position from menu.
// This is useful to avoid sending many redundant packets in your own driveway or office, or just for local privacy.
// You can "re-center" the deadzone from the screen menu.
// Set Radius to zero to disable altogether.
// (Thanks to @Woutch for the name)
#ifndef DEADZONE_LAT
#define DEADZONE_LAT 34.5678
Expand All @@ -60,26 +101,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEADZONE_RADIUS_M 500 // meters
#endif

// Uncomment to enable discarding network settings by long pressing second button
#define PREFS_DISCARD

// -----------------------------------------------------------------------------
// Version
// -----------------------------------------------------------------------------

#define APP_NAME "Helium TTGO"
#define APP_VERSION "1.6.5 MaxP"

// -----------------------------------------------------------------------------
// Less common Configuration iteams
// -----------------------------------------------------------------------------

// Select which T-Beam board is being used. Only uncomment one.
//#define T_BEAM_V07 // AKA Rev0 (first board released) UNTESTED! Expect bugs.
#define T_BEAM_V10 // AKA Rev1 (second board released), this is the common "v1.1"

#define LOGO_DELAY 2000 // Time to show logo on first boot (ms)

#define DEBUG_PORT Serial // Serial debug port
#define SERIAL_BAUD 115200 // Serial debug baud rate (note that bootloader is fixed at 115200)

#define LORAWAN_ADR 0 // Do not enable ADR
// Never enable ADR on Mappers because they are moving, so we don't want to adjust
// anything based on packet reception.
#define LORAWAN_ADR 0 // Do not enable ADR


// If you are having difficulty sending messages to TTN after the first successful send,
// uncomment the next option and experiment with values (~ 1 - 5)
Expand Down
47 changes: 34 additions & 13 deletions main/gps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,29 @@ float gps_speed() {
return _gps.speed.kmph();
}

boolean fresh_gps = false;
uint32_t gps_sentencesWithFix() {
return _gps.sentencesWithFix();
}

void gps_end(void) {
gpsSerial.end();
}

void gps_setup(void) {
gpsSerial.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
gpsSerial.setRxBufferSize(2048); // Default is 256
static boolean serial_ready = false;
if (serial_ready) {
gpsSerial.updateBaudRate(GPS_BAUDRATE);
} else {
gpsSerial.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
gpsSerial.setRxBufferSize(2048); // Default is 256
serial_ready = true;
}
// Drain any waiting garbage
while (gpsSerial.read() != -1)
;
// Flush out line noise from our side
//char zeros[] = {0, 0, 0, 0, 0, 0};
//gpsSerial.write(zeros, sizeof(zeros));

if (0)
myGNSS.enableDebugging();
Expand All @@ -67,31 +85,31 @@ void gps_setup(void) {
// Well, wasn't where we expected it
changed_speed = true;

Serial.println("Trying 115200...");
// Serial.println("Trying 115200...");
gpsSerial.updateBaudRate(115200);
if (myGNSS.begin(gpsSerial)) {
Serial.println("GPS found at 115200 baud");
myGNSS.setSerialRate(GPS_BAUDRATE);
continue;
}

Serial.println("Trying 9600...");
// Serial.println("Trying 9600...");
gpsSerial.updateBaudRate(9600);
if (myGNSS.begin(gpsSerial)) {
Serial.println("GPS found at 9600 baud");
myGNSS.setSerialRate(GPS_BAUDRATE);
continue;
}

Serial.println("Trying 38400...");
// Serial.println("Trying 38400...");
gpsSerial.updateBaudRate(38400);
if (myGNSS.begin(gpsSerial)) {
Serial.println("GPS found at 38400 baud");
myGNSS.setSerialRate(GPS_BAUDRATE);
continue;
}

Serial.println("Trying 57600...");
// Serial.println("Trying 57600...");
gpsSerial.updateBaudRate(57600);
if (myGNSS.begin(gpsSerial)) {
Serial.println("GPS found at 57600 baud");
Expand Down Expand Up @@ -128,11 +146,11 @@ void gps_setup(void) {
myGNSS.disableNMEAMessage(UBX_NMEA_VLW, COM_PORT_UART1);
myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_UART1);
myGNSS.disableNMEAMessage(UBX_NMEA_ZDA, COM_PORT_UART1);
#endif
#endif

myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_UART1); // Don't need SV list (on by default)
myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_UART1); // For Speed
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_UART1); // For Time & Location & SV count
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_UART1); // Don't need SV list (on by default)
myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_UART1); // For Speed
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_UART1); // For Time & Location & SV count

if (changed_speed)
myGNSS.saveConfiguration(); // Save the current settings to flash and BBR
Expand All @@ -148,8 +166,11 @@ void gps_passthrough(void) {
}
}

void gps_loop(void) {
void gps_loop(boolean print_it) {
while (gpsSerial.available()) {
_gps.encode(gpsSerial.read());
char c = gpsSerial.read();
if (print_it)
Serial.print(c);
_gps.encode(c);
}
}
5 changes: 3 additions & 2 deletions main/gps.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <Arduino.h>

void gps_loop(void);
void gps_loop(boolean print_it);
void gps_setup(void);
void gps_time(char *buffer, uint8_t size);
float gps_latitude(void);
Expand All @@ -15,4 +15,5 @@ uint8_t gps_sats(void);
float gps_hdop(void);
float gps_speed(void);
void gps_passthrough(void);

uint32_t gps_sentencesWithFix(void);
void gps_end(void);
6 changes: 3 additions & 3 deletions main/screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void screen_setup() {
extern AXP20X_Class axp; // TODO: This is evil

void screen_header(unsigned int tx_interval_s, float min_dist_moved, char *cached_sf_name, int sats,
boolean in_deadzone, boolean stay_on) {
boolean in_deadzone, boolean stay_on, boolean never_rest) {
if (!display)
return;

Expand Down Expand Up @@ -153,8 +153,8 @@ void screen_header(unsigned int tx_interval_s, float min_dist_moved, char *cache
SATELLITE_IMAGE);

// Second status row:
snprintf(buffer, sizeof(buffer), "%us %.0fm %c%c", tx_interval_s, min_dist_moved, in_deadzone ? 'D' : ' ',
stay_on ? 'S' : ' ');
snprintf(buffer, sizeof(buffer), "%us %.0fm %c%c%c", tx_interval_s, min_dist_moved, in_deadzone ? 'D' : ' ',
stay_on ? 'S' : ' ', never_rest ? 'N' : ' ');
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(0, 12, buffer);

Expand Down
2 changes: 1 addition & 1 deletion main/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ void screen_update(void);
void screen_body(boolean in_menu, const char *menu_prev, const char *menu_cur, const char *menu_next,
boolean highlighted);
void screen_header(unsigned int tx_interval_s, float min_dist_moved, char *cached_sf_name, int sats,
boolean in_deadzone, boolean stay_on);
boolean in_deadzone, boolean stay_on, boolean never_rest);

void screen_off(void);
void screen_on(void);
Expand Down

0 comments on commit dab13d2

Please sign in to comment.