I'm making a project that measures the distance of water and I need a way to be able to calibrate my ultrasonic sensor (JSN-SR04T 2.0) so that it doesn't fluctuate with temperature or at least not as bad. currently when it gets hot outside that makes the speed of sound goes up and so my ultrasonic waves travel faster and it makes my distance go down on the graph and then at night when it's cool the waves travel slow and my distance graph goes up. are there any sensors that can be used with Arduino to get the speed of sound? I I'm currently using a ds18b20 sensor to get the temperature and then converting that to speed of sound but that does not appear to be doing anything as my graph still has high and low fluctuation even though it's measuring a bucket of water that does not change depth... I had a suggestion to use another ultrasonic sensor to measure a fixed distance and calculate speed of sound off of that but I had a colleague who tried that and he still got a graph that varied a lot, also I'd like it to be minimal in size and not have to use two ultrasonic sensors with a tube measuring a fixed distance. In my research of speed of sound calculations I read over a forum that said humidity and air pressure have minimal effects on speed of sound compared to temperature so I don't know if I need those in my calculations... Any suggestions or guidance would be greatly appreciated - thank you.
You can track temperature, humidity or whatsoever together with your distance data. Then try to find out which of these other curves show the same course as the distance, and use that sensor values to fix the distance readings.
Mr_HaleYa:
I'm currently using a ds18b20 sensor to get the temperature and then converting that to speed of sound but that does not appear to be doing anything as my graph still has high and low fluctuation even though it's measuring a bucket of water that does not change depth...
Did the adjustment for temperature reduce the fluctuation? It would be interesting to see the data you've collected.
As I understand it, at fixed altitude, temperature will be the dominant term, but pressure and humidity have an effect. So the possibilities include at least the following:
- One or more of your measurements is incorrect
- There is an error in the calculation
- Compensation for temperature is correct but there is residual error due to pressure, humidity, or some other factor
I had a suggestion to use another ultrasonic sensor to measure a fixed distance and calculate speed of sound off of that but I had a colleague who tried that and he still got a graph that varied a lot
Ignoring the implementation complications, the beauty of directly measuring speed of sound in the target environment is that it shouldn't matter what factors contribute to variation. One problem is that any fixed bias in the reference time of flight measurement needs to be zeroed to accurately calculate speed of sound. One could do this by measuring a couple calibrated distances under fixed air temperature etc. That calibration probably needs to be done for your primary sensor as well.
Mr_HaleYa:
I'm currently using a ds18b20 sensor to get the temperature and then converting that to speed of sound but that does not appear to be doing anything as my graph still has high and low fluctuation even though it's measuring a bucket of water that does not change depth...
Maybe you have a problem in your code.
when it gets hot outside that makes the speed of sound go down
The speed of sound in air increases with temperature. v = 20.05*sqrt(T/K)
Agree, problem with the code.
Compensation for temperature is correct but there is residual error due to pressure, humidity
Pressure has no effect, and the effect due to humidity is probably too small to measure with such simple equipment.
The Arduino clock speed depends on temperature, too.
aarg:
Maybe you have a problem in your code.
It does do something but it's not flattening it out as much as I would like it cuts the fluctuation and half but I was hoping to cut the fluctuation down until it was negligible.
jremington:
The speed of sound in air increases with temperature. v = 20.05*sqrt(T/K)
Sorry that was a typo my speed of sound graph does increase when it gets hot and decrease when it gets cold. My bad. It's not an error in the code because if I make the speed of sound a fixed number instead of calculating it it has pretty large fluctuation but if I put in the current speed of sound the fluctuation is small but is still there. Without speed of sound calculation the fluctuation can vary up to 60 mm with the current speed of sound its varying about 30 mm.
For informed help, please read and follow the directions in the "How to use this forum" post.
Post the code, using code tags, and examples to show what you think is going wrong.
Mr_HaleYa:
I'm making a project that measures the distance of water and I need a way to be able to calibrate my ultrasonic sensor (JSN-SR04T 2.0) so that it doesn't fluctuate with temperature or at least not as bad. currently when it gets hot outside that makes the speed of sound goes up and so my ultrasonic waves travel faster and it makes my distance go down on the graph and then at night when it's cool the waves travel slow and my distance graph goes up. are there any sensors that can be used with Arduino to get the speed of sound? I I'm currently using a ds18b20 sensor to get the temperature and then converting that to speed of sound but that does not appear to be doing anything as my graph still has high and low fluctuation even though it's measuring a bucket of water that does not change depth... I had a suggestion to use another ultrasonic sensor to measure a fixed distance and calculate speed of sound off of that but I had a colleague who tried that and he still got a graph that varied a lot, also I'd like it to be minimal in size and not have to use two ultrasonic sensors with a tube measuring a fixed distance. In my research of speed of sound calculations I read over a forum that said humidity and air pressure have minimal effects on speed of sound compared to temperature so I don't know if I need those in my calculations... Any suggestions or guidance would be greatly appreciated - thank you.
A balanced float on a piece of string wound on a pot shaft kind of looks good right now.
it's measuring a bucket of water
Measure the distance to a wall first, and debug your program.
Buckets have edges and sides that reflect sound.
If the Arduino is in the same temperature environment as the US sensor, I would think the temperature effect on the Arduino's oscillator is the cause.
Most AVR controllers have an ADC channel reserved for their internal temperature.
But I doubt that this temperature will influence the external resonator.
Mr_HaleYa:
I'm currently using a ds18b20 sensor to get the temperature and then converting that to speed of sound but that does not appear to be doing anything as my graph still has high and low fluctuation even though it's measuring a bucket of water that does not change depth..
Hows about we see your code and how your maths compensates for the change in air temperature.
Thanks.. Tom...
PS, I can't believe we are 11 posts in and no code!!!!!!!!!!!!!!
jremington:
Measure the distance to a wall first, and debug your program.Buckets have edges and sides that reflect sound.
I built a stand that's why I bolted to my wall it measured to the other side of movie room to a flat wall and calibrate it that way and then took it outside and the calibration didn't matter because it still varied wildly whereas inside it stayed within one mm but inside the temperature did not change that much where has outside it fluctuates between -5 degrees Celsius 23 degrees. I also have it filled to the very brim of the bucket because I knew about the walls problem and so it's not as much measuring the bucket it's just measuring the water at the very top of the bucket
TomGeorge:
Hows about we see your code and how your maths compensates for the change in air temperature.
Thanks.. Tom...
PS, I can't believe we are 11 posts in and no code!!!!!!!!!!!!!!
I had shown my code in a previous forum post and I thought people were tired of seeing it
All my setup and stuff that calls all my librarys and sets up wifi so I can send my data to thingspeak
#include <ESP8266WiFi.h>; //https://github.com/esp8266/Arduino
#include <WiFiClient.h>;
#include <ThingSpeak.h>; //https://github.com/mathworks/thingspeak-arduino
#include <OneWire.h> //https://github.com/PaulStoffregen/OneWire
#include <DallasTemperature.h> //https://github.com/milesburton/Arduino-Temperature-Control-Library
#define ONE_WIRE_BUS 12 // Define data pin for tempsensor
#define trigPin 5 // Define Trig pin
#define echoPin 4 // Define Echo pin
OneWire oneWire(ONE_WIRE_BUS);
WiFiClient client;
DallasTemperature tempSensor(&oneWire);
const char* ssid = "MY Wi-Fi"; //Your Network SSID
const char* password = "MYWIFIPASSWORD"; //Your Network Password
unsigned long ChannelNumber = 1023056; //Channel Number
const char * WriteAPIKey = "you dont need this lol"; //Write API Key
float freshData, calcDistance, distance, initialMedian, rawSpeedOfSound, calcSpeedOfSound, currentTemp;
float initialData[25];
int initialReadings = 25; //number of data points to chose initial median out of
float refinedData[5];
int refinedReadings = 5; //number of intital median points collected before chosing a refined median
float pureData[5];
int pureReadings = 5; //number of refined medians collected before being averaged
float tempBuffer[15];
int tempReadings = 15; //number of initail tempature readings before choosing a median and calculating SOS
float refinedTemp[5];
int refinedTempReadings = 5; //number of SOS data collected before calculating current SOS
void setup() {
pinMode(trigPin, OUTPUT); //setup trigerPin as an output
pinMode(echoPin, INPUT); //setup echoPin as an input
tempSensor.begin(); //start tempsensor
Serial.begin(9600); //start serial monitor at a baud rate of 9600
Serial.println("\n5 Seconds to clear Serial");
delay(5000);
Serial.println("\n---STARTING UP---");
Serial.println("Starting Wifi ");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("*");
}
Serial.println("\nWiFi Connection Successful");
Serial.print("Connected to: ");
Serial.println(ssid);
Serial.print("IP Address: ");
Serial.println(WiFi.localIP()); // Print the IP address
Serial.println("\n");
ThingSpeak.begin(client);
}
void connectToWifi() {
Serial.println("\nWIFI HAS BECOME DISCONECTED!!!");
Serial.println("Reconnecting ");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("*");
}
Serial.println("Reconnection Sucsessful\n");
}
This is what I use to get the temperature. It records 15 measurements then sorts and takes a median. after doing that 5 times it averages my 5 medians to give a very accurate temperature reading (within +-1°C) the temperature is stored as currentTemp.
void getSOS(){
float calcRefinedTemp = 0; //set to 0 for every calculation or it will double over time
for (int i = 1; i <= refinedTempReadings; i++){
writeTempData(tempBuffer,tempReadings); //collect tempature data
sortData(tempBuffer,tempReadings); //Sort tempature data collected
refinedTemp[i-1] = tempBuffer[(tempReadings-1)/2]; //get median out of tempBuffer then calculate the speed of sound
}
sortData(refinedTemp,refinedTempReadings); //Pass in the values and the size.
for (int i = 0; i < refinedTempReadings; i++){
calcRefinedTemp = calcRefinedTemp + refinedTemp[i];
}
calcSpeedOfSound = (331.3 * sqrt(1+((calcRefinedTemp / refinedTempReadings)/273.15))/1000); //calculate the curent speed of sound
currentTemp = calcRefinedTemp / refinedTempReadings;
}
void writeTempData(float data[], int size){
for (int i = 0 ; i < size; i++){
tempSensor.requestTemperatures();
delay(100);
data[i]=tempSensor.getTempCByIndex(0);
}
}
I then get my distance by taking 25 readings then sorting and recording a median. It does that 5 times then sorts those and takes a median. It does that 5 times and then averages them to get an incredibly accurate reading (+-.1mm indoors ) basically 625 readings give me 1 very accurate reading
void getDist(){
float pureDataTotal = 0; //set to 0 for every calculation or it will double over time
for (int i = 1; i <= pureReadings; i++){
for (int i = 1; i <= refinedReadings; i++){
writeDist(initialData, initialReadings);
sortData(initialData, initialReadings); //Pass in the values and the size.
initialMedian = initialData[(initialReadings - 1) / 2];
refinedData[i-1] = initialMedian;
}
sortData(refinedData, refinedReadings); //Pass in the values and the size.
pureData[i-1] = refinedData[refinedReadings / 2];
}
for (int i = 0; i < pureReadings; i++){
pureDataTotal = pureDataTotal + pureData[i];
}
calcDistance = pureDataTotal / (pureReadings+1);
}
void writeDist(float data[], int size){
for (int i = 0 ; i < initialReadings; i++){
distance = ping() * calcSpeedOfSound / 2; //calls funtion ping() and calculate the results
initialData[i] = distance;
delay(10);
}
}
float ping(){ //function for collecting data
float indata;
digitalWrite(trigPin, LOW); // Clear the trigPin by setting it LOW:
delayMicroseconds(20);
digitalWrite(trigPin, HIGH); // Trigger the sensor by setting the trigPin high for 10 microseconds:
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
indata = pulseIn(echoPin, HIGH);
return indata;
}
my miscellaneous that assist but aren't related are my loop wich just gets temp then distance then posts to thingspeak and my bubble sorter.
void sortData(float data[], int size) {
float swapper;
for(int i = 0; i<(size-1); i++) {
for(int o = 0; o<(size-(i+1)); o++) {
if(data[o] > data[o+1]) {
swapper = data[o];
data[o] = data[o+1];
data[o+1] = swapper;
}
}
}
}
void loop() {
if (WiFi.status() != WL_CONNECTED){ //----Ensure Wi-Fi connection---
connectToWifi();
}
getSOS();
getDist();
Serial.print(currentTemp); Serial.println(" °C");
Serial.print(calcSpeedOfSound*1000); Serial.println(" m/s");
Serial.print(calcDistance); Serial.println(" mm\n");
ThingSpeak.setField(1, (calcSpeedOfSound * 1000));
ThingSpeak.setField(2, calcDistance);
ThingSpeak.setField(3, currentTemp);
ThingSpeak.writeFields(ChannelNumber, WriteAPIKey); //Update in ThingSpeak
}
What I don't know if I'm doing correctly is calculating the speed of sound... I found some formula that only required temperature to give me the speed of sound.
SOS_in_air = 331.3 * √(1 + T/273.15) [m/s] for T in °C
I think I put it in the code right? Im not sure if thats even the right formula...
calcSpeedOfSound = (331.3 * sqrt(1+((calcRefinedTemp / refinedTempReadings)/273.15))/1000); //calculate the current speed of sound
It had this also written in the article I took it from
Did you notice something interesting? The speed of sound in the gas depends only on two constants - γ, R - and on the temperature but not on the air pressure or density as it is sometimes claimed. The humidity of air also has an effect on the speed of sound, but the influence is so small that it can be neglected. The temperature is the only important factor!
Your sensor returns the time for the very first echo it hears. Are you waiting long enough between pings for all the echos to die out? Can't tell from the snippets.
Paul
Mr_HaleYa:
I had shown my code in a previous forum post and I thought people were tired of seeing it
Quite a lot of forum members use smartphones rather than full blown PCs and referring back to other threads can be difficult.
So posting your COMPLETE code, either in code tags if it is not too big , or as an attachment in this thread would be of great help.
Are you using an ESP8266 or an ESP32?
Thanks.. Tom...
Paul_KD7HB:
Your sensor returns the time for the very first echo it hears. Are you waiting long enough between pings for all the echos to die out? Can't tell from the snippets.Paul
there's a 50 millisecond delay between each reading in my most current version of the code because I was concerned about echos.
As for Tom.
I'm using an esp8266 but I'm hoping to be able to use in esp32 in the future I just couldn't get it to work with my GSM module so I ordered one that has a esp32 and GSM module build together on the board and yes I have been replying on my smartphone but I did get on the computer to post my code. I'll have to post it again as an attachment as it says it's too big. That is my complete code and that is how it's structured I just broke it into chunks so it was easier to read... (For me anyways)
Here is my code (attachment) that is currently running on one of my sensors (esp8266) outside and also a picture of the graphs its generating. The left graphs are speed of sound (top left) and temp in Celcius (bottom left). The top right is using the big speed of sound equation and bottom right is using a fixed speed of sound (343 m/s) there is another distance graph that I didn't include that uses the simplified speed of sound equation but it looks the same as the top right except everything is 2 mm closer. It's as if me finding the current speed of sound is having almost no impact on the graph... the high flat parts on the distance graphs are at night when the temperature is below 0c. Any reasons why this isn't working correctly?
tempforAF.ino (12.3 KB)
You forgot to include the Y scale increment for the graphs on the right side of the figure.
The speed of sound in air varies by about 2% over the temperature range of 0C to 10C. So you would expect to see the estimated distance change by 2%, or about 4mm out of 220mm, if you assume constant sound velocity.
If the change in distance is still observed after applying the temperature correction, then either your program is wrong or some other temperature dependence has a larger effect. I would bet on the first possibility.
However, I doubt any of us wants to wade through 350 lines of code to figure out what might be wrong with a calculation that takes two lines of code.