cancel
Showing results for 
Search instead for 
Did you mean: 

PWM1 and TIM2 config for dual ADC

antoine
Associate II
Posted on July 27, 2016 at 15:06

Hi,

I have a code, kindly provided by clive1, to use two ADC in dual mode on STM32F334, and it works well. I can modify some parameters, but something (the ADC itself, the DMA to fill the memory array, or just the loop for printf the values?) begins to stutter when I try to obtain more samples for a higher frequency input signal. I'm quite ok with most of the code, but the timer config function bothers me. Here it is:

void
TIM_Configuration(
void
)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 50) - 1; 
// 50 Hz Sample Rate
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Mode configuration: Channel2 & 3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 10; 
// Some arbitary width
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
}

First, the TIM_Period parameter. I have configured a DAC before, and for it, I divided SystemCoreClock by NumberOfSamples time DesiredFrequency, so I can see a certain logic there.

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock/ (32 * 100000)) - 1;

But a sampling frequency for an ADC is supposed to be way higher than the frequency of the input signal. From that, how is it possible to have 50 Hz as sample rate? (I changed it to 300 max but there I faced the stutter mentioned before) My second question is about the purpose of PWM1 here. It is supposed to configure an output signal linked to the TIM2 timer, but 1) there's no pin connected to it and 2) I don't need it since the signals I study are input, but when I comment the part about PWM1 the ADC don't work anymore (data and common data registers stay empty). How is it possible?
8 REPLIES 8
Posted on July 27, 2016 at 15:55

3.2 MHz is too high to interrupt or printf at, even with decimation with a larger buffer you don't want to be interrupting more than a few 100KHz. Serial ports are SLOW

The ADC can use upto 16 trigger sources, these are usually from internal circuit nodes, so don't need to reach pins, but the sources must be functioning.

Pulse is going to need to be more than ZERO, and no greater than Period, otherwise no triggering event. You could perhaps use the TIM Update as a trigger source if that's documented to exist. Review the table listing the trigger sources in the RM.

There are a number of TIM modes that would work, outputting to a pin would allow you to understand where the ADC is sampling, debug and control phase, etc.

Yes, Nyquist defines that you want a sample rate at least 2x so it doesn't alias, or rotate backward. I picked 50 Hz for demonstration, if i decimate that is is well within the visible rate the eye can perceive, I'd hazard that 300 KHz would be a tad harder. Pick something that works for your requirements, not mine.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
antoine
Associate II
Posted on July 27, 2016 at 17:12

Ok, so, when we talk about rising edge for triggering, it's the rising edge of the PWM, and the TIM2 period determined when the rising edge happens, if I understand correctly.

Nice.

The thing is, I test values for TIM_Period, but I don't know what they mean. I mean, can you explain the logic? 

At first there was 50, which was apparently for 50 Hz.

I change 50 to 300, and you talk about 300 kHz? Or is it really 300 Hz?

The problem is that I couldn't find on the internet or in the RM or datasheet a formula or anything that could help me to know what value I must write to obtain the sample rate I want.  As I said, I fail to see the logic.

Let me illustrate.

The ADC receive each a signal with the same frequency and the same amplitude.

The input sine has a frequency of 30 kHz (I want to go up to 160 kHz, but let's stick with 30 khz for now).

I have some nice curves on Excel from the printf, so the sampling seems to have been well.

How is it possible, if the sample rate is at 50 Hz? 

A sample rate of 50 Hz should be waaaaay too low to perform a correct sampling of a 30 kHz signal, shouldn't it? How come the resulting graph is not bad at all?

Do you see what I mean?

PS: the single line of code was an illustration of the ''formula'' I was talking about, I used it for the DAC not for the ADC, sorry if it confused you.

Posted on July 27, 2016 at 18:51

Let's be clear, the 50 Hz is MY FREQUENCY, I picked it for my purposes, and is unrelated to what YOU are doing.

Here you are computing ticks of the TIMCLK to create a 3,200,000 Hz (3.2 MHz) frequency. It uses the standard relationship between Frequency and Period.

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock/ (32 * 100000)) - 1;

