Author Topic: Sine wave lookup table  (Read 13911 times)

0 Members and 1 Guest are viewing this topic.

Offline rcbuckTopic starter

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: us
Sine wave lookup table
« on: April 28, 2017, 03:17:30 am »
I have a PIC32 and want to use SPI to send data to a MCP4901 DAC to generate a 1 KHz sine wave.

Can someone point me to a link that explains how lookup tables are used to generate sine waves? Or explain how it works? I've searched online but all I have found are complex formulas.

I would like to use a table with 256 values and just need to know how often to step through the table. I guess the idea is to take each value and send it to the MCP4901.
 

Offline ebclr

  • Super Contributor
  • ***
  • Posts: 2328
  • Country: 00
Re: Sine wave lookup table
« Reply #1 on: April 28, 2017, 03:50:30 am »
Basically, you define on an array of variables from 0 to 90 degree precalculated and play with inversion for the signal for others degrees, in other words, you need to define only 1/4 of the cycle, the remaining 3 are easy inversion or 1 subtraction or both.

You can define the full cycle, will be a little faster but will take more memory, after that a simple do-while loop, will simple change the index from the table to the AD ( or 4  for the  reduce memory ) will do the job
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7727
  • Country: ca
Re: Sine wave lookup table
« Reply #2 on: April 28, 2017, 06:28:57 am »
Now if you want to see a discussion of how to go about generating a sine table, either integer/floating with and without the sin(x) function, it's been thoroughly  :horse: over here:
https://www.eevblog.com/forum/microcontrollers/code-used-for-sine-table/
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Sine wave lookup table
« Reply #3 on: April 28, 2017, 08:01:41 am »
Best thing to try.

Use a 32-bit phase accumulator and step size
  uint_32 phase, step;

Use the top8 bits to index your table:

  sample = table[phase>>24];
  phase += step;

Frequency resolution is then (sample_rate/2^32) Hz.

'step' can be calculated as 2^32/sample_rate*desired_freq.
E.g.a step value of 1 would take 2^32 samples before 'phase' overflows back to zero.
or a step value of 2^20 would take 1024 samples to walk through the table back to zero.

It is quick, simple to code and hard to get wrong. :-)

Also, when making you lookup table think about if table entry 'i' is the value at i/n (where n is the size of the table, and I is from 0 to n-1) or is it the value at (2i+1)/2n, which is the middle of the sample period? One gives you a more symtrical table.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline amspire

  • Super Contributor
  • ***
  • Posts: 3802
  • Country: au
Re: Sine wave lookup table
« Reply #4 on: April 28, 2017, 08:28:58 am »
The approach that probably hasn't been discussed much is to ditch the dac, and use a PWM using Don Lancaster's Magic Sinewaves. This is a PWM stream that has harmonic cancellation - so for example with 6 PWM pulses per quadrant, you can have no harmonics below the 25th harmonic.

http://www.tinaja.com/msquant/retry_m/xxxx.shtml



With a 16MHz clock, if you can get the cpu's PWM to output the right pulses, you can achieve 1Khz with 0.108% distortion - as long as you have a filter to cut out 25Khz and above. All without a DAC.

A little bit of work to turn one quadrant into 4 quadrants, but it all can be done. Not as easy or as versatile as a DAC, but for some applications, it can be perfect.

Don's calculator is written in Javascript, so you can capture the page and run it offline. The more pulses per quadrant (for a fixed clock), the higher you can push the first harmonic at the cost of distortion. With 2 pulses per quadrant, you can reduce the distortion to 0.04%, but the first harmonic is the 9th. If you have a fixed frequency, the ideal filter will have a notch (zero) at the frequency of the first harmonic - something like an elliptical filter. The first uncancelled harmonic is always really big.
« Last Edit: April 28, 2017, 08:53:57 am by amspire »
 
The following users thanked this post: ebclr

Online Phoenix

  • Frequent Contributor
  • **
  • Posts: 422
  • Country: au
Re: Sine wave lookup table
« Reply #5 on: April 28, 2017, 08:32:07 am »
It is quick, simple to code and hard to get wrong. :-)

I have had granuality problems generating sine with straight lookup, with some slightly more complex linear interpolation you can get a much cleaner sine wave. Great for arbitrary carrier/lookup frequency vs fundemental frequency.
 

Offline danadak

  • Super Contributor
  • ***
  • Posts: 1875
  • Country: us
  • Reactor Operator SSN-583, Retired EE
Love Cypress PSOC, ATTiny, Bit Slice, OpAmps, Oscilloscopes, and Analog Gurus like Pease, Miller, Widlar, Dobkin, obsessed with being an engineer
 
The following users thanked this post: ebclr

Offline rcbuckTopic starter

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: us
Re: Sine wave lookup table
« Reply #7 on: April 28, 2017, 04:59:07 pm »
Thanks everyone for the suggestions. I will see if I can make one of them work. The PIC is running at 80 MHz so speed isn't an issue.

Quote
The approach that probably hasn't been discussed much is to ditch the dac
This is just a temporary thing to verify SPI code for the DAC is working. I will not be using the sine wave code in my project.

The project will take an analog signal into ADC channel 0. I will send the upper 8 bits to the DAC over SPI. I should hear the same audio out of the DAC that goes into the ADC. The problem I have is the ADC is working but I cannot get anything out of the DAC. It must be some kind of issue with the SPI communication to the DAC. The SPI works with a 25LC256 so I don't know why the DAC doesn't work. I figured the best way to solve the DAC problem was to just generate a tone and send that to the DAC.

I am doing all this on one board just for initial confirmation that everything works. Once I can get the ADC to DAC working on one board I will know my code is correct. The final step is to have the ADC output sent over Ethernet to a second board. The second board will receive the Ethernet data and send it to the DAC. This will be a 2 way link. Board one's ADC output will be reproduced at board two's DAC and vice-versa. I already have the client/server code working and can pass text message back and forth.
 

Offline rcbuckTopic starter

  • Frequent Contributor
  • **
  • Posts: 346
  • Country: us
Re: Sine wave lookup table
« Reply #8 on: April 28, 2017, 07:22:02 pm »
Quote
You are not generating the proper CHIP SELECT (and any other needed ENABLE) signals for the part

Sometimes the dumb things bite you in the ass. I verified the Vdd and Vss voltages were correct. This is a 4 layer board with internal power and ground planes so I didn't think that was the problem.

While verifying Vdd and Vss, I noticed the SDI pin of the MCP4901 was lifted off of its solder pad. I then remembered (how could I forget??) that I had done that. When I first brought the board up I had a problem with the PIC SPI engine communicating with the 25LC256. So I lifted the SDI pin of the DAC thinking it might have been interfering with the EEPROM chip. I got the 25LC256 working with software adjustments. But it was a couple of days later before I started working with the ADC/DAC code. By then I had forgotten the small detail about the DAC pin.

I just soldered the pin back down. Now when I inject a 1KHz tone into the ADC and send the ADC output bytes to the DAC, I hear the tone in my monitor speaker. The DAC is driving an onboard MCP6001 which then drives an external amplifier.

Like Hannibal, I like it when a plan comes together.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf