Jump to content
simpleavr

Educational BoosterPack 8 bit FFT Spectrum Analyzer Attempt

Recommended Posts

So what have you been doing with your Educational BoosterPack lately  :smile:

 

 

  • This is based on the fix_fft code that's been floating around for many years.
  • I tried both 16 bit and 8 bit, currently fixed to 8 bit as I see no difference for my needs (i.e. limited precision, range), I would invest in a good pre-amp for better results.

 

Things to do

  • More precision timing to achieve the frequency band I want.
  • Better front-end, currently using 1/2 LM258.
  • Adopt non-linear horizontal scale, currently linear scale at about 800Hz...1.6Khz, 2.4KHz, 3.2Khz....
  • Adopt logarithm amplitude to make the bars make sense to your eyes.
  • Add / enhance effects like attack / retreat rate.
  • Add dynamic sampling / scaling to input signals.

Share this post


Link to post
Share on other sites

That is awesome! Nice work! I sent a link to the CircuitCo folks who made that BoosterPack. I think they'll like it!

 

Thanks

 

I am going to post it on TI forum when finished. My friends here are more tolerating on my incomplete work.

 

Will have more details and code when things progresses.

 

Right now it can do 16 bands w/ 32 samples or 32 bands w/ 64 samples, I display only 16 as display is confined by the LCD. It measures up to 16Khz in either case.

 

At 32 bands, It's 500Hz between amplitudes and I can pick 500Hz, 1Khz, 1.5Khz on low end, with 12Khz, 14Khz, 16Khz on the high end. But still I want to find a way to do have 60Hz, 120Hz, 200Hz etc at the low end of the spectrum. Will try to do two pass w/ different sampling rate and see if it could work.

 

Also thanks Rei Vilo for the excellent review on the BoosterPack, I relied on the information / links when building this.

Share this post


Link to post
Share on other sites

Also thanks Rei Vilo for the excellent review on the BoosterPack, I relied on the information / links when building this.

 

You're welcome!

 

This is really an impressive project. Do you plan to use the Educational BoosterPack built-in microphone?

Share this post


Link to post
Share on other sites

You're welcome!

 

This is really an impressive project. Do you plan to use the Educational BoosterPack built-in microphone?

 

Thanks for your comment.

 

I did not start out w/ the microphone, but I just did when I tried to explore / maximize what to do w/ the booster. Will upload a video in a day or two.

 

As a bonus, I also utilize the booster potentiometer to bias / offset my op-amp input.

 

Now the front-end use a single 358 and do two stages before going back to ADC4. And I use the potentiometer to bias the input voltage. I worked out very nicely to my liking.

 

You will noticed in the original video, the high-bands are all off, that's caused by doing very high gain and only one stage, plus the 358 is not good at high frequencies.

 

I did change my sampling to have it limited to 8Khz (on 32 bands, which I hand-pick 16 to display on LCD). The reason is I don't have good op-amps handy for the gain bandwidth. A LM324 would do a little bit better but you really need to order audio grade to handle the job. As just an experiment, I am not going to invest.

 

I am happy enough to post the code, also in a day or so.

 

//   LM358 Dual Op-Amp, GBW @0.7Mhz, each stage @x100 gain, bandwidth is 7Khz
//
//                     +------------------------------+
//                    _|_                             |
//                    ___                             |
//                   + |   ---------------            |
//                     +-1|----.       Vcc|8          |
//                     |. |    ^      .---|7--+-------|-----o (A)
//                100k| | |   / \     ^   |   |.      |.
//                    |_| |  /__+\   / \  |  | |100k | |1k
//       0.1u          |  |   | |   /__+\ |  |_|     |_|
// ( o--||--[ 1k  ]--+-2|---+ |    | |  |   |       |
// (C) o-------------+---3|-----+    +-|--|6--+-------+
//                   |   4|Gnd         +--|5----+
//                   |     ---------------      |
//                   |                          |
//                   +--------------------------+
//
//  (A) to P1.4 EduBoost Mic jumper middle pin
//  ( to Condenser Mic, EduBoost Mic Jumper top pin 
//  (C) to Potentiometer, EduBooster Potentiometer Jumper top pin
//  (*) connect Gnd + Vcc to Launchpad

//

/EDIT fixed smileys in code.

 

 

 

Share this post


Link to post
Share on other sites

Features:

 

  • 8 bit integer FFT
  • 32 samples at 500Hz separation
  • shows 16 amplitudes of 250Hz, 500Hz, 750Hz,....... 5.75Khz, 6.75Khz, 7.75Khz non-linear
  • partial logarithm map to show amplitudes, limited as resolution has been reduced for 8 bit FFT
  • LM358 two stage mic pre-amp at 100x 100x gain (can be improve vastly w/ better op-amps)
  • utilize Educational BoosterPack; mic for input, potentiometer for pre-amp biasing
  • draws power from launchpad
  • square signal generator from TA0.1 toggling, good for initial testing

 

 

IMAG0564.jpg

 

 

A longer video showing off the action. Although it may not show well on youtube, but I am surprise w/ the result (consider being a "toy"). The system is very responsive via the microphone and there are no annoying noise levels (I think it's w/ the pre-amp biasing and the reduced resolution.

 

I had built similar one w/ AVR before and I found that it's a lot easier to work w/ on msp430. The timer architecture and being 16 bit is an advantage here.

 

 

 

code to follow..

Share this post


Link to post
Share on other sites

I had created the github project lp_8bitfft.

 

https://github.com/simpleavr/lp_8bitfft

 

@@RobG

 

I wish you a good show and an enjoyable one.

I can build on gcc and ccs but did not try to run the ccs firmware.

I spent more time on the op-amp front-end. There are other general op-amps that can do the job but I want 3V power source, so I had to settle for the LM358.

I hope I had comment enough so others can make adjustments easily, and let me know if I miss something.

I am not a mathematician and really don't understand FFT, I just use the "black box".

Share this post


Link to post
Share on other sites

I love this post so much! I can't wait to see when you post it on the TI Forums. 

This is a great project for students :-)

 

