Implementing Discrete Fourier Transform in Atmega32 to make an audio spectrum analyzer


"All waveforms, no matter what you scribble or observe in the universe, are actually just the sum of simple sinusoids of different frequencies."

Hi,
I am just refreshing the basics of fourier transform. I am not an expert. Now I did a small audio spectrum analyzer(0 - 10KHz) on a 16x2 character lcd using an atmega32 microcontroller. Since I am refreshing from the basics, so I started with simple DFT. Also, I believe I should learn to walk before running. So I am not straight away going towads the FFT, which is nothing but the fastest and a bit complicated algorithm to find DFT.(I will try it later, as soon as possible)
        DFT is too slow compared to FFT. My lcd spectum analyzer doesn't need a great speed like that of an FFT, now if it is capable of providing a speed of around 30 frame/second, then it is more than enough for visualizing the audio spectrum on an LCD. But any way, in my case I can roughly achieve around 100 frames/second(any way it is too high refresh rate for a 16x2 lcd, not recommended also :-)). My audio sampling rate is 20KHz for 32 point DFT. Since the transform result is symmetric, I need to use only the first half, ie the first 16 results. So, it means, it can display upto 10KHz spectrum. So the resolution is 10KHz/16 = 625Hz.
         I have tried to improve the speed of DFT computation. If it is an N point DFT, it needs to find (N^2)/2 sin and cos values. For a 32 point DFT, it needs to find 512 sine and cosine. Before finding the sine and cosine, we need to find the angle(degree) which takes some processor time, so I implemented a lookup table for that. Next two tables are for sine and cosine. I didn't used any float or double since it takes more processing time in 8 bit avr, instead I implemented the sine and cosine lookups as 16bit intiger, by multiplying the real sine and cosine values by 10000. Then after finding the transform, finally I need to divide each result by 10000. This eliminates the need of using float or double and makes it more faster. Now I can calculate 120  32-point DFT operation/sec which is more than enough for my small spectrum analyzer.


LCD   
       Now, looking towards the LCD side, I utilized the custom character feature of LCD to make 8 stacked horizontal bars which takes the entire 64bytes of the LCD RAM for custom character bitmap. I ones seen a video is hackaday.com that a person used a 16x2 lcd in the similar manner for his spectrum analyser. So I also adopted the same idea of using the custom character for my spectrometer.

AUDIO INPUT
       Now one of the most important part of this stuff is the audio sampling via an eletret microphone. Special care must be given while designing the pre-amp for the mic. We need to set the zero-level of the ADC input to exactly half of the ADC reference voltage ie to 2.5v. Now it can have positive and negative swing on this 2.5v level according to the input audio signal but it should not cross the limit ie the amplifier gain should be properly adjusted to prevent clipping. I am using an LM324 op-amp for the mic pre-amp to meet the above conditions. 

PHOTO



CIRCUIT DIAGRAM



SOURCE CODE: (main.c)
#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>
#define N 32
#include "lookup.h"
#define RS PD5
#define EN PD6
#define LCD_NIBBLE PORTC

void adc_init();
uint16_t adc_read();
void TRANSFORM();
void timer1_init();
void LCD_STROBE(void);
void lcd_data(unsigned char c);
void lcd_cmd(unsigned char c);
void lcd_clear(void);
void lcd_init();
void lcd_print(char *p, char l);
void lcd_fill_custom();

uint8_t lcd_buf1[16];
uint8_t lcd_buf2[16];
int32_t fx[N];
int32_t Fu[N/2][2];

