|
|
View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 02, 2010 9:41 am |
|
|
You can use #int_timer2 to do this. It will interrupt at the same
frequency as the PWM, or at a multiple of that frequency (from 1 to 16).
Set the interrupt interval by setting the Postscaler parameter in the
setup_timer_2() function. See the CCS manual.
For example, you could have it interrupt once every 16 PWM cycles.
Then inside the #int_timer2 routine, you could change the duty cycle
with the set_pwm1_duty() function. |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Tue Feb 02, 2010 5:00 pm |
|
|
Thanks PCM programmer, but I've already tried doing it that way. Also I wanted a different interrupt frequency, initially I didn't realise that the PWM was tied in with Timer2, so when I went through the wizard and set them both I didn't realise that the PWM setup was overwriting what I'd set for the timer2 interrupt earlier!
I had thought perhaps that there were issues with calling set_pwm(1/2)_duty() within an interrupt itself, so tried separating it out into a function call, so all the interrupt would have inside it was a call to a function that did all the work, but this method seems to have made no difference in my results.
The isrCount was just a test of doing something only every few interrupts rather than each time.
What I ultimately want to do is get sound playback happening, method being to cycle through an array of values at the sound's sample rate (eg. interrupt at 8kHz, set PWM to new value), whilst having the PWM frequency high enough that it doesn't cause unwanted noise. I figured also that I should set the Timer2 so that the PWM's duty cycle was natively as close to 255 as I could get, so I could set 8bit numbers directly to it without doing calculations first.
But as I said, I can't even get a simple "fade LED" system working via interrupts, and I can't see what I'm doing wrong.
The Roman Black 1-bt wav playback system in the code library only uses delays to set the playback rate, I'm going to be doing other operations with the PIC so wanted to use interrupts to get a consistent playback rate. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 02, 2010 5:36 pm |
|
|
I don't know if this is applicable to your project or not, but I made a
program that ramps the PWM duty cycle up and down continuously.
Look at pin C2 with your oscilloscope and you will see it.
Code: |
#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define MAX_DUTY 255
int8 duty_cycle;
#int_timer2
void timer2_isr(void)
{
static int8 increment = TRUE;
if(increment)
{
duty_cycle++;
if(duty_cycle == MAX_DUTY)
increment = FALSE;
}
else
{
duty_cycle--;
if(duty_cycle == 0)
increment = TRUE;
}
set_pwm1_duty(duty_cycle);
}
//======================================
void main()
{
duty_cycle = 0; // Start with 0 duty cycle
// Setup CCP1 for PWM at 245 Hz.
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 254, 8); // Interrupt at 1/8 PWM freq
set_pwm1_duty(duty_cycle);
clear_interrupt(INT_TIMER2);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(1);
}
|
|
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Tue Feb 02, 2010 5:56 pm |
|
|
Thanks PCM programmer, that's what I'm after, something that has been proven to work by someone else that is triggered by the interrupt. I'll give it a go tonight.
From what I can see, at first glance it looks very similar to stuff I've already tried, but if it works, great I can use it as a starting point, if it doesn't then it should prove that I've got issues with either the chip itself or my breadboard, so I can find the cause of the problem rather than beating my head against a brick wall when the code itself might actually be fine.
PS. I don't have an oscilloscope, I'm just using an LED and the old mk1 human eyeball, so trying to get the timing at a rate that's discernable to a human. |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Tue Feb 02, 2010 11:28 pm |
|
|
PS. I'm wondering what the difference/reasoning is for the two variables:
int8 duty_cycle; //outside the ISR
static int8 increment = TRUE; //inside the ISR
Why the different declaration styles in different locations? They both seem to be accessed the same way in the same function? Does it make "increment" only available within the ISR whereas "duty_cycle" is available anywhere perhaps?
I think I need to do some research on variable scope... |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Wed Feb 03, 2010 7:10 am |
|
|
OK this is bizarre; had no luck whatsoever with the above code, I've just spent a few hours experimenting, just decided to strip it right back and disable the interrupts, just testing a set_pwm1_duty by itself, and I came across the following behavior:
with
duty_cycle = 0;
and
set_pwm1_duty(duty_cycle);
I am getting a lit LED! Maybe about 50% brightness.
but if I say
set_pwm1_duty(0);
the LED doesn't light!!
So what the %@#& is going on here??!
If I set the variable "duty_cycle" to 0, or set it to 255, I'm still getting the same apparent brightness??
Clock is 20MHz, timer2 setup is
setup_timer_2(T2_DIV_BY_16,255,2);
Any thoughts would be greatly appreciated, as I've spent hours on this and haven't gotten anywhere, then find that even the most basic function isn't working as it should be!
PS. I've also swapped out the chips, so hardware doesn't appear to be part of the issue. |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 03, 2010 11:07 am |
|
|
What PIC?.
What compiler version?.
Have you actually tested that the output PWM frequency _is_ what you expect?.
You could get the symptoms being described, if timer2, was not being setup correctly.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Thu Feb 04, 2010 7:35 am |
|
|
Seems at least part of the problem was a compiler issue. I was using 4.028, running a PIC18F2620. Have now tried 4.057, and the PWM works! I'm even getting "noise" out of my sound routine, definitely not the audio I'm after but it's definetely trying to do something that isn't just a tone, sounds like it's trying to use the sound array to some degree or other.
As I said, when setting duty cycle with a variable it didn't matter what the variable value was it would give the same result, but if I put actual numbers directly into the set_pwm1_duty() function then it would work. Now with 4.057 the variables are working as they should be, and seems that most of my failed attempts of code were actually correct, or near enough. Just wasn't compiling properly
Well it's now nearly midnight so I'm off to bed, I'll see if I can get this sucker operational over the weekend! |
|
|
Ttelmah Guest
|
|
Posted: Thu Feb 04, 2010 9:59 am |
|
|
Aargh!.
There for several years was a 'sticky thread' at the top of this forum, about V4. It is still on the forum, but has been allowed to move from the priority 'spot'.
Basically, V4, hardly worked for most chips, up to the late 03X versions.
This is particularly why several posters always ask for 'PIC', and 'Compiler version', when threads start.
Best Wishes |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Fri Feb 05, 2010 7:07 am |
|
|
Just a quick update, I now have recognisable audio output, the frequency needs a little bit of tuning but the system is now proven to definitely work. My initial code for the system seems like it was pretty-much spot-on, it was just because of the variable-to-pwm issue that it seemed like it was bad.
Now to figure out how to generate my own sample files and optimise the interrupt frequencies to suit... |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Wed Feb 10, 2010 11:10 pm |
|
|
Possibly (probably?) a stupid question, but the original soundfile examples that I downloaded had the format of
Code: | #ifndef OK_H
#define OK_H
const char okay[5399]={0x39, 0x26, 0x26, 0x26, 0x26, 0x51, 0x77, 0x8C, 0x7C, 0x85, 0xB2, 0xDA, ...
};
#endif |
Question being, is this correct for such a long array, or should it be const int16 okay[5399] etc?
Reason being I'm getting my sounds cut off much sooner than they should be, but then again it seems like it would quite definitely be more than 256 samples that have played before they cut off...
Or do I need to maybe split up the array and buffer it somehow, ie. might the mcu be struggling to read in the info in time for some reason? Obviously I don't have a clue as to how the mcu actually retrieves the data, I just kinda assumed it could go to the memory and access each element of the array as it was needed, but maybe it actually tried to store the entire thing somewhere first and is having issues...?
PS. The new sounds I'm using are around 13,000 samples long, and seem to be cutting out at around halfway through playback. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Feb 10, 2010 11:35 pm |
|
|
What PIC are you using ?
Is this being done in real hardware ?
What is your compiler version ? |
|
|
RoGuE_StreaK
Joined: 02 Feb 2010 Posts: 73
|
|
Posted: Thu Feb 11, 2010 12:07 am |
|
|
It's actually a few posts back; PIC18F2620
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010284
64kB program memory, 4kB RAM, 1kB data eeprom.
4.057 compiler.
Real hardware, 20MHz crystal (no PLL, might change to 10MHz with PLL), hardware PWM with timer2 set to (div_by_1, 255, 1) (~19.5kHz? Highest setting I could figure out that kept 8bit resolution)
Sound is 16kHz mono 8bit, so timer0 set to interrupt @ ~32kHz, with routine being called every 2nd interrupt. Closest method/settings I could figure out to get close to 16kHz system.
I'll do some more tests tonight with it stripped back to just playing one soundfile in a loop, but from my last few experiments it appeared that the looping was occuring at the right time, but the last half of the time was empty of sound. Would then make a "glitch" sound and restart the loop, seemingly with different lengths of audible sound each time. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Feb 11, 2010 12:28 am |
|
|
Make a test program similar to this, and see if you can display the
first and last elements in the array.
Code: |
#include <18F2620.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
const char okay[5399]={
0x39, 0x26, 0x26, 0x26, 0x26, 0x51, 0x77, 0x8C, 0x7C, 0x85, 0xB2, 0xDA, ...
.
.
.
};
//======================================
void main(void)
{
int16 i;
int8 c;
// Display first element.
i = 0;
c = okay[i];
printf("%X ", c);
// Display last element.
i = 5398;
c = okay[i];
printf("%X ", c);
while(1);
}
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|