Unstable sine PWM output


Closed Thread
Results 1 to 30 of 30

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,617


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    So the problem is clearly DIV32. Apparently this command disturbs DT Instant Interrupts.
    Or the other way around, or there's a problem with the actual values being calculated like overflow/ underflow/whatever. I'm still not convinced but it seems you are so lets go with that for now.

    OK, you're using an analog input to set the desired output frequency, the ADC have a resolution of 10 bits giving you a value of 0-1023. If we're going to try to come up with an alternative way to calculate the reload value (not using DIV32) can you tell us:

    A) What is your minimum output frequency, ie what frequency should an ADC value of 0 give and what TMR1 reload value does that frequency require?

    B) What is your maximum output frequency, ie what frequency should an ADC value of 1023 give and what TMR1 reload value does that frequency require?

    /Henrik.

  2. #2


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Maybe it isn't DIV32... I don't know, but when I remove it, the glitches disapppears. I've also already tried to change the dummy values.

    My min. frequency is 1Hz (freq=10), reload value=about 0
    and my max. frequency is 120Hz (freq=1200), reload value=about 64600

    And I don't directly use the 0-1023 potentiometer value, first I convert it to the "freq" variable :

    Code:
    potsense=(potsense<<6)**maxfreq
    "maxfreq" correspond to the maximum frequency defined by the user. Here, "maxfreq"=1200. So here "freq" variable varies between 0 and 1200. Note I'm using an additional number to have the 0.1Hz accuracy (for exemple, 50.2Hz frequency equals freq=502).

    I have to said, your timer reload routine with DIV32 was pretty accurate and provides very good results. In terms of accuracy, I really had a 0.1Hz precision, both in low and high frequencies.
    Last edited by pxidr84; - 14th May 2011 at 10:52.

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,617


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    OK, so when Freq is 10 you want Reload to be 0 and when Freq is 1200 you want Reload to be 64600. That's 64600 over 1190 or a reload value of 54.286 per unit Freq.
    Code:
    Reload = (Freq */13897) - 542
    When Freq is 10 you'll get (10*13897/256)-542 = 0
    When Freq is 1200 you'll get (1200*13897/256)-542 = 64600
    Do not allow Freq to be less than 10, you'll end up with a negative value.

    This is not perfect but it might work, at least you'll get rid of DIV32. If you use the exact reload values for Freq=10 and Freq=1200 instead of the aproximate ones it might get a bit better in between the two extreme ends.

    By the way, the lowest possible interrupt frequency, when running at 40Mhz and without changing the prescaler is 152.588Hz which equals an output frequency of 1.69Hz so Freq should really only be allowed to range from 17 to 1200 for 1.7 to 120Hz.

    /Henrik.

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Unfortunately, it doesn't work as expected but there is no glitch when I played with the potentiometer.

    For example, at 100.0Hz I obtain an 9.5Hz output,
    at 110.0Hz -> 17.6 Hz
    at 90.0Hz -> 6.5Hz...

    And there is no way to use this? http://www.picbasic.co.uk/forum/showthread.php?t=12433

    or this?
    http://melabs.com/resources/fp.htm

    (just a suggestion)

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,617


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    Aaargh, sorry about that, temporary brain-fart on my behalf.

    At the moment I'm afraid I can't come up with an alternative solution. I'm sure there is one though and hopefully someone else will jump in.

    I've never used the floating point routines and I don't really see any reason to do it here. N-Bit math might be an option but I currently don't have the time to do the experiments for you so you're going to have to try it yourself. Darrels examples in the thread is pretty self explainatory.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    To avoid an useless calculation, I would store the 1120*1000 result (1120000) into a 24-bit variable with the N-bit math function (but how?). And then divide this by the frequency, and so on.

    Thanks anyway. Now I know where is my problem. I think I will open a new thread, because the DIV32 problem is different than PWM and sines.

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,617


    Did you find this post helpful? Yes | No

    Default Re: Unstable sine PWM output

    Hi,
    I gave it a shot anyway:
    Code:
    PRECISION CON 3 SYSTEM          ' 24bits is sufficent for this
    INCLUDE "N-bit_Math.pbp"        ' Include the math routines.
     
    Dummy1 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Dummy2 VAR BYTE[PRECISION]      ' Used by N-Bit math
    Result VAR BYTE[PRECISION]      ' Used by N-Bit math
     
    Frequency VAR WORD              ' Desired output frequency times 10 (123=12.3Hz)
    Reload VAR Word                 ' Caluclated timer reload value to get desired interrupt rate.
    i VAR BYTE                      ' General purpose counter
     
    HSEROUT ["Start",13]
     
    Main:
      For i = 0 to 20
        Lookup2 i, [18, 20, 22, 25, 30, 40, 50, 60, 80, 100, 150, 200, 300, 400, 500, 700, 800, 900, 1000, 1100, 1200], Frequency
        Gosub CalculateIt
        Gosub PrintIt
        Pause 100
      Next
    END
     
    CalculateIt:
      ' There's 90 "steps" for a complete sine-cycle. If we want 1Hz output frequency
      ' we need an interrupt frequency of 90Hz, 1/90=0.01111111111111s.
      ' At 40MHz each instruction cycle (and timertick when prescaler is 1:1) is 100nS
      ' so 0.0111111111111/100E-9 = 111111 but because we want one decimal place on the
      ' frequency variable (123 = 12.3Hz) we multiply that by 10 so 1111111.
     
      ' Load 1111111 into first 24bit math variable.
      Dummy1[2] = $10
      Dummy1[1] = $F4
      Dummy1[0] = $47
     
      'Load frequency variable into second math variable
      Dummy2[2] = 0
      Dummy2[1] = Frequency.HighByte
      Dummy2[0] = Frequency.LowByte
     
      'Perform the division.
    @ MATH_DIV _Dummy1, _Dummy2, _Result
     
      'Move the result to the Reload variable
    @ MOVE?PW  _Result, _Reload          ; Truncate Result into a WORD var
     
      'Negate the value to get the actual reload value.
    Reload = -Reload
     
    RETURN
    End
     
    PrintIt:
      HSEROUT ["Frequency: ", #Frequency/10, ".", #Frequency // 10, "Hz", "   Reload: ", #Reload, 13]
    Return
    1111111 is closer to the real deal than 1120000, upto around Freq=1100 the error is less than 0.01% while at Freq=1200 it "jumps" to 0.1% - pretty good.

    Remember that you can not allow the Frequency variable to be less than 17 or you'll end up with a negative reload value which means the frequency will be WAY off. Ie you can't allow Frequency to be 10 for 1Hz output.

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts