mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-21 18:22:32 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d62a2be85 | ||
|
|
9c971d3686 | ||
|
|
3c1357b732 | ||
|
|
acd5e5d29d | ||
|
|
64109b25f2 | ||
|
|
e93bc76ac9 | ||
|
|
1107c6d23d | ||
|
|
9b2155402d | ||
|
|
35cf8a4859 | ||
|
|
76f21dfd6e | ||
|
|
b101dc2c88 | ||
|
|
9bbd658b9d | ||
|
|
4999da0824 | ||
|
|
a783341df1 | ||
|
|
04258755e7 | ||
|
|
ea711ece1f | ||
|
|
e93187b630 | ||
|
|
eca3cda8b9 | ||
|
|
2874adfd69 | ||
|
|
91227b25df | ||
|
|
4dfac03402 | ||
|
|
9bc895eb57 | ||
|
|
474026d7fe | ||
|
|
9995d2a7ab | ||
|
|
3028ac3f24 | ||
|
|
8605950eef | ||
|
|
0f856dea7b | ||
|
|
2a2bc5b1d6 | ||
|
|
f87cb00940 | ||
|
|
a4ebf83b69 | ||
|
|
635e189007 | ||
|
|
6eba792537 |
18
README.md
18
README.md
@@ -13,7 +13,7 @@ will optionally work with your phone, but no phone is required.
|
||||
|
||||
Typical time between recharging the radios should be about eight days.
|
||||
|
||||
This project is currently early-alpha, but if you have questions please join our chat [](https://gitter.im/Meshtastic/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
|
||||
This project is currently early-alpha, but if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||
|
||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
|
||||
|
||||
@@ -29,7 +29,7 @@ Prebuilt binaries for the supported radios is available in our [releases](https:
|
||||
|
||||
The instructions currently require a few commmand lines, but it should be pretty straightforward. Please post comments on our group chat if you have problems or successes. Steps to install:
|
||||
|
||||
1. Purchase a radio (see above) with the correct frequencies for your country (915MHz for US or JP, 470MHz for CN, 870MHz for EU).
|
||||
1. Purchase a radio (see above) with the correct frequencies for your country (915MHz for US or JP, 470MHz for CN, 433MHz and 870MHz for EU).
|
||||
2. Install "pip". Pip is the python package manager we use to get the esptool installer app. Instructions [here](https://www.makeuseof.com/tag/install-pip-for-python/).
|
||||
3. Run "pip install --upgrade esptool" to get esptool installed on your machine
|
||||
4. Connect your radio to your USB port
|
||||
@@ -87,4 +87,16 @@ After our rate of change slows a bit, we will make beta builds available here (w
|
||||
|
||||
# Development
|
||||
|
||||
We'd love to have you join us on this merry little project. Please see our [development documents](./docs/software/sw-design.md) and join us on the gitter chat above.
|
||||
We'd love to have you join us on this merry little project. Please see our [development documents](./docs/software/sw-design.md) and [join us in our discussion forum](https://meshtastic.discourse.group/).
|
||||
|
||||
# Credits
|
||||
|
||||
This project is run by volunteers. Past contributors include:
|
||||
|
||||
* @astro-arphid: Added support for 433MHz radios in europe.
|
||||
* @claesg: Various documentation fixes and 3D print enclosures
|
||||
* @girtsf: So far our CI system, but soon lots of device improvements
|
||||
|
||||
# IMPORTANT DISCLAIMERS AND FAQ
|
||||
|
||||
For a listing of currently missing features and a FAQ click [here](docs/faq.md).
|
||||
@@ -4,7 +4,7 @@ set -e
|
||||
|
||||
source bin/version.sh
|
||||
|
||||
COUNTRIES="US EU CN JP"
|
||||
COUNTRIES="US EU433 EU865 CN JP"
|
||||
# COUNTRIES=US
|
||||
|
||||
SRCMAP=.pio/build/esp32/output.map
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
export VERSION=0.1.3
|
||||
export VERSION=0.1.6
|
||||
@@ -30,9 +30,9 @@ Not all of these features are fully implemented yet - see **important** disclaim
|
||||
* Eventually (within a couple of months) we should have a modified version of Signal that works with this project.
|
||||
* Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
|
||||
|
||||
This project is currently in early alpha - if you have questions please join our chat [](https://gitter.im/Meshtastic/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
|
||||
This project is currently in early alpha - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||
|
||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [chat](https://gitter.im/Meshtastic/community).
|
||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [forum](https://meshtastic.discourse.group/).
|
||||
|
||||
# Updates
|
||||
|
||||
@@ -52,7 +52,7 @@ But if you want the bleeding edge app now, we'd love to have your help testing.
|
||||
|
||||
1. Join [this Google group](https://groups.google.com/forum/#!forum/meshtastic-alpha-testers) with the account you use in Google Play.
|
||||
2. Go to this [URL](https://play.google.com/apps/testing/com.geeksville.mesh) to opt-in to the alpha test.
|
||||
3. If you encounter any problems or have questions, post in our gitter chat and we'll help.
|
||||
3. If you encounter any problems or have questions, post in our [forum](https://meshtastic.discourse.group/) and we'll help.
|
||||
|
||||
If you'd like to help with development, the source code is [on github](https://github.com/meshtastic/Meshtastic-Android).
|
||||
|
||||
@@ -62,21 +62,12 @@ sure to buy the frequency range which is legal for your country. For the USA, y
|
||||
|
||||
Instructions for installing prebuilt firmware can be found [here](https://github.com/meshtastic/Meshtastic-esp32/blob/master/README.md).
|
||||
|
||||
For a nice TTGO 3D printable case see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
|
||||
For a nice Heltec 3D printable case see this [design](https://www.thingiverse.com/thing:3125854) by [ornotermes](https://www.thingiverse.com/ornotermes).
|
||||
For a nice printable cases:
|
||||
|
||||
# Disclaimers
|
||||
1. TTGO T-Beam V0 see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
|
||||
2. TTGO T_Beam V1 see this [design](https://www.thingiverse.com/thing:3830711) by [rwanrooy](https://www.thingiverse.com/rwanrooy) or this [remix](https://www.thingiverse.com/thing:3949330) by [8ung](https://www.thingiverse.com/8ung)
|
||||
3. Heltec Lora32 see this [design](https://www.thingiverse.com/thing:3125854) by [ornotermes](https://www.thingiverse.com/ornotermes).
|
||||
|
||||
This project is still pretty young but moving at a pretty good pace. Not all features are fully implemented in the current alpha builds.
|
||||
Most of these problems should be solved by the beta release:
|
||||
# IMPORTANT DISCLAIMERS AND FAQ
|
||||
|
||||
* We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
|
||||
* Encryption is turned off for now
|
||||
* A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
|
||||
* The current Android GUI is pretty ugly still
|
||||
* The Android API needs to be documented better
|
||||
* The Bluetooth API needs to be documented better
|
||||
* The mesh protocol is turned off for now, currently we only send packets one hop distant
|
||||
* No one has written an iOS app yet ;-)
|
||||
|
||||
For more details see the [device software TODO](https://github.com/meshtastic/Meshtastic-esp32/blob/master/TODO.md) or the [Android app TODO](https://github.com/meshtastic/Meshtastic-Android/blob/master/TODO.md).
|
||||
For a listing of currently missing features and a FAQ click [here](faq.md).
|
||||
|
||||
36
docs/faq.md
Normal file
36
docs/faq.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Disclaimers
|
||||
|
||||
This project is still pretty young but moving at a pretty good pace. Not all features are fully implemented in the current alpha builds.
|
||||
Most of these problems should be solved by the beta release (within three months):
|
||||
|
||||
* We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
|
||||
* Encryption is turned off for now
|
||||
* A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
|
||||
* The current Android GUI is slightly ugly still
|
||||
* The Android API needs to be documented better
|
||||
* The mesh protocol is turned off for now, currently we only send packets one hop distant. The mesh feature will be turned on again [soonish](https://github.com/meshtastic/Meshtastic-esp32/issues/3).
|
||||
* No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-)
|
||||
|
||||
For more details see the [device software TODO](https://github.com/meshtastic/Meshtastic-esp32/blob/master/docs/software/TODO.md) or the [Android app TODO](https://github.com/meshtastic/Meshtastic-Android/blob/master/TODO.md).
|
||||
|
||||
# FAQ
|
||||
|
||||
If you have a question missing from this faq, please [ask in our discussion forum](https://meshtastic.discourse.group/). And if you are feeling extra generous send in a pull-request for this faq.md with whatever we answered ;-).
|
||||
|
||||
## Q: Which of the various supported radios should I buy?
|
||||
|
||||
Basically you just need the radio + (optional but recommended) battery. The TBEAM is usually better because it has gps and huge battery socket. The Heltec is basically the same hardware but without the GPS (the phone provides position data to the radio in that case, so the behavior is similar - but it does burn some battery in the phone). Also the battery for the Heltec can be smaller.
|
||||
|
||||
In addition to Aliexpress, (banggood.com) usually has stock and faster shipping, or Amazon. If buying a TBEAM, make sure to buy a version that includes the OLED screen - this project doesn't absolutely require the screen, but we use it if is installed.
|
||||
|
||||
@claesg has added links to various 3D printable cases, you can see them at (www.meshtastic.org).
|
||||
|
||||
## Q: Do you have plans to commercialize this project
|
||||
|
||||
Nope. though if some other person/group wanted to use this software and a more customized device we think that would be awesome (as long as they obey the GPL license).
|
||||
|
||||
## Q: Does this project use patented algorithms?
|
||||
|
||||
(Kindly borrowed from the geeks at [ffmpeg](http://ffmpeg.org/legal.html))
|
||||
|
||||
We do not know, we are not lawyers so we are not qualified to answer this. Also we have never read patents to implement any part of this, so even if we were qualified we could not answer it as we do not know what is patented. Furthermore the sheer number of software patents makes it impossible to read them all so no one (lawyer or not) could answer such a question with a definite no. We are merely geeks experimenting on a fun and free project.
|
||||
@@ -10,6 +10,13 @@ See [this site](https://www.rfwireless-world.com/Tutorials/LoRa-channels-list.ht
|
||||
|
||||
The maximum power allowed is +14dBM.
|
||||
|
||||
### 433 MHz
|
||||
|
||||
There are eight channels defined with a 0.2 MHz gap between them.
|
||||
Channel zero starts at 433.175 MHz
|
||||
|
||||
### 870 MHz
|
||||
|
||||
There are eight channels defined with a 0.3 MHz gap between them.
|
||||
Channel zero starts at 865.20 MHz
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ being I have it set at 2 minutes to ensure enough time for a GPS lock from scrat
|
||||
|
||||
* use gps sleep mode instead of killing its power (to allow fast position when we wake)
|
||||
* enable fast lock and low power inside the gps chip
|
||||
|
||||
* remeasure wake time power draws now that we run CPU down at 80MHz
|
||||
* add a SF12 transmit option for _super_ long range
|
||||
|
||||
@@ -37,6 +38,7 @@ Items to complete before the first beta release.
|
||||
|
||||
During the beta timeframe the following improvements 'would be nice' (and yeah - I guess some of these items count as features, but it is a hobby project ;-) )
|
||||
|
||||
* figure out why this fixme is needed: "FIXME, disable wake due to PMU because it seems to fire all the time?"
|
||||
* If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
|
||||
for it (because it will redownload the nodedb when it comes back)
|
||||
* Figure out why the RF95 ISR is never seeing RH_RF95_VALID_HEADER, so it is not protecting our rx packets from getting stomped on by sends
|
||||
@@ -195,3 +197,7 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w
|
||||
* link to the kanban page
|
||||
* add a getting started page
|
||||
* finish mesh alg reeval
|
||||
* ublox gps parsing seems a little buggy (we shouldn't be sending out read solution commands, the device is already broadcasting them)
|
||||
* turn on gps https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example18_PowerSaveMode/Example18_PowerSaveMode.ino
|
||||
* switch gps to 38400 baud https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example11_ResetModule/Example2_FactoryDefaultsviaSerial/Example2_FactoryDefaultsviaSerial.ino
|
||||
* Use Neo-M8M API to put it in sleep mode
|
||||
|
||||
@@ -10,6 +10,7 @@ TODO:
|
||||
* DONE read about mesh routing solutions (DSR and AODV)
|
||||
* DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
||||
* DONE reread the disaster radio protocol docs - seems based on Babel (which is AODVish)
|
||||
* possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack
|
||||
* update duty cycle spreadsheet for our typical usecase
|
||||
* generalize naive flooding on top of radiohead or disaster.radio? (and fix radiohead to use my new driver)
|
||||
|
||||
|
||||
@@ -59,14 +59,14 @@ debug_init_break = tbreak setup
|
||||
; names.
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/RadioHead.git
|
||||
1655 ; TinyGPSPlus
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||
AXP202X_Library
|
||||
SPI
|
||||
1260 ; OneButton
|
||||
; 1260 ; OneButton - not used yet
|
||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/geeksville/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||
|
||||
;[env:tbeam]
|
||||
;board = ttgo-t-beam
|
||||
|
||||
2
proto
2
proto
Submodule proto updated: f309ee8f9e...66e926740a
@@ -5,5 +5,5 @@ release. It is used by the android app for forcing software updates. Do not ed
|
||||
Generated by bin/buildall.sh -->
|
||||
|
||||
<resources>
|
||||
<string name="cur_firmware_version">0.1.0</string>
|
||||
<string name="cur_firmware_version">0.1.6</string>
|
||||
</resources>
|
||||
|
||||
@@ -21,6 +21,7 @@ CustomRF95::CustomRF95(MemoryPool<MeshPacket> &_pool, PointerQueue<MeshPacket> &
|
||||
bool CustomRF95::canSleep()
|
||||
{
|
||||
// We allow initializing mode, because sometimes while testing we don't ever call init() to turn on the hardware
|
||||
DEBUG_MSG("canSleep, mode=%d, isRx=%d, txEmpty=%d, txGood=%d\n", _mode, _isReceiving, txQueue.isEmpty(), _txGood);
|
||||
return (_mode == RHModeInitialising || _mode == RHModeIdle || _mode == RHModeRx) && !_isReceiving && txQueue.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
154
src/GPS.cpp
154
src/GPS.cpp
@@ -4,16 +4,18 @@
|
||||
#include <sys/time.h>
|
||||
#include "configuration.h"
|
||||
|
||||
// stuff that really should be in in the instance instead...
|
||||
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
||||
uint32_t timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
||||
uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
||||
|
||||
RTC_DATA_ATTR bool timeSetFromGPS; // We only reset our time once per _boot_ after that point just run from the internal clock (even across sleeps)
|
||||
|
||||
GPS gps;
|
||||
bool hasValidLocation; // default to false, until we complete our first read
|
||||
bool wantNewLocation = true;
|
||||
|
||||
// stuff that really should be in in the instance instead...
|
||||
static uint32_t timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time
|
||||
static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock
|
||||
|
||||
static bool hasValidLocation; // default to false, until we complete our first read
|
||||
static bool wantNewLocation = true;
|
||||
|
||||
GPS::GPS() : PeriodicTask()
|
||||
{
|
||||
@@ -21,10 +23,64 @@ GPS::GPS() : PeriodicTask()
|
||||
|
||||
void GPS::setup()
|
||||
{
|
||||
readFromRTC();
|
||||
readFromRTC(); // read the main CPU RTC at first
|
||||
|
||||
#ifdef GPS_RX_PIN
|
||||
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
// _serial_gps.setRxBufferSize(1024); // the default is 256
|
||||
// ublox.enableDebugging(Serial);
|
||||
|
||||
// note: the lib's implementation has the wrong docs for what the return val is
|
||||
// it is not a bool, it returns zero for success
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
// try a second time, the ublox lib serial parsing is buggy?
|
||||
// if(!isConnected) isConnected = ublox.begin(_serial_gps);
|
||||
|
||||
if (isConnected)
|
||||
{
|
||||
DEBUG_MSG("Connected to GPS successfully, TXpin=%d\n", GPS_TX_PIN);
|
||||
|
||||
bool factoryReset = false;
|
||||
bool ok;
|
||||
if (factoryReset)
|
||||
{
|
||||
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have GPS_TX connected)
|
||||
ublox.factoryReset();
|
||||
delay(2000);
|
||||
isConnected = ublox.begin(_serial_gps);
|
||||
DEBUG_MSG("Factory reset success=%d\n", isConnected);
|
||||
if (isConnected)
|
||||
{
|
||||
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
|
||||
assert(ok);
|
||||
ok = ublox.setNavigationFrequency(1, 500); //Produce 4x/sec to keep the amount of time we stall in getPVT low
|
||||
assert(ok);
|
||||
//ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M
|
||||
//assert(ok);
|
||||
//ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds
|
||||
//assert(ok);
|
||||
ok = ublox.powerSaveMode(); //use power save mode
|
||||
assert(ok);
|
||||
}
|
||||
ok = ublox.saveConfiguration(2000);
|
||||
assert(ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NEMA at 9600 baud.
|
||||
DEBUG_MSG("ERROR: No bidirectional GPS found, hoping that it still might work\n");
|
||||
|
||||
// tell lib, we are expecting the module to send PVT messages by itself to our Rx pin
|
||||
// you can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call checkUblox cyclically)
|
||||
ublox.assumeAutoPVT(true, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -75,20 +131,13 @@ uint32_t GPS::getValidTime()
|
||||
/// Returns true if we think the board can enter deep or light sleep now (we might be trying to get a GPS lock)
|
||||
bool GPS::canSleep()
|
||||
{
|
||||
return !wantNewLocation;
|
||||
return true; // we leave GPS on during sleep now, so sleep is okay !wantNewLocation;
|
||||
}
|
||||
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
void GPS::prepareSleep()
|
||||
{
|
||||
// discard all rx serial bytes so we don't try to parse them when we come back
|
||||
while (_serial_gps.available())
|
||||
{
|
||||
_serial_gps.read();
|
||||
}
|
||||
|
||||
// make the parser bail on whatever it was parsing
|
||||
encode('\n');
|
||||
ublox.powerOff();
|
||||
}
|
||||
|
||||
void GPS::doTask()
|
||||
@@ -96,49 +145,68 @@ void GPS::doTask()
|
||||
#ifdef GPS_RX_PIN
|
||||
// Consume all characters that have arrived
|
||||
|
||||
while (_serial_gps.available())
|
||||
{
|
||||
encode(_serial_gps.read());
|
||||
// DEBUG_MSG("Got GPS response\n");
|
||||
}
|
||||
// getPVT automatically calls checkUblox
|
||||
ublox.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
if (!timeSetFromGPS && time.isValid() && date.isValid())
|
||||
// DEBUG_MSG("sec %d\n", ublox.getSecond());
|
||||
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
|
||||
|
||||
// If we don't have a fix (a quick check), don't try waiting for a solution)
|
||||
uint8_t fixtype = ublox.getFixType();
|
||||
DEBUG_MSG("fix type %d\n", fixtype);
|
||||
|
||||
// any fix that has time
|
||||
if ((fixtype >= 2 && fixtype <= 5) && !timeSetFromGPS && ublox.getT())
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
DEBUG_MSG("Got time from GPS\n");
|
||||
isConnected = true; // We just received a packet, so we must have a GPS
|
||||
|
||||
/* Convert to unix time
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
|
||||
*/
|
||||
struct tm t;
|
||||
t.tm_sec = time.second();
|
||||
t.tm_min = time.minute();
|
||||
t.tm_hour = time.hour();
|
||||
t.tm_mday = date.day();
|
||||
t.tm_mon = date.month() - 1;
|
||||
t.tm_year = date.year() - 1900;
|
||||
t.tm_sec = ublox.getSecond();
|
||||
t.tm_min = ublox.getMinute();
|
||||
t.tm_hour = ublox.getHour();
|
||||
t.tm_mday = ublox.getDay();
|
||||
t.tm_mon = ublox.getMonth() - 1;
|
||||
t.tm_year = ublox.getYear() - 1900;
|
||||
t.tm_isdst = false;
|
||||
time_t res = mktime(&t);
|
||||
tv.tv_sec = res;
|
||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||
|
||||
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
|
||||
perhapsSetRTC(&tv);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (location.isValid() && location.isUpdated())
|
||||
{ // we only notify if position has changed
|
||||
// DEBUG_MSG("new gps pos\n");
|
||||
hasValidLocation = true;
|
||||
wantNewLocation = false;
|
||||
notifyObservers();
|
||||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only
|
||||
{
|
||||
// we only notify if position has changed
|
||||
isConnected = true; // We just received a packet, so we must have a GPS
|
||||
|
||||
latitude = ublox.getLatitude() * 1e-7;
|
||||
longitude = ublox.getLongitude() * 1e-7;
|
||||
altitude = ublox.getAltitude() / 1000; // in mm convert to meters
|
||||
DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude, longitude, altitude);
|
||||
|
||||
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0
|
||||
if (hasValidLocation)
|
||||
{
|
||||
wantNewLocation = false;
|
||||
notifyObservers();
|
||||
//ublox.powerOff();
|
||||
}
|
||||
}
|
||||
else // we didn't get a location update, go back to sleep and hope the characters show up
|
||||
wantNewLocation = true;
|
||||
|
||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 100ms until we have something over the serial
|
||||
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 100);
|
||||
#endif
|
||||
|
||||
// Once we have sent a location once we only poll the GPS rarely, otherwise check back every 1s until we have something over the serial
|
||||
setPeriod(hasValidLocation && !wantNewLocation ? 30 * 1000 : 10 * 1000);
|
||||
}
|
||||
|
||||
void GPS::startLock()
|
||||
@@ -147,11 +215,3 @@ void GPS::startLock()
|
||||
wantNewLocation = true;
|
||||
setPeriod(1);
|
||||
}
|
||||
|
||||
String GPS::getTimeStr()
|
||||
{
|
||||
static char t[12]; // used to sprintf for Serial output
|
||||
|
||||
snprintf(t, sizeof(t), "%02d:%02d:%02d", time.hour(), time.minute(), time.second());
|
||||
return t;
|
||||
}
|
||||
|
||||
13
src/GPS.h
13
src/GPS.h
@@ -1,18 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <TinyGPS++.h>
|
||||
#include "PeriodicTask.h"
|
||||
#include "Observer.h"
|
||||
#include "sys/time.h"
|
||||
#include "SparkFun_Ublox_Arduino_Library.h"
|
||||
|
||||
/**
|
||||
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
class GPS : public PeriodicTask, public Observable, public TinyGPSPlus
|
||||
class GPS : public PeriodicTask, public Observable
|
||||
{
|
||||
SFE_UBLOX_GPS ublox;
|
||||
|
||||
public:
|
||||
double latitude, longitude;
|
||||
uint32_t altitude;
|
||||
bool isConnected; // Do we have a GPS we are talking to
|
||||
|
||||
GPS();
|
||||
|
||||
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
|
||||
@@ -21,8 +27,6 @@ public:
|
||||
/// Return time since 1970 in secs. If we don't have a GPS lock return zero
|
||||
uint32_t getValidTime();
|
||||
|
||||
String getTimeStr();
|
||||
|
||||
void setup();
|
||||
|
||||
virtual void loop();
|
||||
@@ -46,3 +50,4 @@ private:
|
||||
};
|
||||
|
||||
extern GPS gps;
|
||||
|
||||
|
||||
@@ -13,17 +13,22 @@
|
||||
#define CH_SPACING_US 2.16f // MHz
|
||||
#define NUM_CHANNELS_US 13
|
||||
|
||||
// EU channel settings
|
||||
#define CH0_EU 865.2f // MHz
|
||||
#define CH_SPACING_EU 0.3f // MHz
|
||||
#define NUM_CHANNELS_EU 10
|
||||
// EU433 channel settings
|
||||
#define CH0_EU433 433.175f // MHz
|
||||
#define CH_SPACING_EU433 0.2f // MHz
|
||||
#define NUM_CHANNELS_EU433 8
|
||||
|
||||
// EU865 channel settings
|
||||
#define CH0_EU865 865.2f // MHz
|
||||
#define CH_SPACING_EU865 0.3f // MHz
|
||||
#define NUM_CHANNELS_EU865 10
|
||||
|
||||
// CN channel settings
|
||||
#define CH0_CN 470.0f // MHz
|
||||
#define CH_SPACING_CN 2.0f // MHz FIXME, this is just a guess for 470-510
|
||||
#define NUM_CHANNELS_CN 20
|
||||
|
||||
// CN channel settings
|
||||
// JP channel settings
|
||||
#define CH0_JP 920.0f // MHz
|
||||
#define CH_SPACING_JP 0.5f // MHz FIXME, this is just a guess for 920-925
|
||||
#define NUM_CHANNELS_JP 10
|
||||
@@ -33,10 +38,14 @@
|
||||
#define CH0 CH0_US
|
||||
#define CH_SPACING CH_SPACING_US
|
||||
#define NUM_CHANNELS NUM_CHANNELS_US
|
||||
#elif defined(HW_VERSION_EU)
|
||||
#define CH0 CH0_EU
|
||||
#define CH_SPACING CH_SPACING_EU
|
||||
#define NUM_CHANNELS NUM_CHANNELS_EU
|
||||
#elif defined(HW_VERSION_EU433)
|
||||
#define CH0 CH0_EU433
|
||||
#define CH_SPACING CH_SPACING_EU433
|
||||
#define NUM_CHANNELS NUM_CHANNELS_EU433
|
||||
#elif defined(HW_VERSION_EU865)
|
||||
#define CH0 CH0_EU865
|
||||
#define CH_SPACING CH_SPACING_EU865
|
||||
#define NUM_CHANNELS NUM_CHANNELS_EU865
|
||||
#elif defined(HW_VERSION_CN)
|
||||
#define CH0 CH0_CN
|
||||
#define CH_SPACING CH_SPACING_CN
|
||||
|
||||
@@ -326,11 +326,13 @@ void MeshService::onGPSChanged()
|
||||
MeshPacket *p = allocForSending();
|
||||
p->payload.which_variant = SubPacket_position_tag;
|
||||
Position &pos = p->payload.variant.position;
|
||||
#if 0
|
||||
if (gps.altitude.isValid())
|
||||
pos.altitude = gps.altitude.meters();
|
||||
pos.latitude = gps.location.lat();
|
||||
pos.longitude = gps.location.lng();
|
||||
pos.time = gps.getValidTime();
|
||||
#endif
|
||||
|
||||
// We limit our GPS broadcasts to a max rate
|
||||
static uint32_t lastGpsSend;
|
||||
|
||||
@@ -25,6 +25,7 @@ static void sdsEnter()
|
||||
|
||||
static void lsEnter()
|
||||
{
|
||||
DEBUG_MSG("lsEnter begin\n");
|
||||
screen.setOn(false);
|
||||
|
||||
while (!service.radio.rf95.canSleep())
|
||||
@@ -32,12 +33,16 @@ static void lsEnter()
|
||||
|
||||
gps.prepareSleep(); // abandon in-process parsing
|
||||
|
||||
if (!isUSBPowered) // FIXME - temp hack until we can put gps in sleep mode, if we have AC when we go to sleep then leave GPS on
|
||||
setGPSPower(false); // kill GPS power
|
||||
//if (!isUSBPowered) // FIXME - temp hack until we can put gps in sleep mode, if we have AC when we go to sleep then leave GPS on
|
||||
// setGPSPower(false); // kill GPS power
|
||||
|
||||
DEBUG_MSG("lsEnter end\n");
|
||||
}
|
||||
|
||||
static void lsIdle()
|
||||
{
|
||||
DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
|
||||
|
||||
uint32_t secsSlept = 0;
|
||||
esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
bool reached_ls_secs = false;
|
||||
@@ -69,6 +74,8 @@ static void lsIdle()
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_MSG("wakeCause %d\n", wakeCause);
|
||||
|
||||
// Regardless of why we woke just transition to NB (and that state will handle stuff like IRQs etc)
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
}
|
||||
@@ -76,7 +83,7 @@ static void lsIdle()
|
||||
|
||||
static void lsExit()
|
||||
{
|
||||
setGPSPower(true); // restore GPS power
|
||||
// setGPSPower(true); // restore GPS power
|
||||
gps.startLock();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Select which board is being used. If the outside build environment has sent a choice, just use that
|
||||
#if !defined(T_BEAM_V10) && !defined(HELTEC_LORA32)
|
||||
// #define T_BEAM_V10 // AKA Rev1 (second board released)
|
||||
#define HELTEC_LORA32
|
||||
#define T_BEAM_V10 // AKA Rev1 (second board released)
|
||||
// #define HELTEC_LORA32
|
||||
|
||||
#define HW_VERSION_US // We encode the hardware freq range in the hw version string, so sw update can eventually install the correct build
|
||||
#endif
|
||||
@@ -108,6 +108,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define BICOLOR_DISPLAY // we have yellow at the top 16 lines
|
||||
|
||||
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
|
||||
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
|
||||
|
||||
@@ -341,6 +341,9 @@ void loop()
|
||||
// axpDebugOutput.loop();
|
||||
loopBLE();
|
||||
|
||||
// for debug printing
|
||||
// service.radio.rf95.canSleep();
|
||||
|
||||
#ifdef T_BEAM_V10
|
||||
if (axp192_found)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifdef T_BEAM_V10
|
||||
#include "axp20x.h"
|
||||
extern AXP20X_Class axp;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// deep sleep support
|
||||
RTC_DATA_ATTR int bootCount = 0;
|
||||
@@ -28,8 +28,6 @@ esp_sleep_source_t wakeCause; // the reason we booted this time
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Application
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -63,7 +61,7 @@ void setLed(bool ledOn)
|
||||
|
||||
void setGPSPower(bool on)
|
||||
{
|
||||
DEBUG_MSG("Setting GPS power=%d\n", on);
|
||||
DEBUG_MSG("Setting GPS power=%d\n", on);
|
||||
|
||||
#ifdef T_BEAM_V10
|
||||
if (axp192_found)
|
||||
@@ -84,9 +82,24 @@ void initDeepSleep()
|
||||
wakeButtons = ((uint64_t)1) << buttons.gpios[0];
|
||||
*/
|
||||
|
||||
DEBUG_MSG("booted, wake cause %d (boot count %d)\n", wakeCause, bootCount);
|
||||
}
|
||||
// If we booted because our timer ran out or the user pressed reset, send those as fake events
|
||||
const char *reason = "reset"; // our best guess
|
||||
RESET_REASON hwReason = rtc_get_reset_reason(0);
|
||||
|
||||
if (hwReason == RTCWDT_BROWN_OUT_RESET)
|
||||
reason = "brownout";
|
||||
|
||||
if (hwReason == TG0WDT_SYS_RESET)
|
||||
reason = "taskWatchdog";
|
||||
|
||||
if (hwReason == TG1WDT_SYS_RESET)
|
||||
reason = "intWatchdog";
|
||||
|
||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER)
|
||||
reason = "timeout";
|
||||
|
||||
DEBUG_MSG("booted, wake cause %d (boot count %d), reset_reason=%s\n", wakeCause, bootCount, reason);
|
||||
}
|
||||
|
||||
void doDeepSleep(uint64_t msecToWake)
|
||||
{
|
||||
@@ -164,6 +177,10 @@ void doDeepSleep(uint64_t msecToWake)
|
||||
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
|
||||
uint64_t gpioMask = (1ULL << BUTTON_PIN);
|
||||
|
||||
#ifdef BUTTON_NEED_PULLUP
|
||||
gpio_pullup_en((gpio_num_t) BUTTON_PIN);
|
||||
#endif
|
||||
|
||||
// Not needed because both of the current boards have external pullups
|
||||
// FIXME change polarity in hw so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead of just the first)
|
||||
// gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
||||
@@ -175,9 +192,6 @@ void doDeepSleep(uint64_t msecToWake)
|
||||
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* enter light sleep (preserves ram but stops everything about CPU).
|
||||
*
|
||||
@@ -188,7 +202,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
//DEBUG_MSG("Enter light sleep\n");
|
||||
uint64_t sleepUsec = sleepMsec * 1000LL;
|
||||
|
||||
Serial.flush(); // send all our characters before we stop cpu clock
|
||||
Serial.flush(); // send all our characters before we stop cpu clock
|
||||
setBluetoothEnable(false); // has to be off before calling light sleep
|
||||
|
||||
// NOTE! ESP docs say we must disable bluetooth and wifi before light sleep
|
||||
@@ -196,15 +210,20 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
// We want RTC peripherals to stay on
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
|
||||
#ifdef BUTTON_NEED_PULLUP
|
||||
gpio_pullup_en((gpio_num_t) BUTTON_PIN);
|
||||
#endif
|
||||
|
||||
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
|
||||
gpio_wakeup_enable((gpio_num_t)DIO0_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
|
||||
#ifdef PMU_IRQ
|
||||
gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_HIGH_LEVEL); // pmu irq
|
||||
// FIXME, disable wake due to PMU because it seems to fire all the time?
|
||||
// gpio_wakeup_enable((gpio_num_t)PMU_IRQ, GPIO_INTR_HIGH_LEVEL); // pmu irq
|
||||
#endif
|
||||
assert(esp_sleep_enable_gpio_wakeup() == ESP_OK);
|
||||
assert(esp_sleep_enable_timer_wakeup(sleepUsec) == ESP_OK);
|
||||
assert(esp_light_sleep_start() == ESP_OK);
|
||||
//DEBUG_MSG("Exit light sleep\n");
|
||||
//DEBUG_MSG("Exit light sleep b=%d, rf95=%d, pmu=%d\n", digitalRead(BUTTON_PIN), digitalRead(DIO0_GPIO), digitalRead(PMU_IRQ));
|
||||
return esp_sleep_get_wakeup_cause();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user