Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RAK3172 ADC pins don't work when deep sleep is enabled #15391

Open
goshawk22 opened this issue Mar 13, 2023 · 5 comments
Open

RAK3172 ADC pins don't work when deep sleep is enabled #15391

goshawk22 opened this issue Mar 13, 2023 · 5 comments

Comments

@goshawk22
Copy link

goshawk22 commented Mar 13, 2023

Description of defect

ADC pins on the RAK3172 stops working correctly after deep sleep.
Using the below code to measure the voltage:

#include "mbed.h"
AnalogIn voltage(PB_3);

int main()
{
    //sleep_manager_lock_deep_sleep();
    while (true) {
        float raw_adc;
        float calc_voltage;
        raw_adc = voltage.read();
        calc_voltage = ((3.3f*raw_adc*(5.0f))/(3.0f))*(1.3f);
        printf("\r\nRaw ADC: %f\r\n", raw_adc);
        printf("\r\n Calc Voltage: %f\r\n", calc_voltage);
        ThisThread::sleep_for(5s);
    }
}

When deep sleep is locked, the code works correctly and consistently reports around 3.3v as expected.
When deep sleep is unlocked, it reports around 2.77v the first time and then seems to hang, not reporting anything else.

Target(s) affected by this defect ?

RAK3172 (STM32WL)

Toolchain(s) (name and version) displaying this defect ?

What version of Mbed-os are you using (tag or sha) ?

mbed-os-6.17.0

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

mbed studio 1.4.4

How is this defect reproduced ?

Use the above code on a RAK3172 with the adc pin connected to a voltage divider. Build in develop or release mode to enable deep sleep.

@mbedmain
Copy link

@goshawk22 thank you for raising this issue.Please take a look at the following comments:

Could you add some more detail to the description? A good description should be at least 25 words.
What toolchain(s) are you using?
What Mbed OS version are you using?
How can we reproduce your issue?

NOTE: If there are fields which are not applicable then please just add 'n/a' or 'None'. This indicates to us that at least all the fields have been considered.
Please update the issue header with the missing information.

@goshawk22
Copy link
Author

The apparent hang after the first reading seems to have been caused by #15331. After fixing this, when deep sleep is enabled, analogin reports near zero values around 0.09.

@jeromecoutant
Copy link
Collaborator

From STM32WL ref manual, seems that ADC configuration is not retained with Stop2 (deep sleep) power mode.
So idea could be:

@goshawk22
Copy link
Author

With regards to point 1 and 2, if I put AnalogIn voltage(PB_3) inside a function so that it is called each time I want to read the adc pin, I get wrong values. It returns roughly 2.7 instead of the expected 3.3.

@hallard
Copy link
Contributor

hallard commented Apr 5, 2023

@goshawk22 interesting answer from @jeromecoutant to rewrite hal_deepsleep() for this one (and also for the serial) but I'm far from ST HAL guru, so if anyone have an example on how to reset 115200 on serial console after deep sleep, I take it.
Anyway I don't have the ADC issue mentioned here.

What I'm doing after deep sleep is to call read_sensors() this as follow

bool read_sensors() 
{
  vdda = get_vdda();
  vbat = get_vbat();
  info("Vdda %dmV  Vbat %dmV  ", vdda, vbat);
}

and functions used are

// Defined globally
DigitalOut baten(BAT_EN, 0); // Digital Pin to enable R divider to read battery voltage
AnalogIn adc_vbat(BAT_MON);
uint16_t vdda = 0; // VDD Average in mV (calculated by internal ADC)
uint16_t vbat = 0; // Vbat in mV calculated with Resistor Divider

uint16_t get_vdd() 
{
  uint16_t vref_cal = *((const uint16_t*)VREFINT_CAL_ADDR);
  return ((float)VREFINT_CAL_VREF * vref_cal / (AnalogIn(ADC_VREF).read() * 4095.0));
}

uint16_t get_vdda() 
{
  uint32_t sum = 0;
  // Average 8 measures
  for (int i=0; i<8 ; i++) {
    sum += get_vdd();
  }
  vdda = sum >> 3 ;
  return vdda;
}

uint16_t get_vbat()
{
  float sum = 0;
  baten = 1; // Enable reading analog R/R divider
  adc_vbat.set_reference_voltage((float) vdda / 1000.0f);
  ThisThread::sleep_for(5ms); // voltage to settle
  // Average 8 measures
  for (int i=0; i<8 ; i++) {
    sum += adc_vbat.read_voltage() * 1.27 * 1000.0;
  }
  vbat = (uint16_t) (sum / 8.0f) ;
  baten = 0; // Disable reading analog R/R divider (save R/R power)
  return vbat;
}

vishwamartur added a commit to vishwamartur/mbed-os that referenced this issue Nov 2, 2024
Related to ARMmbed#15391

Fix ADC pins on RAK3172 to work correctly after deep sleep is enabled.

* Add code to save and restore ADC registers in `hal_deepsleep` function in `targets/TARGET_STM/sleep.c`.
* Add code to disable deep sleep when ADC is configured in `analogin_init` function in `targets/TARGET_STM/TARGET_STM32WL/analogin_device.c`.
* Add code to enable ADC only when a measurement is needed in `adc_read` function in `targets/TARGET_STM/TARGET_STM32WL/analogin_device.c`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants