![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
vira
Joined: 12 Feb 2007 Posts: 5
|
Multitasking timer not accurate.... |
Posted: Sat Apr 07, 2007 2:39 pm |
|
|
Hi... i have a problem with multitasking... ive used the model from PCM and was able to get the program running but the strange thing is i get a different timing when ive changed the program from A to B
Program A have interrupt according to what is set but program B have faster interrupts thats makes it look unstable... i dont think ive changed it much though... B is what im planning to do whereas i used A just to check if the routine actually works... im using 20Mhz crystal oscillator and CCS compiler IDE version 3.41
Code: | #define RTCC_PRELOAD (256 - 39)
#define mcp_timer_ticks 100 // 1000 ms
#define led_timer_ticks 100 // 1000 ms
char gc_mcp_timer;
char gc_led_timer;
//Check mcp3551//--------------------------------------------------------------
void check_mcp(void)
{
if(gc_mcp_timer)
return;
else
gc_mcp_timer=mcp_timer_ticks;
read3551();
}
//Check blinkLED//-------------------------------------------------------------
void check_led(void)
{
if(gc_led_timer)
return;
else
gc_led_timer=led_timer_ticks;
output_high(PIN_C0);
}
#int_rtcc
void rtcc_isr(void)
{
set_rtcc(RTCC_PRELOAD);
if(gc_mcp_timer) // Decrement mcp timer
gc_mcp_timer--;
if(gc_LED_timer) // Decrement led timer
gc_LED_timer--;
}
|
A
Code: | void main()
{
gc_mcp_timer = mcp_timer_ticks;
gc_led_timer = led_timer_ticks;
setup_counters(RTCC_INTERNAL, RTCC_DIV_256);
set_rtcc(RTCC_PRELOAD);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
// This is the main loop. You put your "tasks" here.
CS=1;
while(1)
{
check_led();
check_mcp();
display();
}
} |
B
Code: | void main()
{
gc_mcp_timer = mcp_timer_ticks;
gc_led_timer = led_timer_ticks;
setup_counters(RTCC_INTERNAL, RTCC_DIV_256);
set_rtcc(RTCC_PRELOAD);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
// This is the main loop. You put your "tasks" here.
CS=1;
while(1)
{
set_adc_channel(0);
delay_us(20);
readbefore=read_adc();
if(readbefore!=readafter)
{
check_led(); //indicate that measurement is ongoing
check_mcp(); //feed in measurement value
display();
write_eeprom(0x00,byte2);
write_eeprom(0x01,byte1);
write_eeprom(0x02,byte0);
readafter=read_adc();
}
else
{
byte2=read_eeprom(0x00);
byte1=read_eeprom(0x01);
byte0=read_eeprom(0x02);
byte3=0;
display();
output_high(PIN_C0); //stable value achieved
}
}
} |
im not posting everything though... just the codes that is relevant to the problem (i think)...
Program A basically is to feed the ADC value to the loop every 1s and the LED blinks at the same rate...
Program B should be the same with an addition where if a stable(no changes) value is received, it will only display that value continuously...
the reason i need to do program B is so that i wont get a blinking display all the time... i have tried to use faster interrupts for A but the blinking wont disappear since reading from MCP3551 takes time...
Thanks in advance...
PS: thanks PCM and ckieltra for ur help last time with reading MCP3551.... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sat Apr 07, 2007 3:07 pm |
|
|
Different timing on what?.
You realise that when the value is stable, the LED will stop blinking.
Also, if there is even a very small amount of change in the signal, you could quite quickly use up the 'write life' of the EEPROM.
Why read the ADC at the end of the 'non stable' branch?. Yuo have got the current reading in 'readbefore', so just make 'readafter=readbefore'.
Why update the display at all, if the value is not changing?. This wll stop it flickering.
Why not select the ADC channel just once, outside the loop. Once selected, it remains selected, so there is no need to reselect, or delay (since the code in the loop will allow for the charging time).
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
vira
Joined: 12 Feb 2007 Posts: 5
|
|
Posted: Sat Apr 07, 2007 11:42 pm |
|
|
Different timing on what?.
what i mean by timing is the the time when the check_adc ticks... Program A ticks at every 1s but B ticks at a faster rate...
You realise that when the value is stable, the LED will stop blinking.
if ur refering to B, then that is the whole idea... i want the led to stop blinking when value is stable.
Also, if there is even a very small amount of change in the signal, you could quite quickly use up the 'write life' of the EEPROM.
Why read the ADC at the end of the 'non stable' branch?. Yuo have got the current reading in 'readbefore', so just make 'readafter=readbefore'.
Why update the display at all, if the value is not changing?. This wll stop it flickering. Why not select the ADC channel just once, outside the loop. Once selected, it remains selected, so there is no need to reselect, or delay (since the code in the loop will allow for the charging time).
ur rite about readafter=readbefore
the reason i do this is becoz the flickering doesnt stop even if stable reading is achieved... like i said earlier reading MCP3551 takes time... i wouldnt have to resort to all this if there is no flicking to begin with....
code for reading MCP3551
Code: | void read3551()
{
CS=0; //drop CS
delay_cycles(1);
CS=1;
delay_cycles(1);
CS=0; //At this point conversion has been triggered.
delay_us(1);
while (SDI==1) //wait for conversion to complete
{
CS=1;
delay_cycles(1);
CS=0;
}
byte2=spi_read(0); //Now read data
byte1=spi_read(0);
byte0=spi_read(0);
byte3=0;
CS=1;
value=make32(byte3,byte2,byte1,byte0);
} |
can you maybe write it down for me what u suggest... just an outline... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Apr 08, 2007 2:46 am |
|
|
I think you are wrong in thinking that the flickering has anythiing to do with the time taken to read the 3551. This still less than a tenth of a second. I suspect the problem is that the act of updating the display, causes it to flicker, and you are doing it in both branches of your 'B' code, which is why the flickering does not stop.
As an example. if the 'display' routine, involves clearing the display, then writing the data, you will get a flicker. You don't show what you are doing here, but I'd suspect something along these lines.
You don't show what is involved in the 'display' routine, but the normal solution, is to only update the changes, rather than writing the whole display. So (for instance), if a numeric value changes on the second row, do a 'goto', to the start of where the values change, and just write the new value, rather than clearing the whole screen.
By 'check adc', do you mean the check_mcp routine, or the 'read_adc'?. The latter will 'tick' as fast as the loop can be handled (which will depend n the total delays in the routes round the loop).
As posted, both the 'timed' routines are doing unnecessary work, since you branch for the two possible conditions, but have already 'returned' in the first branch, making the presence of the second pointless. Everything after the 'return', is always executed, so why have the first line in an 'else' construct?.
Code: |
//Check mcp3551//--------------------------------------------------------------
void check_mcp(void) {
if(gc_mcp_timer==0) {
gc_mcp_timer=mcp_timer_ticks;
read3551();
}
}
|
I think this form, makes the flow much easier to understand, and is less likely to lead to unexpected behaviour.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
vira
Joined: 12 Feb 2007 Posts: 5
|
|
Posted: Sun Apr 08, 2007 7:38 am |
|
|
i should have made it clearer... now i know what u do not know.... my bad...
my display is using 7 digit 7 segment LED... the act of display is by multiplexing each digit. i have tried both read3551() and display in the same loop but i get flickers all the time, then i tried multitasking at 20ms (and slower rates too) but the flickers is still there... so thats how i got to do what im doing now...
in my 'B' code there no flickers in the second branch, but there is flickers in 1st branch which is what i wanted (actually i had to) but the problem is the rate it flicks which is not 1s...
what i mean by check_mcp (not check_adc ) is read3551()... not read_adc... to make it clearer, read3551 is reading the external 22-bit adc using SPI, the value returned from this is what im going to display, in the other hand, read_adc is just to check if there is changes in sensor input, if there is then do 1st branch of 'B' if no changes do the 2nd branch...
like i said earllier... reading 3551 and display in the same loop gives me flickers all the time, so thats why i had to do what im doing... (am i still wrong? )
anyways the code u gave is exactly like what PCM had in the original code.... i used that as a start and thats how i noticed the flickering... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Apr 08, 2007 9:17 am |
|
|
You need to approach things differently.
If you have a multiplexing task, that is required to be at a reasonably accurate interval, to give good display maintenance, then you should simplify this to the point where the change from one column to the next of the display, is a short piece of code, and include _this_ inside your interrupt handler.
Now at 20MHz, each count of the RTCC, with the 256 prescaler, will be 20000000/(4*256), 51.2uSec, and the timeout for 256 counts, will be every 13.1mSec. Your preload, of '-39 counts', should not give 10mSec, but 2mSec. I'd guess the timings were calculated for a 4MHz crystal, not your current 20MHz. So currently the update will be aboout 0.2 second.
Personally, I'd get rid of the code setting the timer forward, and use a counter of 76, which will then give just fractionally under 1 second. If the display multiplexing advances one line in each tick, the display should be stable, allowing your external code to then do it's job, whilethe display is steadily updated.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|