For a 36 MHz clock there are 36,000,000 ticks in a second, there are 36,000 ticks in 1ms, and 36 ticks in 1us

If I want a 1 MHz clock (1us) from a 36 MHz clock

TIM_TimeBaseStructure.TIM_Period = (36000000 / 1000000) -1;

TIM_TimeBaseStructure.TIM_Period = 36 -1; // ie 36 states, 0 thru 35

Where TIMCLK = SystemCoreClock

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 50) - 1; // 50 Hz

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 1000) - 1; // 1 KHz (1000 Hz)

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / 60000) - 1; // 60 KHz (60000 Hz)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 27, 2016 at 19:06

Where did the 50 Hz come from? It came as a results of a question that didn't provide any context with respect to frequency. [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Two%20ADC%20working%20on%20two%20signals%20at%20the%20same%20time&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx?Paged%3DTRUE%26p_StickyPost%3D%26p_DiscussionLastUpdated%3D20160725%252015%253a47%253a32%26p_ID%3D68316%26View%3D%257bF47A9ED8%252dE726%252d42BE%252dACED%252d732F13B66581%257d%26FolderCTID%3D0x012001%26PageFirstRow%3D41&currentviews=61]Here

''Two ADC working on two signals at the same time

Hi,

I want to read two signals (supposedly quite similar) at the same time, in order to compare them. I have one ADC working, but I'm perplex about the other.

- Does it matter if I use for the second signal, say ADC1_IN2, or ADC12_IN9, or ADC2_IN5, knowing that the first signal is using ADC12_IN7 ? Based on the configuration I'm tempted to prefer ADC2, but I'd like to know why.

-Let's say I configure my second ADC just like the first one. How am I going to make them work simultaneously (or alternatively) when ADC_StartConversion(ADC1) owns the running until the end of conversion?

Since the signals are supposed to vary over time, they need to be converted at the same time, in order to compare sig1t with sig2t and sig1t+1 with sig2t+1, and avoid sig1t+1 with sig2t.

Also, I have at this moment ADC_StartConversion(ADC1) right before while(1) in the main function. If I want the signal to be kept updated, should I move it into the while loop?''

The chronology is that you asked that question, I provided an example with a 50 Hz sample rate and a 5 Hz LED toggle, that one could perceive with the human eye as being functional, and then you started talking about 170 KHz after the fact.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
antoine
Associate II
Posted on August 02, 2016 at 18:24

Hi Clive, sorry for the delay, I've been trying to re-state my question.

First, let's pretty much forget all of the previous things, particularly the several values of any kind that could have been involved. It's confusing for both of us. No more 50 Hz, no more 30 kHz or whatever. Fresh start. Ok. So. In the ADC configuration, I have to establish the sample time with this line:

ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_7Cycles5);

Based on the PLL, the ADC clock cycle is 72 MHz. The Reference Manual says that, for a sample time of 7.5 cycles, the total conversion time Tconv = 5 + 7.5 = 20 ADC clock cycles = 0.27 µs.

What I understand from this:

The sample rate is either 1/(0.27*10^-6) = 3.6 MHz (This would mean SampleRate = 1 / ConversionTime), or 1 / (7.5/72000000) = 9.6 MHz (This would mean SampleRate = 1 / SampleTime, with SampleTime = 7.5 Cycles). The second solution appears more logical to me, but the result of 9.6 MHz feels quite high to me...

Is any of these two possibilities correct?

Now, second thing. Please clear your mind from previous posts. If the Sample Time mentioned before leads to actually choose the Sample Rate,

what is the purpose of TIM2 and does it act?

Let me develop (hoping I'm not confusing you). I have this line in TIM_Config():

TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / ValFreq) - 1;

I made several test, varying only ValFreq, to figure out how it does work. I input two identical signals, of frequency 170 kHz. The phase is 90°. Keeping the same input, I change ValFreq, and I note each time the number of samples I obtain in a single period (number of samples between one top and the very next one). During the process, the frequency of the input signals (170 kHz), and the Sample Time mentioned before (7.5 ADC cycles) remain constant. Those are the results I gathered:

If ValFreq is actually the sample rate, why do I have such erratic number of samples when I vary ValFreq?

If ValFreq is actually the sample rate, what is the purpose of SampleTime mentioned before?

</colgroup>

ValFreq Nb Samples

200 72

250 91

300 3

350 4

370 3

380 2

390 10

400 146

500 184

550 10

600 3

700 7

750 3

As you can see, there is no apparent logic here, the number of samples doesn't seem proportional to the ValFreq value.So.Second big question, more or less linked with the first one:(isn't logically SampleRate = 1/ SampleTime ?)I have tried to make my point as clear as possible.I hope you will take some time to reconsider the problem, regarding the elements I gave here.Thank you.(PS: when I try higher values for ValFreq, like 1000 for example, I obtain on the graphe kind of random portions of what could be a sine, but it's quite impossible to tell. If you tell me this chaotic display is only because the Trace can't keep up and so can't display all the values, it would be wonderful)
Posted on August 02, 2016 at 20:12

You can use the ADC in one of two ways, triggered or saturation (continuous) mode. You can't trigger a continuous conversion with the timer.

In continuous mode the sample time and the conversion time (8-bit, 12-bit, etc) are in units of the ADCCLK. I'm not using the F3, but 12.5 + 7.5 doesn't sound unreasonable. The choice of these two parameters will constrain the sample rate, ie 20 cycles of ADCCLK.

A simple test would be to sample a known frequency signal, and count the samples describing the period of that signal.

One could also configure the DMA to do 1000 samples, and interrupt with a DMA TC, where you toggle a GPIO that you then scope. ie a 3.2 Msps would yield a 1.6 KHz square wave.

The sample+conversion time does not change in triggered (non-continuous) mode, but the sample rate at which the conversion starts is paced by the timer. This cannot of course exceed the ceiling defined by the saturation of the ADC doing one conversion after the other.

Your table of ValFreq vs Samples doesn't make a whole lot of sense to me, and I don't have the code or the time to commit to it.

The SWD/USART are unlikely to have the bandwidth to support rapid data acquisition.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
antoine
Associate II
Posted on August 03, 2016 at 11:12

Haha don't worry the ValFreq vs Nb Samples array doesn't make much sens to me either, it was the whole point^^

So if I understand, they're not complementary, it's either one or the other: if I don't use continuous mode, but triggered instead, I don't need to specify the Sample Time like I did, the timer configuration is enough, am I right?

''The sample+conversion time does not change in triggered (non-continuous) mode, but the sample rate at which the conversion starts is paced by the timer.''

You seem to imply that sample time and sample rate are not directly linked, can you explicit a bit?

Joke aside, what the array was supposed to show is:

At a sample rate of X, I have Y samples.

I expected, at a sample rate of X+k, a number Y+k (more or less, at least something proportional) of samples.

The array shows that it is not the case.

I could get over it if it was only because of the display, but I fear it's something else.

I mean, [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Trace%20function%20too%20slow%20%28Keil%29&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/AllItems.aspx&currentviews=25]Here it's clearly the display that mess up, because some values are skipped, but in my case the very pattern of the graphe is altered: for each ValFreq, I observe a real pattern, regularity, it just the number of samples that doesn't match my expectations.

Posted on August 03, 2016 at 15:46

Damn this is making my head hurt.

You seem to imply that sample time and sample rate are not directly linked, can you explicit a bit?

Look, the ADC in your configuration is going to take 20 ADCCLK between the time it starts the conversion process, and a sample falls out the back end. This is FIXED by the ADC, and the SAMPLE TIME is how long it charges the SAMPLE/HOLD capacitor before doing the 12-bit conversion, nominally 1-bit per cycle, based on how the ADC works and compares levels at each bit position.

The SAMPLE RATE is how often you START the process, not how long it takes to do the conversion. These can be disconnected, but you clearly can't get to a sample rate that exceeds the throughput of the conversion process.

Your graph shows a constant period break in the data, which a) suggests you don't have an adequate buffer/bandwidth, and b) your sample count probably isn't measuring what it should be.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..