Temperature Sensor

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.

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]

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.

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.

In that case, do you have any idea on what I should put instead? This project really confuse me

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

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 "==".

flipflop324:
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.

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'

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':

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.

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

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

adwsystems:
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:
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’

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'**:


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.

Can arduino interpret codes like this?

 if (30 <cel <= 29)
{
do A
}

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

Without the “sieves” you can do:

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.

adwsystems:
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?

falexandru:
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)

adwsystems:
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.

falexandru:
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.

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.

float x = 9.5;
float margin = 0.1;

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

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.

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.

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.

My apologies for popping up here. Perhaps it is better to move the discussion to the software section, I do not know. But in my view is definitely extremely interesting.

Hey. I am not familiar with the case(switch) code. The one that may replace the if() codes. Can you guys help me?

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int val;
int tempPin = 1;
const int buzzer = 9;
LiquidCrystal_I2C lcd(0x3F,16,2);

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


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

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


  lcd.clear();
}

If the temperature is 28, the first if-statement is already true because 28 is lower than 30.

You can also use a few if-statements like this:

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

Or you can convert the temperature into an ‘int’ can compare it with 28, 29, 30 and so on.