How to increase sampling rate when uC has to deal with ...

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

Hi :)

I am writing this post to share your opinion about my project.
This is a project dedicated for my master thesis.
Well in this project I use two devices one is called "simulator" for simulating two shifted sinusoidal signals and second one which is called interpolator is designed to read these signals either from simulator or external optoelectronic converter.
I hope picture below will help you to understand how the design work.

As I mentioned before simulator gives two shifted sinusoidal waves and optoelectronic connverter gives two shifted squere waves.

Don`t going into details I designed these two devices and they work okey but...

In interpolator I used ADC converter rather than comparator. Better was doing it by comparator but I wanted to have a whole sinusoidal in order to visualise it.

Going into conclusion :

Sampling rate of the interpolator allows me just to read signals from the optoelectronic converter which do not exceed velocity of 1/sec.
If I increase this velocity I obviously get mistakes.
I use one microcontroller for: ADC conversion, two algorithms, debouncing keys, LCD_display futher I would like to implement PC comunication.
This is really time consuming and I am thinking of using two microcontrollers rather than one.
For example one would be responsible for making measurments and second one for LCD,PC connection, debouncing etc..

How would you communicate between these two microcontrollers ?

What is your opinion about it ??

Maybe you have other idies how to increase sampling rate using only one uC ??
The worst thing is that you cannot increase speed of LCD or ADC converter by increasing crystal frequency :/
I implemented LCD in timer 1 : frequency of LCD is 10 [HZ] enough for me.

In interpolator I am using atmega8 with 14745600 Mhz crystal.

Adam

Attachment(s): 

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

Hi,

is the limiting factor that the ADC is not able to run at full speed because it is overloaded by other work? If the ADC is interrupt driven then that should not be a problem, you should be able to get very close to the full speed of the ADC if it is interrupt driven.

If the problem is that even at the full speed as defined by the datasheet your ADC is not fast enough then you pretty much have to use a different MCU or get an external ADC chip.

What kind of LCD are you using? I believe there are AVRs with built in LCD controllers, which should speed things up greatly.

For chip to chip communications I believe there are 2 popular options, I2C (atmel calls it TWI) or SPI. I have used both and they are both good, but I feel that SPI is easier to work with.

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

What sampling rate would you like to achieve? How complex are your algorithms?

I think you can get close to what an AVR is capable of (around 8K samples/second), but it will require cleverly writing your code to multi-task between the various tasks. Debouncing switches, reading the ADC, LCD and serial communication don't have to take a lot time.

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

Use 8 bit mode instead of 10 bit mode.

Imagecraft compiler user

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

What is the frequency of the two sin waves?
This impacts the sampling rate required to process them. (Nyquist).

JC

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

toalan wrote:
is the limiting factor that the ADC is not able to run at full speed because it is overloaded by other work?

Yes this is my suspition.

toalan wrote:
If the ADC is interrupt driven then that should not be a problem, you should be able to get very close to the full speed of the ADC if it is interrupt driven.

Well ADC is not driven by interrupts. Yes maybe I should change it. Interrupt are driven LCD and key_debouncer. Do you think I aslo should put ADC routine to the another timer.

If I put ADC_read in interrupt driven by timer then should I use ADFR (free running select)
So then could I resign from waiting till coversion will be done but just read it when overflow will occur .
Am I right ?

In this way in the loop would only stay my algorithms.

Well simulator gives me constant frequency of 50 Hz so measurments are okey but when I connect my external optoelectronic converter measured frequency increase.

equetion is simple:

you manage to give tihis converter motion of max 5 rotation per seconds which give you.
Frequency= 5 x 400(impulses)=2000 [Hz/s]
So sampling frequency should be 4000 [Hz/s]

Yes Bob I have already used 8 bit conversion.

Yeah who knows maybe this AVR_LCD microcontrollers are worth considering.

circuitmangler wrote:
I think you can get close to what an AVR is capable of (around 8K samples/second), but it will require cleverly writing your code to multi-task between the various tasks.

Ok so how to write good code ?? ;)

But I think ADC sampling driven by interrupts is a good idea

Any other ideas ?

Adam

P.S.

Yeah

uint8_t ADC_read(uint8_t channel) 
{   
	ADMUX= ((1<<REFS0)|(1<<ADFR)|(1<<ADLAR)|(channel));
	
	ADCSRA|=(1<<ADSC); //do a single conversation
	while(ADCSRA & (1<<ADSC)); 	 //wait till coversion will be done
	return ADCH; 
}

Yeah wait till conversion will be done in constant loop ;) Definitly this routine should be changed :)

Anyway maybe you have other idies ??

Adam

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

You do not need to dedicate a timer for the ADC. The ADC itself has an interrupt, it will set the ADC interrupt flag whenever the ADC is complete and you just write your own interrupt routine to gather the result and start the next ADC cycle.

REgards,

Alan To

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

Maybe using an external ADC with a higher conversion rate will help. As you are already resigned to 8 bit ADC data width, you could use two FLASH ADC's - one for each quadrature channel and performing simultaneous conversion. This would provide for nearly zero phase measurement error between the two quadrature signals.

A FLASH ADC has extremely low conversion time as, it is nothing more then a series of 256 comparators, referenced to a 256 point voltage reference made up of 256 equal value precision resistors in series and, a 256 in, to 8 bit out multiplexer. The speed limitation of the FLASH ADC is mainly due to propagation delays in the comparator and digital logic, which is orders of magnitude faster then the typical successive approximation or Sigma-Delta based ADC conversion. It's been a while since I've looked ad FLASH ADC's, but it seems to me that conversion times were in the 500 (4MHz) to 200 (5MHz) nanosecond range.

Using two FLASH ADC's, you could set up, say, a 1uS interrupt and simply read the most recently completed ADC conversions, providing two channels at 1,000,000 conversions per second. You'd still have plenty of time to process the display, keyboard, USART, and whatever else needs to be processed in the foreground in main().

Just some thoughts...

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

If the ADC is fast enough, you might consider ATmega 169. It has LCD driver. There is also a product called Butterfly - a small board with ATmega 169 and LCD display. It is quite cheap too.

Debugging is for sissies and delivery for surgeons. Real men do demonstration.

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

When you write to the LCD are you doing it in the timer interrupt and just running a delay routine in there? If so, that's probably what's taking up a ton of your time. If you can write a timer driven state machine of some sort to write to the LCD, then you can be doing more ADC sampling and calculations in the background while you're waiting for the LCD delays.

Unless you're doing a lot of calculations, then reading the ADC as often as possible, writing to the LCD @ 10Hz and debouncing a couple switches should easily allow you to capture more than 1Hz sine waves.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

But the rates in the 1 Hz range make me suspect that there is some waiting for the LCD to get ready. There is still some room to higher clock frequencies.
I really don't think the internal AD is the limit. For 8 bit resolution one can usally use up to 1 MHz adc clock which is 13 us conversion time. With the 14.xx Mhz crystal about 15 us conversion time is possible.

@carl:
Flash AD converters are faster now, usually 20 MHz and up.

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

Hi

toalan wrote:
You do not need to dedicate a timer for he ADC. The ADC itself has an interrupt, it will set the ADC interrupt flag whenever the ADC is complete and you just write your own interrupt routine to gather the result and start the next ADC cycle.

Yes that`s what I did but I don`t know why it is not working. I tested it in AVRStudio and everything looks ok?

Below code :

//Ustawienia potrzebne do odpalenia ADC:
	ADCSRA|=((1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1));
ADMUX|=((1<<ADLAR)|(1<<REFS0));

ADCSRA|=(1<<ADSC); // do a single conversion first takes 25 cycles !!!
while(ADCSRA & (1<<ADSC)); //wait till first coversion will be done
ADCSRA|=(1<<ADIF);//clear flag  
	
sei(); 
 
ADCSRA|=(1<<ADSC); start conversation
	
	
for(;;)

and ISR routine:

ISR(ADC_vect)// cos tu nie dziala
{
    if(ADMUX & (1<<MUX0))
		{
			sygnal_G=ADCH;
			ADMUX&=~(1<<MUX0)
		}
	else
		{
			sygnal_A=ADCH;
			ADMUX|=(1<<MUX0);
		}
		
	ADCSRA|=(1<<ADSC);
}

sygnal_A and sygnal_G are declared as volatile.
What am I doing here wrong that this routine is not working ??

microcarl wrote:

Maybe using an external ADC with a higher conversion rate will help. As you are already resigned to 8 bit ADC data width, you could use two FLASH ADC's - one for each quadrature channel and performing simultaneous conversion. This would provide for nearly zero phase measurement error between the two quadrature signals.

Yes Carl I would love to use these two flash ADC that would definitly solve my problem. But it is extremly hard to get these flash ADC converters don`t mentioning they are expensive.

