Page 1 of 1

ADC support on NUCLEO_H743ZI

Posted: Fri Nov 02, 2018 6:32 am
by Travnicek
I have tried to read adc, but this error is returned: "ValueError: pin A0 does not have ADC capabilities"
I have found missing configuration for ADC in stm32h743_af.csv. Is there some issue related to ADC for NUCLEO_H743ZI or ADC configuration just missing in stm32h743_af.csv?

Re: ADC support on NUCLEO_H743ZI

Posted: Tue Apr 09, 2019 2:32 pm
by Dllanes
Hi,
did you find how to fix this issue?
I am having the same problem
Thanks

Re: ADC support on NUCLEO_H743ZI

Posted: Tue Apr 09, 2019 10:16 pm
by dhylands
Were you trying to use the board pin labelled A0?
Or the CPU pin A0?

Can you post the actual code that used?

And what missing configuration did you find?

I took a look at the pins.csv file for the NUCLEO_H743ZI and it seems to have errors.
https://github.com/micropython/micropyt ... I/pins.csv

It shows that board pin A0 connects to CPU pin A0, but according the user manual for the NUCLEO_H743ZI says that board pin A0 connects to cpu pin A3.
See: https://www.st.com/resource/en/user_man ... 499160.pdf on page 40.

Re: ADC support on NUCLEO_H743ZI

Posted: Wed Apr 10, 2019 10:43 am
by Dllanes
Hi,

thank you for answering.
In fact, I have done the same test in several nucleo boards as the F746ZG with the same results.
I performed the test also with the F767ZI board and only the channels A0,A1,A2, A6 and A7 are working properly. The other ones give out the following error "ValueError: pin XY does not have ADC capabilities".

There are several pins in my design that seem not to be defined in micropython, is there a way to declare these pins to be used?which file should be modified?

I have been using the board pin nomenclature but I also tried with CPU names with same results.
Below can you see, how it is tested.

Code: Select all

from pyb import Pin, ADC
gpio_adc="A0"
adc=pyb.ADC(PIN(gpio_adc))

Re: ADC support on NUCLEO_H743ZI

Posted: Wed Apr 10, 2019 2:28 pm
by dhylands
The way that pins are setup on the STM32 ports is as follows:
1 - In the ports/stm32/boards directory you'll see files which end in _af.csv. The one for the STM32F767 is stm32f767_af.csv This file contains all of the pins that the MCU (STM32F767 in this example) can have, along with all of the alternate functions, and which ADC inputs are tied to which pins.
2 - In the each board directory, you'll see a file called pins.csv which contains a mapping of board pins to MCU pins. This describes the pins which a particular board uses, and will be some subset of the MCU pins. The first field is the board pin name, and the second column is the CPU pin name. These 2 columns will wind up determining what shows up in pyb.Pin.board and pyb.Pin.cpu.

Lets look at board pin A0. In pins.csv it maps to CPU pin PA3, and if we then look in stm32f767_af.csv, for the row containing PA3 (line 6) if scroll way over to the rightmost column (which is the ADC column) we see: ADC123_IN3 which tells us that PA3 is available on ADC1, ADC2, and ADC3 and its on input channel 3.

