View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Thu May 03, 2018 3:45 am |
|
|
The first thing is you need to 'wrapper' time.
Problem is that printing takes a long time. While the number is printing, if the interrupt occurs the time can change. This is why you get the odd spurious numbers:
Code: |
int32 local_time;
//Then to print
do
local_time=time;
while(local_time != time);
//Then print 'local_time' not time
|
What this does is copy time to local_time, and then test that the two are the same. If not, the copy is repeated a second time. This way if there was an interrupt update in the moment of the copy or between the copy and the test the copy will be repeated.
Then the second thing is that 'time' needs to be multiplied by 4 now. Remember you have the prescaler enabled. It is counting from a master clock at 250KHz (8MHz/(4*8)), so each count is 4uSec. |
|
|
irmanao
Joined: 08 Apr 2015 Posts: 77
|
|
Posted: Thu May 03, 2018 4:09 am |
|
|
Ok i changed the code as you said:
Code: | while(TRUE) {
output_high(PIN_B4);
delay_ms(10);
output_low(PIN_B4);
delay_ms(20);
output_high(PIN_B0);
delay_ms(100);
output_low(PIN_B0);
do
local_time=time;
while(local_time != time);
printf("%lu us \n\r", local_time*4 );
delay_ms(1000);
}
} |
and although i am getting the correct results, i still get the odd number here and there.
Quote: | 4294835180 us
4294835180 us
130024 us
4294835180 us
130028 us
130028 us
4294835180 us
130028 us
4294835176 us |
I changed the time of the outputs to make up for a 40ms time difference and it works fine:
Quote: | 40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us |
So i guess there is still an issue with 130ms being too long of a time for the timer? |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu May 03, 2018 5:16 am |
|
|
is LONG signed or unsigned?
It looks like maybe it gets confused when the timer rolls over and you're subtracting a smaller value from a larger one.
Again, printing all of the variables would make it more obvious. |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu May 03, 2018 5:16 am |
|
|
I meant, subtracting a larger value from a smaller one, lol. |
|
|
irmanao
Joined: 08 Apr 2015 Posts: 77
|
|
Posted: Thu May 03, 2018 5:36 am |
|
|
Long was changed to an int32 which is a signed by default, i forgot to change it in my original post.
I actually still get the random number but not as frequently:
Quote: | 40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
4294745180 us
4294745180 us
4294745180 us
4294745176 us
4294745176 us
40024 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
40024 us
40028 us
40028 us
4294745176 us
4294745180 us
4294745176 us
4294745176 us
4294745176 us
40024 us
40028 us
40024 us |
Last edited by irmanao on Thu May 03, 2018 5:47 am; edited 1 time in total |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu May 03, 2018 5:46 am |
|
|
so you're taking a 16-bit value and putting it into a 32-bit signed int, doing the same with another, then subtracting.
Worst case, subtracting larger (32-bit) from smaller would look something like this:
0x000000ff
- 0x0000ffff
____________
Think about how the value will rollover when subtracted.
You need to make them unsigned int16's. |
|
|
irmanao
Joined: 08 Apr 2015 Posts: 77
|
|
Posted: Thu May 03, 2018 6:05 am |
|
|
OK, i changed them to unsigned int16's and i don't get any more random numbers: Quote: | 40028 us
40028 us
40024 us
40028 us
40028 us |
but when the time measured is longer than 60ms i get wrong readings.
For example for 70ms i get:
Quote: | 4488 us
4488 us
4488 us
4488 us
4488 us |
So i played around with the variables and found that this setting, for some reason, works across the board for all ms: Code: | unsigned int16 rise,fall,time;
unsigned int32 local_time; |
When they are all int32's this happens:
Quote: | 4294907017 us //local_time
61084 us //rise
805 us //fall |
just like pmuldoon said. |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu May 03, 2018 6:18 am |
|
|
Look at your printf().
Remove the *4 and check your results. It should work above 60ms now.
Then try casting the variable to an unsigned int32 before multiplying. |
|
|
irmanao
Joined: 08 Apr 2015 Posts: 77
|
|
Posted: Thu May 03, 2018 6:23 am |
|
|
I edited my last post and said that this Code: | unsigned int16 rise,fall,time;
unsigned int32 local_time; |
solves all issues just like you said. But i don't really understand why. Could you elaborate please? |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu May 03, 2018 6:44 am |
|
|
The problem was you were taking a 16-bit value and multiplying it by 4. Think about what that means. You're taking a 16-bit value and trying to make it into an 18-bit value. That works as long as the actual value is less than 2^16/4, after that it will overflow. You need to convert it to a 32-bit value before multiplying. That is what you did when you made it an int32. another way was to cast it to an int32 in the printf(), which was my suggestion. Either is fine. You just need to make it big enough to hold the value after you multiply.
Again, adding some of these interim values to your printf() would have helped make it more obvious. I still do things like that from time to time. I call them 'oversights' instead of mistakes and catch/fix them quickly using a printf(). That saves me from posting them here and embarrassing myself in front of all these smart guys, LOL. |
|
|
irmanao
Joined: 08 Apr 2015 Posts: 77
|
|
Posted: Thu May 03, 2018 6:54 am |
|
|
Ok, thanks to everyone. Not only did i solve my original problem but learnt some new things on the way. Next time i'll try to catch any mistakes using printf() also. |
|
|
|