SOLVED: Average of a sinus signal a a specific time using Atmega16

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

Dear all,

 

I want to connect a Sinus signal to one of the pins of my Atmega16 MCU and calculate the average of its voltage every one second. I know that the total average of a sinus signal is 0, but we may haven't an integer number of the sinus signal period in one second , so the average voltage can be non-zero. I wonder how can I calculate this average and show it on an 2*16 LCD or send it to USART port using RS232 protocol every one second. May I ask you to please guide me how can I calculate the average of my signal?

Not that I must generate a square signal with the same phase and the same frequency of the sinus signal on another port of my Atmega16 during calculation of average of the input signal. So I think that I need a multi-thread program (A thread for generating the square signal and another thread for calculating the average voltage)! Am I right? If so, is it possible anyway?  

 

Kindly Regards.

Thanks in advance.

Last Edited: Fri. Jun 19, 2015 - 12:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is just basic school maths - do you not know how to find the average of a set of numbers??

 

Even if you don't, I'm sure Google does ...

 

I must generate a square signal with the same phase and the same frequency of the sinus signal on another port of my Atmega16 during calculation of average of that signal. So I think I need a multi-thread program 

No, you don't need a multi-threaded program 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It might be simpler to use a diode, resistor and capacitor to derive the average peak voltage.
You might want the RMS though. Google arduino calc rms

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

To average a signal, you need to measure it some number of times per cycle (significantly more samples than 2). Then, you add up an appropriate number of them and divide by that number. By some strange coincidence, you have an "average".

 

This short description hides a number of details. One is that if you have an ordinary sine signal centered about zero volts, most AVR analog to digital converters cannot handle the negative part of the signal. You need to do something to shift the apparent DC level of the sine so that the ADC will read it properly.

 

Every signal that your read with an ADC must be in the range between 0V and Vreference (Vreference might be Vcc). Thus, if it is a large voltage (say 220VAC), it will have to be scaled down to that it never exceeds the limits of 0V and Vref.

 

If you measure (sample) for exactly 1 second, then any 50Hz or 60Hz sine will have an integer number of cycles in that interval and you will measure zero IF THE SIGNAL IS NOT DISTORTED. Distortion might give it an average value that is not zero.

 

Jim

 

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

So I think that I need a multi-thread program

 

No.

 

You can have your Main program reading the ADC to measure the input sin wave. 

 

You should have the input sin wave centered at 2.5 V if you are running your AVR at 5 V.

 

Any ADC reading > 2.5 V is the positive half of the sin wave.

Any ADC reading < 2.5 V is the negative half of the sin wave.

 

If you are in the positive half of the sin wave then you make an output pin High, (Positive half of square wave).

 

If you are in the negative half of the sin wave then you make an output pin zero, (Negative half of square wave).

 

What is the frequency range of the input sin wave?

 

JC

 

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

Is this assignment in an electrical engineering class or a programming class? When I was a kid, programmers werent engineers and engineers werent programmers. If you learn both whats youre degree called? Do you make more money than if you just did one or the other?

 

Imagecraft compiler user

Last Edited: Mon. Jun 15, 2015 - 08:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 If you learn both whats your degree called? 

My degree was "Computing and Electronics" - jointly run by the computer science and electrical engineering departments. In fact it had been called "Computing and Electronics" in previous years and not many people signed up for it but in the year I joined the course (1981) they renamed it to "Microelectronics and Microprocessor Applications" and they were inundated with applications - it was still just "Computing and Electronics" really though. (actually there was also maths, crystallography/material science and sub-atomic physics in there too!).

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

I got an EE deg in '73, but there were a bunch of fortran circuit analysis decks to be punched in. 1st compsci degrees were at Florida Technological Univ, Now Univ of Central Florida about '78.

 

Average of sine wave:

If you know the height of the sine wave at each sample, you can just add them up no matter how many there are, and divide by the number of samples. If the same number of positive and negative samples are in the set, the sum would be zero, and the average would be zero. 'Numerical Integration'

 

Imagecraft compiler user

Last Edited: Wed. Jun 17, 2015 - 02:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The engineering part starts with scaling and limiting the voltage peak excursions to be compatible with an analog-to-digital-converter (ADC) input to the microprocessor.

Since the signal is sinusoidal, you can ignore one half of the signal's period and simplify.

Once YOUR program code has the ADC sampling at a rate of your choice, based on sampling theory and fidelity requirements you must choose, then the necessary math is from early secondary education.

 

If your assignment does not require a microprocessor solution, you could use pencil and paper and a volt meter measuring device, with and without RMS capability. surprise

 

Last Edited: Wed. Jun 17, 2015 - 06:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your replay.

 

I modify my program as below : 

 

/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 6/18/2015
Author  : 
Company : 
Comments: 


Chip type               : ATmega16A
Program type            : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/

#include <mega16a.h>

#include <delay.h>

// Alphanumeric LCD functions
#include <alcd_ks0073.h>

// Declare your global variables here
int counter=0;
int flag=0;


// Standard Input/Output functions
#include <stdio.h>

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Reinitialize Timer1 value
TCNT1H=0xE0C0 >> 8;
TCNT1L=0xE0C0 & 0xff;
// Place your code here
++counter;
if(counter>999)
    {
    flag=1;
    counter=0;
    }
}

// Voltage Reference: AREF pin
#define ADC_VREF_TYPE ((0<<REFS1) | (0<<REFS0) | (1<<ADLAR))

// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCH;
}

void send_average(int average)
{
    char v_average[16];        
    
    sprintf(v_average,"%d",average); 
    lcd_clear();  
    lcd_gotoxy(0,0);
    lcd_puts("Input Average:");
    lcd_gotoxy(1,0);
    lcd_puts(v_average);
    
    printf(v_average);
}


void main(void)
{
// Declare your local variables here
unsigned int average=2.5;
int signal_value=0;

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out 
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (1<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0 
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 1 ms
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0xE0;
TCNT1L=0xC0;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 19200
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x19;

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);

// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: ADC Stopped
// Only the 8 most significant bits of
// the AD conversion result are used
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
SFIOR=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTB Bit 4
// D5 - PORTB Bit 5
// D6 - PORTB Bit 6
// D7 - PORTB Bit 7
// Characters/line: 8
lcd_init(8);

// Global enable interrupts
#asm("sei")

while (1)
      {
      if(flag)
            {
            send_average(average); 
            flag=0;
            }
        
      signal_value = (int) read_adc(PINA.0);
        
      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }
            
        average = (average + signal_value)/2;

      }
}

 

The problem is when I want to compile it I receive the following error: 

 

Error: C:\Users\AmirEbrahim\Desktop\MyProject\MyPrj.c(83): function argument #1 of type 'unsigned char [16]' is incompatible with required parameter of type 'flash unsigned char *'

 

What shall I do? 

Last Edited: Thu. Jun 18, 2015 - 02:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well line 83 is:

    printf(v_average);

I don't know your compiler well enough to know why it is objecting. But it's saying that it expects the parameter to be a pointer to a string in flash but it's being given a string in RAM. Presumably there's an option for printf() in your compiler that says something like "expect strings to be in flash". You need to defeat that. I imagine one way would simply be:

 printf("%s", v_average);

that should happily accept a string in RAM.

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

Thank you. You are right. The issue solved. But still I have some problem with the value. I must modify again. 

Thank you again.

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

Re the output square wave -- isn't this just a job for a simple comparator chip?

 

No-one yet has mentioned (as I can see [now I see an indirect mention]) that the signal must be shifted from +/- (implied as OP said the average V is 0) to something within range of AVR8 reading?

 

OP has yet to answer about the amplitude as well as the range of this signal.  For all we know, the "problem with the value" may be from feeding a high voltage signal right to the AVR pin.

 

Once properly centered and ranged, then the AVR's internal analog comparator can be used to generate the output.  OP must define "same phase".  Unfortunately OP's model doesn't have an ACO pin so it will need to be handled in an ISR.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Thank you dear theusch for your replay.

 

What is AVR8?

 

The input signal is a TTL sine signal (I mean its Low = 0 v and its High = 5 v). Can I use Atmega16 inbuilt comparator instead of its inbuilt ADC to aim my goal? What is ACO pin? Same Phase? which phase?

 

Last Edited: Thu. Jun 18, 2015 - 04:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there any problem whit my above program?

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

How can you have "TTL Sine Wave"? Is it PWM?

 

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Ah! I just found that in the project definition it is mentioned that input is an TTL AC Signal (Not Sine signal) which the value of 2.5v consider as 0 in it! Does this change the scenario? 