void main()
{
    uint8_t mag;
    int i,j, temp_value;
    uint8_t temp_index;
    adc_init();
    lcd_init();
    lcd_fill_custom();
    lcd_print("DFT SPECTROMETER",1);
    lcd_print("0Hz - 10KHz(16)",2);
    _delay_ms(5000);
    lcd_clear();
    timer1_init();
    while(1) {
        TCNT1 = 0;
        TIFR |= 1<<OCF1A;
        for(i=0;i<N;i++) {
            while((TIFR & (1<<OCF1A)) == 0);
            fx[i] = ((int16_t)adc_read());
            TIFR |= 1<<OCF1A;
        }
        TRANSFORM();
        lcd_cmd(0xc0);
        for(i =1; i<N/2; i++) {
            if(Fu[i][0]<0)Fu[i][0]*=-1;
            if(Fu[i][1]<0)Fu[i][1]*=-1;
            mag = (uint8_t)(Fu[i][0] + Fu[i][1])/4;
            if((mag)>7) {
                lcd_buf1[i] = (mag) - 7 - 1;
                if(lcd_buf1[i] > 7)
                lcd_buf1[i] = 7;
                lcd_buf2[i] = 7;
            }
            else {
                lcd_buf1[i] = ' ';
                lcd_buf2[i] = mag;
            }
        }
        lcd_cmd(0x80);
        for(i=1;i<16;i++)
        lcd_data(lcd_buf1[i]);
        lcd_cmd(0xc0);
        for(i=1;i<16;i++)
        lcd_data(lcd_buf2[i]);
        
        
    }
}

void TRANSFORM()
{
    int16_t count,degree;
    uint8_t u,k;
    count = 0;
    for (u=0; u<N/2; u++) {
        for (k=0; k<N; k++) {
            degree = (uint16_t)pgm_read_byte_near(degree_lookup + count)*2;
            count++;
            Fu[u][0] +=  fx[k] * (int16_t)pgm_read_word_near(cos_lookup + degree);
            Fu[u][1] += -fx[k] * (int16_t)pgm_read_word_near(sin_lookup + degree);
        }
        Fu[u][0] /= N;
        Fu[u][0] /= 10000;
        Fu[u][1] /= N;
        Fu[u][1] /= 10000;
    }
}

void timer1_init()
{
    TCCR1B = (1<<WGM12)|(1<<CS10);
    OCR1A = 800;
}

void adc_init()
{
    ADMUX = 0b11000000;
    ADCSRA =0b10000010;
}

uint16_t adc_read()
{
    volatile uint16_t retl,reth;
    ADCSRA |= 1<<ADSC;
    while(!ADIF);
    ADCSRA |= 1<<ADIF;
    retl = ADCL;
    reth = ADCH;
    reth<<=8;
    reth|=retl;
    return reth;
}

void LCD_STROBE(void)
{
    PORTD |= (1 << EN);
    _delay_us(1);
    PORTD &= ~(1 << EN);
}

void lcd_data(unsigned char c)
{
    PORTD |= (1 << RS);
    _delay_us(50);
    LCD_NIBBLE = (c >> 4)|(LCD_NIBBLE&0xf0);
    LCD_STROBE();
    LCD_NIBBLE = (c)|(LCD_NIBBLE&0XF0);
    LCD_STROBE();
}

void lcd_cmd(unsigned char c)
{
    PORTD &= ~(1 << RS);
    _delay_us(50);
    LCD_NIBBLE = (c >> 4)|(LCD_NIBBLE&0xf0);
    LCD_STROBE();
    LCD_NIBBLE = (c)|(LCD_NIBBLE&0XF0);
    LCD_STROBE();
}

void lcd_clear(void)
{
    lcd_cmd(0x01);
    _delay_ms(5);
}

void lcd_init()
{
    DDRC = 0b00001111;
    DDRD |= (1 << RS)|(1 << EN);
    PORTC |= (1<<PC4);
    _delay_ms(15);
    lcd_cmd(0x30);
    _delay_ms(1);
    lcd_cmd(0x30);
    _delay_us(100);
    lcd_cmd(0x30);
    lcd_cmd(0x28);
    lcd_cmd(0x28);
    lcd_cmd(0x0c);
    lcd_clear();
    lcd_cmd(0x6);
}