Now lets look at pin A3 (one of the pins that doesn't work). The pins.csv file says it maps to PF3, and this agrees with the NUCLEO_F767ZI manual. Looking in the stm32f767_af.csv file, the ADC column for PF3 is blank, which is why micropython is reporting that ADC functionality is not supported on that pin. Now let's go check the datasheet: https://www.st.com/resource/en/datashee ... f767zi.pdf Page 67 shows us that PF3 connects to ADC3_IN9

So this tells me that A3 should be available on ADC3 input channel 9, which wasn't recorded in the stm32f767_af.csv file.

However, currently MicroPython only supports a single ADC unit, and on the STM32F767 that would be ADC1. So 2 things need to happen before PF3 can support ADC.
1 - stm32f767_af.csv needs to be corrected
2 - ports/stm32/adc.c needs to be modified to support multiple ADCs.

Re: ADC support on NUCLEO_H743ZI

Posted: Thu Apr 11, 2019 6:56 am
by Dllanes
Hi Dave,

Thanks for your response :) .
dhylands wrote:
Wed Apr 10, 2019 2:28 pm
2 - In the each board directory, you'll see a file called pins.csv which contains a mapping of board pins to MCU pins. This describes the pins which a particular board uses, and will be some subset of the MCU pins. The first field is the board pin name, and the second column is the CPU pin name. These 2 columns will wind up determining what shows up in pyb.Pin.board and pyb.Pin.cpu.
Yeah, I added some pins to .csv and now is working, thanks.
dhylands wrote:
Wed Apr 10, 2019 2:28 pm
Now lets look at pin A3 (one of the pins that doesn't work). The pins.csv file says it maps to PF3, and this agrees with the NUCLEO_F767ZI manual. Looking in the stm32f767_af.csv file, the ADC column for PF3 is blank, which is why micropython is reporting that ADC functionality is not supported on that pin.
I am using 8 April 2019 master commit 74ed06828f4f8d4ec5c04f5b551e90f2fccbd0f3 and in file stm32f767_af.csv the ADC column isn't blank.
Image
dhylands wrote:
Wed Apr 10, 2019 2:28 pm
However, currently MicroPython only supports a single ADC unit, and on the STM32F767 that would be ADC1. So 2 things need to happen before PF3 can support ADC.
1 - stm32f767_af.csv needs to be corrected
2 - ports/stm32/adc.c needs to be modified to support multiple ADCs.
This is not a big issue because I have found this code (https://github.com/micropython/micropython/issues/1681) and it seems to work.

Code: Select all

  from micropython import const
    import stm

    _RCC_APB2ENR_ADC1EN_Pos = const(8)
    _ADC_CR2_ADON_Pos = const(0)
    _ADC_CR2_SWSTART_Pos = const(30)
    _ADC_SR_EOC_Pos = const(1)

    class ADC:
        def __init__(self, adc_block):
            self.adc_block = adc_block
            self.adc = {1: stm.ADC1, 2: stm.ADC2, 3: stm.ADC3}[adc_block]

        def init(self):
            # turn on CLK
            stm.mem32[stm.RCC + stm.RCC_APB2ENR] |= 1 << (_RCC_APB2ENR_ADC1EN_Pos + self.adc_block - 1)

            # reset ADC state
            stm.mem32[self.adc + stm.ADC_CR1] = 0
            stm.mem32[self.adc + stm.ADC_CR2] = 0

            # turn on ADC
            stm.mem32[self.adc + stm.ADC_CR2] |= 1 << _ADC_CR2_ADON_Pos

        def deinit(self):
            # turn off ADC
            stm.mem32[self.adc + stm.ADC_CR2] = 0

            # turn off CLK
            stm.mem32[stm.RCC + stm.RCC_APB2ENR] &= ~(1 << (_RCC_APB2ENR_ADC1EN_Pos + self.adc_block - 1))

        def read_channel(self, channel, sample_time=1):
            # select channel
            stm.mem32[self.adc + stm.ADC_SQR1] = 0
            stm.mem32[self.adc + stm.ADC_SQR2] = 0
            stm.mem32[self.adc + stm.ADC_SQR3] = channel

            # select sample time
            if channel <= 9:
                ch_pos = 3 * channel
                reg = stm.ADC_SMPR2
            else:
                ch_pos = 3 * (channel - 10)
                reg = stm.ADC_SMPR1
            reg += self.adc
            stm.mem32[reg] = (stm.mem32[reg] & ~(7 << ch_pos)) | sample_time << ch_pos

            # start conversion
            stm.mem32[self.adc + stm.ADC_CR2] |= 1 << _ADC_CR2_SWSTART_Pos

            # wait for end of conversion
            while not stm.mem32[self.adc + stm.ADC_SR] & (1 << _ADC_SR_EOC_Pos):
                pass

            # read and return value
            return stm.mem32[self.adc + stm.ADC_DR]