Skip to content

Commit

Permalink
Fixed problems with deepsleep inaccuracy and duty cycle limitation
Browse files Browse the repository at this point in the history
- Fixed problem with duty cycle limitation
- Fixed MCU deepsleep inaccuracy
  • Loading branch information
foorschtbar committed Feb 15, 2022
2 parents c23537d + 10f7bdd commit e9d4a54
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 35 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ avrdude -F -v -c arduino -p atmega328p -P COM4 -b 57600 -D -U flash:w:firmware_1

## Firmware Changelog

### Version 2.5

- Fixed problem with duty cycle limitation
- Fixed MCU deepsleep inaccuracy
### Version 2.4

- An external interrupt during a transmission terminates the transmission and starts a new transmission.
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ build_flags =
-D USE_IDEETRON_AES
-D MIC_ENABLE_arbitrary_clock_error
-D VERSION_MAJOR=2
-D VERSION_MINOR=4
-D VERSION_MINOR=5

[env:config]
build_flags =
Expand Down
76 changes: 42 additions & 34 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ configData_t cfg; // Instance 'cfg' is a global variable with 'configData_t' str
volatile boolean wakedFromISR0 = false;
volatile boolean wakedFromISR1 = false;
unsigned long lastPrintTime = 0;
unsigned long prepareCount = 0;
// unsigned long prepareCount = 0;
boolean TXCompleted = false;
boolean foundBME = false; // BME Sensor found. To skip reading if no sensor is attached
boolean foundDS = false; // DS19x Sensor found. To skip reading if no sensor is attached
Expand Down Expand Up @@ -550,8 +550,8 @@ void do_send(osjob_t *j)
buffer[10] = temp2 >> 8;
buffer[11] = temp2;

log_d("Prepare package #");
log_d_ln(++prepareCount);
log_d_ln("Prepare pck");
// log_d_ln(++prepareCount);
// log_d(F("> FW: v"));
// log_d(VERSION_MAJOR);
// log_d(F("."));
Expand Down Expand Up @@ -579,7 +579,7 @@ void do_send(osjob_t *j)

// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, buffer, sizeof(buffer), cfg.CONFIRMED_DATA_UP);
log_d_ln(F("Packet queued"));
log_d_ln(F("Pck queued"));
}
}

Expand Down Expand Up @@ -654,6 +654,8 @@ void lmicStartup()

// Disable link check validation
LMIC_setLinkCheckMode(0);
// Disable ADR
LMIC_setAdrMode(0);

// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = DR_SF9;
Expand All @@ -670,29 +672,29 @@ void lmicStartup()
// #endif
}

extern volatile unsigned long timer0_overflow_count;
void do_sleep(uint16_t sleepTime)
{

uint16_t sleepTimeLeft = sleepTime;
boolean breaksleep = false;

if (LOG_DEBUG_ENABLED)
{
Serial.print(F("Sleep "));
if (sleepTimeLeft <= 0)
if (sleepTime <= 0)
{
Serial.println(F("FOREVER\n"));
}
else
{
Serial.print(sleepTimeLeft);
Serial.print(sleepTime);
Serial.println(F("s\n"));
}
Serial.flush();
}

// sleep logic using LowPower library
if (sleepTimeLeft <= 0)
if (sleepTime <= 0)
{
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}
Expand All @@ -701,7 +703,11 @@ void do_sleep(uint16_t sleepTime)

// Add LORA_MAX_RANDOM_SEND_DELAY of randomness to avoid overlapping of different
// nodes with exactly the same sende interval
sleepTimeLeft += (rand() % LORA_MAX_RANDOM_SEND_DELAY);
sleepTime += (rand() % LORA_MAX_RANDOM_SEND_DELAY);

// Measurements show that the timer is off by about 12 percent,
// so the sleep time is shortened by this value.
sleepTime *= 0.88;

// sleep logic using LowPower library
uint16_t delays[] = {8, 4, 2, 1};
Expand All @@ -710,12 +716,12 @@ void do_sleep(uint16_t sleepTime)

for (uint8_t i = 0; (i <= 3 && !breaksleep); i++)
{
for (uint16_t x = sleepTimeLeft; (x >= delays[i] && !breaksleep); x -= delays[i])
for (uint16_t x = sleepTime; (x >= delays[i] && !breaksleep); x -= delays[i])
{
// Serial.print("i: ");
// Serial.print(i);
// Serial.print(" TL: ");
// Serial.print(sleepTimeLeft);
// Serial.print(sleepTime);
// Serial.print(" S: ");
// Serial.println(delays[i]);
// Serial.flush();
Expand All @@ -726,11 +732,18 @@ void do_sleep(uint16_t sleepTime)
}
else
{
sleepTimeLeft -= delays[i];
sleepTime -= delays[i];
}
}
}
}