Last Edited: Thu. Jun 18, 2015 - 05:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ebrahim.rcii wrote:

What is AVR8?

8bit AVRs

"One's value is inherent; money is not inherent"

 

Chuck, you are in my heart!

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

There is a problem: In the LCD can only see the first 8 letters! I changed the LCD also, but nothing changed. 

 

In the other word I have "Input Ave" instead of "Input Average"!  I moved the cursor to point 3 using the following code:

 

lcd_gotoxy(3,0);
lcd_puts("Input Average");

And then I have "   Input" instead of "Input Average". Does anyone have any idea?

Kindly Regards

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

 

Does anyone have any idea?

 

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTB Bit 4
// D5 - PORTB Bit 5
// D6 - PORTB Bit 6
// D7 - PORTB Bit 7
// Characters/line: 8
lcd_init(8);

Perhaps because you told the LCD driver that you had an 8xN display?

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Oh Gee... I didnt want you guys to paint the barn red, I really wanted you to paint it green. Sorry. My mistake. I'm just a newbie barn paint color requester.

So what should the thread title REALLY say?

 

 

Imagecraft compiler user

Last Edited: Thu. Jun 18, 2015 - 06:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OMG! you are right. I just found that how silly I am :(

 

I modified that part of my code as below :

.
.
.
.
.
lcd_init(16);
.
.
.
.

And also I changed the "send_average()" method as below:

 

void send_average(int average)
{
    char v_average[16];        
    
    sprintf(v_average,"%d",average); 
    lcd_clear();  
    lcd_gotoxy(0,0);
    lcd_puts("Input Average:");
    lcd_gotoxy(1,1);
    lcd_puts(v_average);
    
    printf("%s",v_average);
    printf("\n");
}

The problem is:

 

1- I don't see anything in the second row of my LCD! (While the first line is okay. i.e in the first line I see "Input Average").

2- The numbers that I receive in the computer using USART seems wrong. Look:

 

When PINA.0 (the pin that I read by read_adc() function ) is connected to 0 volt :

 

 

 

But when PINA.0 is connected to 5 volt :

 

 

I think it must all be 5, doesn't it?

 

3- PORTC.0 (The square wave that I want to generate based on the input signal) is zero when PINA.0 is zero and this is okay. But when PINA.0 is connected to 5 volts, PORTC.0 is about 2 volts instead of 5 volts. 

 

 

Thank you for your guidance and your help. 

Kindly regards.

Last Edited: Thu. Jun 18, 2015 - 07:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh Gee... I didnt want you guys to paint the barn red, I really wanted you to paint it green. Sorry. My mistake. I'm just a newbie barn paint color requester.

May I ask you to explain this part please. Unfortunately my English language knowledge is not well enough to understand it.  Thank you.

 

So what should the thread title REALLY say?

Should I change the title or I must ask a new question for my last post under this title? 

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

I modified that part of my code as below :

.
.
.
.
.
lcd_init(8);
.

???  I don't see any change there.  What display do you really have connected?  How many lines, and how many characters per line?  Which CodeVision library did you link to?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

You had a couple of guys patiently typing out how to calculate the average value of a sinwave, and carfully addressed the complication that the input waveform must be biased to 2.5 volts and not exceed 0v and 5v. Whew. Then after 24 messages, we get "Oh, its a ttl level signal, not a sine wave". Ever watch Saturday Night Live? They had some chick reading the news and she went off on a rant about the "Youth In Asia", then when she found out she was all off in left field, she says "Oh. Never Mind". Emily Lattella?

Imagecraft compiler user

Last Edited: Thu. Jun 18, 2015 - 07:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry. I was meant I changed it to  "lcd_init(16)". It is a 2*16 Alphabetic LCD. Its image attached below :

 

 

First time in the CodeWizard  I select HD44780 as the type of its controller, but the lcd didn't worked with that. (In this case alcd.h included automatically in the above of my program using codeWizard). So in the next time I choose KS0073 as type of LCD controller and now alcd_ks0073.h is included. The last issues that I mentioned are for this case.

 

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

You are completely right. I am so sorry Mr.bobgardner. Unfortunately all I can say now is "I'm so sorry". I will do my best to don't repeat such mistakes. Indeed the answers that explain how I can  calculate the average value of a sinwave will help me in the future. the rule that "input waveform must be biased to 2.5 volts and not exceed 0v and 5v" must apply to the ttl level AC signal also, doesn't it?

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

So, what do you have connected to port B?  Your ISP cable, perhaps?

 

I guess we don't really know what controller your display really has.  We don't really know whether line 2 works or not.

 

A typical memory map has line 1 at address 0x00 and line 2 at 0x40.  So to test, you have to position to 0,0 and then send more than 64 characters and see what shows up on the screen.  I often use upper case A-Z then 0-9 then lower case a-z then 0-9 again as a sanity check.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

So, what do you have connected to port B?  Your ISP cable, perhaps?

Yes, PORTB is connected to the LCD pins.

    lcd_puts("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890");

 

As you said I tried with the following line:

    lcd_puts("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz1234567890");

What I see now is this text in the first line of my LCD:

 

"4567890HIJKLMNOP"

 

Is not it weird?!

 

In the second line I have nothing, 

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

Did you do a lcd_gotoxy(0,0) first?

 

Then rebuild and try again to line 1:  lcd_gotoxy(0,1) and then the puts.

 

Your characters are after 0x20.

 

I guess there is not much to be done without a datasheet for the LCD.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Did you do a lcd_gotoxy(0,0) first?

Yes I did.

 

 Then rebuild and try again to line 1:  lcd_gotoxy(0,1) and then the puts.

I did this also, But still characters appeared on the first row!  

 

 

May I ask you to help me in the two next problems also? I mean the wrong average value in the computer and the wrong voltage of PORTC.0 (2 volts instead of 5 volts.). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unsigned int average=2.5;
int signal_value=0;

 

      signal_value = (int) read_adc(PINA.0);
        
      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }
    