Hmm first I try to solve my problem with ISR routine.
But think about zero phase shifting makes me closer to flash ADC converters. ;)

Anyway who can explain me what I do wrong in this
ISR routine ??

Adam

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

Ifryd wrote:

Yes Carl I would love to use these two flash ADC that would definitly solve my problem. But it is extremly hard to get these flash ADC converters don`t mentioning they are expensive.

Adam

Wouldn't MAXIM (www.maxim-ic.com) have something like this that you could order as a sample?

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

Can you post your code for writing to the LCD? If you have a timer interrupt that every time it kicks, it calls an LCD write function, then I assume that's where your issue is, as that will take quite some time to complete.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

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

I just used a routine for LCD.
LCD is displayed with frequency of 10MHz
I just thick a flag in ISR routine and then later in code I am checking it if it occured or not if yes I just do LCD functions.

if (LCD_flag)
	{
		//metoda x1:
			if (metoda & (1<<KEY0))
			{	
				LCD_GoTo(0,0);
				LCD_WriteText("Mx1 ");
				LCD_WriteText("n=");
				num=(int16_t)(obroty_1);
				LCD_WriteText(int16_to_str(num,2,0,0));
				LCD_WriteText(" k=");
				num=(int16_t)((licznik_1)*36);
				LCD_WriteText(int16_to_str(num,4,1,0));
				LCD_GoTo(0,1);
				LCD_WriteText("impx1=");
				num=(int16_t)(licznik_1);
				LCD_WriteText(int16_to_str(num,3,0,0));
				
				if (obroty_1 > 0)
					{
						LCD_WriteText(" P ");
					}
				else 
					{
						if (obroty_1 < 0)
						{
							LCD_WriteText(" L ");
						}
						else
							{
								if (licznik_1 > 0)
									LCD_WriteText(" P ");
								
								if (licznik_1 < 0)
									LCD_WriteText(" L ");
									
								if (licznik_1 ==0)
									LCD_WriteText(" - ");
							}
					}
								
				if(LCD_kierunek & (1<<KEY0))
					LCD_WriteText("-P>");
				else
					LCD_WriteText(" 0)
									LCD_WriteText(" P ");
								
								if (licznik_2 < 0)
									LCD_WriteText(" L ");
									
								if (licznik_2 ==0)
									LCD_WriteText(" - ");
							}
					}
								
				if(LCD_kierunek & (1<<KEY1))
					LCD_WriteText("-P>");
					
				
				else
					LCD_WriteText(" 0)
									LCD_WriteText(" P ");
								
								if (licznik_4 < 0)
									LCD_WriteText(" L ");
									
								if (licznik_4 ==0)
									LCD_WriteText(" - ");
							}
					}
								
				if(LCD_kierunek & (1<<KEY2))
					LCD_WriteText("-P>");
				else
					LCD_WriteText("

But I don`t think so it is a problem of LCD.
I think it was a problem of waiting each time for channel to be read.
It was taking 970 cycles for one channel.
So each time I had delay of more or less 2000 cycles and what I realized from Carl post that aprox. 1000 delay from one channel to another. :/

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

Ok everything is fine with interrupt routine. I was misleaded by one wire which was accidentaly not connected to the breadboard.

Adam