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 support@ccsinfo.com

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
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.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

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

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);
}
 
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

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

I don't actually have a working rs232 setup yet, so can't trace out anything, hoping to get one operational over the weekend.
RoGuE_StreaK



Joined: 02 Feb 2010
Posts: 73

View user's profile Send private message

PostPosted: Thu Feb 11, 2010 6:50 am     Reply with quote

Hmm, just tried a different method of "tracing" and looks like the problem's uncovered, but I have no idea how to get around it;

Instead of outputing the array values via serial, I thought I'd check the values by lighting an LED if they were true;
Code:
      if(sndLoop1[0] == "0x86") output_bit(PIN_A1, 1);
      if(sndLoop1[12088] == "0x73") output_bit(PIN_A3, 1);

(sndLoop1 being a new sound loop, with 12089 values, first being "0x86", last being "0x73")

But that didn't compile, came up with an error for the second line "Subscript out of range" Sad
According to the help file, "A subscript to a RAM array must be at least 1 and not more than 128 elements. Note that large arrays might not fit in a bank. ROM arrays may not occupy more than 256 locations."
So, looks like I have to figure out a way of spliiting my arrays so that each sub-section has no more than 128 elements in them? I haven't seen any examples anywhere that have come across this issue, any tips on where to start looking for a solution?

[EDIT] just tried splitting a small section into a multidimensional array, const char sndLoop1[11][128], 11 elements with 128 variables in each, but got the errors "Too may subscripts". So now I'm more stumped than Stumpy McStump at a stumping convention Confused
Code:
const char sndLoop1[11][128]={
{
0x86,0x93,0x9D,0xA7,0xAE,0xB4,0xB9,0xBE,0xC2,0xC6,0xCA,0xCE,0xD2,0xD5,0xD8,0xDB,
0xDE,0xE1,0xE4,0xE6,0xE8,0xEA,0xED,0xEE,0xF0,0xF2,0xF3,0xF4,0xF6,0xF7,0xF8,0xF8,
0xF9,0xFA,0xFA,0xFB,0xFC,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,
0xFD,0xFD,0xFC,0xFC,0xFC,0xFB,0xFB,0xFA,0xF9,0xF9,0xF8,0xF7,0xF6,0xF5,0xF3,0xF2,
0xF1,0xEF,0xED,0xEB,0xE9,0xE7,0xE4,0xE2,0xDF,0xDC,0xD9,0xD6,0xD2,0xCF,0xCB,0xC7,
0xC3,0xBF,0xBA,0xB5,0xAF,0xA8,0x9F,0x96,0x87,0x73,0x68,0x5E,0x56,0x4F,0x4A,0x45,
0x40,0x3C,0x38,0x34,0x30,0x2D,0x29,0x26,0x23,0x20,0x1E,0x1B,0x19,0x17,0x14,0x12,
0x11,0x0F,0x0D,0x0C,0x0B,0x09,0x09,0x08,0x07,0x06,0x05,0x05,0x04,0x04,0x04,0x03
},{
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x05,0x05,
0x06,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0E,0x0F,0x11,0x13,0x15,0x17,0x19,0x1B,
0x1E,0x21,0x23,0x27,0x2A,0x2D,0x31,0x34,0x38,0x3C,0x41,0x45,0x4A,0x50,0x57,0x5F,
0x69,0x76,0x87,0x95,0x9F,0xA8,0xAF,0xB5,0xBA,0xBE,0xC3,0xC7,0xCB,0xCF,0xD2,0xD6,
0xD9,0xDC,0xDF,0xE2,0xE4,0xE7,0xE9,0xEB,0xED,0xEF,0xF1,0xF2,0xF4,0xF5,0xF6,0xF7,
0xF8,0xF9,0xF9,0xFA,0xFB,0xFB,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,
0xFD,0xFD,0xFD,0xFD,0xFC,0xFC,0xFC,0xFB,0xFB,0xFA,0xF9,0xF9,0xF8,0xF7,0xF6,0xF4,
0xF3,0xF2,0xF0,0xEE,0xEC,0xEA,0xE8,0xE6,0xE3,0xE1,0xDE,0xDB,0xD8,0xD5,0xD1,0xCE
},{
0xCA,0xC6,0xC2, etc...


Any help or pointers would be greatly appreciated, none of the info on sound playback I've come across ever mentioned issues with large arrays, so I dunno what they were doing differently...

PS. I also tried changing the CONST to ROM in both forms of the array, but it appeared to make no difference at all.
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