I think you had better start over, and think carefully about your code.  Why are you mixing floating point and integer operations?  Why are you talking about PORTC.0 voltage?  What is connected?  

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Your LCD looks pretty much like a regular 16x2 HD44780 type.    I suggest that you build all the LCD programs from the /examples directory.    If they work ok as 16x2,   you should be fine.

Alternatively,   Google your specific LCD module.   Chinese data sheets tend to be pretty useless.

 

Regarding your code.   Think about it.   From message #10:

      signal_value = (int) read_adc(PINA.0);

This is reading the digital contents of PA0 pin.    Then either reading channel#1 or channel#0.

You should be always reading channel 0:

      signal_value = (int) read_adc(0);

I can not see the sense in using ADLAR.   If God gave you a 10-bit ADC,  why not use it?

 

David.

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

All the problems completely solved:

 

---- for the LCD issue: ----

The correct controller for the LCD was HD44780  type. while I choose KS0073.

 

---- for the issue of wrong value of PORTC.0 : ----

 

I was compare a int value with a float value in this part of my code :

   signal_value = (int) read_adc(PINA.0);
        
      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }

As dear  theusch, above code is mixed different types. so I changed it to below :

 

float average= 2.5;
float signal_value=0;

while (1)
      {
      if(flag)
            {
            send_average(average); 
            flag=0;
            }

      signal_value = (read_adc(0) / 1024.0)* 5.0;

      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }

        average = (average + signal_value)/2.0;
      }

send_average() function is changed to below also:

 

void send_average(float average)
{
    char v_average[16];        
   
    ftoa(average, 5,v_average); 
    lcd_clear();  
    lcd_gotoxy(0,0);
    lcd_puts("Input Average");
    lcd_gotoxy(0,1);    
    lcd_puts(v_average);

    printf("%s",v_average);
    printf("\n");
}

 

And also, as you see above and as dear david.prentice suggested me, I replace 

read_adc(PORTA.0);

with

read_adc(0);

But I don't know the difference between this two!

 

* I also are using 10 bit ADC.

 

Thank you all. Now the program works fine.

 

--------------------------------------------------------------------------------

 

For future viewers, this is whole the program that works fine for me:

 

/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 6/19/2015
Author  : 
Company : 
Comments: 


Chip type               : ATmega16A
Program type            : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*******************************************************/

#include <mega16a.h>

#include <delay.h>

// Alphanumeric LCD functions
#include <alcd.h>


#include <stdlib.h>



