Tempreture Measurement with HCSR04 Ultrasonic Sensor

Hi.

I am trying to make a project with HCSR04 Sensor in unconventional way. What i want is measure the temperature with HCSR04 Ultrasonic Sensor. Ultrasonic Sensor works with sound waves to detect distance measurement.

digitalwrite(trig, LOW);
delayMicroseconds(2);
digitalwrite(trig,HIGH);
delayMicroseconds (10);

time= pulseIn(echo, HIGH) ;

So i know the time. I fix the sensor so that it is 10cm away from the wall for calculate the speed of voice.

distance = 10;
speedOfVoice= (2*distance)/time;

Far now, i get the time and speedOfVoice while the sensor is fixed to 10cm away from wall. I need these calculations because;

temperature = (speedOfSound-0.03314)/0.0000606

So i should have calculate the temperature with these equations but i dont know where i make mistake. What shluld i do?

Welcome to the forum

Please post your full sketch

This will calculate the speed of sound in units of centimetres per microsecond.

What units for speed of sound does this equation require in order to give the correct result as a temperature in C or F?

You are implying that you have made a mistake. What evidence do you have for this mistake? That would have been a very helpful thing to include in your original post

you get the traveltime in µseconds.

Example for a temperature of 18°C speed of sound is

331.5 + 0.6 * 18 = 342,3 m/sec

traveltime for a distance of 0.2 m

t = 0.2 m / 342.3 m/sec = 584 µsec.

584 µsec is the time that you measure

