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. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,007
    Likes:
    316
    Location:
    Brisbane Australia
    When you switch to the 20MHz crystal you need to increase the value in PR2 from 124 to 249 so that the interrupts still happen every 200uS.

    Mike.
     
  2. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Right, I double the prescaler to fit the 20MHz frequency, but then with 10MHz crystal the values are still wrong though, why is that?

    It worked fine with 8MHz, and it seems 20MHz is dead on, yet with 10MHz it's all off?

    And what about the LED flashing part, is that still correct for the 64 value sine table?

    Thanks.
     
    Last edited: Jan 15, 2008
  3. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,007
    Likes:
    316
    Location:
    Brisbane Australia
    I think your getting confused as we changed both the crystal frequency and the output frequency.

    When we were using 8MHz and 500us (2KHz) then timer 2 was,
    setup_timer_2(T2_DIV_BY_4, 249, 1); // 500us = 1/8000000 * 4 * 4 * (249+1) = 1000 clock cycles

    With 20MHz and 200uS (5KHz) it's
    setup_timer_2(T2_DIV_BY_4, 249, 1); // 200us = 1/20000000 * 4 * 4 * (249+1) = 1000 clock cycles

    With 10MHz and 200uS (5KHz) it's
    setup_timer_2(T2_DIV_BY_4, 124, 1); // 200us = 1/10000000 * 4 * 4 * (124+1) = 500 clock cycles

    The LED is the same as it is on when the signals are out of phase.

    Mike.
     
  4. dave

    Dave New Member

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


     
  5. 3dluvr

    3dluvr Member

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

    What I was referring to as being off is the factor used to compute the step parameter, N = F * factor

    10MHz crystal would be:
    factor = 200us * 32bit * 65536 possible values, 200*10e-6 * 32 * 65536

    thus my step parameter formula equals
    N = F * 419.43

    for 200Hz that is 83886 and yet when I use that frequency on output frequency is actually ~80Hz.

    Please tell me if my calculation is correct and if I'm doing something wrong for 10MHz so that output does not match the input?
     
  6. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,007
    Likes:
    316
    Location:
    Brisbane Australia
    Can you post your complete code as there are a few things that can effect frequency.

    Mike.
     
  7. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Here's the code I use for 10MHz, I have commented out the PlayTone part since the dynamic frequency output is wrong anyway so makes no difference.

    Code (text):

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

    int timeCount;
    long TempA, TempB, hundreths;
    long long 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);
       
        if((TempA&8)!=(TempB&8)){
            output_bit(PIN_A4, 1);
        }
        else{
            output_bit(PIN_A4, 0);
        }
       
        if(timeCount++ == 50){
            timeCount=0;
            hundreths++;
        }
    }

    void PlayTone(long long Freq1, long long Freq2, long Duration) {
        signed long long work;
        hundreths=0;
        While(hundreths<Duration) {
            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)
       
        step = 88542; // dynamic frequency PortB 211.1Hz
        step2 = 83886; //167772; // static frequency PortA 200Hz
        enable_interrupts(INT_TIMER2);
        enable_interrupts(GLOBAL);    
       
        while(TRUE) {
            //PlayTone(88542,88542,500);
        //PlayTone(88542,86403,500);
        //PlayTone(86403,86403,500);
            //PlayTone(86403,88542,500);
        delay_us(1);
        }
        disable_interrupts(INT_TIMER2);
    }
     
    Thanks.
     
  8. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,007
    Likes:
    316
    Location:
    Brisbane Australia
    You are still doing your calculations for a 32 entry sine table.

    It should be 200*10^-6*64*65536

    Which is 838.86

    So for 200Hz the value would be 167772.

    However, this does not explain you getting 80Hz, it should have been 100Hz. The only explanation I can think of is that somehow the internal oscillator is still being used. Could the external oscillator be faulty and the Fail safe clock monitor is switching to the internal oscillator?

    Mike.
     
  9. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    I use the same source code for the 20MHz clock with the change in the delay/oscillator and PR2, and that works fine when calculated.

    Yet, for 10MHz it's all wrong, even with 64 instead of 32 I get values that are 1/3 or 1/2 of what they should be??

    If the internal oscillator was kicking-in, wouldn't that affect the 20MHz setup as well?

    I'll go look for another 10MHz crystal and try with it just to make sure it's not a hardware fault.
     
  10. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Well, I'm such a dope. All this time I have been using a 1MHz resonator instead of 10MHz one. I have no idea why I even read it as 10MHz when my other resonators (4 and 8MHz) had higher number than the one I called 10MHz.

    In any case, I have found a real 10MHz crystal with a small footprint and will use that one, and it works just fine...

    Next step is to see if I can script out session sequences or convert them the way they originally did in Perl, but adapted for my MCU.
     
  11. Funny NYPD

    Funny NYPD New Member

    Joined:
    Oct 4, 2007
    Messages:
    177
    Likes:
    2
    Location:
    USA
    PIC PWM is very very hard to use. Some time, I see people using software PWM instead of using the PIC hardware, so is the I2C and SPI on PICs.
     
  12. 3dluvr

    3dluvr Member

    Joined:
    Aug 25, 2003
    Messages:
    76
    Likes:
    0
    Actually I wasn't using PWM because I needed two independent channels and most PICs have only one PWM. The original design was on an AVR which apparently has two PWM...figures.
     

Share This Page