ADC synchronised to Timer0

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

This is my first post, because I'm a bit confused with usage of ADC on the ATMEGA328p. I spent a lot of time reading here and on the datasheet, but it's not clear sorry about this !

So here are my several questions :

With Prescaler timer0 = 8
F_CPU/256/8 = frequency of Timer0 overflow ? Is that true ?

F_CPU/prescaler(ADPS) = ADC_CLOCK ? Is that true ?

In fact, I need to synchronize my ADC readings with my TIMER0, which is mastering a PWM signal. And I'm looking for the best way to do this :

So if I set :
ADCSRB = 0x04;
each time the timer0 overflow, a new ADC reading will begin automatically ? Or should I do something to begin by hand in
ISR(TIMER0_OVF_vect){}
? What is a good practice for that purpose (the faster) ?

And each time the measure ends, the following interrupt will be executed ?
ISR(ADC_vect){}
Or should I read by hand in ISR(TIMER0_OVF_vect){} before to launch a new reading ?

After a new measure begin, I know I have to wait ADC_CLOCK / 13.5 (Conversion time) before to read the ADC register ? And in fact, if I'm sure that the reading is ended between 2 Timer0 overflow, I can read it directly without checking in ISR(TIMER0_OVF_vect){} ?

How can I test the actual measure is done and ready in register if needed ?

It's a long question for sure ! Hope you are patient ! ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is F_CPU?

Personally I'd set the timer (in CTC mode) to your sample rate - if you can't achieve it using 8bit then use 16bit (this would be a huge period though) then set ADSC in the COMP interrupt and catch the readings in a later ADIF interrupt.

Perhaps tell us more about the actual application, what's being sampled and so on?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
So if I set :
ADCSRB = 0x04;
each time the timer0 overflow, a new ADC reading will begin automatically ?
As long as you have the ADATE bit in ADCSRA set, then yes.
Quote:
And each time the measure ends, the following interrupt will be executed ?
ISR(ADC_vect){}
As long as you have the ADC set up to use the ISR, then yes.
Quote:
Or should I read by hand in ISR(TIMER0_OVF_vect){} before to launch a new reading ?
No.
Quote:
After a new measure begin, I know I have to wait ADC_CLOCK / 13.5 (Conversion time) before to read the ADC register ?
If you are using the ISR, it will do the waiting for you.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks both !

In fact I drive a DC Motor with PWM, and my H-bridge has a current proportionnal feedback, that I read with the ADC. So the current increase in an exponentional way for each period of high level of PWM, then decrease exponentialy too (due to inductance).

So for the ADC, I set :
ADCSRB = 0x04; ///// 00000100 : timer0 Overflow
ADCSRA = 0xBF; ///// 10111111
And it works (synchronized to PWM).

But my readings may be corrupted by a wrong timing :

F_CPU is my master clock : 20000000 on Atmega328p.
So my PWM frequency is :
20000000/256/8 = 9765 Hz is that true ?

Then I set
20000000/128 = 156250 Hz (clock_ADC)
156250 / 13.5 = 11574 Hz

This is a problem because my PWM period is superior to my ADC reading time ?

How is working an ADC, is it a mean level of the voltage during the 1/11574 second, or something else ?

I believe it's not a problem if reading is done on the same portion of the PWM duty cycle, even if this one is not complete. But I get strange results...

What do you think about this ?

Thanks again for your answers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
156250 / 13.5 = 11574 Hz
Conversion takes 13 clocks, not 13.5, so the sample frequency would be 12019Hz.
Quote:
This is a problem because my PWM period is superior to my ADC reading time ?
Your timer starts the ADC every 102µs, and the ADC completes in 83µs, so there is no problem.
Quote:
How is working an ADC, is it a mean level of the voltage during the 1/11574 second, or something else ?
No, it is sample and hold (the sample is in the first 1.5 clocks after the start of conversion).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your answers !
If I understand well :
- OVERF : Timer0 overflow
- DELAY_measure = approx 10 µs after (1.5 clock ADC), measurement is done and hold until...
- end of ADC period (83 µs after OVERF)

Is DELAY_measure a reproductive delay or fluctuative between 0 and 1.5 ADC clock ?

Another question : if I change ADC prescaler, will DELAY_measure change ? Where can I find the source in the datasheet (keyword ?), please ?

