Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Why does my arduino get unresponsive?
New Posts  All Forums:Forum Nav:

Why does my arduino get unresponsive?

post #1 of 10
Thread Starter 

Hey guys, I just got an arduino uno and started programming on it a little in C. (I'm a bloody beginner in terms of programming) Anyway, I coded it so it calculates the square root of the number I send it via virtual serial monitor though I ran into a problem. With some numbers, it becomes unresponsive and I have to reset it so it works again. I used to not have the part where it waits for a number from the serial monitor; I used to have to change the float right in the code. Then it worked properly. What am I doing wrong? I know you can just calculate it with the sqrt command, but I wanted to try to program with the Heron's formula.

Thanks.

 

 

float y; 
float z;
int i;
float x;

void setup () {
  
  Serial.begin (9600);
  Serial.println ("-------------------------");
  Serial.println ("Root Calculator");
  Serial.println ("-------------------------");
}

void loop () {

if (Serial.available() > 0) {

  x = Serial.parseFloat();
  y = random (50);
    for (i = 0; y != z; i++) {
    
      z = (y + (x / y)) / 2;
    
      y = (z + (x / z)) / 2; }
 
  Serial.println ( x );  
  Serial.println ( "The result is:");
  Serial.println ( y, 40 );
  Serial.println ( "Rounded:");
  Serial.println ( y, 3 );
  Serial.println ( "I needed this many tries:");
  Serial.println (i * 2);
  Serial.println ("-------------------------");
  
}}
    
  

    
    


Edited by noobhell - 1/25/13 at 1:53pm
post #2 of 10
Only place I'd see it get stuck is in for loop where there is possibility for an infinite loop when z = y never matches.

As for a solution for this I suggest that you simply loop it ten times. It should still give you almost accurate answer.
My version! (Click to show)
Code:
float y; 
float z;
int i;
float x;

void setup () {
  
  Serial.begin (9600);
  Serial.println ("-------------------------");
  Serial.println ("Root Calculator");
  Serial.println ("-------------------------");
}

void loop () {

if (Serial.available() > 0) {

  x = Serial.parseFloat();
  y = random (50);
    for (i = 0; i != 11; i++) {
    
      z = (y + (x / y)) / 2;
    
      y = (z + (x / z)) / 2;

      if(z == y)
         break; 
      }
 
  Serial.println ( x );  
  Serial.println ( "The result is:");
  Serial.println ( y, 40 );
  Serial.println ( "Rounded:");
  Serial.println ( y, 3 );
  Serial.println ( "I needed this many tries:");
  Serial.println (i * 2);
  Serial.println ("-------------------------");
  
}}
   }

Edited by nikolauska - 1/25/13 at 4:31pm
post #3 of 10
Thread Starter 
Quote:
Originally Posted by nikolauska View Post

Only place I'd see it get stuck is in for loop where there is possibility for an infinite loop when z = y never matches.

As for a solution for this I suggest that you simply loop it ten times. It should still give you almost accurate answer.
My version! (Click to show)
Code:
float y; 
float z;
int i;
float x;

void setup () {
  
  Serial.begin (9600);
  Serial.println ("-------------------------");
  Serial.println ("Root Calculator");
  Serial.println ("-------------------------");
}

void loop () {

if (Serial.available() > 0) {

  x = Serial.parseFloat();
  y = random (50);
    for (i = 0; i != 11; i++) {
    
      z = (y + (x / y)) / 2;
    
      y = (z + (x / z)) / 2;

      if(z == y)
         break; 
      }
 
  Serial.println ( x );  
  Serial.println ( "The result is:");
  Serial.println ( y, 40 );
  Serial.println ( "Rounded:");
  Serial.println ( y, 3 );
  Serial.println ( "I needed this many tries:");
  Serial.println (i * 2);
  Serial.println ("-------------------------");
  
}}
   }

Hmm... Now, if I give in a large number it gives me wrong results. For example, I give in 0 and it gives me some weird number. Or if I give in 3987.382723897382 I receive -0.03203098297119140625. It thinks I gave in -0.000192682018280029296875.
 

post #4 of 10
Sorry my bad. You need to run it 20 or even 30 times according to my calculations because your random number is too small for big numbers.