void lcd_print(char *p, char l)
{
    if(l==1)lcd_cmd(0x80);
    else lcd_cmd(0xc0);
    while(*p)
    lcd_data(*p++);
}

void lcd_fill_custom()
{
    uint8_t i,j;
    i=0;j=0;
    lcd_cmd(64);
    for(i=1;i<=8;i++) {
        for(j=8;j>i;j--)
        lcd_data(0);
        for(j=i;j>0;j--)
        lcd_data(0xff);
    }
}
lookup.h
//LOOKUP TABLE//
#include <avr/pgmspace.h>

PROGMEM const int16_t cos_lookup[]= {
    10000,9998,9993,9986,9975,9961,9945,9925,9902,
    9876,9848,9816,9781,9743,9702,9659,9612,9563,
    9510,9455,9396,9335,9271,9205,9135,9063,8987,
    8910,8829,8746,8660,8571,8480,8386,8290,8191,
    8090,7986,7880,7771,7660,7547,7431,7313,7193,
    7071,6946,6819,6691,6560,6427,6293,6156,6018,
    5877,5735,5591,5446,5299,5150,5000,4848,4694,
    4539,4383,4226,4067,3907,3746,3583,3420,3255,
    3090,2923,2756,2588,2419,2249,2079,1908,1736,
    1564,1391,1218,1045,871,697,523,348,174,
    0,-174,-348,-523,-697,-871,-1045,-1218,-1391,
    -1564,-1736,-1908,-2079,-2249,-2419,-2588,-2756,-2923,
    -3090,-3255,-3420,-3583,-3746,-3907,-4067,-4226,-4383,
    -4539,-4694,-4848,-4999,-5150,-5299,-5446,-5591,-5735,
    -5877,-6018,-6156,-6293,-6427,-6560,-6691,-6819,-6946,
    -7071,-7193,-7313,-7431,-7547,-7660,-7771,-7880,-7986,
    -8090,-8191,-8290,-8386,-8480,-8571,-8660,-8746,-8829,
    -8910,-8987,-9063,-9135,-9205,-9271,-9335,-9396,-9455,
    -9510,-9563,-9612,-9659,-9702,-9743,-9781,-9816,-9848,
    -9876,-9902,-9925,-9945,-9961,-9975,-9986,-9993,-9998,
    -10000,-9998,-9993,-9986,-9975,-9961,-9945,-9925,-9902,
    -9876,-9848,-9816,-9781,-9743,-9702,-9659,-9612,-9563,
    -9510,-9455,-9396,-9335,-9271,-9205,-9135,-9063,-8987,
    -8910,-8829,-8746,-8660,-8571,-8480,-8386,-8290,-8191,
    -8090,-7986,-7880,-7771,-7660,-7547,-7431,-7313,-7193,
    -7071,-6946,-6819,-6691,-6560,-6427,-6293,-6156,-6018,
    -5877,-5735,-5591,-5446,-5299,-5150,-5000,-4848,-4694,
    -4539,-4383,-4226,-4067,-3907,-3746,-3583,-3420,-3255,
    -3090,-2923,-2756,-2588,-2419,-2249,-2079,-1908,-1736,
    -1564,-1391,-1218,-1045,-871,-697,-523,-348,-174,
    0,174,348,523,697,871,1045,1218,1391,
    1564,1736,1908,2079,2249,2419,2588,2756,2923,
    3090,3255,3420,3583,3746,3907,4067,4226,4383,
    4539,4694,4848,5000,5150,5299,5446,5591,5735,
    5877,6018,6156,6293,6427,6560,6691,6819,6946,
    7071,7193,7313,7431,7547,7660,7771,7880,7986,
    8090,8191,8290,8386,8480,8571,8660,8746,8829,
    8910,8987,9063,9135,9205,9271,9335,9396,9455,
    9510,9563,9612,9659,9702,9743,9781,9816,9848,
    9876,9902,9925,9945,9961,9975,9986,9993,9998
};

