logo elektroda
logo elektroda
X
logo elektroda

How to Generate a Sine Wave Output Using 8-bit R/2R DAC on Arduino or PIC?

285 16
Best answers

How can I generate a sine-wave output from an 8-bit R/2R DAC on an Arduino or PIC?

Use a sine lookup table: calculate one cycle of sine values, scale them to the DAC range (for an 8-bit DAC, 0 to 255), and step through those values at a fixed rate to create the waveform [#21682865][#21682871] If your DAC cannot output negative voltages, offset the sine so it runs from 0 to 255 instead of -1 to +1 before scaling [#21682871] The time spacing between samples is set by your timer/sample rate, not by dividing the sine frequency by the number of DAC steps, because the DAC steps control amplitude resolution, not time [#21682878] For a fixed frequency, a precomputed table is the simplest method; for variable frequency, use a numerically controlled oscillator: add a fixed phase increment to an N-bit accumulator each clock, use the accumulator’s MSBs as the table address, and set the output frequency with frequency = clock_frequency × phase_increment / 2^N [#21682868] If needed, generate the table in Excel or a script, and using a power-of-2 table size like 256 makes indexing efficient [#21682865][#21682868]
Generated by the language model.
ADVERTISEMENT
  • #1 21682864
    Simon M
    Anonymous  
  • ADVERTISEMENT
  • #2 21682865
    Sean Ellis
    Anonymous  
  • ADVERTISEMENT
  • #3 21682866
    Simon M
    Anonymous  
  • #4 21682867
    Rick Curl
    Anonymous  
  • #5 21682868
    PeterTraneus Anderson
    Anonymous  
  • #6 21682869
    Simon M
    Anonymous  
  • #7 21682870
    Simon M
    Anonymous  
  • #8 21682871
    David Ashton
    Anonymous  
  • ADVERTISEMENT
  • #9 21682872
    David Ashton
    Anonymous  
  • #10 21682873
    Simon M
    Anonymous  
  • #11 21682874
    David Ashton
    Anonymous  
  • #12 21682875
    PeterTraneus Anderson
    Anonymous  
  • ADVERTISEMENT
  • #13 21682876
    Simon M
    Anonymous  
  • #14 21682877
    David Ashton
    Anonymous  
  • #15 21682878
    David Ashton
    Anonymous  
  • #16 21682879
    Simon M
    Anonymous  
  • #17 21682880
    PeterTraneus Anderson
    Anonymous  

Topic summary

✨ The discussion addresses generating a sine wave output using an 8-bit R/2R DAC connected to an Arduino or PIC microcontroller. The original project involved a 5-bit DAC producing a sine wave for a turntable motor driver, which was expanded to 8 bits, initially producing a triangle wave by counting linearly. To achieve a sine wave, the recommended approach is to use a sine lookup table representing one full cycle with a convenient number of steps (e.g., 256), allowing efficient indexing via bit shifts. The sine values can be precomputed using tools like Excel or Python scripts and stored in program memory. For fixed frequency output, the DAC values are stepped through at a rate corresponding to the desired frequency, calculated by dividing the clock frequency by the number of samples per cycle. For variable frequency, adjusting the step rate or interpolating between table values improves output quality. The numerically controlled oscillator (NCO) method involves a phase accumulator that increments by a phase increment value each clock cycle; the most significant bits of the accumulator address the sine table, producing the output frequency as a function of clock frequency and phase increment. Alternative hardware methods include using an 8-bit shift register (e.g., 4015) with weighted resistors to generate sine wave approximations. The discussion also clarifies that DAC resolution relates to amplitude steps, not time steps, and emphasizes the importance of matching sample rate and output frequency for accurate waveform generation.
Generated by the language model.

FAQ

TL;DR: Generate a clean sine by driving a 256‑entry “sinewave lookup table” with a phase‑accumulator; f_out = f_clk × phase_increment / 2^N. Statistic: 256 samples/cycle for an 8‑bit table. Quote: "sinewave lookup table". [Elektroda, Anonymous, post #21682868]

Quick Facts

How do I generate a sine wave with an 8‑bit R/2R DAC on Arduino or PIC?

Use a sine lookup table and step through it with a timer interrupt. Output each value to the R/2R pins. For variable pitch, change the step rate or use a phase accumulator for fractional stepping. Power‑of‑two table sizes simplify indexing. “Use a look‑up table.” [Elektroda, Anonymous, post #21682865]

How do I calculate sample values for a fixed 50 Hz sine?

Pick table length (e.g., 256). For entry k, value = round((sin(2πk/256)+1)×127.5). Export with Excel or Python. Scale to your DAC range and output with a fixed sample rate (256×50 = 12,800 updates/s for 256 entries). Expect minor rounding steps; low bit depth adds distortion. [Elektroda, Anonymous, post #21682871]

How do I set frequency precisely using a phase accumulator (DDS/NCO)?

Keep a N‑bit accumulator. Each tick add phase_increment. Use the top table‑address bits to read the sine table. Frequency is f_out = f_clk × phase_increment / 2^N. Change phase_increment at runtime to retune without rebuilding the table. [Elektroda, Anonymous, post #21682868]

What phase_increment do I need for 50 Hz?

Rearrange DDS: phase_increment = round(f_out × 2^N / f_clk). Example with 8‑bit accumulator: phase_increment = round(50 × 256 / f_clk). phase_increment = 1 gives f_out = f_clk/256 (statistic). Use a larger N for finer resolution and lower jitter. [Elektroda, Anonymous, post #21682880]

How many samples per cycle should I store?

Use a power‑of‑two length, like 256, for simple indexing and fast wrapping. For higher quality at the same rate, add linear interpolation between entries. For small tables, increase the update rate to push images higher. [Elektroda, Anonymous, post #21682865]

How can I change frequency without recalculating the table?

Keep the sine table fixed. Vary playback speed. Step faster for higher pitch and slower for lower. For smooth audio, interpolate between table entries at fractional addresses. This avoids heavy runtime sin() math on small MCUs. [Elektroda, Anonymous, post #21682865]

How do I save RAM/Flash for the sine table?

Store only the first quarter cycle. Recreate 0–360° by mirroring and sign‑inverting that quarter. Drive the DAC with those reconstructed values. This cuts table memory by 4× with identical output. [Elektroda, Anonymous, post #21682868]

How do I smooth the stepped DAC output into a cleaner sine?

Add a simple RC low‑pass after the R/2R ladder. If you clock 16× faster than the target sine, a modest RC removes most stair‑step energy. The shift‑register approach demonstrates this with 16× oversampling and filtering. [Elektroda, Anonymous, post #21682872]

What is the shift‑register sine method, and when is it useful?

Feed a CD4015 with a clock so its outputs fill with 1s then 0s. Weight each output with resistors chosen to approximate a sine. Filter the stepped sum with RC. It’s pin‑efficient and good for fixed 45–55 Hz sources. [Elektroda, Anonymous, post #21682872]

Why does my shift‑register DAC glitch at startup?

All flip‑flops must release reset on the same clock edge. Use a synchronous reset (e.g., gate through a D flip‑flop). As one expert warned, an unsynced release causes misoperation and waveform corruption. [Elektroda, Anonymous, post #21682875]

I divided 440 Hz by 32 for delays and got the wrong musical note. Why?

Fixed delays assume one sample per equal time step, but frequency accuracy depends on the sample clock, table length, and rounding. DDS solves this: set phase_increment = 440 × 2^N / f_clk for exact tuning, independent of table size. [Elektroda, Anonymous, post #21682880]

How do I make a bipolar sine with a unipolar DAC?

Add a DC offset before scaling. Use value = round((sinθ + 1) × half_scale). This shifts −1…+1 to 0…full scale. Quote: “If your DAC can’t do negative numbers…add 1 to the sine value.” [Elektroda, Anonymous, post #21682871]

Quick How‑To: 50 Hz sine on Arduino with an 8‑bit R/2R

  1. Precompute a 256‑entry 0–255 sine table and store in PROGMEM.
  2. Set a hardware timer to tick at 12,800 Hz; in ISR output table[idx].
  3. Increment idx with a phase accumulator to allow fine frequency control; wrap on overflow. [Elektroda, Anonymous, post #21682865]

Why do adjacent table entries sometimes repeat or jump by 2?

Rounding to integers and limited bit depth cause unequal steps. Expect small inconsistencies near peaks, with slight harmonic distortion. This is normal at 5–8 bits and improves with filtering or more bits. [Elektroda, Anonymous, post #21682871]

Can I do this with a 5‑bit DAC or only 8‑bit?

Yes. A 5‑bit ladder gives 32 amplitude levels. The sine works but has more quantization distortion. Filter the output and keep update frequency high to push errors out of band. [Elektroda, Anonymous, post #21682871]
Generated by the language model.
ADVERTISEMENT