sandeepmistry / arduino-LoRa

An Arduino library for sending and receiving data using LoRa radios.
MIT License
1.61k stars 621 forks source link

High current in idle mode lora sx1276 #625

Open EvansPM opened 1 year ago

EvansPM commented 1 year ago

I use Lora sx1276 and all work well. I need to be able to wake up the chip ATMega328p when Lora receive data with lowest consumption possible (i will use coin battery). I expect 1 or 2 years on battery CR2032. For now i work on improvement on the Lora module. From what i understood i should use LoRa.idle() and not LoRa.sleep(). When i use LoRa.sleep() the current drop to 1uA max but with LoRa.idle() nothing change still at 1.6 mA. The pinout is same as this Library. Here is my code:

#include <LoRa.h>   // sandeepmistry 
#include <SPI.h>
// Software SPI pins for ATmega328
#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11
#define SS 10
#define RST 9 
#define DIO0 2 

void setup() {
    Serial.begin(9600);
    while (!Serial);
    LoRa.setPins(SS, RST, DIO0);
    LoRa.setSPIFrequency(8);  //8Mhz frequency

//LoRa.setSPI(SCK_PIN, MISO_PIN, MOSI_PIN); // before begin
  while (!LoRa.begin(freq_US)){
    LoRa.end();
    Serial.println("Starting LoRa failed!");
    delay(50);
    //blinkError();
  }
  LoRa.setTxPower(LORA_TX_POWER);  // s
  Serial.println("LoRa Setup Successful.");

attachInterrupt (digitalPinToInterrupt (DIO0), wakeUpChip, CHANGE);  // interrupt MUST be attached if DIO0 used interrupt 
  pinMode(touchPin, INPUT);
  LoRa.onTxDone(onTxDone);
  LoRa.onReceive(onReceive);
  //LoRa.sleep();
  LoRa.idle();
}

void loop() {
}

void onTxDone() {
 Serial.print("Lora send done! ");
}

void onReceive(int packetSize) {
 Serial.print("Lora received data! ");
}
Kongduino commented 1 year ago

LoRa.sleep(); and LoRa.idle(); do not affect the ATMega328p at all. It is not sleeping. You should not put the LoRa chip to sleep anyway or you won't receive anything. You should put the ATMega328p to sleep, with a wakeup set on the DØ pin.

EvansPM commented 1 year ago

Based on the datasheet https://cdn-shop.adafruit.com/product-files/3179/sx1276_77_78_79.pdf, LoRa.idle() should use around 1.5uA, by the way i do not know what mean "RC oscillator" which should be enabled. And I'm not trying to save anything on ATMega328p with this code, but on the Lora module itself. From my search with LoRa.sleep() we won't receive anything but we can with LoRa.idle(). I will later try to save on ATMega328p with the library "LowPower" for example. Even if i have 0uA on ATMega328p Lora will suck all the battery with 1.6 mA so i need to reduce that.

Kongduino commented 1 year ago

You said, in your original post:

I need to be able to wake up the chip ATMega328p

And that's what I was answering... In order to wake up the atmega, you need to put it to sleep first – which is not what the LoRa.sleep() command does. So, yes indeed, you need to work things out with LowPower. This will decrease your overall consumption.

As for the LoRa chip, how did you measure the power consumption? Could it be possible that you measured the board's overall consumption?

EvansPM commented 1 year ago

You are right, sorry for my lack of clarity. I just wanted to set the context, the final goal of this project. But at the moment I'm just trying to reduce the consumption of Lora to the max while keeping the possibility to detect the reception of messages.

For Lora, I just connected the voltmeter in series on the power that goes to Lora, here is my schematic: Lora test

Yes I use an Arduino without chip as power source just for testing.

Kongduino commented 1 year ago

Ah, nice. This gives me a much better understanding. However, I do believe that you are still measuring the total consumption – Vcc comes from the Arduino and thus it's the total circuit's consumption you are measuring. You could test by connecting a separate 3.3v source to the LoRa chip, and severe the Vcc line between the atmega and LoRa chip. Then measure that.

But my advice here would be to put the atmega to sleep and wake up, and measure this in the exact same way. This might give you different results.

EvansPM commented 1 year ago

I tried right now with a separated source for the Lora module and i got same value. I tried to sleep the atmega (about 200uA) yesterday to see if it may influence the value of Lora, but same thing, did not chance the consumption of Lora.

EvansPM commented 1 year ago

After reading again the doc, what i understand is actually LoRa.idle() is not for idle mode but for standby mode. image So my value are correct and for my need it's look like what i'm looking for is CAD detection, i'm trying this.

Kongduino commented 1 year ago

CAD is actually an active procedure, and consumes quite a bit of power. There's a good article about CAD, which explains what it does, and how. It's used to make sure the channel is clear before sending – not at all what you need.

Idle and standby are mostly synonymous – Idle a mode where the LoRa chip is doing nothing, either sleeping, or not. It applies to both Standby and Sleep modes. Confusing I know.

Idle

And as you discovered, in this library, idle() is putting the chip in standby:

void LoRaClass::idle() {
  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
}
EvansPM commented 1 year ago

Thank you for the link of that article. If i understood CAD == check before send, while saying CAD allow saving power, they do not provide values. Anyway the CAD code i was trying did not work for me. So back to square one.

So should I understand this library did not implement that case (IDDIDLE) where the consumption is 1.5 uA? And did Semtech provided a library where i can check?

I was thinking also to implement my own method: Increase the preamble, and go to sleep for a lower time value then wake up and check if there is message then go to sleep, in loop. Not sure what gonna be the consumption...

Kongduino commented 1 year ago

This is indeed strange. I'll try and do some experiments over the weekend.