rocketscream / Low-Power

Low Power Library for Arduino
www.rocketscream.com
1.27k stars 345 forks source link

328P 3v3 8mhz not enabling all systems after wakeup period #124

Open Rustie0125 opened 1 year ago

Rustie0125 commented 1 year ago

Hello, I'm trying to use low power library with periodically wakeup in conjuction with Radiolib library for lorawan transmissions but it's not working.

If I use LP library just with blink example I can get it to work as expected. If I use the radio lib library on its own it works.

If I combine them ( and use the led to see if the wakeup happens it ) does not work at all. I'll post the code on following comment but I wanted to clarify the opperation first.

1) I see serial. Print event almost do not work after wakeup. Do I manually need to enable all system again with UART0_ON; statement or how is it expected to work ?

2) I tried power down and idle but seem to kill the SPI bus which I need to take to radio. I moved all initial of the radio lib and serial lib to main loop to make sure they get restarted but the serial window just puts out garbage and the led does not flash again.

Rustie0125 commented 1 year ago

Here is an example just inserting the sleep command in the RadioLib library

`/*
   RadioLib SX126x Transmit Example

   This example transmits packets using SX1262 LoRa radio module.
   Each packet contains up to 256 bytes of data, in the form of:
    - Arduino String
    - null-terminated char array (C-string)
    - arbitrary binary data (byte array)

   Other modules from SX126x family can also be used.

   For default module settings, see the wiki page
   https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>
#include LowPower.h

// SX1262 has the following connections:
// NSS pin:   10
// DIO1 pin:  2
// NRST pin:  3
// BUSY pin:  9
SX1262 radio = new Module(10, 2, 3, 9);

// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 radio = RadioShield.ModuleA;

// or using CubeCell
//SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);

void setup() {
  Serial.begin(9600);

  // initialize SX1262 with default settings
  Serial.print(F("[SX1262] Initializing ... "));
  int state = radio.begin();
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // some modules have an external RF switch
  // controlled via two pins (RX enable, TX enable)
  // to enable automatic control of the switch,
  // call the following method
  // RX enable:   4
  // TX enable:   5
  /*
    radio.setRfSwitchPins(4, 5);
  */
}

void loop() {
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
  Serial.print(F("[SX1262] Transmitting packet ... "));

  // you can transmit C-string or Arduino string up to
  // 256 characters long
  // NOTE: transmit() is a blocking method!
  //       See example SX126x_Transmit_Interrupt for details
  //       on non-blocking transmission method.
  int state = radio.transmit("Hello World!");

  // you can also transmit byte array up to 256 bytes long
  /*
    byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
    int state = radio.transmit(byteArr, 8);
  */

  if (state == RADIOLIB_ERR_NONE) {
    // the packet was successfully transmitted
    Serial.println(F("success!"));

    // print measured data rate
    Serial.print(F("[SX1262] Datarate:\t"));
    Serial.print(radio.getDataRate());
    Serial.println(F(" bps"));

  } else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
    // the supplied packet was longer than 256 bytes
    Serial.println(F("too long!"));

  } else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
    // timeout occured while transmitting packet
    Serial.println(F("timeout!"));

  } else {
    // some other error occurred
    Serial.print(F("failed, code "));
    Serial.println(state);

  }

  // wait for a second before transmitting again
  delay(1000);
}`

and here is a more integrated approach, I have tried many many iterations all ends in the same result so I suspect im missing somehting


`#include "LowPower.h"
#include <RadioLib.h>
unsigned long Wake_Counter =0;

SX1262 radio = new Module(10, 2, 3, 9);

void setup()
{
  Serial.begin(9600);
  radio.begin(917.5, 250.0, 12, 5, 0x18, 10, 8);
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(5,OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);    
}

void loop() 
{
    // Enter power down state for 8 s with ADC and BOD module disabled
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
    Serial.begin(9600);
    //Wake_Counter++;
    //if ( Wake_Counter > 2)
    //{
    digitalWrite(5,HIGH);
    radio.begin(917.5, 250.0, 12, 5, 0x18, 10, 8);
    radio.transmit("Hello World!");
    digitalWrite(LED_BUILTIN,HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN,LOW);
    digitalWrite(5,LOW);
    //Wake_Counter = 0;
    //}
    Serial.println(Wake_Counter);
}`
rocketscream commented 1 year ago

Not too sure on the RadioLib, but if you are using Serial.print(), always call Serial.flush(), else it doesn't finish up all the UART transmission and went to power down instead. This is more apparent when used with slower baud rate like 9600 bps. 1 bit of 1ms is plenty for the processor to run so many instructions and hence the Serial.print never actually finish all characters.

Rustie0125 commented 1 year ago

Not too sure on the RadioLib, but if you are using Serial.print(), always call Serial.flush(), else it doesn't finish up all the UART transmission and went to power down instead. This is more apparent when used with slower baud rate like 9600 bps. 1 bit of 1ms is plenty for the processor to run so many instructions and hence the Serial.print never actually finish all characters.

Thank you, Makes sense Ill give that a go, as far as the single line " LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); " when the 8 seconds have passed, does the system automatically turn all peripherals back on before the code resumes or do I manually need to able these before continuing ? the RadioLib very dependent on the SPI bus so just need to see what needs to be setup after sleep

rocketscream commented 1 year ago

They will be in the state is was before. But some small delay would help for the clock to stablized before running any crucial clock dependant process like SPI.

Rustie0125 commented 1 year ago

Interesting, Okay Ill try a small delay, my baud is already 9600 see if it solves it. Do you for see any issue in extending the sleep period with code snippet like this? I know if will wake up every 8 but it should be very quick

Counter++;
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF)
If (Counter >7 ) // more or less a minute
    { 
    Concur the world here
    Counter = 0;
    }
Rustie0125 commented 1 year ago

Still struggling with this, the 100ms delay after wakeup helped getting the system up and running again, but now reagrdless what I do, current does not drop below 500uA is I use lowpower idle. the current is around 1.2mA if i use power down its 500uA im expecting closer to 5uA the only thing connected is a radio in SPI bus and a output on pin 5 to shut off the power to the radio while sleeping. I suspect the library puts the GPIOs in some sort of state during sleep and some leakage current is either going thru the GPIO pin or the SPI pins,