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

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

1. ### PommieWell-Known MemberMost Helpful Member

Joined:
Mar 18, 2005
Messages:
10,365
Likes:
368
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. ### 3dluvrMember

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. ### PommieWell-Known MemberMost Helpful Member

Joined:
Mar 18, 2005
Messages:
10,365
Likes:
368
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.

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

5. ### 3dluvrMember

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. ### PommieWell-Known MemberMost Helpful Member

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

Mike.

7. ### 3dluvrMember

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. ### PommieWell-Known MemberMost Helpful Member

Joined:
Mar 18, 2005
Messages:
10,365
Likes:
368
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. ### 3dluvrMember

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. ### 3dluvrMember

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 NYPDNew 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. ### 3dluvrMember

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.