Atmega8 crashes when ADC value reads at a fast rate

Status
Not open for further replies.

thannara123

Advanced Member level 5
Joined
Jan 7, 2010
Messages
1,602
Helped
122
Reputation
244
Reaction score
116
Trophy points
1,353
Activity points
10,616
Hello ,
I am making an automatic stabilzer by using atmega8 . I am taking AC input and output directly (with very low gain) and connected to ADC and the part of mesuaring and relay section works correctely [not finall].

But when i varies the voltage speedly the atmega8 is crashes

FOR MORE plesas see the the working video .
what will be the problem .

I am using float to int by typecasting

PART OF THE CODE

Code:
 data_value();         input_volt =  volt_read_disply(0);
	     DELAY_ms(100);
	     volt =(int)input_volt;       // double to int casting
	     LCD_GoToXY(0,7);
	     LCD_DisplayNumber(10,volt,3);
		 output_volt =  volt_read_disply(1);
		 DELAY_ms(100);
		 LCD_GoToXY(1,7);
		 LCD_DisplayNumber(10,output_volt,3);

Code:
double volt_read_disply(int c){   int i,adc_value[40]={0}; int temp =0;
	
	adc_init();
	
	  
	  for(i=0; i<40;i++)                        // samples taking from 41 times 9.4milli second taken about on complte half cycle
	  { DELAY_ms(5);
		 adc_value[i] = read_adc(c);  // reading voltage 		  	  	  
	 }
	  
	 temp = adc_value[0];	 
	for(i=0; i<40; i++)
	{
		if(temp<adc_value[i])
		temp=adc_value[i];
	}	 
	
      return (double)(temp-307)*0.660;	// int to double casting

REFERANCE : https://www.edaboard.com/showthread.php?373986-Atmega8-voltmeter-hang-up-somewhere
 
Last edited:

Hi,

I didn't go through your code.
But you do a time critical control loop. I recommend to avoid float calculations.

Use 16 bit integers (signed or unsigned ...depending what you need) ..I assume for a voltage stabilizer even 8 bit calculations/resolution could work.


Additionally I recommend to learn how to use interrupt driven control loops.
Don't waste 99.9% of your processing power for busy waits like "delay_ms()".
(An AVR has enough processing power to continously process 1600 samples/s on two channels, squaring, averaging, square root on two channels, with an output data rate of 2.5ms in real time - without missing a single conversion - while it is still able to update the display and communicate via UART)

Klaus
 
Code:
	  for(i=0; i<40;i++)             	  
         { DELAY_ms(5);
		 adc_value[i] = read_adc(c);  // reading voltage 		  	  	  
	 }

Don't seem clear that you're wasting at least 200ms for every A/D conversion doing nothing?
What is the usefulness of the loop, considering that only the last value will be computed?
 
Don't seem clear that you're wasting at least 200ms for every A/D conversion doing nothing?
What is the usefulness of the loop, considering that only the last value will be computed?

Sorry for late ,
That delay doing nothing , but without that delay the volatge showing like 229,135 ,220,110 etc shows low value some time.

May i need to take the avarage value ?

- - - Updated - - -

https://youtu.be/6OncbopIX2I
please see the video.

- - - Updated - - -


changed the double to unsigned 16 bit uint16_t .
what wrong i did with intrupt driven ?
may i know the details ?
 
Last edited:

That delay doing nothing , but without that delay the volatge showing like 229,135 ,220,110 etc shows low value some time.

Seems like you have solved the problem by accident, without properly knowing the reason, and this is a bad practice. From the time you are here, you should have already assimilated some of the tips given on other occasions, and the avoid to use long delays where often mentioned.

May i need to take the avarage value ?

Not for a voltage stabilizer supposed to act realtime, and using so long delays. Moreover, how to know without knowing the circuit you are using ? Why don't you make simulations in software before testing in real world?
 
Hi,

May i need to take the avarage value ?
I assume you talk about an AC voltage stabilizer.
Then for sure you know that the AC voltage moves from zero to positiv peak, to zero, to negative peak ...in a loop.
So a random measurement will give unpredictable results some where between negative peak and positive peak.
You don't show your schematic, so we just have to guess how you process the analog signal before it goes to the ADC.

In the end it is urgent that you average the (rectified) signal somehow. You may do this on the analog side or at the digital side.
I personally like to do it at the digital side. It's reduces part count and cost, it more precise and stable and it is easier to adjust.
But it needs some clean AD sampling and a bit more software effort.

Klaus
 

I am making an automatic stabilzer by using atmega8 . I am taking AC input and output directly (with very low gain) and connected to ADC and the part of mesuaring and relay section works correctely [not finall]

The original description seemed as an AC stabilzer, as well as the video title refers to a voltage stabilizer.
 


There is nothing in your code that ensures the reading of the input synchronously to the AC waveform, so that since you are not rectifying the input signal the average of a big ammount of samples is perhaps the most viable solution, but you will have to remove any useless delay or void loop from your program, as well as you will have to deal with a larger response time, assuming the original scenario of the stabilizer that you have suddenly changed.
 
Hi,

As far as I can see there is no averaging in the analog side.
This means all the averaging needs to be done by software.
I assume the voltage at the ADC input is about 1.5V DC when there is no signal input.
With AC at the input you will see the: divided_AC_voltage + this 1.5V DC at the ADC.
--> Use a scope (and a DVM) to verify this. Give us your results.

--> What's your AC frequency range? A rough estimation will do. Is it grid mains?

--> How often per second do you need a calculated value? (Or calculation interval / regulation interval time)

--> what resolution of your calculated values do you need?
--> what precision of your calculated values do you need? (Or: how much noise and ripple can you accept)

********
There are some methods to determine the amplitude*
1) doing a lot of random samples, find the +/- peak values, multiply them by a constant factor. --> simple math but not the output values will vary a lot.
2) doing a lot of random samples. Subtract offset, rectifying, averaging. --> simple math. Much better than the "peak" solution, but still there will be some ripple in the output signal
3) doing a calculated count of perfectly timed samples. Subtract offset, rectifying, averaging. --> simple math. Much better than the "peak" solution. Much better ripple suppression.
4) doing a calculated count of perfectly timed samples. Subtract offset, squaring, averaging, square root (true RMS) --> needs carefully selected variable sizes, square root takes some processing power. Exact RMS value with low ripple.

I don't recommend 1) because of the huge uncertainty
I don't recommend 4) for beginners. (This is how I'd do it, but I'm a perfectionist)

--> you have to choose a your way.

Klaus
 
Reactions: thannara123

    V

    Points: 2
    Helpful Answer Positive Rating

    thannara123

    Points: 2
    Helpful Answer Positive Rating


Sir ,

1) Yes the voltage at the ADC pin is 1.5DC when there is no signal .

2)what doees mean "divided voltage "? is it the value /2 +1.5dc ?

3)unfortunately i dont have a scope ?

4)The Mesuaring AC Frequency is 50 HZ ,230 volt . yes it is grid voltage .

calculations and details
**************************
,Here is i planned to take the 40 ADC value of every 10milli second (ie, the half cycles of the 50 Hz signals) .
In that 10 milli second we gets 40 samples And in which the highest value i taken
[(that value) - 307] * 0.660.

****************************

ADC Prescalar is 128 , frequency is 8M/128 = 62.5KHz

As i calculated as follows

1 ADC conversion required 230 micro second , so we can take about 44 samples to complete one (10 milli second input) half wave .

- - - Updated - - -


changed the float to 16 bit integer uint16_t adc_value1=0; But some time the grabage value comes and hangaup .

- - - Updated - - -

I changed the samples from 40 to 160 approximatly 2 full wave samples and its peak value .It reduce the flcutuations ( see post #4 ).
Code:
int volt_read_disply(int c)
{   int i,adc_value[160]={0}; int temp =0;
	
	adc_init();	
	
	  for(i=0; i<160;i++)                        // samples taking from 41 times 9.4milli second taken about on complte half cycle
	  { 
		 adc_value[i] = read_adc(c);  // reading voltage 		  	  	  
	 }
	  
	 temp = adc_value[0];	
	  
	for(i=0; i<160; i++)
	{ 
		if(temp<adc_value[i])
		temp=adc_value[i];
	}
 

Here is i planned to take the 40 ADC value of every 10milli second (ie, the half cycles of the 50 Hz signals) . In that 10 milli second we gets 40 samples And in which the highest value i taken

Considering that the period of a 50Hz sine wave is 20ms, this means that with the 10ms ADC rate you will be effectively obtaining only 20 usable samples (=40/(20ms/10ms)), since you will be reading consecutively one sample of the positive and another sample of the negative half-cycle, alternately.

Another aspect to consider is that even if you are not using a crystal, if by accident your circuit achieves a reasonable accuracy in the frequency of the internal oscillator, you will be computing almost the same value at all the time (not necessarily the maximum), that is, all samples will refer to the same phase.

A solution to this would be to instead set a multiple of the mains frequency to the read rate (currently 100Hz), instead use something asynchronous (eg 49 or 51Hz) so that during the reading period of the 50Hz waveform you will be effectively reading one distinct value at each angle of the sinewave.
 
Hi,

2)what doees mean "divided voltage "? is it the value /2 +1.5dc ?
You may also say "attenuated" --> The real AC input voltage is higher than the AC voltage at the ADC

3)unfortunately i dont have a scope ?
Then use a piece of paper an a pencil to draw the (expected) ADC input voltage. With magnitude and timing. Then insert lines for every ADConcersion.
Post this drawing.
You may also lend a scope.

4)The Mesuaring AC Frequency is 50 HZ ,230 volt . yes it is grid voltage .
Even mains frequency has a frequency range. If you want to do a reliable measurement then you should be aware of this.
..oh, and now I know what your input voltage is: 230V AC. ...For sure this voltage needs to be divided before it enters the ADC,

Here is i planned to take the 40 ADC value of every 10milli second
So you´ve chosen the most unreliable solution.
[(that value) - 307] * 0.660.
Don´t know where 307 and 0.660 come from. Maybe its correct, maybe not.

changed the float to 16 bit integer uint16_t adc_value1=0; But some time the grabage value comes and hangaup .
.. like expectable...

I changed the samples from 40 to 160 approximatly 2 full wave samples and its peak value .It reduce the flcutuations ( see post #4 ).
I doubt it reduces the fluctuations. It most likey just takes the (most erronenous) value from 160 instead of 40 values....

***
Your code includes no timing for the ADC sampling. Thus I assume it´s just an assumption that it takes 230us per conversion.

if(temp temp=adc_value;

I doubt that this can work... but I´m no C specialist..

Klaus
 
1) Don´t know where 307 and 0.660 come from. Maybe its correct, maybe not.

* 307 is the offset (ADC value directly minused ,or 5/1023 =.0048875 *307 = 1.5volt)
* 0.660 is not correct it is 0.707 ,Vrms is findout from Vpeak , But I cannot get the correct value by 0.707 so tried and used 0.660 which shows correct .
2) Your code includes no timing for the ADC sampling. Thus I assume it´s just an assumption that it takes 230us per conversion.

I used Lowest ADC frequency 62.5KHZ (50khz to 200khz in atmega 8) the data sheet show 260microsecond needs one conversion thats why .

I will upload the drwaing as you said soon .
 

Hi,

* 0.660 is not correct it is 0.707 ,Vrms
This makes me assume you have a lot of noise an uncertainty..like expected.

****
You can't achieve 230us ... when the datasheet says 260us.
Remember you have some (random) code between the conversions that add some delay..
--> as already recommended: use interrupts or any hardware driven ADC timing. Don't use software timing.

Klaus
 
Hi,



--> as already recommended: use interrupts or any hardware driven ADC timing. Don't use software timing.

Klaus


May i get some more information or a sample one ?
 

Hi,

Did you read the datasheet about starting a conversion, and what options there are?
Did you already do a forum search?
Did you already do an internet search?

Klaus
 

what about may i use as follows .

Detecting the Peak values by using the same adc .That the Half value reading until ,in between the given vaLue.

while((lower_value > adc_read()) && (Higher_value < adc_read()) .

please comment me
 

Hi,

repeated:
Then use a piece of paper an a pencil to draw the (expected) ADC input voltage. With magnitude and timing. Then insert lines for every ADConcersion.
Post this drawing.
You may also lend a scope.

Klaus
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…