Go Down

Topic: Temperature Sensor (Read 327 times) previous topic - next topic

flipflop324

Hi Im a newbie in arduino. I have a project that uses LM35 as Temperature Sensor. And Piezo Buzzer that acts as an alarm. I want the frequency of the buzzer to increase as the temperature decreases. The problem with my code is that, even if the temperature is high enough for the buzzer not to ring. The buzzer still rings. Here is my initial code.

Code: [Select]
int val;
int tempPin = 1;
const int buzzer = 9;

void setup()
{
Serial.begin(9600);
pinMode(buzzer, OUTPUT);
}
void loop()
{
val = analogRead(tempPin);
float mv = ( val/1024.0)*5000;
float cel = mv/10;


Serial.print("TEMPRATURE = ");
Serial.print(cel);
Serial.print("*C");
Serial.println();
delay(1000);

if (cel = 29){
  tone(buzzer, 200, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}
if (cel = 28){
  tone(buzzer, 500, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}

if (cel = 27){
    tone(buzzer, 700, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}

  if (cel = 26){
      tone(buzzer, 900, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
  }[code][code]
[/code]
 
  if (cel = 25){
      tone(buzzer, 1000, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
  }
}

[/code]

Koepel

#1
Mar 20, 2018, 10:23 am Last Edit: Mar 20, 2018, 10:24 am by Koepel
The variable 'cel' is a 'float'. You test if it is equal to the integer 25, but 'cel' could be 25.0194843.
Even when in theory a 'float' variable should be a certain number, it still is not that number. Every calculation with a 'float' will change it a little.

The Serial.println() rounds a 'float' number when it is printed. That might be confusing.

flipflop324

The variable 'cel' is a 'float'. You test if it is equal to the integer 25, but 'cel' could be 25.0194843.
Even when in theory a 'float' variable should be a certain number, it still is not that number. Every calculation with a 'float' will change it a little.

The Serial.println() rounds a 'float' number when it is printed. That might be confusing.
In that case, do you have any idea on what I should put instead? This project really confuse me

flipflop324

I revised my codes and now, the buzzer doesn't work even at its working temperatures.

Code: [Select]
int val;
int tempPin = 1;
const int buzzer = 9;

void setup()
{
Serial.begin(9600);
pinMode(buzzer, OUTPUT);
}
void loop()
{
val = analogRead(tempPin);
float mv = ( val/1024.0)*5000;
float cel = mv/10;


Serial.print("TEMPRATURE = ");
Serial.print(cel);
Serial.print("*C");
Serial.println();
delay(1000);

if (cel == 29){
  tone(buzzer, 200, 500);
  delay(1000);        
  noTone(buzzer);    
  delay(1000);
}
if (cel == 28){
  tone(buzzer, 500, 500);
  delay(1000);        
  noTone(buzzer);    
  delay(1000);
}

if (cel == 27){
  tone(buzzer, 700, 500);
  delay(1000);        
  noTone(buzzer);    
  delay(1000);
}

  if (cel == 26){
      tone(buzzer, 900, 500);
  delay(1000);        
  noTone(buzzer);    
  delay(1000);
  }
  
  if (cel == 25){
      tone(buzzer, 1000, 500);
  delay(1000);        
  noTone(buzzer);    
  delay(1000);
  }
}


The only thing I change is the "=" that I change to "==".

adwsystems

The only thing I change is the "=" that I change to "==".

That's a good change. You changed the equation from set cel to a value to check if it is equal to a value.

Your cel if statements have to problems. They are only true if cel is equal to the singular value. What happens is cel = 25.1? Nothing. Luckily as as Koepel alluded, a float cannot be tested to be equal to number. The float data type must be tested to see if the variable is within a range. If you want to test for 25, then cel must be >= 25 and also < 26. You can then carry method through the tests for 26, 27, 28 and 29.

Koepel

#5
Mar 20, 2018, 01:15 pm Last Edit: Mar 20, 2018, 01:20 pm by Koepel
You can convert the temperature into an integer. An integer can only be a whole number, for example: 25, 26, 27, 28.

A variable that is a 'float' is (almost) never a certain number. You can not compare it with a number.

Do you know the "sieve" method ?
Start with a course sieve, then a finer sieve, then a more finer sieve, and so on.
See the temperature as a stone, and higher temperatures are bigger stones. They will fall down the "if ... else if ... else if" structure into finer and finer sieves.

Sieve with a 'float'
Code: [Select]

float x;

if ( x >= 100.0 )
{
  // x is 100 or above it
}
else if ( x >= 90.0 )
{
  // x is between 90 and 100
}
else if ( x >= 80.0 )
{
  // x is between 80 and 90
}
else
{
  // x is below 80
}


Sieve with a 'int':
Code: [Select]

int n;

if ( n >= 100 )
{
  // n is 100 or above it
}
else if ( n >= 90 )
{
  // n is between 90 (inclusive) and 100
}
else if ( n >= 80 )
{
  // n is between 80 (inclusive) and 90
}
else
{
  // x is below 80
}


I'm not sure if this is called the "sieve-method" in English, but that is what it is called in my country.

flipflop324



Thank you so much for your help. I appreciate it a lot. Although I'm not yet done, I can now visualize the course of this project. Any help further will be much appreciated. So far, my codes are working according to my choice. The only problem is that, I dont know the limits of the piezo buzzer's frequency. But I think it is re-searchable. I still accepts help from you guys. haha


Code: [Select]
int val;
int tempPin = 1;
const int buzzer = 9;

void setup()
{
Serial.begin(9600);
pinMode(buzzer, OUTPUT);
}
void loop()
{
val = analogRead(tempPin);
float mv = ( val/1024.0)*5000;
float cel = mv/10;


Serial.print("TEMPRATURE = ");
Serial.print(cel);
Serial.print("*C");
Serial.println();
delay(1000);

  if (cel <= 29){
  tone(buzzer, 200, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}
  else if (cel <= 28){
  tone(buzzer, 500, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}

  else if (cel <= 27){
  tone(buzzer, 700, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
}

  else if (cel <= 26){
      tone(buzzer, 900, 500);
  delay(1000);       
  noTone(buzzer);     
  delay(1000);
  }
 
  else if (cel <= 25){
      tone(buzzer, 1000, 500);
  }
}


I changed those "==" with "<=" like that "sieve-method" of Mr. Koepel and adwsystems. Thanks a lot guys


That's a good change. You changed the equation from set cel to a value to check if it is equal to a value.

Your cel if statements have to problems. They are only true if cel is equal to the singular value. What happens is cel = 25.1? Nothing. Luckily as as Koepel alluded, a float cannot be tested to be equal to number. The float data type must be tested to see if the variable is within a range. If you want to test for 25, then cel must be >= 25 and also < 26. You can then carry method through the tests for 26, 27, 28 and 29.
You can convert the temperature into an integer. An integer can only be a whole number, for example: 25, 26, 27, 28.

A variable that is a 'float' is (almost) never a certain number. You can not compare it with a number.

Do you know the "sieve" method ?
Start with a course sieve, then a finer sieve, then a more finer sieve, and so on.
See the temperature as a stone, and higher temperatures are bigger stones. They will fall down the "if ... else if ... else if" structure into finer and finer sieves.

Sieve with a 'float'
Code: [Select]

float x;

if ( x >= 100.0 )
{
  // x is 100 or above it
}
else if ( x >= 90.0 )
{
  // x is between 90 and 100
}
else if ( x >= 80.0 )
{
  // x is between 80 and 90
}
else
{
  // x is below 80
}


Sieve with a 'int':
Code: [Select]

int n;

if ( n >= 100 )
{
  // n is 100 or above it
}
else if ( n >= 90 )
{
  // n is between 90 (inclusive) and 100
}
else if ( n >= 80 )
{
  // n is between 80 (inclusive) and 90
}
else
{
  // x is below 80
}


I'm not sure if this is called the "sieve-method" in English, but that is what it is called in my country.

flipflop324

Can arduino interpret codes like this?


Code: [Select]
if (30 <cel <= 29)
{
do A
}


to indicate that that action A will only take effect if my temperature is less than 30*C and greater than or equal to 29*C?

Koepel

#8
Mar 20, 2018, 05:40 pm Last Edit: Mar 20, 2018, 05:42 pm by Koepel
Without the "sieves" you can do:
Code: [Select]

if ( cel >= 29.0 && cel < 30.0)


The && means AND in the 'c' language. You can only compare a variable with a single value.

Your sketch with the sieves had the sieves upside down. You started with "if (cel <= 29){", but all the others are also below 29. Comparing it after that for 28 was not executed, because it already dropped out of the sieves at the first sieve.

Note that I use "29.0" and not "29". When using 'float' variables I like to use 'float' numbers. It is a reminder for myself, but also the compiler knows that it should be done with float numbers.

falexandru

T Luckily as as Koepel alluded, a float cannot be tested to be equal to number.
I came to this post by chance.

That float can not be tested is a serious question in my view. In fact, I never thought to this problem. I imagine floats can be tested, because thy are numbers, at the end.

Anyway, hoping that this is not hijacking the thread - how to test floats then? 

adwsystems

#10
Mar 20, 2018, 07:45 pm Last Edit: Mar 20, 2018, 07:48 pm by adwsystems
I came to this post by chance.

That float can not be tested is a serious question in my view. In fact, I never thought to this problem. I imagine floats can be tested, because thy are numbers, at the end.

Anyway, hoping that this is not hijacking the thread - how to test floats then?  
Keep reading the post you quoted. (adding extra lines for clarity)

Luckily as as Koepel alluded, a float cannot be tested to be equal to number.

The float data type must be tested to see if the variable is within a range.

If you want to test for 25, then cel must be >= 25 and also < 26.
That float can not be tested is a serious question in my view. In fact, I never thought to this problem. I imagine floats can be tested, because thy are numbers, at the end.
They are numbers but you would have to enter the exact IEEE 754 number that you are looking for.

Koepel

#11
Mar 20, 2018, 07:56 pm Last Edit: Mar 20, 2018, 07:59 pm by Koepel
Either such a fall-through-sieve system is used to split the range into seperate pieces, or a number of if-else statements or else a margin.

Code: [Select]

float x = 9.5;
float margin = 0.1;

// Test if 'x' is near 10.
if ( x > (10.0 - margin) && x < (10.0 + margin))
{
  ...
}

falexandru

#12
Mar 20, 2018, 08:04 pm Last Edit: Mar 20, 2018, 08:14 pm by falexandru
Yes, but full significand is still finite and precise, right?

So comparing 2.000000 to 3.0000000 does return a correct answer?

I had some similar problems in working with EEPROMs, but I never compare, just store numbers.


Koepel

Comparing is okay.

But if the number 2.000000 was divided by 15 and after that multiplied by 15, it might no longer be 2.000000, but perhaps 1.999999.

falexandru

Then it comes to reproducing a half-adder using C commands (sort of speaking). That is really annoying. Not elegant. Must be some other way.

Go Up