I also suggest that you use
Code:
random(5, 50)
so you get random number from 5 to 49.
Edited by nikolauska - 1/26/13 at 3:21am
post #5 of 10
Thread Starter 
Quote:
Originally Posted by nikolauska View Post

Sorry my bad. You need to run it 20 or even 30 times according to my calculations because your random number is too small for big numbers.

I also suggest that you use
Code:
random(5, 50)
so you get random number from 5 to 49.

 

Thanks allot, that solved the problem, but now I have a second one. On the message bar you see the number I gave in. The first number under the title "Root calculator" indicates which number it received. What's up with that? I thought if I use the parseFloat function it should convert the number from ASCII properly?

post #6 of 10
In general you should never use a float comparison to terminate a loop. Floats are not infinitely accurate and therefor one value may only be very close to another, but not equal. Better is to use something like abs(x-y) <.0001, where the comparison value is the level of precision you are looking for. That last value can only be so small as the number of significant digits in a float is limited, but varies depending on float precision and implementation.
In your case, since you were rounding to 3 digits, .0001 is sufficient.
Floating point calculations have a number of gotchas like this and one should be familiar with the limitations if intending to do any complex calculations in order to ensure appropriate coding safeguards are in place. For instance long chains of float calculations can result in a significantly inaccurate results due to cumulative rounding errors.
I suspect your input problem is resulting from an issue with the parseFloat function as the number you entered has more significant digits than can be stored in a float. The Arduino is not intended for complex mathematical modeling and it is unlikely that the appropriate controls have been included in the libraries to manage such issues.
post #7 of 10
I cannot unfortunately test this but try
Code:
x = Float(Serial.readString());
post #8 of 10
Thread Starter 
Quote:
Originally Posted by kbwaldron View Post

In general you should never use a float comparison to terminate a loop. Floats are not infinitely accurate and therefor one value may only be very close to another, but not equal. Better is to use something like abs(x-y) <.0001, where the comparison value is the level of precision you are looking for. That last value can only be so small as the number of significant digits in a float is limited, but varies depending on float precision and implementation.
In your case, since you were rounding to 3 digits, .0001 is sufficient.
Floating point calculations have a number of gotchas like this and one should be familiar with the limitations if intending to do any complex calculations in order to ensure appropriate coding safeguards are in place. For instance long chains of float calculations can result in a significantly inaccurate results due to cumulative rounding errors.
I suspect your input problem is resulting from an issue with the parseFloat function as the number you entered has more significant digits than can be stored in a float. The Arduino is not intended for complex mathematical modeling and it is unlikely that the appropriate controls have been included in the libraries to manage such issues.

What is the highest number possible for a float? Also, is there another data type which can store more?

 

Quote:
Originally Posted by nikolauska View Post

I cannot unfortunately test this but try
Code:
x = Float(Serial.readString());


readString is not a valid function...

post #9 of 10
From Arduino reference:
Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information.

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.

Interesting that they specify the range of floats using 8 digits precision and then indicate only 6-7 digits precision in the next paragraph. The reason for a range of precision is because of the binary representation of the floats.

As noted in the reference, if you want speed, then work in int or longint. That means scaling your numbers up by say 10,000 to get three digits of precision after the decimal point. Execute your loop, looking for a difference of 9 or less as being equivalent to equal, then scale down by 10,000 to break out the pre and post decimal numbers. This puts the maximum number for which you can determine square root at just under 215,000 if using longint.

By the way, your scaling factor must be a power of 100. It is left as an exercise for the student to determine why this is. smile.gif
post #10 of 10
Thread Starter 
Quote:
Originally Posted by kbwaldron View Post

From Arduino reference:
Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information.

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.

Interesting that they specify the range of floats using 8 digits precision and then indicate only 6-7 digits precision in the next paragraph. The reason for a range of precision is because of the binary representation of the floats.

As noted in the reference, if you want speed, then work in int or longint. That means scaling your numbers up by say 10,000 to get three digits of precision after the decimal point. Execute your loop, looking for a difference of 9 or less as being equivalent to equal, then scale down by 10,000 to break out the pre and post decimal numbers. This puts the maximum number for which you can determine square root at just under 215,000 if using longint.

By the way, your scaling factor must be a power of 100. It is left as an exercise for the student to determine why this is. smile.gif


Thanks dude, helped me a lot!

New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Coding and Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › Why does my arduino get unresponsive?