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

Why does this happen??
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
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

Why does this happen??
PostPosted: Fri Apr 23, 2004 2:20 am     Reply with quote

Hello,

Here is a snippet of code that generates a pulse of a varying size dependant on the value of PosServo0.

I need a minimum pulse of around 900uS to drive a servo but i get some very strange readings.

If PosServo0 is = 0 then with the initial delay of 900 i would expect to see a pulse of around 900uS but i don't it is around 400uS higher. I have to set my initial pulse to around 516uS to get the required 900Us, can anybody explain why this happens. I don't mind living with this situation, but i wouldn't mind knowing why it does it. Here is the code.

Code:
x = 5;
   output_high(PinServo0);      
   delay_us(516);
   do {
                delay_us(PosServo0);
        } while(--x);
   output_low(PinServo0);


It goes round the do-while loop 5 times, but surely this can't add around 400uS if 1 instruction takes 1us (i'm using a 4MHz crystal)

Any thoughts greatly appreciated

John
_________________
There are 10 kinds of people who understand binary, those who do and those who don't
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 2:32 am     Reply with quote

Quaoting from the manual:

Quote:

The delay time may be longer than requested if an
interrupt is serviced during the delay. The time spent in
the ISR does not count toward the delay time.


This might be the case with your code.
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 2:40 am     Reply with quote

Hmmm,

I don't think so.. This delay is triggered by an interrupt every 16.5mS so each time this delay is triggered the ISR has just started and this delay is over well before the next ISR 16.5mS later
_________________
There are 10 kinds of people who understand binary, those who do and those who don't
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 2:51 am     Reply with quote

The fact that the delay looks like a constant 400us makes me suspicious.... Are you sure of your 'x=5' on entrance? If x=0, then you would loop for 255 times which would take about 400us...
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 2:56 am     Reply with quote

Yes certain of X=5 because if i have a value in PosServo0 then it moves the servo by the calculated amount. If X=0 then this would not happen, it would just generate a HUGE pulse.


Puzzling..!
_________________
There are 10 kinds of people who understand binary, those who do and those who don't
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 3:26 am     Reply with quote

The code generated for delay_us() is different when called with a contant than when called with a parameter.

Calling delay_us() with a constant value is accurate.

When calling delay_us() with a variable as parameter it has an overhead of about 20-25 instruction cycles. This means that with a 4MHz crystal the minimum delay time you can get is about 25us. You are calling it 5 times, that would explain 125us of your 400us delay.

I don't know what happened to the other 275us....
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 3:29 am     Reply with quote

Yeah, that does account for some of the extra delay, but not all of it.

I suppose i will just have to say it is one of those things, but i hate to do that. It would be better to know.
_________________
There are 10 kinds of people who understand binary, those who do and those who don't
Ttelmah
Guest







PostPosted: Fri Apr 23, 2004 4:24 am     Reply with quote

johnh wrote:
Yeah, that does account for some of the extra delay, but not all of it.

I suppose i will just have to say it is one of those things, but i hate to do that. It would be better to know.

A lot depends also on the 'types' of the data. If 'x' is a long integer, it takes several times as long to do an addition/subtraction (the carry has to be dealt with). PosServo, should be an unsigned int.
I suspect you either have a different value in your registers than you think, or are using 'long' data types that add a lot more overhead.
For instance:

0026: NOP(FFFF)
0028: CLRF FEA
002A: MOVLW 19
002C: MOVWF FE9
002E: MOVLW FC
0030: ANDWF FEF,F
0032: RRCF FEF,F
0034: RRCF FEF,F
0036: MOVF FEF,W
0038: BTFSC FD8.2
003A: GOTO 0048
003E: GOTO 0044
0042: NOP
0044: DECFSZ FEF,F
0046: BRA 0042
0048: GOTO 01C4 (RETURN)

.................... delay_us(516);
01B0: MOVLW AB
01B2: MOVWF 00
01B4: DECFSZ 00,F
01B6: BRA 01B4
01B8: NOP
01BA: NOP
.................... do {
.................... delay_us(var);
01BA: MOVFF 18,19
01BE: CALL 0026
.................... } while(--x2);
01C2: DECFSZ 17,F
01C4: GOTO 01BA
Is the entire assembler sequence generated for your code, if int8 data types are chosen. Staring at the begining, the entry point is 1B0, the loop value used is 171, and the count takes 3uSec/loop, but only 2uSec on the last pass, then 4Sec are added for the loading, and the NOP's at the end. Total=516uSec.
If 'var' contains 10, and x2 contains 5, then the main loop will execute 5 times. The delay for each 'var', will be 3uSec (initial load and call), plus 14uSec if the count is zero (17uSec total overhead in this case), but for ten, the code takes the high six bits of the number (giving '2'), taking 15uSec to calculate this, and then executes a 4uSec loop for this many counts. It then takes 2uSec to return. So for the '10', the total delay will be 25uSec. The 'while' loop then adds another 4uSec/pass, so the total time becomes 145uSec.
There are a couple of uSec, then added by the time you 'clear' the pin. However the error _is not_ the scale that you are seeing. This suggests that there is something radically 'wrong' with either the numbers you are passing, or the data types (to make things worse...). The very 'suspicious' thing, is that the 'extra', is allmost exactly 256 instruction times.
However the possible errors are unfortunately large.
Consider using a timer for this. So loop with something like:
int16 delay;
delay=1000+((long)PosServo*4);
set_timer1(0);
output_high(PinServo0);
while (get_timer1()<delay) ;
output_low(PinServo0);
You will have to calculate the required multiplication factor, and offset value, to get the right time, depending on which timer you are using, but the delay then becomes a much more predictable value.
Ideally use the hardware PWM, or CCP (you can set the CCP to clear the pin when a particular count is reached).

