kopia lustrzana https://github.com/Max-Plastix/tbeam-helium-mapper
rodzic
44c03ed850
commit
dab13d2297
|
@ -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.
|
||||
//
|
||||
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
// All time settings here are SECONDS
|
||||
|
||||
#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
|
||||
// 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.
|
||||
|
||||
#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
|
||||
// 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.
|
||||
|
||||
#define SCREEN_IDLE_OFF_S (30) // If there are no Uplinks sent for this long, turn the screen off.
|
||||
// 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
|
||||
|
||||
#define BATTERY_LOW_VOLTAGE 3.4 // Below this voltage, power off until USB power allows charging
|
||||
// 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
|
||||
|
||||
#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)
|
||||
// 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
|
||||
|
@ -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)
|
||||
|
|
47
main/gps.cpp
47
main/gps.cpp
|
@ -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();
|
||||
|
@ -67,7 +85,7 @@ 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");
|
||||
|
@ -75,7 +93,7 @@ void gps_setup(void) {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serial.println("Trying 9600...");
|
||||
// Serial.println("Trying 9600...");
|
||||
gpsSerial.updateBaudRate(9600);
|
||||
if (myGNSS.begin(gpsSerial)) {
|
||||
Serial.println("GPS found at 9600 baud");
|
||||
|
@ -83,7 +101,7 @@ void gps_setup(void) {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serial.println("Trying 38400...");
|
||||
// Serial.println("Trying 38400...");
|
||||
gpsSerial.updateBaudRate(38400);
|
||||
if (myGNSS.begin(gpsSerial)) {
|
||||
Serial.println("GPS found at 38400 baud");
|
||||
|
@ -91,7 +109,7 @@ void gps_setup(void) {
|
|||
continue;
|
||||
}
|
||||
|
||||
Serial.println("Trying 57600...");
|
||||
// Serial.println("Trying 57600...");
|
||||
gpsSerial.updateBaudRate(57600);
|
||||
if (myGNSS.begin(gpsSerial)) {
|
||||
Serial.println("GPS found at 57600 baud");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Ładowanie…
Reference in New Issue