kopia lustrzana https://github.com/Max-Plastix/tbeam-helium-mapper
Reset FCount at 50,000 uplinks.
rodzic
b64e90e9fb
commit
32f51fd068
|
@ -3,3 +3,4 @@
|
||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
|
.vscode/extensions.json
|
||||||
|
|
|
@ -3,5 +3,8 @@
|
||||||
// for the documentation about the extensions.json format
|
// for the documentation about the extensions.json format
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"platformio.platformio-ide"
|
"platformio.platformio-ide"
|
||||||
|
],
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"ms-vscode.cpptools-extension-pack"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,10 @@ void build_mapper_packet() {
|
||||||
txBuffer[10] = sats & 0xFF;
|
txBuffer[10] = sats & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helium requires a FCount reset sometime before hitting 0xFFFF
|
||||||
|
// 50,000 makes it obvious it was intentional
|
||||||
|
#define MAX_FCOUNT 50000
|
||||||
|
|
||||||
boolean send_uplink(uint8_t *txBuffer, uint8_t length, uint8_t fport, boolean confirmed) {
|
boolean send_uplink(uint8_t *txBuffer, uint8_t length, uint8_t fport, boolean confirmed) {
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
Serial.println("ACK requested");
|
Serial.println("ACK requested");
|
||||||
|
@ -206,6 +210,21 @@ boolean send_uplink(uint8_t *txBuffer, uint8_t length, uint8_t fport, boolean co
|
||||||
Serial.println("Surprise send failure!");
|
Serial.println("Surprise send failure!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helium requires a re-join / reset of count to avoid 16bit count rollover
|
||||||
|
// Hopefully a device reboot every 50k uplinks is no problem.
|
||||||
|
if (ttn_get_count() > MAX_FCOUNT) {
|
||||||
|
Serial.println("FCount Rollover!");
|
||||||
|
|
||||||
|
// I don't understand why this doesn't show at all
|
||||||
|
screen_print("\n\nRollover Reset!\n");
|
||||||
|
screen_update();
|
||||||
|
delay(1000); // Give some time to read the screen
|
||||||
|
|
||||||
|
ttn_erase_prefs();
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,12 +658,12 @@ void axp192Init() {
|
||||||
|
|
||||||
// Configure REG 36H: PEK press key parameter set. Index values for
|
// Configure REG 36H: PEK press key parameter set. Index values for
|
||||||
// argument!
|
// argument!
|
||||||
axp.setStartupTime(2); // "Power on time": 512mS
|
axp.setStartupTime(2); // "Power on time": 512mS
|
||||||
axp.setlongPressTime(2); // "Long time key press time": 2S
|
axp.setlongPressTime(2); // "Long time key press time": 2S
|
||||||
axp.setShutdownTime(2); // "Power off time" = 8S
|
axp.setShutdownTime(2); // "Power off time" = 8S
|
||||||
axp.setTimeOutShutdown(1); // "When key press time is longer than power off time, auto power off"
|
axp.setTimeOutShutdown(1); // "When key press time is longer than power off time, auto power off"
|
||||||
axp.setVWarningLevel1(2950); // These warning IRQs do not clear until charged, and inhibit other IRQs!
|
axp.setVWarningLevel1(2950); // These warning IRQs do not clear until charged, and inhibit other IRQs!
|
||||||
axp.setVWarningLevel2(2900); // We effectively disable them by setting them lower than we'd run
|
axp.setVWarningLevel2(2900); // We effectively disable them by setting them lower than we'd run
|
||||||
|
|
||||||
// Serial.printf("AC IN: %fv\n", axp.getAcinVoltage());
|
// Serial.printf("AC IN: %fv\n", axp.getAcinVoltage());
|
||||||
// Serial.printf("Vbus: %fv\n", axp.getVbusVoltage());
|
// Serial.printf("Vbus: %fv\n", axp.getVbusVoltage());
|
||||||
|
@ -686,7 +705,7 @@ void axp192Init() {
|
||||||
// Low battery also seems to inhibit the USB present/lost signal we use to wake up.
|
// Low battery also seems to inhibit the USB present/lost signal we use to wake up.
|
||||||
axp.enableIRQ(APX202_APS_LOW_VOL_LEVEL1_IRQ, 0);
|
axp.enableIRQ(APX202_APS_LOW_VOL_LEVEL1_IRQ, 0);
|
||||||
axp.enableIRQ(AXP202_APS_LOW_VOL_LEVEL2_IRQ, 0);
|
axp.enableIRQ(AXP202_APS_LOW_VOL_LEVEL2_IRQ, 0);
|
||||||
|
|
||||||
// The Charging Current available is less than requested for battery charging.
|
// The Charging Current available is less than requested for battery charging.
|
||||||
// Another Persistent IRQ. Clear it after showing it once?
|
// Another Persistent IRQ. Clear it after showing it once?
|
||||||
// TODO: Show it every X minutes? Adjust charge current request?
|
// TODO: Show it every X minutes? Adjust charge current request?
|
||||||
|
@ -718,7 +737,7 @@ void setup() {
|
||||||
wakeup();
|
wakeup();
|
||||||
|
|
||||||
// Make sure WiFi and BT are off
|
// Make sure WiFi and BT are off
|
||||||
//WiFi.disconnect(true);
|
// WiFi.disconnect(true);
|
||||||
WiFi.mode(WIFI_MODE_NULL);
|
WiFi.mode(WIFI_MODE_NULL);
|
||||||
btStop();
|
btStop();
|
||||||
|
|
||||||
|
@ -837,7 +856,7 @@ void low_power_sleep(uint32_t seconds) {
|
||||||
// screen_setup();
|
// screen_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(100); // GPS doesn't respond right away.. not ready for baud-rate test.
|
delay(100); // GPS doesn't respond right away.. not ready for baud-rate test.
|
||||||
gps_setup(false); // Resync with GPS
|
gps_setup(false); // Resync with GPS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,7 +1197,7 @@ void menu_change_sf(void) {
|
||||||
struct menu_entry menu[] = {
|
struct menu_entry menu[] = {
|
||||||
{"Send Now", menu_send_now}, {"Power Off", menu_power_off}, {"Distance +", menu_distance_plus},
|
{"Send Now", menu_send_now}, {"Power Off", menu_power_off}, {"Distance +", menu_distance_plus},
|
||||||
{"Distance -", menu_distance_minus}, {"Time +", menu_time_plus}, {"Time -", menu_time_minus},
|
{"Distance -", menu_distance_minus}, {"Time +", menu_time_plus}, {"Time -", menu_time_minus},
|
||||||
{"Change SF", menu_change_sf}, {"Helium ReJoin", menu_flush_prefs}, {"USB GPS", menu_gps_passthrough},
|
{"Change SF", menu_change_sf}, {"Full Reset", menu_flush_prefs}, {"USB GPS", menu_gps_passthrough},
|
||||||
{"Deadzone Here", menu_deadzone_here}, {"No Deadzone", menu_no_deadzone}, {"Stay On", menu_stay_on},
|
{"Deadzone Here", menu_deadzone_here}, {"No Deadzone", menu_no_deadzone}, {"Stay On", menu_stay_on},
|
||||||
{"GPS Reset", menu_gps_reset}, {"Experiment", menu_experiment}};
|
{"GPS Reset", menu_gps_reset}, {"Experiment", menu_experiment}};
|
||||||
#define MENU_ENTRIES (sizeof(menu) / sizeof(menu[0]))
|
#define MENU_ENTRIES (sizeof(menu) / sizeof(menu[0]))
|
||||||
|
|
20
main/ttn.cpp
20
main/ttn.cpp
|
@ -105,7 +105,8 @@ void forceTxSingleChannelDr() {
|
||||||
ttn_sf(ttn_tx_sf);
|
ttn_sf(ttn_tx_sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DevEUI generator using devices's MAC address - from https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/lorawan.cpp
|
// DevEUI generator using devices's MAC address - from
|
||||||
|
// https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/lorawan.cpp
|
||||||
void gen_lora_deveui(uint8_t* pdeveui) {
|
void gen_lora_deveui(uint8_t* pdeveui) {
|
||||||
uint8_t *p = pdeveui, dmac[6];
|
uint8_t *p = pdeveui, dmac[6];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -275,7 +276,7 @@ bool ttn_setup() {
|
||||||
return (1 == os_init_ex((const void*)&lmic_pins));
|
return (1 == os_init_ex((const void*)&lmic_pins));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ttn_join() {
|
void ttn_join(void) {
|
||||||
// Reset the MAC state. Session and pending data transfers will be discarded.
|
// Reset the MAC state. Session and pending data transfers will be discarded.
|
||||||
LMIC_reset();
|
LMIC_reset();
|
||||||
|
|
||||||
|
@ -382,14 +383,16 @@ void ttn_join() {
|
||||||
uint32_t netId = p.getUInt("netId", UINT32_MAX);
|
uint32_t netId = p.getUInt("netId", UINT32_MAX);
|
||||||
uint32_t devAddr = p.getUInt("devAddr", UINT32_MAX);
|
uint32_t devAddr = p.getUInt("devAddr", UINT32_MAX);
|
||||||
uint8_t nwkKey[16], artKey[16];
|
uint8_t nwkKey[16], artKey[16];
|
||||||
bool keysgood = p.getBytes("nwkKey", nwkKey, sizeof(nwkKey)) == sizeof(nwkKey) && p.getBytes("artKey", artKey, sizeof(artKey)) == sizeof(artKey);
|
bool keysgood = devAddr != UINT32_MAX && netId != UINT32_MAX &&
|
||||||
|
p.getBytes("nwkKey", nwkKey, sizeof(nwkKey)) == sizeof(nwkKey) &&
|
||||||
|
p.getBytes("artKey", artKey, sizeof(artKey)) == sizeof(artKey);
|
||||||
p.end(); // close our prefs
|
p.end(); // close our prefs
|
||||||
|
|
||||||
if (!keysgood) {
|
if (!keysgood) {
|
||||||
// We have not yet joined a network, start a full join attempt
|
// We have not yet joined a network, start a full join attempt
|
||||||
// Make LMiC initialize the default channels, choose a channel, and
|
// Make LMiC initialize the default channels, choose a channel, and
|
||||||
// schedule the OTAA join
|
// schedule the OTAA join
|
||||||
Serial.println("No session saved, joining from scratch");
|
Serial.println("Joining from scratch");
|
||||||
screen_print("Joining...\n");
|
screen_print("Joining...\n");
|
||||||
LMIC_startJoining();
|
LMIC_startJoining();
|
||||||
} else {
|
} else {
|
||||||
|
@ -410,7 +413,7 @@ void ttn_get_sf_name(char* b, size_t len) {
|
||||||
u1_t sf, bw;
|
u1_t sf, bw;
|
||||||
sf = getSf(txrps) + 6; // 1 == SF7
|
sf = getSf(txrps) + 6; // 1 == SF7
|
||||||
bw = getBw(txrps);
|
bw = getBw(txrps);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
snprintf(b, len, "%3d.%02d SF%d BW%d",
|
snprintf(b, len, "%3d.%02d SF%d BW%d",
|
||||||
LMIC.freq / 1000000,
|
LMIC.freq / 1000000,
|
||||||
|
@ -454,9 +457,10 @@ void ttn_write_prefs() {
|
||||||
static void ttn_set_cnt() {
|
static void ttn_set_cnt() {
|
||||||
LMIC_setSeqnoUp(count);
|
LMIC_setSeqnoUp(count);
|
||||||
|
|
||||||
// We occasionally mirror our count to flash, to ensure that if we lose power we will at least start with a count that is almost correct
|
// We occasionally mirror our count to flash, to ensure that if we lose power we will at least start with a count that
|
||||||
// (otherwise the TNN network will discard packets until count once again reaches the value they've seen). We limit these writes to a max rate
|
// is almost correct (otherwise the TNN network will discard packets until count once again reaches the value they've
|
||||||
// of one write every 5 minutes. Which should let the FLASH last for 300 years (given the ESP32 NVS algoritm)
|
// seen). We limit these writes to a max rate of one write every 5 minutes. Which should let the FLASH last for 300
|
||||||
|
// years (given the ESP32 NVS algoritm)
|
||||||
static uint32_t lastWriteMsec = UINT32_MAX; // Ensure we write at least once
|
static uint32_t lastWriteMsec = UINT32_MAX; // Ensure we write at least once
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (now < lastWriteMsec || (now - lastWriteMsec) > 5 * 60 * 1000L) { // write if we roll over (50 days) or 5 mins
|
if (now < lastWriteMsec || (now - lastWriteMsec) > 5 * 60 * 1000L) { // write if we roll over (50 days) or 5 mins
|
||||||
|
|
Ładowanie…
Reference in New Issue