Can't get ADC MUX to work

Hi,

I’m having trouble initializing a MUX on an ADC channel. I’m using a 4051 with 8 pots, output connected to ADC10 on the Seed, and mux select pins 0, 1 and 2 connected to daisy pins 14, 13 and 12 respectively.

I’m trying to initialize 8 single ADC channels and 1 MUX channel with the following:

//ADC
AdcChannelConfig adc[9];

//CV inputs
adc[0].InitSingle(hw.GetPin(15));
adc[1].InitSingle(hw.GetPin(16));
adc[2].InitSingle(hw.GetPin(17));
adc[3].InitSingle(hw.GetPin(18));
adc[4].InitSingle(hw.GetPin(19));
adc[5].InitSingle(hw.GetPin(20));
adc[6].InitSingle(hw.GetPin(21));
adc[7].InitSingle(hw.GetPin(22));

//Pots on mux
adc[8].InitMux(hw.GetPin(25),8,hw.GetPin(14),hw.GetPin(13),hw.GetPin(12));

hw.adc.Init(adc, 9);
hw.adc.Start();

And I’m attempting to get floats from the MUX inputs using the following (for the first MUX channel):

PotValue = hw.adc.GetMuxFloat(8,0);

This however results in none of the ADC channels working at all. When the .InitMux line is commented out the rest work fine. Any idea what I’m doing wrong? I’m totally stumped.

Thanks in advance!

1 Like

Have you looked at diaisy_field.cpp ?

When you say “This however results in none of the ADC channels working at all.” - what are they doing-what results are you getting?

Static seemingly random values between 0 and 1:

Screen Shot 2021-02-13 at 7.08.52 PM

Yeah I tried to set it up pretty much the same as in daisy_field.cpp - only difference is I have 9 ADC channels in total on the same AdcChannelConfig (the last one the MUX of 8 pots) whereas the field has 5.

OK so I’ve got it working when the total number of ADC channels is 8 or less. So 7 normal ADC channels and 1 MUX. It’s funny because DSY_ADC_MAX_CHANNELS is defined as 14 in adc.cpp.

Hi Adam,

Maybe a bit late in the discussion, but here I’ve made one circuit with 8 pots on a multiplexer on one ADC channel, and another pot on another ADC channel, so 9 pots in total, and apart from some crosstalk between the 8 pots because of the multiplexer, the circuit is behaving as expected.

As I understand it in the daisy code, DSY_ADC_MAX_CHANNELS is the total number of ADC channels, but so it shouldn’t impact the total number of pots.

I don’t see what would be wrong in your setup code, I have somehow the same code. I was going to soon make an experiment with 8 CVs, 2 * 8 Pots using 2 multiplexer sharing the same address line, so I’ll be able to report “soon” (I’m waiting for alternative 4051 ICs with less RON between channels to measure the impact)

Did you try instead to deactivate some of your CVs and see if it had any impact?

For reference below the circuit I was evaluating on that subject:

Thanks,

Raphael

1 Like

Hi Raphael,

Yes so deactivating one CV channel made it work, so that gives me 8 pots on the MUX and 7 CV inputs. Not sure why this would be, but for now that’s all I need. If I ever need more I think I’ll also try using 2 MUX chips.

I haven’t noticed any cross talk however, but I haven’t been monitoring it closely. I have LPFs on all the sensitive controls (like delay time). How much are you getting? Perhaps that is to do with your breadboard setup? My design is on a PCB, with ground planes.

Cheers!

Adam

Hi Adam,

I will need to measure it, and for this to hame some sort of UART or even a debugger.

Your screenshot upper suggest you are using a debugger right?

Yes, I’m using an ST-Link with VS Code, works quite nicely

I am seeing the same issue. If I configure 9 channels of normal adc channels (no mux) the issue goes away.

I tried stepping through in the debugger and I got really confused :upside_down_face: But I did find that HAL_ADC_ConvCpltCallback() does not appear to get called? I’m still reading through code and docs trying to understand how this all is hooked up…

1 Like

I did some more digging. When stepping through HAL_DMA_IRQHandler() I noticed that the branch corresponding to a complete dma transfer (?) doesn’t execute.

This means the conversion complete callback doesn’t get called, which means DMA is not restarted?

I am a little out of my element so I have just been comparing the code path to what happens if I have fewer than 9 ADC channels configured (including one 8-channel mux). In the latter case, both the “half transfer complete” and “transfer complete” branches seem to be executed. Not sure if that is helpful…

@shensley I noticed your name on some of the adc.cpp commits :sweat_smile: if the problem isn’t immediately obvious to you here I am happy to keep digging but I might need some pointers on docs or something I can read to better understand how the ADC peripheral (and DMA) works.

1 Like

Hi @formsie and welcome to the forum!

If you could share the AdcConfig that you’re doing to set up your channels that might help me find out what’s not working correctly.

When not using the Mux, the DMA is configured in Circular mode, and both the HAL_ADC_ConvCplt and HAL_ADC_ConvHalfCplt will fire, but are unimplemented currently. The data just fills the buffer, and can be filtered externally (using the AnalogControl class, etc.

When using the Mux, the DMA is configured in Normal mode, which will not call the HalfCplt callback, but should still end up calling the Cplt callback. During this, the internal callback will receive the data, update the GPIO for the mux, and then restart the DMA.

I have code that uses multiple single ADC channels, and one channel as a Mux on several boards (including the DaisyField).

So I can confirm that the callbacks do fire with those configurations(usually 4-6 single ADCs and one mux input with 8 channels), but your specific use case might have something that’s unique causing it to misbehave.

Thanks shensley!

Here is my stripped down program: example daisy seed program for adc mux bug · GitHub

I have seed.StartAudio() commented out so that my breakpoints in the DMA code were only stopping for the ADC and not the DAC. The problem exists either way. I think this is functionally the same as @adam_f 's config.

When I configure only 7 single ADCs and 1 mux (8 total ADC channels) the callbacks fire, but adding one more single ADC causes them to stop (9+ total channels).

@shensley I’ve confirmed that the HalfCplt callback is always called when using a mux, but the full Cplt callback is only called when the total number of ADC channels is <= 8. I did so by stepping through with gdb and by implementing a dummy HalfCplt callback.

I see in this PR that the code was actually changed from using the HalfCplt to the Cplt callback. Do you know why that is? I can’t quite figure it out.