PROGMEM const int16_t sin_lookup[]= {
    0,174,348,523,697,871,1045,1218,1391,
    1564,1736,1908,2079,2249,2419,2588,2756,2923,
    3090,3255,3420,3583,3746,3907,4067,4226,4383,
    4539,4694,4848,4999,5150,5299,5446,5591,5735,
    5877,6018,6156,6293,6427,6560,6691,6819,6946,
    7071,7193,7313,7431,7547,7660,7771,7880,7986,
    8090,8191,8290,8386,8480,8571,8660,8746,8829,
    8910,8987,9063,9135,9205,9271,9335,9396,9455,
    9510,9563,9612,9659,9702,9743,9781,9816,9848,
    9876,9902,9925,9945,9961,9975,9986,9993,9998,
    10000,9998,9993,9986,9975,9961,9945,9925,9902,
    9876,9848,9816,9781,9743,9702,9659,9612,9563,
    9510,9455,9396,9335,9271,9205,9135,9063,8987,
    8910,8829,8746,8660,8571,8480,8386,8290,8191,
    8090,7986,7880,7771,7660,7547,7431,7313,7193,
    7071,6946,6819,6691,6560,6427,6293,6156,6018,
    5877,5735,5591,5446,5299,5150,4999,4848,4694,
    4539,4383,4226,4067,3907,3746,3583,3420,3255,
    3090,2923,2756,2588,2419,2249,2079,1908,1736,
    1564,1391,1218,1045,871,697,523,348,174,
    0,-174,-348,-523,-697,-871,-1045,-1218,-1391,
    -1564,-1736,-1908,-2079,-2249,-2419,-2588,-2756,-2923,
    -3090,-3255,-3420,-3583,-3746,-3907,-4067,-4226,-4383,
    -4539,-4694,-4848,-4999,-5150,-5299,-5446,-5591,-5735,
    -5877,-6018,-6156,-6293,-6427,-6560,-6691,-6819,-6946,
    -7071,-7193,-7313,-7431,-7547,-7660,-7771,-7880,-7986,
    -8090,-8191,-8290,-8386,-8480,-8571,-8660,-8746,-8829,
    -8910,-8987,-9063,-9135,-9205,-9271,-9335,-9396,-9455,
    -9510,-9563,-9612,-9659,-9702,-9743,-9781,-9816,-9848,
    -9876,-9902,-9925,-9945,-9961,-9975,-9986,-9993,-9998,
    -10000,-9998,-9993,-9986,-9975,-9961,-9945,-9925,-9902,
    -9876,-9848,-9816,-9781,-9743,-9702,-9659,-9612,-9563,
    -9510,-9455,-9396,-9335,-9271,-9205,-9135,-9063,-8987,
    -8910,-8829,-8746,-8660,-8571,-8480,-8386,-8290,-8191,
    -8090,-7986,-7880,-7771,-7660,-7547,-7431,-7313,-7193,
    -7071,-6946,-6819,-6691,-6560,-6427,-6293,-6156,-6018,
    -5877,-5735,-5591,-5446,-5299,-5150,-5000,-4848,-4694,
    -4539,-4383,-4226,-4067,-3907,-3746,-3583,-3420,-3255,
    -3090,-2923,-2756,-2588,-2419,-2249,-2079,-1908,-1736,
    -1564,-1391,-1218,-1045,-871,-697,-523,-348,-174
};

