Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

How do i read multiplexed ADC Channels? #438

Closed
PaulReichhold opened this issue Jul 22, 2020 · 3 comments
Closed

How do i read multiplexed ADC Channels? #438

PaulReichhold opened this issue Jul 22, 2020 · 3 comments

Comments

@PaulReichhold
Copy link

PaulReichhold commented Jul 22, 2020

I am currently struggling to read all 4 main Channel from multiple ADC. I use a custom board file for a STM32F303CBT6 and more or less every thing works fine till I try to read the Multiplexed GPIOs on the ADCs. There are some problems that i am struggling with, one of them being that there is no example, where multiple channels are read. So I am not sure if I do it correctly and if that what I do is supposed to work with multiple channels.

One attempt that looked promising but failed.
Somehow the Stm crashes when i set the Interrupt for the second ADC Adc2::enableInterrupt(Adc2::Interrupt::EndOfRegularConversion);

uint16_t analog_adc_1[4];
uint16_t analog_adc_2[4];

uint8_t adc_1=0;
uint8_t adc_2=0;

int main() {

    Usart1::connect<GpioOutputA9::Tx>();
    Usart1::initialize<Board::SystemClock, 115200_Bd>();

    Board::initialize();
    Adc1::initialize(Adc1::ClockMode::Asynchronous, Adc1::Prescaler::Div2, Adc1::CalibrationMode::SingleEndedInputsMode, true);
    Adc1::enableInterruptVector(5);
    Adc1::enableInterrupt(Adc1::Interrupt::EndOfRegularConversion);
    Adc1::connect<GpioInputA0::In1,GpioInputA1::In2,GpioInputA2::In3,GpioInputA3::In4>();
    Adc1::setPinChannel<GpioInputA0>(Adc1::SampleTime::Cycles2);
    Adc1::startConversion();
    modm::delay_ms(10);

    Adc2::initialize(Adc2::ClockMode::Asynchronous, Adc2::Prescaler::Div2, Adc2::CalibrationMode::SingleEndedInputsMode, true);
    Adc2::enableInterruptVector(6);
    Adc2::enableInterrupt(Adc2::Interrupt::EndOfRegularConversion);
    Adc2::connect<GpioInputA4::In1,GpioInputA5::In2,GpioInputA6::In3,GpioInputA7::In4>();
    Adc2::setPinChannel<GpioInputA4>(Adc2::SampleTime::Cycles2);
    Adc2::startConversion();
    Board::LedUser::reset();
    modm::delay_ms(10);
    while(true){
        Board::LedUser::toggle();
        switch(adc_1){
            case 0:
                Adc1::setChannel(Adc1::Channel::Channel1);
                Adc1::startConversion();
                break;
            case 1:
                Adc1::setChannel(Adc1::Channel::Channel2);
                Adc1::startConversion();
                break;
            case 2:
                Adc1::setChannel(Adc1::Channel::Channel3);
                Adc1::startConversion();
                break;
            case 3:
                Adc1::setChannel(Adc1::Channel::Channel4);
                Adc1::startConversion();
                break;
        }
        switch(adc_2){
            case 0:
                Adc2::setChannel(Adc2::Channel::Channel1);
                Adc2::startConversion();
                break;
            case 1:
                Adc2::setChannel(Adc2::Channel::Channel2);
                Adc2::startConversion();
                break;
            case 2:
                Adc2::setChannel(Adc2::Channel::Channel3);
                Adc2::startConversion();
                break;
            case 3:
                Adc2::setChannel(Adc2::Channel::Channel4);
                Adc2::startConversion();
                break;
        }
        MODM_LOG_INFO << adc_1 << ": ADC_1 = " << analog_adc_1[adc_1] << modm::endl;
        MODM_LOG_INFO << adc_2 << ": ADC_2 = " << analog_adc_2[adc_2] << modm::endl;
        modm::delay_ms(1000);
    };
    return 0;
}

MODM_ISR(ADC1){
    if(Adc1::getInterruptFlags() & Adc1::InterruptFlag::EndOfRegularConversion){
        Adc1::acknowledgeInterruptFlag(Adc1::InterruptFlag::EndOfRegularConversion);
        analog_adc_1[adc_1] = Adc1::getValue();
        adc_1++;
        if(adc_1 > 3){
            adc_1 = 0;
        }
    }
}
MODM_ISR(ADC2){
    if(Adc2::getInterruptFlags() & Adc2::InterruptFlag::EndOfRegularConversion){
        Adc2::acknowledgeInterruptFlag(Adc2::InterruptFlag::EndOfRegularConversion);
        analog_adc_2[adc_2] = Adc2::getValue();
        adc_2++;
        if(adc_2 > 3){
            adc_2 = 0;
        }
    }
}
@salkinium
Copy link
Member

I believe @rleh has more knowledge of the ADC and perhaps this particular issue.

@salkinium
Copy link
Member

Sorry for the long wait, I was busy with work/uni.

As far as I can see, the F303CB only has a shared interrupt ADC1_2.
The ADC API is wrong to allow you to set separate interrupt, they will overwrite each other. See issue #409.

Try this:

MODM_ISR(ADC1_2)
{
    if(Adc1::getInterruptFlags() & Adc1::InterruptFlag::EndOfRegularConversion){
        Adc1::acknowledgeInterruptFlag(Adc1::InterruptFlag::EndOfRegularConversion);
        analog_adc_1[adc_1] = Adc1::getValue();
        adc_1++;
        if(adc_1 > 3){
            adc_1 = 0;
        }
    }
    if(Adc2::getInterruptFlags() & Adc2::InterruptFlag::EndOfRegularConversion){
        Adc2::acknowledgeInterruptFlag(Adc2::InterruptFlag::EndOfRegularConversion);
        analog_adc_2[adc_2] = Adc2::getValue();
        adc_2++;
        if(adc_2 > 3){
            adc_2 = 0;
        }
    }
}

The STM32 may crash or restart if an interrupt is not hooked correctly. It's unfortunate that there isn't a warning about providing the wrong handler. I'll try to see what I can do (it's difficult since this would need to happen at link time).

I strongly recommend overwriting the modm_abandon function, which will tell you about a lot of failures, especially in debug profile.
You can adapt the modm_abandon function from the modm BSP files.

@rleh
Copy link
Member

rleh commented Jul 27, 2020

I believe @rleh has more knowledge of the ADC and perhaps this particular issue.

Sorry for the delay. I was busy studying for my exams, and now I have a lot of unread github notifications.

The STM32F303 series have the same ADC IP as the STM32G4 series, which I started adding modm support for. Maybe I have broken the STM32F303 ADC driver while adding STM32G4 support in 1ab7834 (#287)?
Could you check-out a modm version before 1ab7834 and check the problem?

While testing the STM32G4 ADC driver from #324 on real hardware, I encountered unexpected problems that I have not yet investigated in detail.

See also #409 and #324.

@modm-io modm-io locked and limited conversation to collaborators Sep 29, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Development

No branches or pull requests

3 participants