CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Set PWM on interrupt?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

Set PWM on interrupt?
PostPosted: Tue Feb 02, 2010 7:50 am     Reply with quote

Hi, trying to get back into PICs and attempting to convert some of my old code from using delays to using interrupts, but am having real issues getting even the basics working.
Can anyone give some pointers on how to change the duty of a PWM on timer interrupt, to fade an LED up and down? I can't even get that working, but if I can see an example that actually works I think I can sort myself out for the rest of my projects.

Here's a snippet example of things I've tried with no success
Code:

int8 isrCount = 0;//count 9 interupts before triggering

int8 led_duty = 0;
int1 goingup = 1;
int8 pwm_max = 254;

void pwm1Change(void)
{
      if(led_duty < pwm_max && goingup == 1)
      {
         led_duty++;
      }else if(led_duty == 0)
      {
         goingup = 1;
      }else
      {
         goingup = 0;
         led_duty--;
      }
      set_pwm1_duty(led_duty);
}

#int_RTCC
void  RTCC_isr(void)
{
   if(isrCount >= 9)
   {
      pwm1Change();
      isrCount = 0;
   }
   isrCount++;
}

That fade function used to work fine when I used delays with it, but I can't seem to get any change when triggering via interrupt, I appear to only get a 100% duty cyle (PWM range via timer2 is 255, as I want to be able to natively chuck in some 8bit numbers at a later stage, and get the full dynamic range)

PS. I have succeeded in getting an interrupt to toggle LEDs on and off, so the actual interrupt setup seems OK.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 9:41 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 5:00 pm     Reply with quote

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

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

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 5:36 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 5:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Feb 02, 2010 11:28 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Feb 03, 2010 7:10 am     Reply with quote

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!! Evil or Very Mad

So what the %@#& is going on here??! Confused
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







PostPosted: Wed Feb 03, 2010 11:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Feb 03, 2010 12:46 pm     Reply with quote

Try a more simple program. This program reads a voltage from a
trimpot, and uses it to set the PWM duty cycle. The brightness of an
LED is controlled by turning the trimpot:
http://www.ccsinfo.com/forum/viewtopic.php?t=40007&start=1
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

PostPosted: Thu Feb 04, 2010 7:35 am     Reply with quote

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 Confused

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







PostPosted: Thu Feb 04, 2010 9:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Feb 05, 2010 7:07 am     Reply with quote

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... Smile
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

PostPosted: Wed Feb 10, 2010 11:10 pm     Reply with quote

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...? Confused

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

View user's profile Send private message

PostPosted: Wed Feb 10, 2010 11:35 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Feb 11, 2010 12:07 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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