PROGMEM const uint8_t degree_lookup[]= {
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,5,11,16,22,28,33,39,45,50,56,61,67,
    73,78,84,90,95,101,106,112,118,123,129,135,140,146,151,
    157,163,168,174,0,11,22,33,45,56,67,78,90,101,112,
    123,135,146,157,168,0,11,22,33,44,56,67,78,90,101,
    112,123,134,146,157,168,0,16,33,50,67,84,101,118,135,
    151,168,5,22,39,56,73,90,106,123,140,157,174,11,28,
    45,61,78,95,112,129,146,163,0,22,45,67,90,112,135,
    157,0,22,44,67,90,112,134,157,0,22,45,67,89,112,
    134,157,0,22,45,67,89,112,135,157,0,28,56,84,112,
    140,168,16,44,73,101,129,157,5,33,61,89,118,146,174,
    22,50,78,106,135,163,11,39,67,95,123,151,0,33,67,
    101,135,168,22,56,90,123,157,11,45,78,112,146,0,33,
    67,101,135,168,22,56,90,123,157,11,44,78,112,146,0,
    39,78,118,157,16,56,95,134,174,33,73,112,151,11,50,
    89,129,168,28,67,106,146,5,44,84,123,163,22,61,101,
    140,0,45,90,135,0,44,90,134,0,45,89,134,0,45,
    89,135,0,44,90,135,179,44,89,134,0,45,90,134,179,
    44,90,135,0,50,101,151,22,73,123,174,45,95,146,16,
    67,118,168,39,90,140,11,61,112,163,33,84,134,5,56,
    106,157,28,78,129,0,56,112,168,44,101,157,33,89,146,
    22,78,135,11,67,123,179,56,112,168,45,101,157,33,90,
    146,22,78,134,11,67,123,0,61,123,5,67,129,11,73,
    134,16,78,140,22,84,146,28,89,151,33,95,157,39,101,
    163,44,106,168,50,112,174,56,118,0,67,135,22,90,157,
    45,112,0,67,135,22,90,157,44,112,0,67,134,22,90,
    157,44,112,0,67,134,22,89,157,45,112,0,73,146,39,
    112,5,78,151,45,118,11,84,157,50,123,16,90,163,56,
    129,22,95,168,61,134,28,101,174,67,140,33,106,0,78,
    157,56,134,33,112,11,89,168,67,146,44,123,22,101,179,
    78,157,56,134,33,112,11,89,168,67,146,44,123,22,101,
    0,84,168,73,157,61,146,50,135,39,123,28,112,16,101,
    5,90,174,78,163,67,151,56,140,45,129,33,118,22,106,
    11,95
};

To compile it using avr-gcc in linux, check my previous post (atmega32 based wav player), there I have explained it in detail.