// LMIC does not get that the MCU is sleeping and the
// duty cycle limitation then provides a delay. A manual
// overflow of timer0_overflow_count (wiring.c from the arduino core)
// which is used for micros() fix that.
// https://www.thethingsnetwork.org/forum/t/adafruit-feather-32u4-lora-long-transmission-time-after-deep-sleep/11678/11
timer0_overflow_count += 3E6;
}

void onEvent(ev_t ev)
Expand Down Expand Up @@ -773,23 +786,23 @@ void onEvent(ev_t ev)
break;
case EV_JOIN_FAILED:
log_d_ln(F("Join failed"));
lmicStartup(); //Reset LMIC and retry
lmicStartup(); // Reset LMIC and retry
break;
case EV_REJOIN_FAILED:
log_d_ln(F("Rejoin failed"));
lmicStartup(); //Reset LMIC and retry
lmicStartup(); // Reset LMIC and retry
break;

case EV_TXSTART:
// log_d_ln(F("EV_TXSTART"));
break;
case EV_TXCOMPLETE:
log_d(F("TX complete #")); // (includes waiting for RX windows)
log_d(F("TX done #")); // (includes waiting for RX windows)
log_d_ln(LMIC.seqnoUp);
if (LMIC.txrxFlags & TXRX_ACK)
log_d_ln(F("> Received ack"));
log_d_ln(F("> Got ack"));
if (LMIC.txrxFlags & TXRX_NACK)
log_d_ln(F("> Received NO ack"));
log_d_ln(F("> Got NO ack"));

// if (LMIC.dataLen)
// {
Expand Down Expand Up @@ -897,11 +910,11 @@ void setup()
delay(100); // per sample code on RF_95 test
}

log_d(F("\n=== Starting LoRaProMini v"));
log_d(F("\n= Starting LoRaProMini v"));
log_d(VERSION_MAJOR);
log_d(F("."));
log_d(VERSION_MINOR);
log_d_ln(F(" ==="));
log_d_ln(F(" ="));

readConfig();

Expand All @@ -921,13 +934,13 @@ void setup()
}
}

log_d(F("Search DS18x..."));
log_d(F("Srch DS18x..."));

ds.begin();
ds.requestTemperatures();

log_d(ds.getDeviceCount(), DEC);
log_d_ln(F(" found"));
log_d_ln(F(" fnd"));

for (uint8_t i = 0; i < ds.getDeviceCount(); i++)
{
Expand Down Expand Up @@ -964,11 +977,11 @@ void setup()
}

// BME280 forced mode, 1x temperature / 1x humidity / 1x pressure oversampling, filter off
log_d(F("Search BME280..."));
log_d(F("Srch BME..."));
if (bme.begin(I2C_ADR_BME))
{
foundBME = true;
log_d_ln(F("1 found"));
log_d_ln(F("1 fnd"));
if (CONFIG_MODE_ENABLED)
{
bme.takeForcedMeasurement();
Expand All @@ -985,7 +998,7 @@ void setup()
}
else
{
log_d_ln(F("not found"));
log_d_ln(F("0 fnd"));
}

// Allow wake up pin to trigger interrupt on low.
Expand All @@ -1007,7 +1020,7 @@ void setup()
// Reset the MAC state. Session and pending data transfers will be discarded.
lmicStartup();

Serial.print(F("Join Mode: "));
Serial.print(F("Join mode "));

// ABP Mode
if (cfg.ACTIVATION_METHOD == ABP)
Expand All @@ -1025,10 +1038,6 @@ void setup()
// Join the network, sending will be started after the event "Joined"
LMIC_startJoining();
}
else
{
Serial.println(F("?"));
}
}
}

Expand Down Expand Up @@ -1058,7 +1067,7 @@ void loop()
}
else
{
log_d_ln(F("Batt V to low!"));
log_d_ln(F("Bat to low!"));
}
}

Expand All @@ -1067,10 +1076,9 @@ void loop()
// sleep ended. do next transmission
doSend = true;
}
else if (lastPrintTime == 0 || lastPrintTime + 5000 < millis())
if (lastPrintTime == 0 || lastPrintTime + 5000 < millis())
{
log_d(F("Can't sleep. txCnt="));
log_d_ln(LMIC.txCnt);
log_d_ln(F("> Cant sleep"));
lastPrintTime = millis();
}

Expand All @@ -1082,4 +1090,4 @@ void loop()
do_send(&sendjob);
}
}
}
}

0 comments on commit e9d4a54

Please sign in to comment.