1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Output two different sine waves with 16F88 and CCS C?

Discussion in 'Microcontrollers' started by 3dluvr, Jan 5, 2008.

  1. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I am using plain headphones connected to the output of my RC filter...but I have used Mic-In of my laptop to record the sounds through Audacity program.
     
  2. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Lastly...I have compiled the provided ASM source and I still hear the jitter on the PortB output (lower nibble). The PortA output (lower nibble) does not seem to be active but I do not see PortA output in the code either.

    I have swapped PortB with PortA in the source and the jitter is still there... :(
     
  3. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I have ran the test with 818 and 820. Both have jitter, one slower the other faster, audio recordings are attached.

    I am totally clueless why is this happening but will go dig out another PIC and try it just in case this one is defective.
     

    Attached Files:

  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0

    Turns out the problem is not just with the computation of the figures but with their values and the timer itself.

    There seems to be a point after which the jitter disappears, perhaps after 835 or 840, so the PortA which is always on 868 sounds fine because the tone is above (some?) threshold.

    So the idea is to use a higher frequency on the PortB instead of lower. Fine, I tried that but then a totally new problem occurs. The numbers computed do not correspond to the frequencies generated.

    For example, 934 should make 228.02Hz but output is closer to 226.2Hz and I somehow do not believe it is my scope that's broken. The base 868 produces 210.3Hz while it should be 211.9Hz.

    Is there a way to increase stability and resolution by perhaps using Timer1 instead, it being a 16bit timer?
     
  6. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    The errors in the frequencies are due to using the internal oscillator. It is only accurate to 1% and your errors are less than 1%. The only way to get it more accurate is to use a crystal. You could also try setting the OSCTUNE register but this would vary between chips.

    Can you try the following code, it runs twice as fast but should produce the same frequency,
    Code (text):

                             
                    LIST    p=16F88
                    #INCLUDE <P16F88.INC>
                             
                    errorlevel -302
    ;------------------------------------------------------------------------------    
                             
                    __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
                    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
                             
    ;------------------------------------------------------------------------------    
                             
                    CBLOCK  0x20            ; Sample GPR variable registers allocated contiguously
    Position:2              
    Step:2                  
    TempB                    
                    ENDC    
                             
    W_TEMP          EQU     0x7D            ; w register for context saving (ACCESS)
    STATUS_TEMP     EQU     0x7E            ; status used for context saving (ACCESS)
    PCLATH_TEMP     EQU     0x7F            ; variable used for context saving
                             
    ;------------------------------------------------------------------------------    
    ; RESET VECTOR            
    ;------------------------------------------------------------------------------    
                             
    RESET           ORG     0x0000          ; processor reset vector9
                    PAGESEL START
                    GOTO    START           ; go to beginning of program
                             
    ;------------------------------------------------------------------------------    
    ; INTERRUPT SERVICE ROUTINE    
    ;------------------------------------------------------------------------------    
                             
    ISR             ORG     0x0004          ; interrupt vector location
    ;         Context saving for ISR    
                    MOVWF   W_TEMP          ; save off current W register contents
                    MOVF    STATUS,W        ; move status register into W register
                    MOVWF   STATUS_TEMP     ; save off contents of STATUS register
                    MOVF    PCLATH,W        ; move pclath register into W register
                    MOVWF   PCLATH_TEMP     ; save off contents of PCLATH register
                             
    ;------------------------------------------------------------------------------    
    ; USER INTERRUPT SERVICE ROUTINE GOES HERE    
    ;------------------------------------------------------------------------------    
                             
                    movfw   Step            ;Position+=Step
                    addwf   Position,F
                    movfw   Step+1
                    btfsc   STATUS,C
                    addlw   1
                    addwf   Position+1,F
                    movlw   high GetSine    ;Prepare to get sine value
                    movwf   PCLATH
                    rlf     Position,W
                    rlf     Position+1,W
                    andlw   .31             ;TempB=(Position>>7)&31
                    call    GetSine
                    movwf   TempB
                    movwf   PORTB
                             
                    bcf     PIR1,TMR2IF
                             
                             
    ;         Restore context before returning from interrupt    
                    MOVF    PCLATH_TEMP,W   ; retrieve copy of PCLATH register
                    MOVWF   PCLATH          ; restore pre-isr PCLATH register contents
                    MOVF    STATUS_TEMP,W   ; retrieve copy of STATUS register
                    MOVWF   STATUS          ; restore pre-isr STATUS register contents
                    SWAPF   W_TEMP,F
                    SWAPF   W_TEMP,W        ; restore pre-isr W register contents
                    RETFIE                  ; return from interrupt
                             
    ;------------------------------------------------------------------------------    
    ; MAIN PROGRAM            
    ;------------------------------------------------------------------------------    
                             
    START                    
                    bsf     STATUS,RP0
                    movlw   0xf0
                    movwf   TRISA
                    movwf   TRISB
                    movlw   b'00000111'     ;   disable comparator
                    movwf   CMCON
                    movlw   B'01110000'     ;select 8MHz clock
                    movwf   OSCCON
                    clrf    ANSEL           ;no ADCs
                    bcf     STATUS,RP0
                             
                    movlw   1<<TMR2ON|b'01'<<T2CKPS0
                    movwf   T2CON
                    bsf     STATUS,RP0
                    movlw   .124
                    movwf   PR2
                    bsf     PIE1,TMR2IE
                    bcf     STATUS,RP0
                             
                    movlw   low(.819)
                    movwf   Step
                    movlw   high(.819)
                    movwf   Step+1
                             
                    movlw   (1<<GIE|1<<PEIE|0<<TMR0IE|0<<INTE|0<<RBIE|0<<TMR0IF|0<<INTF|0<<RBIF)
                    movwf   INTCON          ;       enable Peripheral interupts
                             
                             
    ;------------------------------------------------------------------------------    
    ; PLACE USER PROGRAM HERE    
    ;------------------------------------------------------------------------------    
                             
                    GOTO    $
                             
                    org     0x0400
    GetSine         addwf   PCL,F
                    dt      .7,.8,.10,.11,.12,.13,.13,.14,.14,.14,.13,.13,.12,.11,.10,.8
                    dt      .7,.6,.4,.3,.2,.1,.1,.0,.0,.0,.1,.1,.2,.3,.4,.6
                             
                    END      
     
    Mike.
     
  7. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Thank you for sticking out with me this long, I know this is pretty tedious especially when you do not have hardware in front of you. :)

    I have tested the code and it produces a frequency on PortB (lower nibble) of about 795Hz. You can hear periodic jitter in the signal, sounds like a record player needle going over the grooves in the record, hehe :)

    So I guess I should stick a crystal oscillator in here then, do you reckon 4MHz should be enough or do I go up to 20MHz?
    I would just like to minimize any distortions and possible interference from outside sources as well (have enough problems with self-oscillation as you can see).
     
  8. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    If you are going to use a crystal then you may as well use a 20MHz one as this will allow more flexibility. Do the frequencies have to be that accurate? I'd have thought that a 1% error would be accurate enough.

    I altered that code the wrong way can you try this and also try increasing the capacitor value in the filter.
    Code (text):

                           
                    LIST    p=16F88
                    #INCLUDE <P16F88.INC>
                           
                    errorlevel -302
    ;------------------------------------------------------------------------------  
                           
                    __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
                    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
                           
    ;------------------------------------------------------------------------------  
                           
                    CBLOCK  0x20            ; Sample GPR variable registers allocated contiguously
    Position:2              
    Step:2                  
    TempB                  
                    ENDC    
                           
    W_TEMP          EQU     0x7D            ; w register for context saving (ACCESS)
    STATUS_TEMP     EQU     0x7E            ; status used for context saving (ACCESS)
    PCLATH_TEMP     EQU     0x7F            ; variable used for context saving
                           
    ;------------------------------------------------------------------------------  
    ; RESET VECTOR          
    ;------------------------------------------------------------------------------  
                           
    RESET           ORG     0x0000          ; processor reset vector9
                    PAGESEL START
                    GOTO    START           ; go to beginning of program
                           
    ;------------------------------------------------------------------------------  
    ; INTERRUPT SERVICE ROUTINE  
    ;------------------------------------------------------------------------------  
                           
    ISR             ORG     0x0004          ; interrupt vector location
    ;         Context saving for ISR  
                    MOVWF   W_TEMP          ; save off current W register contents
                    MOVF    STATUS,W        ; move status register into W register
                    MOVWF   STATUS_TEMP     ; save off contents of STATUS register
                    MOVF    PCLATH,W        ; move pclath register into W register
                    MOVWF   PCLATH_TEMP     ; save off contents of PCLATH register
                           
    ;------------------------------------------------------------------------------  
    ; USER INTERRUPT SERVICE ROUTINE GOES HERE  
    ;------------------------------------------------------------------------------  
                           
                    movfw   Step            ;Position+=Step
                    addwf   Position,F
                    movfw   Step+1
                    btfsc   STATUS,C
                    addlw   1
                    addwf   Position+1,F
                    movlw   high GetSine    ;Prepare to get sine value
                    movwf   PCLATH
                    rrf     Position+1,W
                    andlw   .31             ;TempB=(Position>>9)&31
                    call    GetSine
                    movwf   TempB
                    movwf   PORTB
                           
                    bcf     PIR1,TMR2IF
                           
                           
    ;         Restore context before returning from interrupt  
                    MOVF    PCLATH_TEMP,W   ; retrieve copy of PCLATH register
                    MOVWF   PCLATH          ; restore pre-isr PCLATH register contents
                    MOVF    STATUS_TEMP,W   ; retrieve copy of STATUS register
                    MOVWF   STATUS          ; restore pre-isr STATUS register contents
                    SWAPF   W_TEMP,F
                    SWAPF   W_TEMP,W        ; restore pre-isr W register contents
                    RETFIE                  ; return from interrupt
                           
    ;------------------------------------------------------------------------------  
    ; MAIN PROGRAM          
    ;------------------------------------------------------------------------------  
                           
    START                  
                    bsf     STATUS,RP0
                    movlw   0xf0
                    movwf   TRISA
                    movwf   TRISB
                    movlw   b'00000111'     ;   disable comparator
                    movwf   CMCON
                    movlw   B'01110000'     ;select 8MHz clock
                    movwf   OSCCON
                    clrf    ANSEL           ;no ADCs
                    bcf     STATUS,RP0
                           
                    movlw   1<<TMR2ON|b'01'<<T2CKPS0
                    movwf   T2CON
                    bsf     STATUS,RP0
                    movlw   .124
                    movwf   PR2
                    bsf     PIE1,TMR2IE
                    bcf     STATUS,RP0
                           
                    movlw   low(.819)
                    movwf   Step
                    movlw   high(.819)
                    movwf   Step+1
                           
                    movlw   (1<<GIE|1<<PEIE|0<<TMR0IE|0<<INTE|0<<RBIE|0<<TMR0IF|0<<INTF|0<<RBIF)
                    movwf   INTCON          ;       enable Peripheral interupts
                           
                           
    ;------------------------------------------------------------------------------  
    ; PLACE USER PROGRAM HERE  
    ;------------------------------------------------------------------------------  
                           
                    GOTO    $
                           
                    org     0x0400
    GetSine         addwf   PCL,F
                    dt      .7,.8,.10,.11,.12,.13,.13,.14,.14,.14,.13,.13,.12,.11,.10,.8
                    dt      .7,.6,.4,.3,.2,.1,.1,.0,.0,.0,.1,.1,.2,.3,.4,.6
                           
                    END    
     
    Mike.
     
  9. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Great, I'll switch to a 20MHz crystal, I hoped to have as few components as possible and the original design used internal oscillator too but I guess AVR works differently than PIC. :)

    I would like to have fairly accurate frequencies, to the first decimal place but if there's room for better I wouldn't complain. :)

    I have tried the new code and it produces 198.2Hz on PortB (lower nibble) but the jitter is still there occurring in periodic intervals. Perhaps as I mentioned before there's a frequency below which the jitter happens due to computational error and cannot be avoided?

    In any case, do you think I should produce the tones from one port (PortB for example) and hook the LEDs to the PortA?

    What I've noticed is that when I had PortA + PortB (lower nibbles) combo and put the LED on pin A4 there was noise in PortB each time the LED went on (or off, not sure but it sounded like static coming from the blinking).
    When I remove the LED everything is fine on PortB tone, only when the LED is connected do I get that.
    I have LED driving directly from the interrupt routine, I hope that's ok? It's just one command setting pin A4 bit to 0 or 1 as per your original code.

    Thanks!
     
  10. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    If you use a 20MHz Crystal then I would suggest using a faster update time and using 32 bit variables. By rearranging the code we can get better resolution by using 16.16 - that is 16 bits after the decimal point.

    See how this code goes, you will have to change the oscillator code to use a HS crystal, I don't know the syntax.
    Code (text):

    #include <16F88.h>
    #fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,PUT
    #use delay(clock=20000000)

    int timeCount; //int = int8
    long TempA, TempB; //long = int16
    int32 step, step2, position, position2;

    CONST unsigned int SineTab[32] = {
        7,8,10,11,12,13,13,14,14,14,13,13,12,11,10,8,
        7,6,4,3,2,1,1,0,0,0,1,1,2,3,4,6};

    #INT_TIMER2
    void interrupt(){
            position+=step;
            TempB=SineTab[(position>>16)&31];
            output_b(TempB);
            position2+=step2;
            TempA=SineTab[(position2>>16)&31];
            output_a(TempA);
    }

    void main(void) {
        setup_oscillator(OSC_8MHZ | OSC_INTRC);   // Use internal 8MHz oscillator
        set_timer2(0);
        setup_timer_2(T2_DIV_BY_4, 249, 1); // 200us = (1/20000000 * 4 * 4 * 249+1)

    //  N = F * 200*10-6*32*65536
    //  N = F * 419.42

    // For 200Hz N = 83886
            step = 83886; // changing frequency

    // For 211.4 N = 88665
        step2 = 88665; // base frequency

        enable_interrupts(INT_TIMER2);
        enable_interrupts(GLOBAL);
       
        while(TRUE)
        {
            delay_us(1);
        }
       
            disable_interrupts(INT_TIMER2);
    }
     
    As for the LED causing noise, this is most likely because there is a maximum current per port and the LED will therefore effect the sound. Try using a transistor to power the LED and therefore reduce the load on the port.

    Mike.
     
  11. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I just tried the new code and there's jitter if I change the frequencies from your default parameters, ugghh. Should I be looking to switch to AVR and give up PIC? :(

    On the other hand, I have tried merging those other bits of code for PlayTone routine and ramping up works fine but ramping down makes these wau-wau sounds. :)
    I narrowed this to a compiler deficiency due to the sum using a negative signed parameter (step = work + Freq1; // when work < 0 it goes crazy).

    The code worked for the most part but my LEDs did not blink properly, matter a fact only time I saw blinking was during the ramps, while other times they stayed on or blinked too fast for me to see (> 15 Hz or so).

    I did try both "if" statements as in the code and neither produced desired result...

    Here's the code I used so far prior to 32bit update, using a 10MHz ceramic resonator:
    Code (text):

    #include <16F88.h>
    #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT
    #use delay(clock=10000000)

    int timeCount;
    long TempA, TempB, step, step2, hundreths, position, position2;

    CONST unsigned int SineTab[32] = {
        7,8,10,11,12,13,13,14,14,14,13,13,12,11,10,8,
        7,6,4,3,2,1,1,0,0,0,1,1,2,3,4,6};

    #INT_TIMER2
    void interrupt(){
        position+=step;
        TempB=SineTab[(position>>8)&31];
        output_b(TempB);
        position2+=step2;
        TempA=SineTab[(position2>>8)&31];
        output_a(TempA);
       
        //if((TempA-7)+(TempB-7)>0){
        if((TempA&7)!=(TempB&7)){
            output_bit(PIN_A4, 0);
        }
        else{
            output_bit(PIN_A4, 1);
        }
       
        if(timeCount++ == 50){
            timeCount=0;
            hundreths++;
        }
    }

    void PlayTone(long Freq1, long Freq2, long Duration) {
        signed long long work;
        hundreths=0;
        While(hundreths<Duration){
            //work=Freq2-Freq1;
            //work*=hundreths;
            //work/=Duration;
            //step=work+Freq1;
           
            if (Freq2 >= Freq1) { // ramp up
                work = Freq2 - Freq1;
                work *= hundreths;
                work /= Duration;
                step = work + Freq1;
        } else { // ramp down
            work = Freq1 - Freq2;
            work *= hundreths;
                work /= Duration;
                step = Freq1 - work;    
        }
        }
    }

    void main(void) {
        setup_comparator(NC_NC_NC_NC);
        set_timer2(0);
        setup_timer_2(T2_DIV_BY_4, 124, 1); // 200us = (1/10000000 * 4 * 4 * 124+1)

            // N = F * 1.6384

        enable_interrupts(INT_TIMER2);
        enable_interrupts(GLOBAL);    
       
        while(TRUE)
        {
                PlayTone(360,360,500);
                PlayTone(360,450,500);
                    PlayTone(450,360,500);
        }  
            disable_interrupts(INT_TIMER2);
    }
     
    As always, thanks!
     
  12. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    Have you tried the 32 bit code? It should provide much better accuracy for the frequency. It is effectively now doing DDS at 5kHz which should produce a clean signal. If there is still artifacts then the next step would be a higher resolution sine table.

    The out of phase LED should be,
    if((TempA&8)!=(TempB&8)){
    I edited the original post but you obviously copied it before the edit. Sorry.

    BTW, if any of you analogue guys have any suggestions what these artifacts could be just go right ahead and shout.

    Mike.
     
  13. blueroomelectronics

    blueroomelectronics Well-Known Member

    Joined:
    Jan 21, 2007
    Messages:
    12,536
    Likes:
    170
    Location:
    Toronto, Canada
    If you need the speed just move up to an 18F (40MHz and 8x8 multiply) or a dsPIC.
     
  14. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Hi,

    Pommie, I guess you missed the first sentence in my last post. I did try the new code and there is jitter in the tones, when I change the frequency from the default parameters you set. The jitter is now just more subtle but is it still there and can be heard through the headphones.

    From my tests it appears that this jitter is caused by FP computation or low-res sine table, or both but I do not believe it is due to the output circuits. You are probably right that a higher resolution sine table might be needed...or at least maybe I should test it out.

    I feel that higher speed MCU will not make a difference since we moved from internal 8MHz oscillator to 10 and 20MHz external ceramic resonators while artifacts were still present at times.

    Thanks.
     
  15. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Oh I forgot, I'm having a problem computing the proper numbers for the frequencies when running at 10MHz with 32bit variable, my factor is not correct.

    I tried using this value but it is not right and doubling the computed factor did not work either, the frequency was higher:

    N = F * 419.42, N = F * 200*10-6*32*65536 // for 20MHz, 200us period, 16.16bits (32bit)

    I know that 200*10e-6 is the 200us period, 65536 is the max value but where does that 32 come from, is that 4*prescaler, because prescaler is 4 not 8 in my timer2?
     
  16. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    The reason I asked if you had tried the 32 bit code was because you posted 16 bit code. With 32 bit code the calculations are accurate to 5 decimal places and I'm sure this is more than adequate for this purpose.

    The 32 is the number of entries in the sine table. The 65536 is multiplying by 2^16 so as to get the 5 decimal place accuracy.

    If you'd like to give it one more try I could do a version with a 64 byte sine table and 32 bit variables with the hope that the greater accuracy cures the problem.

    Mike.
     
  17. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I would most certainly like to continue and see this project through. I learned much about PIC interrupts with the help received here that it would not be right to stop now.

    Could we try the 64 byte sine table and 32bit variables, please?

    I did try the new code by the way, as I wrote in my previous email, and there was jitter in tones after changing the frequencies from the defaults you had set.

    I would also like to expand the code to use PlayTone routine and include LEDs so that it creates a whole project.

    Thanks.
     
  18. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    This is the 32 bit code with a 64 byte sine table. My only worry with this code is the 10MHz clock. At 10MHz the interrupt is occurring every 500 cycles, this is not a lot of time especially when doing 32 bit maths. Luckily, the ISR code should compile into efficient machine code. I tried to download the CCS demo but it won't work (claims the time has expired!). Can you check (and post if possible) the code that is produce for the line, TempB=SineTab[(position>>16)&63];


    Mike.
    Code (text):

    #include <16F88.h>
    #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT
    #use delay(clock=10000000)

    int timeCount; //int = int8
    long TempA, TempB; //long = int16
    int32 step, step2, position, position2;

    CONST unsigned int SineTab[64] = {
        7,8,8,9,10,10,11,11
        12,12,13,13,13,14,14,14
        14,14,14,14,13,13,13,12
        12,11,11,10,10,9,8,8
        7,6,6,5,4,4,3,3
        2,2,1,1,1,0,0,0
        0,0,0,0,1,1,1,2
        2,3,3,4,4,5,6,6};

    #INT_TIMER2
    void interrupt(){
            position+=step;
            TempB=SineTab[(position>>16)&63];
            output_b(TempB);
            position2+=step2;
            TempA=SineTab[(position2>>16)&63];
            output_a(TempA);
    }

    void main(void) {
        setup_comparator(NC_NC_NC_NC);
        set_timer2(0);
        setup_timer_2(T2_DIV_BY_4, 124, 1); // 200us = (1/10000000 * 4 * 4 * 124+1)

    //  N = F * 200*10-6*64*65536
    //  N = F * 838.86

    // For 200Hz N = 167772
            step = 167772; // changing frequency

    // For 211.4 N = 177335
        step2 = 177335; // base frequency

        enable_interrupts(INT_TIMER2);
        enable_interrupts(GLOBAL);
       
        while(TRUE)
        {
            delay_us(1);
        }
       
            disable_interrupts(INT_TIMER2);
    }
     
  19. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Thanks for the new code, I am testing it right now and it appears that the jitter is still present but not as frequent as with previous versions.
    The iterations are spaced further apart and it sounds as if the frequency is getting higher, although the scope does not show any increase in frequency?!

    When you say 500 cycles is not enough on a 10MHz clock, how many interrupts should I have instead so that it gives enough time to do 32-bit math?

    Here's the code generated for the TempB=SineTab line...

    Code (text):

    ....................     TempB=SineTab[(position>>16)&63];
    0089:  MOVF   3A,W
    008A:  MOVWF  41
    008B:  MOVF   3B,W
    008C:  MOVWF  42
    008D:  CLRF   43
    008E:  CLRF   44
    008F:  MOVF   3A,W
    0090:  ANDLW  3F
    0091:  MOVWF  45
    0092:  CLRF   46
    0093:  CLRF   47
    0094:  CLRF   48
    0095:  MOVF   45,W
    0096:  MOVWF  77
    0097:  MOVF   46,W
    0098:  MOVWF  78
    0099:  MOVF   47,W
    009A:  MOVWF  79
    009B:  MOVF   48,W
    009C:  MOVWF  7A
    009D:  MOVF   45,W
    009E:  CALL   037
    009F:  MOVWF  78
    00A0:  CLRF   2D
    00A1:  MOVF   78,W
    00A2:  MOVWF  2C
     
    Do you think I'm too picky here about using 32-bit math and it being an overkill for this application?
    Sadly, I do not have a frame of reference how this device should function since I did not build the original AVR version so cannot say whether the output is better or worse...just going based on a gut feeling. :)
     
  20. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,162
    Likes:
    340
    Location:
    Brisbane Australia
    If you can perceive a higher frequency then that suggest that the output frequency is not being filtered fully, try increasing the value of the filter capacitor.

    The 500 cycles worry is not a problem, looking at the generated code, it is more than fast enough.

    Mike.
     
  21. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I have been trying something out just now. If I use a 10MHz crystal with the same setting #use delay(clock=10000000) then the PortA and PortB frequencies are ~169 and ~159.

    Then if I switch the crystals and use 20MHz crystal and set the #use delay(clock=20000000) then PortA is ~422 and PortB is ~400.

    Either way the computation N = F * 838.86 to get the step variables from the desired frequency is not correct yet the way it's derived appears to be fine. What could be the problem?

    This seems to have started happening after switching to higher frequencies and using external oscillators (10 and 20MHz)...
     

Share This Page