Current consumption deviation

Home Forums mDot/xDot Current consumption deviation

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #13391

    Hi everybody,

    We are already finishing the design of a LORA device using MDOT. As a final check we have tested different values according to datasheet such as current consumption during transmission and deep sleep mode.

    After performing the measurements in our PCB we realize that the consumption is too high: 80 mA during wake up and 70 mA during stand by mode. In order to isolate our design from the MDOT board, we have tested several simple codes such as the sleep mode test example. Test has also been performed over your development board MTUDK2.

    We have connected ground of MDOT to board in appropriate pin, and VCC with a multimeter in series during deep sleep (No other pin connected). In order to guarantee the measurement the period used was 10 s/10 s (Wake Up/Stand By). We also obatin the same results as in our board, this is:80mA/70mA.

    We are working over the last version of firmware and LB P/N is silkscreened on PCB. Could you help us with this? Is this maybe a hardware failure in MDOT? Could you give us exactly the same test setup (including code) used by you during datasheet writing (35 uA) ?

    Fast reply would be really appreciated.

    Thanks in advance,

    #13402

    Hi Alejandro,
    That’s a very high current reading. On the MTUDK2.0 board, you can measure the current draw at JP90. See ‘http://www.multitech.com/manuals/s000612_2_0_7.pdf’ page 52. Look for JP90 in area D3(A-E and 1-4 on edge of schematic). On page 44 of the same document it shows the MTUDK2.0 PCB. Between ‘Serial Disconnect Header’ and ‘J-Link Header’ is where JP90 is and R118 is the little part to the left of JP90. With R118 removed and a current meter connected from the 3.3v pin to the center pin, I measure about 28uA when in sleep mode. I am using the mdot LoRa sleep example on mbed. To simplify the code, I commented out the network join code and had it go straight to sleep after configuration. Have you tried more than one mdot?
    Kind regards,
    Leon

    #18196
    Aitor Gartziandia
    Participant

    Hi,

    I am also measuring the current consumption of a MDOT and it is showing a very strange behaviour.

    I started working with the “Dot_example” program the values I obtained are:

    Configuration: 21 mA
    Transmit join request: 85-90 mA
    Waiting until RX window opens: 24 mA
    RX window 34 mA
    Sleep: 50 uA

    After this, I started making some changes in the program and apparently unsignificant changes increased the consumption of the MDOT a lot.

    Just taking the “Dot_example” program as it is and including this line “PwmOut led(PC_9)” increases the consumption of the MDOT like follows:

    Configuration: 21 mA
    Transmit join request: 95 mA
    Waiting until RX window opens: 34 mA
    RX window 45 mA
    Sleep: 50 uA

    Other changes as (never used) function declarations causes the same issue.

    What may be causing this behaviour? Maybe a hardware problem with my MDOT?

    The measurements are being made connectet to the MTUDK 2.0 board, with the R118 removed.

    Thanks.

    #18201

    Hi Aitor,

    The mDot power draw numbers can be found on page 25 of the developer guide.
    http://www.multitech.com/documents/publications/manuals/s000612.pdf
    Your higher readings align closely with what we measured.

    I am having a difficult time imagining how a single undefined function declaration could affect power draw. Are you building on line or off line? If off line, which compiler?

    Kind regards,
    Leon

    #18217
    Aitor Gartziandia
    Participant

    Hi Leon, thanks for your response.

    I do not understand it either. I am using the mbed online compiler.

    Thank you.

    #18225
    Mike Fiore
    Blocked

    Aitor,

    We need more information.

    Please let us know the following:
    – mbed-os version
    – dot-library version

    Can you provide the source code for the application where you get increased current draw?

    -MIke

    #18234
    Aitor Gartziandia
    Participant

    Hi Mike,

    I have updated the ‘libmDot-mbed5’ (revision 58:b0703fd) and ‘mbed-os’ (revision 2992:42be5c0) libraries. After doing some more tests I think the problem is caused by the pin configuration. I have posted my code below, which is divided in 3 files: main.cpp, dot_util.cpp & dot_util.h.

    The consumption of the mDot with this program is:

    Configuration: 21 mA
    Transmit join request: 72 mA
    Waiting until RX window opens: 23 mA
    RX window 26 mA
    Sleep: 50 uA

    If I uncomment the ‘PwmOut led(PC_9);’ line, just before the main functions starts, the current consumption rises to the following values:

    Configuration: 21 mA
    Transmit join request: 82 mA
    Waiting until RX window opens: 33 mA
    RX window 39 mA
    Sleep: 50 uA

    However, if I remove the configuration of the other 2 pins as AnalogIn pins and the part of the code where I read their values, in the ‘readData()’ function, the consumption rises even more:

    Configuration: 21 mA
    Transmit join request: 86 mA
    Waiting until RX window opens: 35 mA
    RX window 41 mA
    Sleep: 50 uA

    I hope it is enough information so you can make some conclusion about what is happening here. My first thought was that the mDot was “broken” but 2 mDot are showing the same behaviour here…

    Thanks for your help.

    Aitor

    *****main.cpp*****
    #include “dot_util.h”

    static uint8_t network_id[] = { 0x70, 0xB3, 0xD5, 0x7E, 0xF0, 0x00, 0x1F, 0x79 };
    static uint8_t network_key[] = { 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88 };
    static uint8_t frequency_band = 0;
    static bool public_network = true;
    static uint8_t ack = 0;
    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);

    mDot* dot = NULL;

    Serial pc(USBTX, USBRX);

    std::vector<uint8_t> tx_data;

    AnalogIn lightPin(PA_6);
    AnalogIn batteryPin(PC_1);
    uint16_t light;
    uint16_t battery;

    void sendData(){
    tx_data.push_back((battery >> 8) & 0xFF);
    tx_data.push_back(battery & 0xFF);
    tx_data.push_back((light >> 8) & 0xFF);
    tx_data.push_back(light & 0xFF);
    dot->send(tx_data);
    tx_data.clear();
    }
    void readData(){
    int batterInt = (int) floor(0.5+(1000*batteryPin.read()));
    battery = (uint16_t) batterInt;
    int lightInt = (int) floor(0.5+(1000*lightPin.read()));
    light = (uint16_t) lightInt;
    }
    //PwmOut led(PC_9);
    int main()
    {

    pc.baud(115200);

    dot = mDot::getInstance();

    dot->resetConfig();
    dot->resetNetworkSession();

    dot->setJoinMode(mDot::OTA);

    update_ota_config_id_key(network_id, network_key, frequency_band, public_network, ack);

    update_network_link_check_config(3, 5);

    dot->saveConfig();

    while (true) {
    if (!dot->getNetworkJoinStatus()) {
    join_network();
    readData(); }
    sendData();

    sleep_save_io();
    sleep_configure_io();
    dot->sleep(60,mDot::RTC_ALARM,false);
    sleep_restore_io();
    }

    return 0;
    }

    ******dot_util.h*****

    #ifndef __DOT_UTIL_H__
    #define __DOT_UTIL_H__

    #include “mbed.h”
    #include “mDot.h”

    extern mDot* dot;

    void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);

    void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);

    void join_network();

    void sleep_save_io();

    void sleep_configure_io();

    void sleep_restore_io();

    #endif

    *****dot_util.cpp*****

    #include “dot_util.h”

    #if defined(TARGET_MTS_MDOT_F411RE)
    uint32_t portA[6];
    uint32_t portB[6];
    uint32_t portC[6];
    uint32_t portD[6];
    uint32_t portH[6];
    #endif

    void join_network() {
    int32_t j_attempts = 0;
    int32_t ret = mDot::MDOT_ERROR;

    // attempt to join the network
    while (ret != mDot::MDOT_OK) {
    logInfo(“attempt %d to join network”, ++j_attempts);
    ret = dot->joinNetwork();
    if (ret != mDot::MDOT_OK) {
    logError(“failed to join network %d:%s”, ret, mDot::getReturnCodeString(ret).c_str());
    // in some frequency bands we need to wait until another channel is available before transmitting again
    uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
    if (delay_s < 2) {
    logInfo(“waiting %lu s until next free channel”, delay_s);
    wait(delay_s);
    } else {
    logInfo(“sleeping %lu s until next free channel”);
    sleep_save_io();
    sleep_configure_io();
    dot->sleep(delay_s, mDot::RTC_ALARM, false);
    sleep_restore_io();
    }
    }
    }
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }

    void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
    std::vector<uint8_t> current_network_id = dot->getNetworkId();
    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
    bool current_public_network = dot->getPublicNetwork();
    uint8_t current_ack = dot->getAck();

    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);

    if (current_network_id != network_id_vector) {
    logInfo(“changing network ID”);
    if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
    logError(“failed to set network ID”);
    }
    }

    if (current_network_key != network_key_vector) {
    logInfo(“changing network KEY”);
    if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
    logError(“failed to set network KEY”);
    }
    }

    if (current_frequency_sub_band != frequency_sub_band) {
    logInfo(“changing frequency sub band from %u to %u”, current_frequency_sub_band, frequency_sub_band);
    if (dot->setFrequencyBand(frequency_sub_band) != mDot::MDOT_OK) {
    logError(“failed to set frequency sub band to %u”, frequency_sub_band);
    }
    }

    if (current_public_network != public_network) {
    logInfo(“changing public network from %s to %s”, current_public_network ? “on” : “off”, public_network ? “on” : “off”);
    if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
    logError(“failed to set public network to %s”, public_network ? “on” : “off”);
    }
    }

    if (current_ack != ack) {
    logInfo(“changing acks from %u to %u”, current_ack, ack);
    if (dot->setAck(ack) != mDot::MDOT_OK) {
    logError(“failed to set acks to %u”, ack);
    }
    }
    }

    void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
    uint8_t current_link_check_count = dot->getLinkCheckCount();
    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();

    if (current_link_check_count != link_check_count) {
    logInfo(“changing link check count from %u to %u”, current_link_check_count, link_check_count);
    if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
    logError(“failed to set link check count to %u”, link_check_count);
    }
    }

    if (current_link_check_threshold != link_check_threshold) {
    logInfo(“changing link check threshold from %u to %u”, current_link_check_threshold, link_check_threshold);
    if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
    logError(“failed to set link check threshold to %u”, link_check_threshold);
    }
    }
    }

    void sleep_save_io() {

    portA[0] = GPIOA->MODER;
    portA[1] = GPIOA->OTYPER;
    portA[2] = GPIOA->OSPEEDR;
    portA[3] = GPIOA->PUPDR;
    portA[4] = GPIOA->AFR[0];
    portA[5] = GPIOA->AFR[1];

    portB[0] = GPIOB->MODER;
    portB[1] = GPIOB->OTYPER;
    portB[2] = GPIOB->OSPEEDR;
    portB[3] = GPIOB->PUPDR;
    portB[4] = GPIOB->AFR[0];
    portB[5] = GPIOB->AFR[1];

    portC[0] = GPIOC->MODER;
    portC[1] = GPIOC->OTYPER;
    portC[2] = GPIOC->OSPEEDR;
    portC[3] = GPIOC->PUPDR;
    portC[4] = GPIOC->AFR[0];
    portC[5] = GPIOC->AFR[1];

    portD[0] = GPIOD->MODER;
    portD[1] = GPIOD->OTYPER;
    portD[2] = GPIOD->OSPEEDR;
    portD[3] = GPIOD->PUPDR;
    portD[4] = GPIOD->AFR[0];
    portD[5] = GPIOD->AFR[1];

    portH[0] = GPIOH->MODER;
    portH[1] = GPIOH->OTYPER;
    portH[2] = GPIOH->OSPEEDR;
    portH[3] = GPIOH->PUPDR;
    portH[4] = GPIOH->AFR[0];
    portH[5] = GPIOH->AFR[1];
    }

    void sleep_configure_io() {

    /* GPIO Ports Clock Enable */
    __GPIOA_CLK_ENABLE();
    __GPIOB_CLK_ENABLE();
    __GPIOC_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct;

    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10
    | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // PC_9 & PC_13 to analog nopull
    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
    }

    void sleep_restore_io() {

    GPIOA->MODER = portA[0];
    GPIOA->OTYPER = portA[1];
    GPIOA->OSPEEDR = portA[2];
    GPIOA->PUPDR = portA[3];
    GPIOA->AFR[0] = portA[4];
    GPIOA->AFR[1] = portA[5];

    GPIOB->MODER = portB[0];
    GPIOB->OTYPER = portB[1];
    GPIOB->OSPEEDR = portB[2];
    GPIOB->PUPDR = portB[3];
    GPIOB->AFR[0] = portB[4];
    GPIOB->AFR[1] = portB[5];

    GPIOC->MODER = portC[0];
    GPIOC->OTYPER = portC[1];
    GPIOC->OSPEEDR = portC[2];
    GPIOC->PUPDR = portC[3];
    GPIOC->AFR[0] = portC[4];
    GPIOC->AFR[1] = portC[5];

    GPIOD->MODER = portD[0];
    GPIOD->OTYPER = portD[1];
    GPIOD->OSPEEDR = portD[2];
    GPIOD->PUPDR = portD[3];
    GPIOD->AFR[0] = portD[4];
    GPIOD->AFR[1] = portD[5];

    GPIOH->MODER = portH[0];
    GPIOH->OTYPER = portH[1];
    GPIOH->OSPEEDR = portH[2];
    GPIOH->PUPDR = portH[3];
    GPIOH->AFR[0] = portH[4];
    GPIOH->AFR[1] = portH[5];
    }

    #18239

    Hi Aitor,

    When IO pins are programmed as analog inputs they draw the least amount of power. So if you have pins configured as PWM or digital you will see additional power draw. That is why you see all pins being configured as analog during sleep mode… to reach lowest power consumption.

    Kind regards,
    Leon

    #18243
    Aitor Gartziandia
    Participant

    Hi Leon, thanks for your response.

    I get that, but a 10 mA increase is not too much? Besides, in the code I posted 2 pins are configured as analog inputs. If I remove the configuration of these 2 pins, the power consumption rises. But if I configure more pins as analog inputs, the consumption also rises. The lowest power consumption I achieve is when only 2 pins are configured.

    Any idea why this can be happening?

    Aitor

    #18247
    Mike Fiore
    Blocked

    Aitor,

    Some IOs need to be in specific states to minimize current consumption on the Dots. This is based on the HW design and our testing.

    See the function sleep_configure_io() in our Dot-Examples code.

    https://developer.mbed.org/teams/MultiTech/code/Dot-Examples/file/b7da620f9ae3/examples/src/dot_util.cpp

    -Mike

Viewing 10 posts - 1 through 10 (of 10 total)
  • You must be logged in to reply to this topic.