← index #12048Issue #15687
Off-topic · high · value 0.868
QUERY · ISSUE

STM32H5 machine.ADC core temperature sensor not working

openby renestraubopened 2023-07-20updated 2023-10-23
bugport-stm32

Description

While testing with an STM32H5 Nucleo board I noticed the internal ADC channels are not working as expected. External (I/O) pins return expected values. Internal ADC input are not reporting reasonable values.

I understand the STM32H5 port is under work and some features not working. I hope my input helps to fix a problem. Let me know if I can help with more testing.

Problem description:

  • ADC(ADC.CORE_TEMP) returns incorrect values.
>>> from machine import ADC
>>> coretemp=ADC(ADC.CORE_TEMP)

Expected result:

  • Values should lie around 30°C calibration point, or slightly higher.
>>> from machine import mem16
>>> mem16[0x08FFF814]
760
>>> mem16[0x08FFF818]
1014

Observed result:

  • ADC value incorrect, indicates wrong core temperature
  • Value is far below 30°C calibration point
>>> coretemp.read_u16() >> 4
173

See detailed log below.

The issue could be in machine_adc.c, adc_config_channel(). ADC object shows channel is an encoded number containing additional information besides the ADC channel number. For ADC.CORE_TEMP channel is 0xc3210000. Using this channel number value leads to incorrect loading of the SMPR register.

Note: The same kind of problem will be present for ADC.CORE_VREF, ADC.CORE_VBAT.

>>> coretemp=ADC(ADC.CORE_TEMP)
>>> coretemp
<ADC1 channel=3273719808>
>>> hex(3273719808)
'0xc3210000'

For G4 cores the channel number is extracted via __LL_ADC_CHANNEL_TO_DECIMAL_NB. Maybe this is required for H5 cores as well.

STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t sample_time) {
    [removed]

    #if defined(STM32G4)
    channel = __LL_ADC_CHANNEL_TO_DECIMAL_NB(channel);
    adc->DIFSEL &= ~(1 << channel); // Set channel to Single-ended.
    #endif
    adc->SQR1 = (channel & 0x1f) << ADC_SQR1_SQ1_Pos | (1 - 1) << ADC_SQR1_L_Pos;
    __IO uint32_t *smpr;
    if (channel <= 9) {
        smpr = &adc->SMPR1;
    } else {
        smpr = &adc->SMPR2;
        channel -= 10;
    }
    *smpr = (*smpr & ~(7 << (channel * 3))) | sample_time << (channel * 3); // select sample time

    #endif
}

Version Information

% git lg1
* 7d66ae603 - (9 days ago) esp32/machine_timer: Switch from legacy driver to timer HAL. - Damien George (HEAD -> master, origin/master, origin/HEAD)
* 671b35cea - (2 weeks ago) py/builtinimport: Fix built-in imports when external import is disabled. - Jim Mussared
* 606ec9bfb - (9 weeks ago) py/compile: Fix async for's stack handling of iterator expression. - Damien George

MicroPython v1.20.0-282-g671b35cea-dirty on 2023-07-14; STM32H573I-DK with STM32H573IIK3Q
Type "help()" for more information.

Log

>>> from machine import ADC

### Working external inputs, PF12 taken as example
>>> adcext=ADC(machine.Pin('F12'))
>>> adcext
<ADC1 channel=6>

# Tied to 3.3 V
>>> adcext.read_u16()
65471
>>> adcext.read_u16()
65519
>>> adcext.read_u16()
65503
>>> adcext.read_u16()
65519

# Tied to GND
>>> adcext.read_u16()
48
>>> adcext.read_u16()
0
>>> adcext.read_u16()
16

### Test with core temperature

>>> coretemp=ADC(ADC.CORE_TEMP)
>>> coretemp
<ADC1 channel=3273719808>
>>> hex(3273719808)
'0xc3210000'

# Check low (30°C) and high (130°C) calibration points
>>> from machine import mem16
>>> mem16[0x08FFF814]
760
>>> mem16[0x08FFF818]
1014

# Read sensor, should be between two calibration points, actually close to 30° value
# Right align 12 bit ADC value

>>> coretemp.read_u16() >> 4
173
>>> coretemp.read_u16() >> 4
176
>>> coretemp.read_u16() >> 4
178
>>> coretemp.read_u16() >> 4

# Computes to a core temperature of -199 °C...

>>> (178-760)/((1014-760)/(130-30))+30
-199.1339
CANDIDATE · ISSUE

PICO2 internal temperature sensor not accessible at ADC(4)

closedby CGsamaopened 2024-08-21updated 2025-03-03
bug

Port, board and/or hardware

PICO2

MicroPython version

RPI_PICO2-20240809-v1.24.0-preview.201.g269a0e0e1

Reproduction

from machine import ADC
temp_sensor = ADC(4)

Expected behaviour

able to read ADC

Observed behaviour

ValueError: Pin doesn't have ADC capabilities

Additional Information

adc channel defined at https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf section 12.4.6.
tried both 4 and 8 no luck

Code of Conduct

Yes, I agree

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied