|
|
View previous topic :: View next topic |
Author |
Message |
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
Help with IF statement?????? |
Posted: Fri Oct 29, 2010 10:01 am |
|
|
Hello,
I am using Ver 4.114 of the PCD compiler. I am trying to make a simple IF compare statement. Basically, I take an A/D sample and put it in an Float array. I then want to compare that element to a limit. If true set a bit, if false unset the bit. I know the inter value is 1.6. when I go into the if statement it always comes up with a false(else) answer. Could this be a compiler issue. The program originally worked with version 4.087.
Any suggestion would be appreciated.
Code is below.
Thanks :
Code: |
for (x=0;x<=12;x++) // get normal sweep
{
mux_control(x);
delay_ms(200);
run_volts_start[x]=get_voltage(); // from ad
mux_control(15);
delay_ms(50);
//printf("30 second sweep %u %f\n\r",x,run_volts_start[x]);
} // end of get voltages
//enable_interrupts(int_timer1);
restart_WDT();
float upper_limit=1.3; // upper limit
float Inter =0;
for (x=0;x<=12;x++) // check status
{
inter=run_volts_start[x]; // inter was created to try transfer to
// a variable
IF(inter(1.6) > (1.3)upper_limit )
{
bit_set(running,x);
}
ELSE
{
bit_clear(running,x); // always jumps here
}
} |
|
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Oct 29, 2010 12:02 pm |
|
|
I would start by forcing 'inter' to the value you think you know it is.
My guess is it is not what you assume it to be.
Either way, it will give you a better idea of what is broken.
Something like:
Code: |
inter=run_volts_start[x]; // inter was created to try transfer to
// a variable
|
to
just to see it execute every time.
Then maybe depending on the result, assign values to your run_volts_start[x] array and see if the bits change as expected. |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Oct 29, 2010 12:07 pm |
|
|
I have had a lot of issues with the PCD, so it could very well be a compiler bug.
My general suggestion is don't do anything fancy in your code. Keep it as simple and basic as possible.
I've looked at the assembly mneumonics for the 30F chips I was working with and don't blame CCS for having trouble with the compiler. It's hugely more complex than the old 18F world. |
|
|
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
|
Posted: Fri Oct 29, 2010 1:19 pm |
|
|
Thank you for the response.
It is correct, I can only get it to work when I hard code in
IF(1.6>1.3) this works every time. Its only when I pass variables to the IF statement it doesnt work. I am sure of what the variables are. I have them in a watch window. And The code does work with Version 4.087 with no problem. I suspect the compiler to be at fault. I am no to proficent is assembler at this time.
Thanks again, |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Oct 29, 2010 1:27 pm |
|
|
You might want to consider converting your limit to an int16 and doing everything with int16's instead of floats. You only have the resolution of the 10 or 12 bit (not sure of your chip) AD converter anyway.
I'm sure integers would compare properly. And the code will run faster as well. |
|
|
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
|
Posted: Fri Oct 29, 2010 1:46 pm |
|
|
Thanks,
I was thinking of trying that. It will mean changing quite a bit of code coming out of AD routine, Which I change to volts so other functions can massage the data in volts..
Regards, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 29, 2010 1:46 pm |
|
|
Quote: | I am using Ver 4.114 of the PCD compiler |
What PIC are you using ? |
|
|
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
|
Posted: Fri Oct 29, 2010 2:04 pm |
|
|
DSPIC30F6015.
Works great except for this bug.. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Oct 29, 2010 2:14 pm |
|
|
I checked the arithmetic operation with the below code extracted from your example, and it works correctly in PCD V4.112 and V4.114. Please try to make a short complete example that reproduces the problem for further tests. Otherwise I assume, that the problem is either located in a part of the code not shown yet, e.g. loading the array, or it only occurs under specific conditions.
Code: | int16 running;
int16 x;
float upper_limit=1.3;
float Inter =0;
float run_volts_start[12] = {3.2,0.4,0.6,0.8,1.0,1.2,1.4,1.6,1.8,2.0,22,-12};
for (x=0;x<=12;x++) // check status
{
inter=run_volts_start[x]; // inter was created to try transfer to
IF(inter > upper_limit )
{
bit_set(running,x);
}
ELSE
{
bit_clear(running,x); // not always jumps here
}
} |
|
|
|
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
|
Posted: Sun Oct 31, 2010 7:27 am |
|
|
Thanks FVM,
The only thing not shown, is the loading of the array, which comes from an A/D capture routine. The float #'s are more like 1.336464784 etc. The other puzzling part is that it works perfectly with compiler version 4.087. Another interesting thing, is the listing for both routines is substantually different. Another interesting glitch I found is:
#define FALSE 0
#define TRUE 1
#define BYTE unsigned int8
#define BOOLEAN int1
byte x;
Byte samples =130;
For(x=0,x<=samples,x++)
//do something
the interesting part is that samples comes up as -126 and the loop never runs. by changing samples to long the routine works correctly. I thought a byte was unsigned and the max was 255.It appears that byte is a signed number even when defined as unsigned. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Oct 31, 2010 8:29 am |
|
|
I didn't want to doubt, that you observed a bug related to V4.114. It won't be the first newly introduced one. But I couldn't reproduce it under the reported circumstances. To avoid guessing and possible misunderstandings, I think, it would be reasonable to provide a short complete example application, that allows to reproduce the bug.
I could not reproduce the other issue. By the BRA NC instruction, the compiler is performing an unsigned compare. But accessing a byte variable on an odd memory location by a shift operation seems to be a new kind of PCD confusion. (not using MOV.B 923 W4L)
Code: | .................... for(x=0;x<=samples;x++) y++;
*
00B9C: CLR.B 922
00B9E: MOV.B 922,W0L
00BA0: MOV 922,W4
00BA2: LSR W4,#8,W4
00BA4: CP.B W4L,W0L
00BA6: BRA NC,BB0
00BA8: INC 0820
00BAA: INC.B 0922
00BAC: GOTO B9E |
P.S.: I realized, that the strange kind of byte access has been present since V4.087 before. As a general hint, as long as you don't run absolutely short of RAM, use int16 rather than int8 for indexes and similar purposes.
Code: | .................... for(ix=0;ix<=isamples;ix++) y++;
*
00B80: CLR 924
00B82: MOV 924,W0
00B84: MOV 926,W4
00B86: CP W4,W0
00B88: BRA NC,B92
00B8A: INC 0820
00B8C: INC 0924
00B8E: GOTO B82 |
P.P.S.: Seeing the BYTE value as -126 simply means using a wrong format when watching the variable. |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Oct 31, 2010 10:33 am |
|
|
There can be confusion about floats. The coder enters values in base ten notation specifically in this example 1.6. The floating point is also notational but the base is binary and it is further normalized ( an implied 0.bbbbb...bbb). Now when the floating pt notation is 64 bit binary ( as on most PC's) the differences in notation base 10 to base two are less noticeable except in compares ( if x==y )where a single bit difference in bit 63 matters.
Frankly it is often better just to use floating pt in multiplications and or divisions that result in a very broad range of results. For compares a cast after scaling to an integer produces a more certain result. Some coders throw in fudge factors that they call rounding but it's really just notational issues. The good news is that the notation of integers is compatible ( loss less) for all bases. The compiler can have bugs but remember 0.1 in decimal can't be notated in binary loss lessly just as 1/3 can't be notated as 0.33333....333 in base ten losslessly.
There is no mathematical error or compiler error here it is just we use notation to represent numbers and changes in notation like translations from different spoken languages introduce variances. |
|
|
armondo_522
Joined: 20 Mar 2010 Posts: 9
|
Thanks. |
Posted: Mon Nov 01, 2010 7:03 am |
|
|
Thanks to everyone who responded. I changed all the float arrays to INT16 and the program is now working. I can't explain why the floats didn't work, but I will not use floats unless absolutely necessary in the future.
Regards to All.
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Nov 01, 2010 10:55 am |
|
|
Quote: | I changed all the float arrays to INT16 and the program is now working. |
A number of PCD bugs has been (and apparently is still) related to float and int32 operations. A general reason is that PCD (respectively it's programmers at CCS) get often confused with the large amount of PIC24 working registers. There seem to be a long way until these issues are completely overcome.
I just noticed another newly introduced PCD bug, with a construct, that has been working correctly since long until V4.012, but now fails in V4.014.
Here's a complete example.
Code: | #include <24FJ128GA106.h>
#use delay(clock=8000000)
#use RS232(baud=1200, UART1)
void main()
{
signed x,y,z;
x=1000;
y=0;
z = x + (((signed int32)x*y) >> 16);
printf("%i %i %i\r\n",x,y,z);
while(1);
} |
With the present values, the code gives z = 0 although it should be 1000. The assembly listing reveals, that an intermediate result is overwritten due to working register confusion.
I have reset my working PCD version to V4.012.
Code: | .................... z = x + (((signed int32)x*y) >> 16);
0035C: MOV 802,W5
0035E: CLR W6
00360: BTSC W5.F
00362: SETM W6
00364: MOV 804,W0
00366: CLR W1
00368: BTSC W0.F
0036A: SETM W1
0036C: MOV W0,W2
0036E: MOV W1,W3
00370: MOV W5,W0
00372: MOV W6,W1
00374: CALL 200
00378: MOV 802,W5
0037A: CLR W6
0037C: BTSC W5.F
0037E: SETM W6
00380: MOV W0,W5 // PREVIOUS VALUES ARE OVERWRITTEN!
00382: MOV W1,W6 // PREVIOUS VALUES ARE OVERWRITTEN!
00384: MOV W6,W0
00386: MOV #0,W1
00388: ADD W0,W5,W0
0038A: ADDC W1,W6,W1
0038C: MOV W0,806 |
|
|
|
|
|
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
|