ARMmbed / mbed-os-example-lorawan

Simple LoRaWAN example application for mbed OS
Apache License 2.0
78 stars 92 forks source link

DISCO_L072CZ_LRWAN1 LOW POWER #222

Open evandavey opened 3 years ago

evandavey commented 3 years ago

This is a follow-on from #119 which never seems to have adequately resolved.

In addition to getting ~300uA on VDD_MCU when the event loop is idle, I always see ~1mA on VDD_USB. I believe this is due to TCXO being powered by PA_12 (with JP9 in position 1-2) and this always staying high in the SX1276 library. If JP9 is in position 2-3 then the 1mA shifts to VDD_LRA (since this hard-wires TCXO to always on).

So problem 1 is how to control PA_12/TCXO so it is off when the event loop is idle. This could be done manually by setting sx1276-lora-driver.tcxo to NC and manually turning it on before a send and off following a send but this seems a bit hacky.

And problem 2 is how to further reduce MCU consumption in deep sleep.

Both of these are crucial for a battery powered IoT application which is the target of this library.

ciarmcom commented 3 years ago

@evandavey This issue has an incomplete or old issue template.For future reference please use an up to date clone of the repository before raising issues. Many thanks.

ciarmcom commented 3 years ago

Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers. Internal Jira reference: https://jira.arm.com/browse/IOTOSM-3836

evandavey commented 2 years ago

The SX12... drivers look considerably out of date relative to https://github.com/Lora-net/LoRaMac-node/tree/master/src/radio.

The SX1276 driver for example has a call to SX1276SetBoardTcxo(...) which is not used in the mbed driver.

It also looks like there is some work on a new SX126X driver here: https://github.com/Lora-net/sx126x_driver.

This look like a much better design with a HAL abstraction that could be used to de-couple the SX12... driver logic from the framework implementation, however it looks like a lot of work to port across as the MBED implementation is very opinionated.

These libraries also seem to account for gpio_deinit for low power.

MustafaYassin commented 1 year ago

I'm trying to deep sleep DISCO_L072CZ_LRWAN1 between transmissions and facing the same issues: TXCO needs to be manually put off by PA_12 & VDD_MCU draws ~450uA after lorawan initialization. I step-debugged the lorawan.initialize(..) function while measuring the current. The current increases at the call to _radio->random() in LoRaPHY.cpp. It seems that the SPI peripheral remains enabled after first transmission. Disabling SPI between transmissions removed the 450uA. Added this code in TX_DONE event:

{
    DigitalIn spi_pin1(MBED_CONF_SX1276_LORA_DRIVER_SPI_MOSI, PullNone); 
    DigitalIn spi_pin2(MBED_CONF_SX1276_LORA_DRIVER_SPI_MISO, PullNone); 
    DigitalIn spi_pin3(MBED_CONF_SX1276_LORA_DRIVER_SPI_SCLK, PullNone);
}

And this in the beginning of send_message() function:

{
    mbed::SPI _spi(MBED_CONF_SX1276_LORA_DRIVER_SPI_MOSI, 
            MBED_CONF_SX1276_LORA_DRIVER_SPI_MISO, 
            MBED_CONF_SX1276_LORA_DRIVER_SPI_SCLK);
    _spi.select();
    _spi.deselect();
}

Hope Mbed team would provide an API to disable/enable SPI.

sillevl commented 1 year ago

@MustafaYassin thank you for your solution. I can confirm this also working on a custom STM32L432 targit with SX1276. I can get as low as 3µA between transmits.

Did you improve this implementation, or have some other insights or ideas to solve in a better way?

Currently I'm trying to get it working using the SX1276_LoRaRadio::sleep() in the mbed library. This way, I would like to achieve the low power state between TX and RX windows, which is not the case now.

UnCanard14 commented 1 year ago

Hi @MustafaYassin @sillevl I'm trying to use this card but I can't get down from 4.80mA with mbed os 6... Can any of you share your code that consumes less than 1mA? Thank you for your answer :)

MustafaYassin commented 10 months ago

@sillevl The issue is that you need to re-configure the SPI pins after wake-up so deactivating SPI in SX1276_LoRaRadio::sleep() alone won't do it. Note that mbed targets provides spi_init() & spi_free() functions that configure and reset SPI pins respectively hence they can be used for this purpose. I thought of having an 'initialized' flag in the SPI class and calling spi_init() when read or write is requested while initialized is false. And have a free() function that calls spi_free() and sets initialized to false. Then calling _spi.free(); at the end of SX1276_LoRaRadio::sleep().

@UnCanard14 Please check this fork I created to explain this "quick" fix. https://github.com/MustafaYassin/mbed-os-example-lorawan/ Assuming you are using DISCO_L072CZ_LRWAN1 board, you need to put JP9 in position 1-2 to allow controlling TCXO (high speed oscillator) from PA_12.

sillevl commented 10 months ago

@UnCanard14 you can see my implementation at https://github.com/vives-dust/firmware/commit/afadd3e9885bcfee6d2807edeaca738f342d845f

@MustafaYassin Your solution is almost identical like the implementation i settled with. I can confirm this works correctly and solves the problem. I develloped on a custom board.

MustafaYassin commented 10 months ago

@sillevl Good to confirm! Thanks. PS: The link you posted is not reachable.

UnCanard14 commented 10 months ago

Thank you @sillevl @MustafaYassin for your answers!

I tried @MustafaYassin solution but I'm still at 6mA. In the code I've only changed the import of the DigitalOut classes in your code to mbed::DigitalOut because the project didn't want to build. I set my build profile to 'Release'.

On the hardware side, I removed the SB37<->NRST bridge to be able to supply the card with usb and added a jumper wire onto SB37 which we could connect to CN12(5) to be able to continue flashing my card. I placed JP9 in poistion 1-2 (jumper facing down when looking at the board with the antenna at the bottom). I didn't remove the board's LED and resistors, which consume a bit of power (I'm guessing their total consumption won't save me 6mA).

To take my measurements, I use a lab power supply that gives me a voltage of 4.5V, allowing me to simulate my batteries, and I add an amperemeter in series in the circuit to measure the board's power consumption. Do you see anything I might have forgotten?

MustafaYassin commented 10 months ago

@UnCanard14 6mA is too much to be caused by the issue of the thread. Answering your questions, your practice with SB37<->NRST is correct. Your JP9 configuration is also correct. LEDs? seriously? one LED could consume up to 20mA; you need to remove all LEDs for this experiment. Here are a few more tips: Remove SB28 & SB29, I remember one of STLINK_TX/RX caused current drain. Confirm whether your MCU enters into deep sleep at all. Use sleep tracing (MBED_SLEEP_TRACING_ENABLED) feature to debug this. Remove one of R26, R27 because they form a path from 3V3 to GND.

You better measure the current at VDD_USB, VDD_RF & VDD_MCU instead of +5V to get only MCU current. Edit: Also need to set lora.duty-cycle-on to false in mbed_app.json.

Hope these help.

jeromecoutant commented 8 months ago

Dear Lora user with STM32L0 or STM32WL, maybe you could have a look on https://github.com/ARMmbed/mbed-os/pull/15464 Regards,

hallard commented 8 months ago

FYI I used STM32L0 on custom boards by the past with 3µA sleep mode without any issue with this PR (now merged) https://github.com/ARMmbed/mbed-os/pull/15181

So with basic board with only STM32L0 you should be able to achieve this 3µA sleep.