// Standard Input/Output functions
#include <stdio.h>

// Declare your global variables here
int counter = 0;
int flag = 0;


// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
// Reinitialize Timer1 value
TCNT1H=0xE0C0 >> 8;
TCNT1L=0xE0C0 & 0xff;
// Place your code here
++counter;
if(counter>999)
    {
    flag=1;
    counter=0;
    }
}

// Voltage Reference: AREF pin
#define ADC_VREF_TYPE ((0<<REFS1) | (0<<REFS0) | (0<<ADLAR))

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}



void send_average(float average)
{
    char v_average[16];        
   
    ftoa(average, 5,v_average); 
    lcd_clear();  
    lcd_gotoxy(0,0);
    lcd_puts("Input Average");
    lcd_gotoxy(0,1);    
    lcd_puts(v_average);

    printf("%s",v_average);
    printf("\n");
}


void main(void)
{
// Declare your local variables here
float average= 2.5;
float signal_value=0;


// Calibration Bits for 8MHz internel oscillator
OSCCAL = 0xAD;



// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out 
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (1<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0 
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 1 ms
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0xE0;
TCNT1L=0xC0;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 19200
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x19;

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);

// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: ADC Stopped
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
SFIOR=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTB Bit 4
// D5 - PORTB Bit 5
// D6 - PORTB Bit 6
// D7 - PORTB Bit 7
// Characters/line: 16
lcd_init(16);

// Global enable interrupts
#asm("sei")

while (1)
      {
      if(flag)
            {
            send_average(average); 
            flag=0;
            }

      signal_value = (read_adc(0) / 1024.0)* 5.0;

      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }

        average = (average + signal_value)/2.0;
      }
      
      
}

 

I really appreciate you time, your consideration and you patience.

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

The average value of a bunch of binary numbers on a wire is the number of 111s. If you send a stream of FFs, the average works up to 5V. A stream of 0000s is zero volts. A stream of 55s or AAs is 2.5 volts. Can you describe a plan for counting the number of 111s in a bunch of bytes Mr Ebrahim?

Imagecraft compiler user

Last Edited: Sat. Jun 20, 2015 - 03:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OMG! I just see this replay and now I delivered the project to my boss. Really thank you Mr bobgardner. You are right. I calculate the average wrongly, but I don't know how to correct it. (I couldn't understand your replay! What does "s" means in 111s?) May I ask you to help me correct it?  

 

Last Edited: Wed. Jun 24, 2015 - 08:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I must use this program instead : 

 

int counter = 1;
.
.
.
while (1)
      {
      if(flag)
            {
            send_average(average); 
            flag=0;
            }

      signal_value = (read_adc(0) / 1024.0)* 5.0;

      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }

        average = ((average*counter) + signal_value)/(counter+1);
        ++counter;
      }

 

Or simply use the below program instead :

int counter = 1;
float sum =2.5;
.
.
.
while (1)
      {
      if(flag)
            {
            send_average(sum/counter); 
            flag=0;
            }

      signal_value = (read_adc(0) / 1024.0)* 5.0;

      if (signal_value > 2.5)
            {
            PORTC.0 = 1;   
            } 
            else
            {           
            PORTC.0 = 0;
            }

        sum = sum + signal_value;
        ++counter;
      }

 

Am I right?

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

Somebody please help me. Is there any problem with the previous methods? Which frequencies can I calculate average with the above program? The the maximum input signal frequency limited to 8 MHz (MCU Clock frequency) or ....? 

Last Edited: Sat. Jun 27, 2015 - 07:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should be able to answer these questions yourself. How many samples per second is the program doing? Have you measured it?

At a guess, I'd say the max input frequency would be a few hundred Hz.

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

A few hundred Hz?! Ah! I thought it can calculate average of input signals with frequencies about ~7 MHz! Is it possible in any way? (With clock frequency fixed to 8 Mhz)

 

Another question :

 

average and sum is defined  float and counter is int;

 

In this line:

average = sum / counter;

Will I have any problem? I mean dividing a float by an integer doesn't make any casting? (I mean if I loose the pointing parts of average in this line? I mean the output of sum / counter is float or int?)

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

You haven't read the datasheet on the adc have you?? It can only do 12000 samples a second. The code you posted does floating point calculations that take 100's of cycles. So basically there's no hope of it doing MHz.
You're going to need a high speed adc to do 7MHz. You're also going to need some compute horsepower.
Did you tell your boss that you are just getting the solution off the internet and not doing any work yourself?

Last Edited: Sat. Jun 27, 2015 - 08:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't understand your reply, will I losing the pointing number part in sum / counter part?

When I run the above program in my micro controller and connect the input signal with frequency of about 100 Hz, I see average of ~zero! Why?

 

Actually it is not my boss, he is my friend that requested me to help him do his project. I know that I asked a lot of questions, please don't blame me, please help me to finish this project and I promise I won't ask these kind of questions anymore :(

 

 

I need a high speed adc ? does Atmega16 has any one? 

 

Is there any any way to calculate average of an input signal with frequency greater than MCU clock frequency? (for example input signal frequency = 1.5 * MCU clock frequency)

 

I appreciate your time and I'm sorry that I am wasting it.

 

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

As Kartman has said, you can only do so many samples per second. Of course, you can sample a high frequency if you have a stable signal. Think about it. Providing your sample frequency and target signal are not exact multiples, each sample is taken from a different part of a new cycle. You can read very high frequencies but you need very stable signals and stable ADC clock.
If the sample and target are multiples, each sample would be taken from the same point(s) in a new cycle of the target signal.
Obviously, most signals are not stable, so you want to sample a single cycle. If you want 100 samples this limits you to 120Hz or so.

Last Edited: Sat. Jun 27, 2015 - 09:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again, you can answer the question yourself. Atmel Studio has a simulator. In a few minutes of simulation you would have the answer.

For sampling MHz signals you need a specialised ADC. No, the AVR doesn't have one. I don't know of a microcontroller that does. You'll need to connect a high speed DSP processor to the high speed ADC. Unfortunately, these are not the things you lash up on a breadboard and expect to work. A simple solution is to use a digital oscilloscope and use it to capture the data.

Why do you get an average of zero? It could be a number of things. What have you done to find the problem? Work logically through the problem.

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

Shouldn't the above program works fine for 100 Hz input signal?

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

why do you think there is a problem with the code? There could be a number of problems.

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

Really?! I didn't know that Atmel Studio has a simulator. Thank you, I'll try it soon.

 

 

What have you done to find the problem? Work logically through the problem.

I just want to know if is there any bug in the program? I reviewed the code again and again, but I didn't found any bug!

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

I think the first step is to be sure about the program and then check the other thinks, am I right?

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

The first step is to identify the problem. What have you done to check the adc input? Personally, i'd suggest you write code to output the raw adc values. Analyse this data then add scaling, then averaging.

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

Kartman wrote:

The first step is to identify the problem. What have you done to check the adc input? Personally, i'd suggest you write code to output the raw adc values. Analyse this data then add scaling, then averaging.

Good suggestion.

ebrahim.rcii wrote:

...

I know that I asked a lot of questions, please don't blame me, please help me to finish this project and I promise I won't ask these kind of questions anymore :(

...

Here is for you and any ATMEL's consumer but really sometimes we AVRfreaks cannot help you because there are tons of probabilities about your problem(s). in many cases we can check your code out and tell you all problems which we can see. you must test or debug your code in any way that you can and tell us about them.

the key factor in solving the problems is YOURSELF!

then move on and do everything that these guys are saying to you.

Kartman wrote:
...

 Unfortunately, these are not the things you lash up on a breadboard and expect to work.

...

Indeed,

I think he have to do impedance matching due to this sample rate( for a MHz signal).

Kartman wrote:
...

A simple solution is to use a digital oscilloscope and use it to capture the data.

...

Good suggestion again.

 

ebrahim.rcii wrote:

I just want to know if is there any bug in the program? I reviewed the code again and again, but I didn't found any bug!

Don't review it over and over. don't bother yourself.
as Kartman pointed out, a simple and quick approach is to simulate or debug it.
absolutely there must to be a problem. if not, then why it doesn't work?

 

I think for first off, it's better to make sure the ADC works very well. then as Kartman said,

i'd suggest you write code to output the raw adc values. Analyse this data then add scaling, then averaging.

"One's value is inherent; money is not inherent"

 

Chuck, you are in my heart!

Last Edited: Sat. Jun 27, 2015 - 12:27 PM