View previous topic :: View next topic |
Author |
Message |
spark
Joined: 03 Jan 2012 Posts: 17
|
Interrupt control problem - BAM example |
Posted: Wed Jan 04, 2012 11:39 am |
|
|
Hello
I'm trying to create 8 independently dimming LED's with BAM.
(what BAM is)
I'm struggling with the code, at the moment the interrupts are creating problems. The idea is to make 8 interrupts, each is half as long as the one before. So if one cycle would take one second (in reality it would be 1/150 seconds), the first cycle would be 1/2 sec, the 2nd 1/4, the 3rd 1/8, (and so on...) and the last one 1/256 sec. The cycles should be controlled be an interrupt of a timer. After each cycle LATB will set new data (taken from an array of bytes). Now I need help to set the timer to create a new interrupt.
I checked to web and to manual for an example, but I didn't find anything simple that I understood and that covers setting the timer to a new time. I would be really glad if somebody could post me an example or help me with the code. Thanks so much. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Jan 04, 2012 12:22 pm |
|
|
You should learn how to use 'Google' better.
Asking for BAM C code examples pulled up over 3 million hits, within the first 3-4 pages was complete code, very easily converted to CCS style C.
The 'Net' is a wonderful place, chock full of interesting stuff.... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Jan 04, 2012 1:35 pm |
|
|
b-a-m--interesting but I think no sale.
I did some work on a long life battery power light backup system for a military application - and in order to defeat problems with "flicker persistence" - seen as fine points of patterned light "flashes" -
while moving your gaze through the LED light field - I had to use a
multiplexing frequency of 100 kHz.
The low, and variable duty cycle of b-a-m worries me greatly on that issue.
The real possibility of saturating your PIC 's interrupt structure follows closely as a concern. |
|
|
spark
Joined: 03 Jan 2012 Posts: 17
|
|
Posted: Wed Jan 04, 2012 2:03 pm |
|
|
???
I asked google for "BAM C code examples". It didn't bring up anything useful at all. I checked the first five links though I doubted that it could be useful. In fact it showed C code but nothing had anything to do with Bit Angle Modulation. Please check the links first before you're saying something like that. Post me a link if you discover something completly different.
@asmboy: Would you say, it won't work? Do you think the processor is to slow to switch the ports that fast? PWM wouldn't work for that many channels.
I would be really glad if somebody could post me a simple example for the interrupts with setting timers and so on. If you have a useful link, please post it, but please don't just refer on google - belive me, I used it! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Jan 04, 2012 3:35 pm |
|
|
Quote: |
Do you think the processor is to slow to switch the ports that fast? PWM wouldn't work for that many channels.
|
yes a slow PIC IMHO - has no hope of doing this - with enuf speed- to do anything BUT flash the leds ( annoyingly ) && maybe not even that...
you might pull the data sheet for the 18f2450 // 4450 -
which i believe can be operated with external oscillator or combo +PLL
@ up to Fosc =48mhz
if i was going to TRY to do this - i would probably start by using the timer0 interrupt ONLY -and then manipulate the prescalar //manipulate initial && rollover timer load - in a variable way - and lastly craft the tightest state machine code i could inside the ISR to flip the pins up and down;-))
i just don't see how external interrupts can play a useful role in what you want to do. no matter what -- this is NOT A BEGINNER Project you are considering. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Jan 04, 2012 3:48 pm |
|
|
Only looking at 5 links of the 3 million hits really isn't good enough, I scanned a few pages and found some applicable code but haven't time to list them all...
Google is extemely powerful if you ask Google right, it is surprising what it can find. if you only want CCS C code, you have to specify that. Any AVR code will not be shown. 'BAM' might not be good enough, also add Bit Angle Modulation to the search parameters.
Odds are real good, if you give Google say 15-120 keywords it'll come up with what you want. PCM pgmr found the AVR and non CCS C code easily.
As for examples of using timers and ISRs, CCS has lots in their 'examples' folder. |
|
|
spark
Joined: 03 Jan 2012 Posts: 17
|
|
Posted: Wed Jan 04, 2012 4:09 pm |
|
|
ok, thanks for the links. I will make a more advanced search (though I was usually successful with my method - but for now I'll try more keywords). I was struggling with the code I found (in the links) but I'll try it again. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Why BAM and not PWM. |
Posted: Thu Jan 05, 2012 5:01 am |
|
|
Please supply more detail of why you have to use BAM.
If you are only driving 8 LEDs then you may be able to use a simple PWM system and only one interrupt.
It all depends on the required performance level.
How many brightness levels do you want for each LED?
What is the lowest brightness modulation frequency you can tolerate?
etc.
OR
Why not interrupt at the highest rate required. In the 1st cycle use the 1st interrupt then ignore the next 127, for the 2nd cycle ignore next 63 .........none for the 8th?
Mike |
|
|
spark
Joined: 03 Jan 2012 Posts: 17
|
|
Posted: Thu Jan 05, 2012 10:18 am |
|
|
I'm using BAM because it allows me to set individual brightness levels for each LED. I don't think that this is possible with PWM.
I'm using the internal oscillator which provides a maximum frequency of 8 Mhz. I planned to use an 8 bit timer (so I'd have 16 levels) at 150 hz. With the 16 bit timer I'd have 256 levels, but the maximum frequency would be 61.04 hz (4Mhz/65536).
I prefer the bigger framerate over the bigger resolution.
I think it doesn't matter if I use more interrupts or just the ones required (or does it?) - what I'm struggling with is the general interrupt and timer setup (ok... basic stuff... sry).
That's what I have so far:
Code: | #include "18F4550.H"
//#include <math.h>
#use standard_io(B)
#use delay (internal=8000000)
#fuses INTXT
#byte LATB=getenv("SFR:LATB")
#int_timer0
int8 j[14] = {0b01110000,0b10110000,0b11010000,0b11100000,0b11111000,
0b00001011,0b11111101,0b00000001,0b11110010,0b11110100,
0b11111000,0b00011111,0b11010000,0b01001111};
int16 i = 0;
int16 frames = 0;
int16 k = 0xFFFF;
int32 z = 0;
setup_timer1(TMR_INTERNAL);
void main(void)
{
enable_interrupts (INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
void timer0_isr(void)
{
if(z > 149){
z = 0;
frames++;
}
z++;
if(i>6*(frames))
i = 0;
else
i++;
output_b(j[i]);
if(k == 1)
k = 0xFFFF;
else
k = k/2;
set_timer1(0xFFFF-k); // clear the timer register
} |
For some reason it doesn't work, I don't know why. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Thu Jan 05, 2012 11:27 am |
|
|
I haven't gone through it extensively, but here are some things that stuck out:
needs to be right above the isr code I think:
Code: |
#int_timer0
void timer0_isr(void)
{
if(z > 149){
z = 0;
frames++;
}
z++;
if(i>6*(frames))
i = 0;
else
i++;
output_b(j[i]);
if(k == 1)
k = 0xFFFF;
else
k = k/2;
set_timer1(0xFFFF-k); // clear the timer register
}
|
Also,
Code: | setup_timer1(TMR_INTERNAL); |
should be placed in the main (at the beginning of it) |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Jan 05, 2012 1:11 pm |
|
|
Quote: |
set individual brightness levels for each LED
|
the whole premise of what you want to do is being hampered by pesky old physics & human biology.
in a "white light LED" project i did some time ago - i found that a wide range of PWM led drive variation produced a very linear difference of light
measured on a solar cell light METER- B U T - when VIEWED by the human eye - it is QUITE different. I could vary the PWM duty over a 40% range - from 100% heading down - with very little perceived dimming when the rate was 100khz. even motion persistence strobing is minimal.
BUT , the same persistence of vision that makes watching a scanned CRT work - or leaves a bright spot after a bright flash -- greatly hampers all pulsed LED attempts at brightness control.
IN short - i think you will find that to get much apparent dimming - to the human eye- only when you get to very VERY low duty cycles will you see much difference in brightness for you efforts.
U C ., I've BT, DT , && GT-TS
regards |
|
|
spark
Joined: 03 Jan 2012 Posts: 17
|
|
Posted: Thu Jan 05, 2012 5:18 pm |
|
|
Finally I got a working example. The difference between the LED's is not that big (and not I think not linear yet, but I'll change that). Eventually I'll take the 16 bit timer (but use just 10 bits) to get a darker first level. Thanks for helping. Any ideas for improvements (EDIT: especially how to store the animation data?)?
Code: | #include "18F4550.H"
//#include <math.h>
#use standard_io(B)
#use delay (internal=8000000)
#fuses INTXT
#byte LATB=getenv("SFR:LATB")
int8 j[16] = {0b10000000, 0b11000000, 0b11100000, 0b11110000, 0b11111000, 0b11111100, 0b11111110, 0b11111111,
0b00000001, 0b00000011, 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111, 0b11111111};
int16 currScene = 0
int16 arr = 0;//current arraynumber = current output
int8 time = 0xFF;
int16 currFrame = 0;
const int8 maxScenes = 2;
#int_timer0
void timer0_isr(void)
{
if(time == 1){
if(currFrame == 15625){//15625 = frameRate, 15625 frames = 1 scene = 1 sec
currFrame = 0;
if(currScene == maxScenes-1)
currScene = 0;
else
currScene++;
}else{
currFrame++;
}
arr = currScene*8;
time = 0xFF;
}else{
arr++;
time = time/2;
}
output_b(j[arr]);
set_timer0(0xFF-time);
}
void main(void)
{
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_4);
enable_interrupts (INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
} |
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
PWM vs BAM |
Posted: Fri Jan 06, 2012 3:15 am |
|
|
Quote: |
the whole premise of what you want to do is being hampered by pesky old physics & human biology.
in a "white light LED" project i did some time ago - i found that a wide range of PWM led drive variation produced a very linear difference of light
measured on a solar cell light METER- B U T - when VIEWED by the human eye - it is QUITE different. I could vary the PWM duty over a 40% range - from 100% heading down - with very little perceived dimming when the rate was 100khz. even motion persistence strobing is minimal.
|
What asmboy is telling you is that human brightness perception is logarithmic (like most other human senses). I.e. linear brightness changes are less noticable at higher intensities.
Quote: |
I'm using BAM because it allows me to set individual brightness levels for each LED. I don't think that this is possible with PWM.
|
You can achieve PWM by creating a regular timed interrupt, then turn each LED on/off for an integral number of interrupt periods.
For the above PWM scheme and your BAM scheme each ON period is an integral number of interrupt periods.
The best resolution you can achieve is set by the shortest achievable interrupt interval which will be roughly the same for either method.
There is the possiblity of a fiddle you can do to improve resolution. In the olden days, UK TVs had a true frame rate of 25Hz, which should have produced noticable flicker. On one scan of the screen only odd number lines were drawn, on the next scan even numbered lines were drawn. Each scan took 20msec. The human eye percieved the frame rate as 50Hz even though only half a complete picture was drawn on each scan. With either PWM or BAM you may be able to get the illusion of a half bit resolution by modulating the duty ratio on alternate frames. So when the duty should be say 35/256 you use 35/256 on all frames. To get 35.5/256 you use 35/256 on one frame then 36/256 on the next. It's possible that the mild flicker will not be noticed and you get say 9 bit resolution with an 8 bit system.
[This fiddle was also used to create tones for electronic musical instruments. A high frequency clock (MHz region) was divided by integers to generate a chromatic scale. More accurate scales were achieved by dividing alternately by adjacent integers when needed. In practice very few people noticed the minor pitch modulation.]
Mike |
|
|
|