t =
t = distance / V(T) = distance / (331.5 m/sec + 0.6 m/ (secK) * T
t = distance / (331.5 m/sec + 0.6 m/(sec
K) *T
transforming the equation to T (Temperature)

Temperature T = ( (D / t) - 331.5) * 10 / 6

With "standard"-units like m you would get a float-calculation

Temperature T = (0.2 / (584.0/1000000.0) - 331.5) * 10.0 / 6.0
which might be unprecise as floats in C++ do not have many digits

So using bigger numbers to do the calculation with integers might be more precise

unsigned longs can hold values up to 2^32 = 4_294_967_296

to make the division D / t more precise the numbers can be multiplied by 1000 / 100
should give the temperature

unsigned long dfactor = 1000;
unsigned long zfactor = 100;

unsigned long speedOfSoundAt0C = 3315UL * zfactor; 
//                       123456
//                       200000 µm * 1000 = 200_000_000
//                       1234567890
//                       4294967296
unsigned long distance = 200000UL * dfactor;  

unsigned long travelTime = 584UL;
unsigned long temperature = 0;

float  FspeedOfSoundAt0C = 331.5;
float Fdistance = 0.2;
float FtravelTime = 584.0 / 1000000;
float Ftemperature = 0.0;


void setup() {
  Serial.begin(115200); 
  Serial.println("Setup-Start");
  
  temperature = ( ( (distance ) / travelTime) - (speedOfSoundAt0C)  ) * 10 / 6;
  Serial.print("integer-calc temperature=");
  Serial.println(temperature / 1000.0,6);

  Ftemperature = (  (Fdistance/ FtravelTime - FspeedOfSoundAt0C) * 10.0 ) / 6.0;
  Serial.print("float-calc  Ftemperature=");
  Serial.println(Ftemperature,6);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Serial output shows no big difference

Setup-Start
integer-calc temperature=18.274999
float-calc  Ftemperature=18.276266

Commas are used in regular writing when dealing with large numbers. There is no need to introduce a new character for that purpose.

3,315,000,000

a7

i will try this code now sorry for late reply.
Here is my code.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_SSD1306.h>
/////
#define SDA_PORT PORTC
#define SDA_PIN 4  // A4
#define SCL_PORT PORTC
#define SCL_PIN 5  // A5
#define I2C_FASTMODE 1
#include <SoftI2CMaster.h>
#include "OLED_SoftI2C.h"
#include "term8x14_font.h"
#include <SSD1306Ascii.h>

OLEDSoftI2C oled(0x3c);
char txt[10];
/////
#define OLED_RESET 5
#define echoPin 6
#define trigPin 7
// LM35 Sıcaklık Sensörü için Tanımlamalar
int lm35Pin = A0;

int lm35Val = 0;
// HC-SR03 Sensörü için Tanımlamalar
float maximumRange=400.0;
float minimumRange=0.0;

float temp_voltage ;
float temp;

Adafruit_SSD1306 display(OLED_RESET);

void setup()
{


pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
////
  oled.init();
  oled.clrScr();
  oled.setFont(Term8x14PL);
  oled.printStr(0, 0, "LM35:");

  oled.printStr(0, 4, "HCSR:");
  oled.setMinCharWd(8);
/////
Serial.begin(9600);
}



float tempHCSR(float distance) {
  float speedOfSound, measuredHCSR_temp, cm;
    long durationHCSR;

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);

  durationHCSR = pulseIn(echoPin, HIGH);

  cm = ((durationHCSR / 2.0) * 0.0343);
  // Ses hızını hesapla (m/s)
  speedOfSound = (2.0 * (distance)) / (durationHCSR);
  Serial.println(durationHCSR);
  Serial.println(cm);
Serial.println(speedOfSound);
  // Sıcaklığı hesapla
  //sicaklikHCSR = (sesHizi - 0.03314) / 0.0000606;
measuredHCSR_temp = (speedOfSound*10000.0-331.4)/0.6;
  return measuredHCSR_temp;
}


void loop()
{

float measuredHCSR_temp = tempHCSR(28.96);

lm35Val = analogRead(lm35Pin);
temp_voltage = (5.0/1023.0)*lm35Val;
temp = temp_voltage /0.01;
Serial.println(temp);

Serial.println(measuredHCSR_temp);


 
    dtostrf(temp,5,2,txt);
    oled.printStr(38,0,txt);

    dtostrf(measuredHCSR_temp,5,2,txt);
    oled.printStr(38,4,txt);
delay(200);
}

i was using this code to calcualte temperature.

Used the SRF04 (compatible) with temperature and humidity compensation.

There is a table how to compensate for T and H and some links in the repo

related docs posted recently here

Thanks but i am trying to measure the temperature with HCSR04 from speed of sound and distance. I am not trying to make pricise the measurement of sensor.

Had some errors in my first posting.
Now evyrthing is correct.

I did not analyse your calculation.

For my my demo-code I calculated speed of sound for 18°C. 342.5 m/sec
Then calulated traveltime for 0.2 m 584 µsec

And then calculated back to temperature with these values and got 18.28°C (instead of 18.00°C)

Calcuation-code

float  FspeedOfSoundAt0C = 331.5;
float Fdistance = 0.2;
float FtravelTime = 584.0 / 1000000;
float Ftemperature = 0.0;

  Ftemperature = (  (Fdistance/ FtravelTime - FspeedOfSoundAt0C) * 10.0 ) / 6.0;

You can not measure temperature.

What you CAN do is measure the speed of sound and interpolate, which travels at a known speed in an environment of known altitude, pressure and temperature.

You know the distance from your transmitter to your reflector. As the temperature changes, so will the time to receive the reflection. See @StefanL38 @robtillaart @PaulRB replies.

You may need to take many distance measurements and average them to remove random noise from the readings.

Even then, on most Arduino, pulseIn() may not be accurate to 1us, I'm not sure. If it is only actuate to, say 4us, then your temp readings will only be accurate to 4~5 degrees C.

I made the calculations

float-calc  Ftemperature=18.276266
float-calc 4 µsec too short  Ftemperature=22.212677
float-calc 4 µsec too long  Ftemperature=14.393413

ups pretty big difference

So increasing the disctance will have longer traveltimes and a smaller error with the 4 µsec unprecision/inaccuracy.

Still a very interesting project with a lot of opportunities to learn about programming, engineering and science

just a side note:
In terms of accuracy/precision recall that

340 m/sec == 340 mm / millisec == 0.34 mm / microsec.

So an Arduino UNO which has a resolution of 4 us equals 1.4 mm.

I may be crying wolf. I remember that on Uno/Nano 3/Mega (16MHz AVR MCUs) the micros() function is only accurate to about 4us.

However, I also seem to remember that pulseIn() does not rely on micros() but rather uses a tight loop that increments a count during the pulse. That count is then converted microseconds using a calibrated constant. So maybe it is accurate to 1us.

100%, in fact its core is written in assembler IIRC.

What pulseIn does not do is disabling interrupts so there is a chance it gets disrupted e.g. if you do a Serial.print("whatever"); just before the call of pulseIn.
So I think for precise measurements I would add noInterrupts() or cli() before PulseIn(),
To investigate...

micros() is hardware timer based so it will "count" even during interrupts, price is its 4us resolution.

Well
I made some progress on project and already made the presentation to my advisor prof. I will share the code here and hope that it works for you guys too. It is not precise but if you can compansite the errors on HC-SR04 sensor with bm280 it would be work better. Compansite is important because the speed of sound also depends to the temp, humidity and presure. If you do the calibration of these, you can measure the Temp from HC-Sr04 more precisely. Here is the code and other Lib Files;

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_SSD1306.h>
/////
#define SDA_PORT PORTC
#define SDA_PIN 4  // A4
#define SCL_PORT PORTC
#define SCL_PIN 5  // A5
#define I2C_FASTMODE 1
#include <SoftI2CMaster.h>  // These 
#include "OLED_SoftI2C.h"   // Are
#include "term8x14_font.h"  // For
#include <SSD1306Ascii.h>   // OLED 
OLEDSoftI2C oled(0x3c);     // Display

char txt[100];
/////
#define OLED_RESET 5
#define echoPin 6
#define trigPin 7
// LM35 Temp Sensor 
int lm35Pin = A0;
int lm35Val = 0;
// HC-SR03 Sensor 
double temp_voltage ;
double temp;

Adafruit_SSD1306 display(OLED_RESET);

void setup()
{

pinMode(trigPin,OUTPUT);    // pin7
pinMode(echoPin,INPUT);
////
  oled.init();
  oled.clrScr();
  oled.setFont(Term8x14PL);
  oled.printStr(0, 0, "LM35:");

  oled.printStr(0, 4, "HCSR:");
  oled.setMinCharWd(8);
/////
Serial.begin(9600);
}
double tempHCSR(float distance) {
  double speedOfSound, measuredHCSR_temp ;
    long durationHCSR;

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(2);
// Getting the value of pulse duration for speed of sound
  durationHCSR = pulseIn(echoPin, HIGH);

  // Speed of Sound Calculation (m/s)
  speedOfSound = (2.0 * (distance)) / (durationHCSR);
  Serial.println(durationHCSR);
  Serial.println(speedOfSound);
  // Calculating the HC-SR04 Temp
  measuredHCSR_temp = (speedOfSound - 0.03314) / 0.0000606; // (Celsius)
  //measuredHCSR_temp = (speedOfSound*10000.0-331.4)/0.6;
  return measuredHCSR_temp;
}
void loop()
{

float measuredHCSR_temp = tempHCSR(20.0);  // write the distance of wall to inside(dont change the distance while trying to get temp. Sensor has to be fixed.)
delay(20);
lm35Val = analogRead(lm35Pin);             // getting the true temp value analog
delay(20);
temp_voltage = (5.0/1023.0)*lm35Val;
temp = temp_voltage /0.01;

Serial.println(temp);
Serial.println(measuredHCSR_temp);
// OLED Displays
    dtostrf(temp,5,2,txt);                  
    oled.printStr(38,0,txt);

    dtostrf(measuredHCSR_temp,5,2,txt);
    oled.printStr(38,4,txt);
    
delay(2000);
}

term8x14_font.h (13.6 KB)
OLED_SoftI2C.h (6.9 KB)

thanks for sharing the result

Just wondering, is the forum (thread) mentioned in your "used resources" list?

1xArduino Uno
1xHC-SR04 Ultrasonic Distance Measurement Sensor
1xLM35 Temperature Sensor
1x 0.96 Inch I2C Oled Display Module
Cables and Breadboard for connections. You can see the connections if you check the code.