Sine wave lookup table - Page 1
Forum section: electronics / general

author: rcbuck
author_rank: Frequent Contributor
timestamp: April 28, 2017, 03:17:30 am
content: 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.

author: ebclr
author_rank: Super Contributor
timestamp: April 28, 2017, 03:50:30 am
content: 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

author: BrianHG
author_rank: Super Contributor
timestamp: April 28, 2017, 06:28:57 am
content: 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 thoroughlyover here:https://www.eevblog.com/forum/microcontrollers/code-used-for-sine-table/

author: hamster_nz
author_rank: Super Contributor
timestamp: April 28, 2017, 08:01:41 am
content: Best thing to try.Use a 32-bit phase accumulator and step sizeuint_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.

author: amspire
author_rank: Super Contributor
timestamp: April 28, 2017, 08:28:58 am
content: 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.shtmlWith 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.

author: Phoenix
author_rank: Frequent Contributor
timestamp: April 28, 2017, 08:32:07 am
content: Quote from: hamster_nz on April 28, 2017, 08:01:41 amI 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.

author: danadak
author_rank: Super Contributor
timestamp: April 28, 2017, 11:02:54 am
content: Some ref material -No table needed, just IIR structurehttp://www.cypress.com/forum/psoc-community-components/simple-dds-state-variable-iirUse PSOC WAVEDAChttp://ww1.microchip.com/downloads/en/AppNotes/00001523A.pdfhttp://www.atmel.com/Images/Atmel-2542-Using-the-AVR-High-speed-PWM_ApplicationNote_AVR131.pdfhttp://www.xilinx.com/support/documentation/application_notes/xapp448.pdfRegards, Dana.

author: rcbuck
author_rank: Frequent Contributor
timestamp: April 28, 2017, 04:59:07 pm
content: 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.QuoteThis 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.

author: rcbuck
author_rank: Frequent Contributor
timestamp: April 28, 2017, 07:22:02 pm
content: QuoteSometimes 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.