Furthermore, if 83µs => 255 (PWM max)
10 µs => 24

If my PWM is upper 24, my measurement is taken on the rising part of the intensity : it's a good measure ?

Thanks again

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

if I change ADC prescaler

But why would you ever do that? You said the CPU clock was 20MHz and you are therefore using /128 to get into the 50kHz..200kHz range (156.25kHz in fact). That is the best you can get with a 20MHz clock. So unless you plan to suddenly change crystals why would you ever change the ADC prescaler?

As for the timing - the datasheet is very clear isn't it. Your mysterious 0x04 and 0xBF values in the ADC register are picking to use ADATE with Timer0 overflow. You know that if the ADC clock is 156.25kHz then the period is 6.4us. So when the timer overflows it sets starts a conversion. You know that it completes the sample/hold after 1.5ADC clocks so 1.5*6.4=9.6us after the timer overflow it will be holding the sample and converting. The conversion completes after 13 ADC clocks. So 13*6.4=83.2us after the timer interrupt the ADC reading will be ready, the ADIF will be set and it will enter the ADC interrupt handler where you can collect the reading.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson !

Your wright : 128 is the best prescaler for me, that's why I set to that value.
But when reading to the first values, I'm a bit confused with the results, and that's why I tried to change the prescaler in order to debug the "apparent" problem.

I say apparent because I'm not sure if the values are normal or not. In fact changing prescaler from 128 to 32 just change nothing to the value I read.

Perhaps are you DC motor guru, so here are my strange reading :
I draw the following curves (in steady state, stabilized speed and voltage) :
- Rotation_speed(Voltage) : perfectly linear relation, absolutely normal for sure
- Current_from_ADC(Voltage) or Current_from_ADC(Speed), that's the same, and I get a strange parabolic curves with a maximum at approx 125 PWM, then it decrease to reach the begin Current level...

I'm not sure if it's a normal behavior or not, so I first check my ADC ! Now, with your help, I begin to think it's a normal behavior...

Did you ever work on DC motor current ???

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'm a bit confused with the results, and that's why I tried to change the prescaler in order to debug the "apparent" problem.

Fiddling about with things you don't understand is not a good debug technique! Read the data and if that doesn't help, ask questions here - but don't just change registers at random in the hope of stumbling over a solution.

(you may find that you can "get away" with reducing the prescaler and so running the ADC at above the 200kHz stated value).

And, no, while I have huge experience of USING brushed and brushless motor controllers (in all kinds of model aircraft) I've never bothered building one as you cannot design/build one as cheap as you can buy one these days. I have built brushless motors by gluing magnets and rewinding CD ROM motor cores so I understand all about Delta, Y and 3 phase motor energisation but while I know the voltages are switched in phase by the MOSFETS in the ESC and that rotor positioned is read by induced EMF in the non-energised coils using ADC, that's about as much as I know about ESC design/operation.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Fiddling about with things you don't understand is not a good debug technique! Read the data and if that doesn't help, ask questions here - but don't just change registers at random in the hope of stumbling over a solution.

I believe experimental understanding of unknowed phenomena is the source, Cliff. Especially when AVR datasheet reading still a bit confused for you. And that's my case : I still can't find the 1.5 clock reading information in the datasheet for example.

This modification (if DELAY_measure change by prescaler modification) is a good beginning of proof that there is no timing issue in my readings, and that the observed curve is "normal". This is interesting data too, with the motor inductance rising curve.

There is no random in my approach, you know...

Your understanding of DC motor seams to be advanced, for sure, we may be on the same basis today. I try to reach the best result I can for my needings, and of course there is no matching product on the market that match my needings today, that's why I work on that.

Thanks for your answer

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I still can't find the 1.5 clock reading information in the datasheet for example.

Eh? In my copy of the 48/88/168/328P datasheet I just went to the ADC chapter, pressed Ctrl-F and entered "1.5" and it said:
Quote:
A normal conversion takes 13 ADC clock cycles. The first conversion after the ADC is switched on (ADEN in ADCSRA is set) takes 25 ADC clock cycles in order to initialize the analog circuitry.

When the bandgap reference voltage is used as input to the ADC, it will take a certain time for the voltage to stabilize. If not stabilized, the first value read after the first conversion may be wrong.

The actual sample-and-hold takes place 1.5 ADC clock cycles after the start of a normal conversion and 13.5 ADC clock cycles after the start of an first conversion. When a conversion is complete, the result is written to the ADC Data registers, and ADIF is set. In Single Conversion mode, ADSC is cleared simultaneously. The software may then set ADSC again, and a new conversion will be initiated on the first rising ADC clock edge.

When Auto Triggering is used, the prescaler is reset when the trigger event occurs. This assures a fixed delay from the trigger event to the start of conversion. In this mode, the sample-and-hold takes place two ADC clock cycles after the rising edge on the trigger source signal. Three additional CPU clock cycles are used for synchronization logic.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
When Auto Triggering is used, the prescaler is reset when the trigger event occurs. This assures
a fixed delay from the trigger event to the start of conversion. In this mode, the sample-and-hold
takes place two ADC clock cycles after the rising edge on the trigger source signal. Three additional
CPU clock cycles are used for synchronization logic.

It still chinese for me ! And I believe I should understand that, because Timer0 overflow is auto-trigering : does it mean :
- it's not 1.5 clock to wait before to take the measure, but 2 clocks ?
- or 2 + 1.5 ?
- or 2 + 3 + 1.5 ?

English is not my natural langage, but I understand that changing prescaler change DELAY_measure ??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You keep mentioning "DELAY_measure" but I haven't a clue what this relates to?!? Is this in some existing software you are trying to use or something?

As for the sequence of things. You said your CPU is 20MHz. that means one CPU cycle is 50ns and we already know that 1 ADC clock is 6.4us.

So reading that datasheet text it seems to me that the trigger event (Timer 0 overflow) occurs. Then because of "the sample-and-hold takes place two ADC clock cycles after the rising edge on the trigger source signal" then I'd suggest that the sample is taken 12.8us after the clock has overflowed (256 CPU cycles). It takes 1.5 ADC clocks so will finish 9.6us later. That is after 12.8+9.6=22.4us. It takes a remaining 13-1.5 = 11.5 ADC clocks later which is 11.5*6.4us = 73.6us and added to the 22.4us that's already elapsed this means the reading is ready 96us after the trigger event.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Crossed post Cliff...

I was meaning : "I still can't find the 1.5 clock EXPLANATION" perhaps : translated as : I don't understand what is the delay between :
- beginning of PWM period
- and exact instant of picking measure by the ADC

Because Koshchi said :

Quote:
the sample is in the first 1.5 clocks

I'm not sure :
- it's within 0-1.5 clocks (and perhaps changing the prescaler don't change the true DELAY_measure)
- or after 1.5 clocks exactly (and DELAY_measure change with prescaler)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The 1.5 clocks are presumably the time it takes to charge up a sampling capacitor. So from the moment of ADSC the applied voltage starts to charge a capacitor. It holds the sample voltage 1.5 clocks (9.6us) later and then the stepped approximation process starts to determine the actual voltage. If, after 1.5 clocks the applied external voltage now goes away it will not matter as it's the held value that is now subject to conversion - it's like a "snapshot".

BTW the timing diagrams in the ADC chapter look very useful - a picture is worth 1,000 words.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Another crossed post, but you answer my cross question !

But what do you think of the Table 24-1 p 257 ? It says :

Quote:
Auto Triggered conversions 2 clocks || 13.5 clock

Timer0 overflow is a auto triggered is that true ?

And what about the :

Quote:
Three additional CPU clock cycles are used for synchronization logic.

The very important fact I have to understand is : what is the exact instant of the measure, after the PWM beginning period. Because I have to know if PWM level is High or Low at this instant, to know if my measure is corrupted.

Thanks for your help !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the "issue" here is that you want total timing control rather than trying to work around system imposed delays then forget trying to use auto-triggering and take complete control yourself so you know exactly when things start and stop.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you said in your first post, using the 16 bit timer ? Humm... It could be the best thing to do, for sure.

Do you think this is possible :
- knowing my actual PWM
- for each PWM cycle

- reprogram the instant of 1.5 ADC clock integration in order that it occurs in the last instant of PWM high level, where the current is at his higher level ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I understand it could be possible using only "First conversion" readings, knowing the "Sample & hold" is after 13.5 cycles.

Or perhaps should I use Timer1 overflow or Timer1 Capture event in auto-triggering ?

Thanks for your patience !