66 comments :

  1. nice project!
    I would like to do almost the same thing for my Amp. :-)

    ReplyDelete
  2. Hi, nice project.

    Can you tell how much percent of memory you used and how much still available?

    Thanks

    ReplyDelete
  3. Wouldn't it be faster if you multiply the sin and cos values by a power of 2, instead of 10000? That way multiplying and dividing is only a matter of shifting.

    ReplyDelete
  4. nice project

    Do you happen to have an Arduino PDE sketch for the code ?

    Regards

    Rupert

    ReplyDelete
  5. @REGISCRUZBR:
    memory used = 9710 bytes (FLASH) out of 32KB


    @Laurens:
    Yes it will become faster if we are using a value 2^x. But any way in my code, that division operations with 10000 is less in number.So the overall effect will be negligible compared to the total time taken for all other operations. But stil it is a great point which we should remember. Thanks for reminding me....

    @Rupert Hirst:
    Sorry I don't have it.. But I think already some one have ported an FFT library for arduino. So, you can have a google search for it. I think it is there...

    ReplyDelete
  6. @REGISCRUZBR:
    Actually I told it is 9710bytes with optimization -O3 in avr-gcc.
    If I am using size optimization -Os then the size become just 3708 bytes. Both are working fine and couldn't feel any problem with the performance with using size optimization.....

    ReplyDelete
  7. Why did you put a low pass filter (with a cutoff frequency of 2.821 kHz) between the opamp and the ADC? Are the values for R5 and C8 correct in the schematic? The video clearly showed it was sensitive to frequencies greater than 3k.

    ReplyDelete
  8. Actually that mic pre-amp schematic is copied from my previous post, so I forgot to change the design there. But here, I didn't used it while testing... (We can use .01 uF and 1.5K here) I will update that schematic soon..

    ReplyDelete
  9. thank you , it is great
    how about , if i do it by 16f877a ???

    P/s : my english is not good .

    ReplyDelete
  10. Great Work, but a question: You choose to use Mega32 because of bigger SRAM size or it is possible to run the program on smaller AVRs like Mega8?

    ReplyDelete
  11. @thientanvt:
    In PICF877a, I believe there is no hardware multiplier. If I am right, then it will be little more slow in PIC16f877a.

    @sحامد. د :
    RAM will not be a problem here. Possible chance is a fash overflow. But still I think it will not overflow since atmega8 have 8KB flash.

    ReplyDelete
  12. Hello, great work! I have a few questions though. I am trying to compile the source code using AVR Studio (or ATMEL Studio 6.0), and I keep getting the message "main must return int" and the compilation fails. I am not acustomed with creating makefiles (that is why I use AVR studio, not avr-gcc) and I was hoping you could give me a few suggestions on how to solve my issue. Thank you

    ReplyDelete
  13. If it is showing like that, then try using "int main" instead of "void main" and at last (at the END of main, just put "return 0" and try to compile it...

    ReplyDelete
  14. Greetings friend ... I'm really a rookie, I have a problem with the simulation please if you could help me in ISIS Proteus

    ReplyDelete
  15. postingan yang anda buat bagus,,,,,,,,,

    ReplyDelete
  16. Can I replace the 16MHz crystal with the smaller one? Does it affect the calculation & result? Please reply..

    ReplyDelete
  17. Hi, I just tried to build your circuit and I had a hard time figuring out why it wouldn't work...
    Turns out that you swapped PD5 and PD6 on your schematics.
    PD5 should go to E and PD6 should go to RS.

    Thank you for another fun project on your blog :)

    ReplyDelete
  18. Ooops...Actually it was a drawing mistake....;)..
    Any way I will modify it in code now...

    ReplyDelete
  19. No problem, I like to have to debug, it's not fun when something works on the first try ;)

    I was wondering... How can I increase the microphone sensitivity, which resistor(s) should I fiddle with ?

    ReplyDelete
  20. hey vinod

    i am a 3rd year btech student and i liked this project of yours very much..
    please could you tell me the code which you have given above..in which compiler should i run it..because running it in C is not successful due to header files and libraries not available in C..
    reply asap

    ReplyDelete
  21. @avioIO IIST: you can use AVR Studio if you're running windows (full featured environment), or avr-gcc on linux (command line)

    ReplyDelete
  22. i have AVR studio 4..created a new source file..copied the code in it..created a new header file..copied the the lookup table and saved it with lookup.h ..... now when i compile the code it is giving no error, however when i buil it it is showing the following error
    "avr-objcopy: 'instrue.elf': No such file"

    instrue is the name of project and c file..

    do i need to connect my hardware and MCU to build it??

    and do i have to header files or there are some pre added files to the project??

    ReplyDelete
  23. please guys i need urgent help..just have a ay's time more

    ReplyDelete
  24. Ok, now that you've got avr-gcc on your computer (AVR Studio installed it) it may be simpler to build the project using the command line.
    First take the Makefile from the atmega32 based wav player project that's somewhere on this website then copy it next to your .c .h files and modify it to work with these sources.
    Make sure that the "make" command is in your PATH environment variable.
    In a DOS prompt cd to your source folder.
    type "make" and it should build the .hex to flash onto your AVR chip.

    ReplyDelete
  25. If you have avr-studio in your windows, then just copy the two files to the build environment (I am not much familiar with avr-studio gui app). Then a simple build will give the hex I guess... Just modify the compiler optimization to -O3, it will be there in build properties.

    Now if you are using a command line, things are very easy as goebish said....
    avr-gcc -mmcu=atmega32 -O3 -I./ -o project.out main.c
    avr-objcopy -j .text -j .data -O ihex project.out project.hex

    Now to burn it, the command depends on the tool you are using.... Almost all burning hardware will be there in the avr-dude list...
    for example to burn the hex using usbasp programmer, u need to type
    avrdude -c usbasp -p m32 -u -U flash:w:project.hex:i

    in linux may be u need to create a udev rule for usbasp otherwise need to add a sudo infront of avr-dude . ie "sudo avrdude --------"

    Just type

    ReplyDelete
  26. You may also need to set your fuses correctly before burning the .hex, here's the command line for usbasp too:
    avrdude -p m32 -c usbasp -U lfuse:w:0xef:m

    ReplyDelete
  27. guys..what i did is..
    I have downloaded AVR studio 4
    Started a new project..added a new file to the project under source files..copied the C code to it..
    Then added lookup.h under libraries..
    compiled and Build..

    it gave the following error

    Build started 21.10.2012 at 17:31:45
    mmcu=atmega32a -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT instrue.o -MF dep/instrue.o.d -c ../instrue.c
    /usr/bin/sh: -Wall: command not found
    make: [instrue.o] Error 127 (ignored)
    mmcu=atmega32a -Wl,-Map=instrue.map instrue.o -o instrue.elf
    /usr/bin/sh: -Wl,-Map=instrue.map: command not found
    make: [instrue.elf] Error 127 (ignored)
    avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature instrue.elf instrue.hex
    avr-objcopy: 'instrue.elf': No such file
    make: *** [instrue.hex] Error 1
    Build failed with 1 errors and 0 warnings...


    have no idea what it means..

    and
    @goebish : i am not able to find the make file..
    and how to add it..please help

    ReplyDelete
  28. Forget about AVR studio, I don't use it a lot neither (only when I need to debug with my AVR Dragon).
    Use the command line (just make sure your environment variables are OK for avr-gcc).
    You can do just as Vinod explained and you won't require a Makefile, or you can get the AVR wav player Makefile there: http://bit.ly/OTrtQt ,it works with this project too.

    ReplyDelete
  29. This comment has been removed by the author.

    ReplyDelete
  30. I can't find the post that you explain how to compile it into atmega32.

    Can you explain it again or send us the page?

    I really have no idea how to do it "/
    how can i link my pc to the atmega?
    Via arduino or something?

    ReplyDelete
  31. i can get my preamp to work i think... i should test it on oscilloscope

    ReplyDelete
  32. This comment has been removed by the author.

    ReplyDelete
  33. why is it in 0 - 10KHz why not in 0~20KHz or in 20Hz~20KHz its the audio rang? my e-mail is manoj_srilanaka@hotmail.com

    ReplyDelete
  34. You are using external voltage reference for ADC, but adc_init() in source code sets this to internal 2.56V.

    ReplyDelete
  35. Hello, I would like to know how you calculated table values ​​of angles. I know sixteen frequency bands that form the spectrum and the amplitude of each frequency band is given by the sum of 32 words, then the table must have 512-degree terms. However, I did not understand how the values ​​were obtained.

    ReplyDelete
  36. What IDE did you use? Was it CodeVision AVR?
    thanks for your information. it's very useful for me

    ReplyDelete
  37. hex code sent for the projects tank

    ReplyDelete
  38. its an amazing project...well done sir

    ReplyDelete
  39. Please send me the project for ISIS. e-Mail: megalooser@gmail.com
    i cant run it on proteus

    ReplyDelete
  40. This comment has been removed by the author.

    ReplyDelete
  41. Hi there
    What is the Vcc value ?
    12 v?
    Thank you

    ReplyDelete
  42. Hi there
    What is the Vcc value ?
    12 v?
    Thank you

    ReplyDelete
  43. i can't make hex file by code vision! plz help me...
    if u have hex file plz send me email: omid0740@gmail.com
    thanks...

    ReplyDelete
  44. Sir, I downloaded the program into ATMEGA16 but the LCD didn't show anything. What was the problem? Please, help me. Thx.

    ReplyDelete
  45. Try keeping the pins D0,D1,D2 and D3 open by removing the connection from GND.

    ReplyDelete
  46. i found on internet your code:
    https://github.com/vinodstanur/dft-based-audio-spectrum-analyzer-using-atmega32-and-16x2-lcd
    The library lookup.h in that webside alot much more than that you post above.?? i wonder if the longer one is the better?
    Beside that. i found hex file in that webside. Can i use that file too? may i swap pd5 and pd6 when use that.

    ReplyDelete
  47. when i build hex file form your codes in avr studio: i found 3 warning of not using temp_value ; temp_index ; j
    I wonder why you put them there
    I'm new to microcontroller so i met problem with fusebit. Is it true when i set CKSEL 0, 1,2,3 to 1 and CKOPT to 0 to use external 16MHZ crystal
    and i set JTAGEN to 1 to be able to access port C is it Right? Other bits are set default. Am i Right? please help me. I'm desperate for the circuit to run.

    ReplyDelete
  48. Can I use audio input from mobile phone instead of mic?

    ReplyDelete
  49. For that you can remove R4 and mic. And connect audio signal across the capacitor and gnd. But one issue is, audio signal from mobile phone audio socket is more powerful than mic signal, so in this case you have to reduce the gain of amplifier by reducing value of R1 and increasing value of R9, you may need to play with it.

    ReplyDelete
  50. This comment has been removed by the author.

    ReplyDelete
  51. This comment has been removed by the author.

    ReplyDelete
  52. what will be the changes for 20*4 LCD?
    can u please explain

    ReplyDelete
  53. What will the changes for 20*4 lcd?
    can u please explain?(Sorry for my bad english)

    ReplyDelete
  54. hi
    can i compile the source code with codevision or bascom or etc?

    ReplyDelete
  55. Hii sir your work is excellent.I'm from thrissur, doing btech computer science.I'm very interested in embedded electronics.how to change the code for 16*2 lcd to 20*4 lcd can you please explain
    Email : nakzhatra@gmail.com

    ReplyDelete
  56. How do I enter the library "lookup.h" to this project code in Atmel studio?

    ReplyDelete
  57. Vinod, can u please rearrange the code for this project. .bas and .hex codes are given and Please send me to lan2882@gmail.com

    http://www.instructables.com/id/AVR-acoustic-spectrum-analyzer/

    ReplyDelete
  58. Characteristically of much code shared on the internet, the documentation is lacking and renders it difficult to port to another platform. For an explanation of how this works, the sine and cosine tables are generated by computing the functions over 360 points form 0 to 2 PI. The degree lookup table was generated deg[j+k*N] = (int) (2*pi*j*k/N) module 2*pi) where j covers the range of 0 to N-1 and k ranges from 0 to N/2 -1. The "k" for loop is the outside loop. The degree lookup table generates an index used in the sine and cosine tables. Since the Fu array elements are accumulators and hence the TRANSFORM code above should initialize the Fu arrays upon entry.

    ReplyDelete
  59. Hey. And how can you determine the frequency peaks?

    ReplyDelete
  60. Build started 22.2.2018 at 14:04:09
    avr32-gcc -mmcu=atmega32 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT mega32.o -MF dep/mega32.o.d -c ../mega32.c
    make: *** [mega32.o] Error 1

    cc1.exe: error: unrecognized command line option "-mmcu=atmega32"
    Build failed with 1 errors and 0 warnings...

    ReplyDelete
  61. Talking about electronics, Xender is an amazing app to share files on pc. Xender for windows phone

    ReplyDelete
  62. This comment has been removed by the author.

    ReplyDelete
  63. This comment has been removed by the author.

    ReplyDelete
  64. This comment has been removed by the author.

    ReplyDelete