Thank you so much for sharing (and your awesome photos). 

Share this post


Link to post
Share on other sites

@@LariSan

 

Thanks for your comment. It would look great on one of your proto plates. You may want to put one together, it only requires a few common components.

 

@@RobG

 

I just added buzzer support (don't understand why I had missed that). Now the P1.3 button will cycle thru (1) no output, (2) P1.6 green LED output, (3) P2.6 buzzer output. The buzzer output you will see the bars not showing up at what it should be. I would suspect it being the frequency response / limit of both the buzzer and the condenser microphone.

 

You may want to do another pull if you are building. Also we need the -lm flag to link the math library.

 

Code is not optimized. They are places that could use some in-line assembler to speed things up if anyone is interested.

Share this post


Link to post
Share on other sites

Nice project!

Am I the only one seeing these posts coming from the future?

post-26656-0-28473700-1373128545_thumb.jpg

View the pic and look down at my date / time in the corner.

 

Never mind. I just realized it's July, not June now. :oops:

Share this post


Link to post
Share on other sites

Hi,

 

Having a nice matrix led display laying around with no use of I assembled a test circuit with launchpad and modified the code of @simpleavr to run on it.

post-13119-0-69689700-1448740018_thumb.jpg

The display is driven by four MAX7219 chips chained on SPI bus.

I noticed that the only floating point operation that your code was using is a square root operation in line 257. Once I added a fixed-point square root routine, linking with math lib is not necessary anymore - spared a lot of flash space. The fixed-point routine is also 3 times faster than mathlib floating point one: 50us vs 150us

#ifdef FLOATING_POINT
// sqrt: 150us
#include <math.h>
#else // FLOATING_POINT
// 50us
unsigned char sqrt16(unsigned short a) {
        unsigned short rem = 0, root = 0;
        int i;
        for(i = 0; i < 8; ++i) {
                root <<= 1;
                rem = ((rem << 2) + (a >> 14));
                a <<= 2;
                ++root;

                if(root <= rem) {
                        rem -= root;
                        ++root;
                } else {
                        --root;
                }
        }
        return (unsigned char)(root >> 1);
}
#endif // FLOATING_POINT

Further I've added Hamm windowing to minimize spectral leakage:

// scilab 255 * window('kr',64,6)
//const unsigned short hamming[32] = { 4, 6, 9, 13, 17, 23, 29, 35, 43, 51, 60, 70, 80, 91, 102, 114, 126, 138, 151, 163, 175, 187, 198, 208, 218, 227, 234, 241, 247, 251, 253, 255 };
// scilab 255 * window('kr',64,4)
const unsigned short hamming[32] = { 23, 29, 35, 42, 50, 58, 66, 75, 84, 94, 104, 113, 124, 134, 144, 154, 164, 174, 183, 192, 201, 210, 217, 224, 231, 237, 242, 246, 250, 252, 254, 255 };
// scilab 255 * window('kr',64,2)
//const unsigned short hamming[32] = { 112, 119, 126, 133, 140, 147, 154, 161, 167, 174, 180, 186, 192, 198, 204, 209, 214, 219, 224, 228, 232, 236, 239, 242, 245, 247, 250, 251, 253, 254, 255, 255 };

Applying windowing on 32 samples uses fixed point math:

	for (i=0;i<Nx;i++) {
		int hamm = hamming[i<(FFT_SIZE-1)?i:(Nx-1)-i] * data[i];
		data[i] = (hamm >> 8);
	}

Finally the display buffer is filled in with output of FFT function:

        unsigned long mask = 1UL;
        for (i=0; i<32; ++i, mask <<= 1) {
            for(j=0;j<8;++j) {
                if(j<plot[i])
                    dbuff.ulongs[j] |= mask;
                else
                    dbuff.ulongs[j] &= ~(mask);
            }
        }

where dbuff is display buffer organized as:

typedef union
{
	unsigned long longs;
	unsigned int ints[2];
	unsigned char chars[4];
} longbytes;

union {
	unsigned char bytes[8*4];
	longbytes lbytes[8];
	unsigned long ulongs[8];
} dbuff;

which make it easy to manipulate:

unsigned char spibuff[8];

void SPI_Write(unsigned char* array) {
	P2OUT &= ~LED_CS;
	__delay_cycles(50);
	unsigned int h = 8;
	while(h) {
		UCB0TXBUF = *array;
		while (UCB0STAT & UCBUSY);
		++array; --h;
	}
	P2OUT |= LED_CS;
}

void update_display() {
	unsigned char i;
	for(i = 0; i < 8; ++i) {
		spibuff[0] = spibuff[2] = spibuff[4] = spibuff[6] = i+1;
		spibuff[1] = dbuff.lbytes[i].chars[3];
		spibuff[3] = dbuff.lbytes[i].chars[2];
		spibuff[5] = dbuff.lbytes[i].chars[1];
		spibuff[7] = dbuff.lbytes[i].chars[0];
		SPI_Write(spibuff);
	}
}

BTW I got a second 8x32 led matrix displays from the same ebay offer, and it turned out to be mirrored - LED matrix is turned around 180deg, so the update_display() routine for the other one have to push bytes in order 0 through 3, and bit-shift operations ( << and >> ) yield opposite display reaction (left vs right scroll).

 

https://youtu.be/Nen6yd5kvZs

 

s.

 

Edit: correct photo attachement and source code snippets

led_fft.tar.bz2

Edited by sq7bti

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×