Shop OBEX P1 Docs P2 Docs Learn Events
Generating high frequency signal with parallel DAC - Page 3 — Parallax Forums

Generating high frequency signal with parallel DAC

13»

Comments

  • deSilvadeSilva Posts: 2,967
    edited 2008-02-08 15:53
    Phil Pilgrim (PhiPi) said...
    ... I guess my point is that with a smooth enough function, the realized resolution can be computed over a time span comprising multiple data points.
    Right, Phil! I think I argued in the same direction above, when saying you only need 2 bits of true information to distinguish between square, sine, sawtooth, and triangle smile.gif The distortion wrt the requested KIND of function depends much on the downstream signal conditioning, for the better or for the worse smile.gif

    Considering arbitrary signal forms (continious ones, of course) the information in a PWM signal of a defined period is limited to ld(period/clock). A (high-order) lowpass with a cut frequency around that period will be able to generate nearly a full voltage swing. This by definition will allow you to generate any signal containing harmonics upto 1/(2*period).

    Especially when using PDM you sometimes do not strive for the "full voltage swing" during the period but for an incremental change of the voltage at the lowpass cap ("delta-sigma modulation") This is a good compromise exchanging resolution for higher harmonics.

    As you already said the low-pass must be dimensioned in a different way then, not for the period but for 10 or 100 * period depending of the needed harmonics.
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-10 09:33
    Another nice way for high speed DAC is using the video logic.
    You can either use the full 8 bit mode, alowing the shiftout of 4 parallel bytes in one WAITVID
    :loop
    WAITVID theLongAddress, #%%3210
    ADD :loop, bit9
    DJNZ nmbOfLongs, #:loop
    


    This will produce 256 samples in 256*3*50/4 ns = 8µs = 125kHz
    Videoclock has to be set to 37.5 MHz.

    Another option is to output true PWM by shifting 0/1 out of 8 independant channels.
    This is more tricky.

    A simplified version will use one channel only and 2-color mode. The shift sequence consists of 32 bits before the next interaction is required
    :loop
    WAITVID theLongAddress, allOnes
    ' compute next 32 bit string
    DJNZ ... #:loop
    


    The clock must be set to match the amount of computation needed between two 32 bit strings.
    There are cases where a 5 bit resolution will suffice.
    A 64 MHz Videoclock will give you 8 instructions to compute the next value.

    Timers/counters are of more use here, the reason is that a PWM pulse is mainly redundant...
    The video logic however will allow flexibility with 7 more channels.. including sync marks, phase shifting the signal.. all with little extra cost...

    Post Edited (deSilva) : 2/10/2008 9:40:04 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-02-10 10:14
    deSilva,

    I like the video output approach! That's probably the fastest way to feed a parallel converter from the Prop.

    One thing I tried but didn't post because it worked so poorly was to feed a transimpedance amplifier (current-to-voltage converter) with a base-3 encoder. In such an encoder, the output pins are weighted via series resistors in 1:3:9:27 ratios, which allows 81 different levels from four pins. The pin states are high, low, and floating. The latter state is achieved by setting DIRA for the pin to 0. The op amp is rigged so that its positive input is tied to Vdd/2. That way each pin feeding the negative input (which is also held to Vdd/2 by the feedback resistor) will either source current, sink current, or have no effect on the op amp's negative input.

    One difficulty with this setup is that DIRA and OUTA cannot be changed simultaneously. This leaves a 50ns-long glitchy intermediate state that has a greater impact on the output than one might expect. Another issue is the residual charge left on the pin capacitance when the pin transits from driven to floating. This charge has to be equalized, through the pin's series resistor, with the op amp's input, which entails a current flow that gets recorded on the output as a voltage. I tried various strategems for sequencing the OUTA and DIRA changes to minimize the glitch impact, all to no avail. (As an interesting side note, the DIRA pin sequence from low (maximum sink current) to high (maximum source current) forms a Gray code. The OUTA sequence, unfortunately, does not.)

    In theory, the pin-count savings seemed pretty sweet; in practice, the outcome was rather bitter.

    -Phil
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-10 11:38
    Phil,
    a) I should not have expected the pin capacitance (10pF) issue to be one with higher current (i.e. 100 .. 2k7 resistors) But of course it will beyond 5 MHz with the LSB...
    b) DIRA and OUTA can be switched glitch free usind the correct sequence:
    1 -> 0
    0 -> 1
    are the easy cases smile.gif

    0 -> T: DIRA := 0 only
    1 -> T: DIRA := 0 only
    T -> 0: OUTA := 0 then DIRA:=1
    T -> 1: OUTRA := 1 then DIRA :=1

    I think the best way is to use a conditioned sequence to keep the general timing in phase
    Edit:
    Oops, I just noticed my error. It will not help to do that with one line only, but with all 3 lines at the same time! So there are 27x27 possibilities to consider...
    On the other hand.. Why should there be an abrupt change? Switching one after another might not always switch in the right direction, but I wouldn't think it will be too bad...

    Post Edited (deSilva) : 2/10/2008 7:52:42 PM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-02-11 18:53
    deSilva,

    Yup, tried that. In fact, it's quite easy:

    1. AND old DIRA with new value. (Takes care of DIRA 1->0 transistions.)
    2. Write new OUTA. (Takes care of all OUTA transistions.)
    3. Write new DIRA. (Takes care of DIRA 0->1 transistions.)

    It turns out that the problem wasn't with the code but with the choice of op amps. I was using an LM358, which has a very limited frequency response. Other op amps I tried (LMC6482, MC34082) fared much better. The attached scope traces show the results using both a triangle wave and a sawtooth wave. (The LM358 clips on the low side, since I had the gain set too high for its output range.) I've included the traces for the summing junction, since this reveals the issues with slew rate most clearly. Ideally, this trace should be a constant, equal to 1.67V. It's only when the output can't keep up with the input that the voltage on the summing junction will vary. The schematic for the circuit I used is also attached. Power Vdd for the op amp was 5V.

    Here's the program I used to generate the triangle wave. The sawtooth wave used the same program with a period of 80 instead of 160:

    [b]CON[/b]
    
      [b]_clkmode[/b]      = [b]xtal[/b]1 + [b]pll[/b]16x
      [b]_xinfreq[/b]      = 5_000_000
    
    [b]VAR[/b]
    
      [b]long[/b]  waveform[noparse][[/noparse]41]
    
    [b]PUB[/b] Start | i, conv, skip
    
      [b]word[/b][noparse][[/noparse]@waveform][noparse][[/noparse]0] := 160                     'First WORD of waveform is Period.
      [b]byte[/b][noparse][[/noparse]@waveform][noparse][[/noparse]2] := 12                      'Next BYTE is Pin Number.
      [b]repeat[/b] i [b]from[/b] 0 to 159
        [b]if[/b] i < 80
          [b]byte[/b][noparse][[/noparse]@waveform&#093;[noparse][[/noparse]i + 3&#093; := convert(i)
        [b]else[/b]
          [b]byte[/b][noparse][[/noparse]@waveform&#093;[noparse][[/noparse]i + 3&#093; := convert(160 - i)
      [b]cognew[/b](@dac, @waveform)
    
    [b]PRI[/b] convert(x) : r | i, rem
    
    '' Convert x to base-3: high nybble is OUT; low nybble, DIR.
    
      r := 0
      [b]repeat[/b] i [b]from[/b] 1 to 4
        rem := x // 3 + 1                               ' rem = 0:1, 1:0, 1:1, i.e. OUT:DIR.
        r := r >> 1 | (rem & 2) << 6 | (rem & 1) << 3
        x /= 3
    
    [b]DAT[/b]
                  [b]org[/b]       0
    dac           [b]mov[/b]       buffer,[b]par[/b]              'Get the waveform address.
                  [b]rdword[/b]    period,buffer           'Get the period from first word.
                  [b]add[/b]       buffer,#2               'Point to next byte.
                  [b]rdbyte[/b]    basepin,buffer          'Get the output pin number.
                  [b]add[/b]       buffer,#1               'Point to beginning of waveform.
                  [b]mov[/b]       dirmask,#$0f            'Create the mask for DIRA.
                  [b]shl[/b]       dirmask,basepin
                  [b]add[/b]       basepin,#28             'Basepin is used to rotate, but four bits shy the first time.
    
    mainlp        [b]mov[/b]       ptr,buffer              'Main loop: Initialize pointer
                  [b]mov[/b]       ctr,period              '  and loop counter.
    
    :loop         [b]rdbyte[/b]    out,ptr
                  [b]add[/b]       ptr,#1
    
                  [b]rol[/b]       out,basepin             'Get the four bits for OUTA in position.
                  [b]mov[/b]       dir,out
                  [b]rol[/b]       dir,#4                  'Get DIRA's bits in position.
                  [b]and[/b]       dir,dirmask             'Mask out OUTA's bits.
                                
                  [b]and[/b]       [b]dira[/b],dir                'Do DIRA 1->0
                  [b]mov[/b]       [b]outa[/b],out                'Do OUTA
                  [b]mov[/b]       [b]dira[/b],dir                'Do DIRA 0->1
                  
                  [b]djnz[/b]      ctr,#:loop              'Loop within period.
                  [b]jmp[/b]       #mainlp                 'Loop next period.
    
    period        [b]res[/b]       1
    ptr           [b]res[/b]       1
    ctr           [b]res[/b]       1
    buffer        [b]res[/b]       1
    basepin       [b]res[/b]       1
    out           [b]res[/b]       1
    dir           [b]res[/b]       1
    dirmask       [b]res[/b]       1
    
    
    


    -Phil
    640 x 720 - 51K
    493 x 274 - 3K
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-11 20:50
    The LM 358 is a part of the Parallax Edu-Kit..
Sign In or Register to comment.