ARMmbed / mbed-os-example-lorawan

Simple LoRaWAN example application for mbed OS
Apache License 2.0
79 stars 93 forks source link

How to get <340uA in deepsleep for DISCO_L072CZ_LRWAN1 #119

Closed sillystudent96 closed 4 years ago

sillystudent96 commented 5 years ago

Hi LoRaWAN experts,

I am trying to get my LoRaWAN application running with the lorawan-mbed-os-example (latest version of Jan, 2019, Board: DISCO_L072CZ_LRWAN1) and I'm impressed so far. Everything works fine except the sleep modes. The control of the sx1276 works perfectly fine (<1uA in sleep) but i can't get the controller current below ~340uA. The tracing output looks good (~99% of the idle time in deepsleep), LPTICKER set on RTC, MBED_TICKLESS activated and the low-power-timeout in radio driver is set. In comparison I can reach about 8 uA with an easy mbed-os program (e.g. mbed-os-blinky). I also tried some of other things but nothing worked. What am I doing wrong?

Thank you for your help!

Kind regards.

ciarmcom commented 5 years ago

ARM Internal Ref: IOTCELL-1676

hasnainvirk commented 5 years ago

@sillystudent96 You may need to consult the data sheet of the MCU in this regard. Print out the value of SystemCoreClock and you will know what clock speed your MCU is running on. The clock speed determines the active power state of the MCU. A word of caution though: Do not slow down too much.

I had recently been playing around with a board clocked at mere 4MHz and that ended up interrupting smooth flow of the application because a large processing delay was introduced. I could cover it up though by using an insanely high error compensation (about a 100ms) for the stack computations. I am aware of the fact that the 4MHz clock is probably the boot mode clock only (as that particular board can be clocked to about 90MHz), and the people would actually be using much higher clocks. But there are always some adventurers :) who wouldn't mind going ultra ultra low power.

Alright, back to your question: You can reduce power consumption by communicating less often for a starter. As said above, consult datasheet for activating MCU low power modes. I am not aware of a standard method in Mbed OS that can change power mode and Clock speed of the MCU. You need to dig through HAL code under targets/ directory. In blinky example, no other peripherals are on and there is almost no processing overhead. With LoRaWAN stack if you would change the application to be less frequent you will see better results in power consumption.

janjongboom commented 5 years ago

@sillystudent96 This might help as well to bring the STM32 into standby mode. You'll need that for lowest power. https://github.com/janjongboom/stm32-standby-rtc-wakeup. Note that it will not retain RAM.

sillystudent96 commented 5 years ago

First of all thank you guys, I'm glad you help me!

@hasnainvirk I digged through the data sheet and realized that the controller has to be in active running mode during deepsleep. I am actually playing with the clock speeds but i don't think thats the core of the problem. Also, I'm waking up just every 10 minutes to reduce overall power consumption but 340 uA during sleep is simply too much. What I am trying to understand is: Why is there such a big difference between deepsleep in the blinky example and deepsleep in the LoRaWAN example (even with the LoRaWAN stack overhead)

@janjongboom I tried the library and as well as your solutions for greenhouse example but I had no success. What worked for me is calling ev.queue.call_every(TX_TIME, &send_message) in the connect event and wait(sleep_time) right at the end of the send message function. This way I'm achieving the 8uAs for that specified wait time. This solution however would require to calculate the sleep time dynamically, depending on the LoRaWAN-Stack's specific state and im at a loss on how to approach this. Ideally, i would not need to worry about sleep times and just let the OS handle going into the deepest possible sleepmode whenever possible. Any hints on how to approach this?

Kind regards

janjongboom commented 5 years ago

@sillystudent96 I've been using the normal sleep API and that works fine for LoRaWAN... Device shows deepsleep for most of the time. It feels that there's some peripheral blocking sleep? Could you look at the sleep stats and see if there's any sleep locks active?

DaedalosSG commented 5 years ago

Hey guys,

I have almost the same problem. I am using the DISCO-L072CZ-LRWAN1 for my project. Similar to @sillystudent96 approach i want to reduce the power consumption as much as possible. Not modifying the mbed-os-example-lorawan there is an average current of 330µA (Sending every minute and Duty_cycle is off). Further i set lpticker_lptim to 0 in the targets.json. That means i use RTC wakeup timer. Using the tracer i got the following results: Uptime: 41871704 idle time: 41693479 sleep time: 11715 depp sleep time: 41681764 Thus, it seems like that deepsleep is working just fine and is not blocked, but still i am not getting lower than 330µA. Shouldn't the OS go lower than that by itself? And if not, what do i have to add in code to get close to 8µA. @janjongboom standby is an option of course, but i would prefer not to clear all states.

Thank you for your help!

Kind regards

hasnainvirk commented 5 years ago

@DaedalosSG You must not disable duty cycle because you are breaking regulation here by doing so. Turning off duty cycle is only allowed during Device Certification process under controlled environment. Answering your question, as I had tried before to @sillystudent96, you must change how the application is behaving. Because the way application is written, it will use every opportunity to transmit, i.e., it will send as fast as it can. That means essentially the application is not letting you sleep properly. As soon as the state machine is done performing a task, it goes into another cycle. You got to understand that. Now that I can see that you are transmitting after a minute or so and trying to average out the power consumption. Here you need to understand that MCUs run on several power states e.g., lowest power mode could be the Boot Mode in which an MCU runs on a staggeringly low clock speed. To clock down the device to consume an average current of 8 uA you got to hack around the MCU porting code. This code is mostly contributed to Mbed OS by our vendor partners. It would be actually very interesting to come up with a standard mechanism in Mbed OS to clock up or Clock down an MCU, I would let the architects know. If you wish to do that yourself, please look into the porting layer of the particular board you are using and consult the data sheet. That will enable you to clock down the MCU which will in turn help you achieve lower power state near to your desired value.

hasnainvirk commented 5 years ago

@sillystudent96 Actually you have a point here. It kind of slipped through when I was going through your text previously. We may need to check the core timer code for the stack if there is anything blocking there and how is it effecting. Because if you can see a significant drop in power consumption using call_in() method over the event queue, then there must be something in our timer instance (the LoRaMacTimer class) which may be locking the system and preventing it to go for deep sleep. In @DaedalosSG's comment, I can see the idle time and deep sleep time are almost equal, that can't be right. Either there is something wrong with the configuration you guys are using or there is a real problem. I will investigate that and come back to you guys when I have an answer.

janjongboom commented 5 years ago

@bulislaw @0xc0170 You have been working on the deepsleep APIs, right? Any idea what might be going on?

YoannBo commented 5 years ago

@sillystudent96
340uA sounds like the debugger is likely to be still activated when MCU enters sleep mode. In I-CUBE-LRWAN this in done in file debug.c 1/ disable debug under sleep modes:

  __HAL_RCC_DBGMCU_CLK_ENABLE( );
  HAL_DBGMCU_DisableDBGSleepMode( );
  HAL_DBGMCU_DisableDBGStopMode( );
  HAL_DBGMCU_DisableDBGStandbyMode( );
  __HAL_RCC_DBGMCU_CLK_DISABLE( );

2/ disable sw interface (debug pins) PA13 and PA14 by setting them in analog input:

 GPIO_InitTypeDef GPIO_InitStructure ={0};

  GPIO_InitStructure.Mode   = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Pull   = GPIO_NOPULL;
  GPIO_InitStructure.Pin    = (GPIO_PIN_13 | GPIO_PIN_14);
  __GPIOA_CLK_ENABLE() ;  
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  __GPIOA_CLK_DISABLE() ;
sillystudent96 commented 5 years ago

Hey guys, thanks for your help. For testing, I switched back to a L4 host controller and put the LoRaWAN module into AT Command mode (using st's at-modem firmware). Of course, thats not representative for the LoRaWAN stack itself, but I got the low power modes running with the mbed os 5 on the L4 - and it worked as it should. Now I am waiting for my sx1276 and sx1272 dev boards and will then test the LoRaWAN stack on the L4. I also had some issues with the low power modes of the Nucleo L433RC-P as well: The sleep current was about 100uA, as opposed to the microamps described in the datasheet. A floating input pin was the issue there. I fixed it by pulling PB_3 low (connected to SWO on the nucleo board). Maybe some other boards also have issues like that.

0xc0170 commented 5 years ago

@sillystudent96 thanks for the feedback!

cc @ARMmbed/team-st-mcd

sillystudent96 commented 5 years ago

Hey guys, so I received my SX1272MB2DAS shield and the SX1276MB1MAS shield and connected them to the well known Nucleo_L476RG (here I know that the sleep modes work). I made the new pin mapping in the mbed_app.json for the Nucleo_L476RG, autogenerated a new DEVEUI by TTN and tried to run the code on the L4. Now I have the problem that the program is stucking while joining. "Connection - In Progress ..." is the detailed message for both the sx1272 and the sx1276. The device isn't joining and I can see no gateway traffic. Anybody an idea how to continue here?

hasnainvirk commented 5 years ago

@sillystudent96 Sounds like a pin clash .. Can you please share your json file and any trace ? Most probably you will be getting Radio TX timeout which means radio was unable to transmit. That's why you are not seeing any traffic at the base station.

hasnainvirk commented 5 years ago

You can enable trace by adding this line in target_overrides section: "mbed-trace.enable": true,

sillystudent96 commented 5 years ago

Hi,

here's my trace. I think it's not a pin clash but maybe something wrong with the receive procedure. I am wondering if I have to connect the DIO4 pin on the sx1272 module. I checked the gateway and it works fine. I have two other nodes running with the mbed-os-lorawan example Trace output:

[DBG ][LSTK]: Initializing MAC layer

Mbed LoRaWANStack initialized

CONFIRMED message retries : 3

Adaptive data rate (ADR) - Enabled [DBG ][LSTK]: Initiating OTAA [DBG ][LSTK]: Sending Join Request ... [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: TX: Channel=1, TX DR=5, RX1 DR=5

Connection - In Progress ... [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: TX: Channel=1, TX DR=4, RX1 DR=4 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868300000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 4961 ms [DBG ][LMAC]: TX: Channel=1, TX DR=3, RX1 DR=3 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868300000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 14069 ms [DBG ][LMAC]: TX: Channel=0, TX DR=2, RX1 DR=2 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868300000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 30404 ms [DBG ][LMAC]: TX: Channel=2, TX DR=1, RX1 DR=1 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 75250 ms [DBG ][LMAC]: TX: Channel=0, TX DR=0, RX1 DR=0 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868500000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 140491 ms [DBG ][LMAC]: TX: Channel=0, TX DR=5, RX1 DR=5 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: TX: Channel=0, TX DR=4, RX1 DR=4 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 4961 ms [DBG ][LMAC]: TX: Channel=0, TX DR=3, RX1 DR=3 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 14068 ms [DBG ][LMAC]: TX: Channel=1, TX DR=2, RX1 DR=2 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868100000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 30403 ms [DBG ][LMAC]: TX: Channel=1, TX DR=1, RX1 DR=1 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868300000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000 [DBG ][LMAC]: Frame prepared to send at port 0 [DBG ][LMAC]: DC enforced: Transmitting in 75251 ms [DBG ][LMAC]: TX: Channel=1, TX DR=0, RX1 DR=0 [DBG ][LSTK]: Transmission completed [DBG ][LMAC]: RX1 slot open, Freq = 868300000 [DBG ][LMAC]: RX2 slot open, Freq = 869525000

OTAA Failed - Check Keys

And here the mbed_app.json with the changes keys:

{
    "config": {
        "lora-radio": {
            "help": "Which radio to use (options: SX1272,SX1276)",
            "value": "SX1276"
        },
        "main_stack_size":     { "value": 4096 },

        "lora-spi-mosi":       { "value": "NC" },
        "lora-spi-miso":       { "value": "NC" },
        "lora-spi-sclk":       { "value": "NC" },
        "lora-cs":             { "value": "NC" },
        "lora-reset":          { "value": "NC" },
        "lora-dio0":           { "value": "NC" },
        "lora-dio1":           { "value": "NC" },
        "lora-dio2":           { "value": "NC" },
        "lora-dio3":           { "value": "NC" },
        "lora-dio4":           { "value": "NC" },
        "lora-dio5":           { "value": "NC" },
        "lora-rf-switch-ctl1": { "value": "NC" },
        "lora-rf-switch-ctl2": { "value": "NC" },
        "lora-txctl":          { "value": "NC" },
        "lora-rxctl":          { "value": "NC" },
        "lora-ant-switch":     { "value": "NC" },
        "lora-pwr-amp-ctl":    { "value": "NC" },
        "lora-tcxo":           { "value": "NC" }
    },
    "target_overrides": {
        "*": {
            "platform.stdio-convert-newlines": true,
            "mbed-trace.enable": true,
            "platform.stdio-baud-rate": 115200,
            "platform.default-serial-baud-rate": 115200,
            "lora.over-the-air-activation": true,
            "lora.duty-cycle-on": true,
            "lora.phy": "EU868",
            "lora.device-eui": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}",
            "lora.application-eui": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }",
            "lora.application-key": "{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}"

        },

        "NUCLEO_L476RG":{
            "lora-radio":           "SX1272",
            "lora-spi-mosi":       "D11",
            "lora-spi-miso":       "D12",
            "lora-spi-sclk":       "D13",
            "lora-cs":             "D10",
            "lora-reset":          "A0",
            "lora-dio0":           "D2",
            "lora-dio1":           "D3",
            "lora-dio2":           "D4",
            "lora-dio3":           "D5",
            "lora-dio4":           "NC",
            "lora-dio5":           "NC",
            "lora-rf-switch-ctl1": "NC",
            "lora-rf-switch-ctl2": "NC",
            "lora-txctl":          "NC",
            "lora-rxctl":          "NC",
            "lora-ant-switch":     "NC",
            "lora-pwr-amp-ctl":    "NC",
            "lora-tcxo":           "NC"
        },

        "DISCO_L072CZ_LRWAN1": {
            "main_stack_size":      1024,
            "lora-radio":          "SX1276",
            "lora-spi-mosi":       "PA_7",
            "lora-spi-miso":       "PA_6",
            "lora-spi-sclk":       "PB_3",
            "lora-cs":             "PA_15",
            "lora-reset":          "PC_0",
            "lora-dio0":           "PB_4",
            "lora-dio1":           "PB_1",
            "lora-dio2":           "PB_0",
            "lora-dio3":           "PC_13",
            "lora-dio4":           "NC",
            "lora-dio5":           "NC",
            "lora-rf-switch-ctl1": "NC",
            "lora-rf-switch-ctl2": "NC",
            "lora-txctl":          "PC_2",
            "lora-rxctl":          "PA_1",
            "lora-ant-switch":     "NC",
            "lora-pwr-amp-ctl":    "PC_1",
            "lora-tcxo":           "PA_12"
        }
    },
    "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_lora_config.h\""]
}
hasnainvirk commented 5 years ago

@sillystudent96 I doubt that it is DIO4 pin. We are not looking for sync word detect interrupt. Actually we have disabled it. We favoured a single interrupt option on DIO0 which would mark reception only if a given portion of the preamble is received. Are you adding keys run-time ? Can you please check by attaching a debugger that you are getting an RX interrupt ?

hasnainvirk commented 5 years ago

Anyway you are setting DIO4 to NC, which is the correct thing to do.

AnttiKauppila commented 4 years ago

Closed due to inactivity

loloduran commented 4 years ago

Hello @sillystudent96. I need help, I have the same problem like you. I am making a proyect with Lorawan usin LRWAN1 board, but I can not sleep the micro. I do not know if I have to break the ev.queue or what to do with send_message. I am already learning about C++ and all about it.

Thanks a lot

Regimbal commented 4 years ago

Hello everyone, Sorry to say this but it seems you're all wrong (no issue with any pin or debug pin - Mbed takes care of that).! While entering the program the instantaneous consumption is indeed the targeted one. However, consumption increases to 340uA during lorawan.initialize(&ev_queue) Believing the stats, this does not prevent the MCU from going to the Mbed DeepSleep state. But I suspect in this case Deepsleep is no longer the STM32L Stop Mode.

evandavey commented 3 years ago

In addition to seeing ~340uA on VDD_MCU (measuring using JP3), I am also seeing ~1mA on VDD_USB (measuring using JP2) - any ideas what might be causing this?

UPDATE: this is due to TXCO on PA_12. This never seems to go low to disable TXCO power.