Best Wishes
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 4:25 am     Reply with quote

Post the (relevant) generated code from the .LST file. This way we can see exactly how many instructions are being issued.
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 4:39 am     Reply with quote

I appreciate all the help you guys are giving.
Ttelmah, thanks for your suggestions. I will look at using a timer i think.

Here is the full list of the code, it pretty simple really..

Code:
// SEOS HMD servo development
// Include file that defines crystal speed (4Mhz) and that we are using PIC16F873
// and declares void genpulse(void) as a function
#include <Seosdev.h>

#define PinServo0 PIN_B7   //map PinServo0 to pin 28


// all variables used throughout code
int PosServo0 = 127;
int RawValue = 0;




int x = 0;
int i = 1;

 // start of interrupt service routine occurs every 16.5ms
#int_TIMER0
TIMER0_isr()
{
   genpulse();
}

void main()
{
   // setting up interrupt routine
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);
   // setting up the ADC
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(A_ANALOG);
   
   output_low(PinServo0);
   PosServo0 = 127; // default servo pos
   
   i = 1;
   do {
   
   set_adc_channel(0);
   delay_ms(5);
   RawValue = read_adc();
   PosServo0 = RawValue;
   } while (i = 1);
}

void genpulse(void)
{
   x = 5;
   output_high(PinServo0);      
   delay_us(516);
   
   do {
        delay_us(PosServo0);
        } while(--x);
   output_low(PinServo0);

   
}

and this is the relevant LST file code


Code:
.................... void genpulse(void) 
.................... { 
....................    x = 5; 
*
0054:  MOVLW  05
0055:  MOVWF  30
....................    output_high(PinServo0);       
0056:  BSF    03.5
0057:  BCF    06.7
0058:  BCF    03.5
0059:  BSF    06.7
....................    delay_us(516);   
005A:  MOVLW  AB
005B:  MOVWF  20
005C:  DECFSZ 20,F
005D:  GOTO   05C
005E:  NOP
005F:  NOP
....................     
....................    do {   
....................         delay_us(PosServo0);   
0060:  MOVF   2E,W
0061:  MOVWF  33
0062:  GOTO   045
....................         } while(--x);   
0063:  DECFSZ 30,F
0064:  GOTO   060
....................    output_low(PinServo0); 
0065:  BSF    03.5
0066:  BCF    06.7
0067:  BCF    03.5
0068:  BCF    06.7
....................   
....................     
.................... } 

_________________
There are 10 kinds of people who understand binary, those who do and those who don't
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 4:42 am     Reply with quote

Also post the instructions from the address 0045 onwards. That's the code for the delay_us() function.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 4:51 am     Reply with quote

No offence, but just to make sure: What have you specified for "#use delay" ?
Ttelmah
Guest







PostPosted: Fri Apr 23, 2004 5:14 am     Reply with quote

ckielstra wrote:
No offence, but just to make sure: What have you specified for "#use delay" ?


One obvious other comment. Change the variables to _unsigned_ integers (int8, or unsigned int). For signed, '127' is the maximum value that can properly be held....

Best Wishes
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Fri Apr 23, 2004 3:45 pm     Reply with quote

Sorry, left work at Lunch time.

As for the LST code from 0045, i won't be able to get that until monday, so i will post it then. (sorry didn't notice it jumped back up to 0045!)

Is an int signed then unless you specify unsigned int or int8? This could be a problem, i'll change this on monday and check the result.

Cheers for all your help guys, much appreciated. have a good weekend.

John
_________________
There are 10 kinds of people who understand binary, those who do and those who don't
johnh



Joined: 03 Jan 2004
Posts: 19
Location: UK - Brighton

View user's profile Send private message

PostPosted: Mon Apr 26, 2004 3:50 am     Reply with quote

Quote:
Is an int signed then unless you specify unsigned int or int8? This could be a problem, i'll change this on monday and check the result.


Haven't had chance to try this bit yet, but here is the code at 0045 as promised on Friday. Also ckielstra, #use delay is 4000000

Code:
.................... #use delay(clock=4000000) 
0045:  MOVLW  33
0046:  MOVWF  04
0047:  MOVLW  FC
0048:  ANDWF  00,F
0049:  RRF    00,F
004A:  RRF    00,F
004B:  MOVF   00,W
004C:  BTFSC  03.2
004D:  GOTO   052
004E:  GOTO   050
004F:  NOP
0050:  DECFSZ 00,F
0051:  GOTO   04F
0052:  BCF    0A.3
0053:  GOTO   063 (RETURN)

_________________
There are 10 kinds of people who understand binary, those who do and those who don't
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