Ds18b20 and interrupt with anemometer

448/5000
On a Arduino Mega board, I make a weather station application …
On the other hand, I have an interaction between the reading of the temperature with a DS18B20 and the interruption of the reading of the wind speed … everything seems to work well, except that the temperature Mini and Maxi when one lets turn a certain time, records temperatures at 0, 1000, -2000 ° C.
Do you have any research leads, or notices of errors in my code ??
cordially

AWS_Basic_Web_Server_Sketch_Tpar_DS_BME_Force_vent_V2.ino (11.9 KB)

I think you are correct and your timer interrupt could be interfering with reading the temperature from the one wire bus. There is some rather specific timing required to read a temperature from a DS18B20. If that gets interrupted at the wrong place, you could get a false reading of temperature value.

Interrupts should be as small a code as needed as other things (like delays) might not be planning to be running off doing other things unexpectedly. You could try turning off the interrupts during the readSensor() event and see if this helps at least confirm this is the issue. It might alter your windspeed a little and eventually your rain gauge when you get that working.

cli(); //turn off interrupts temporarily
ds.readSensor();
sei(); //turn back on interrupts

If this works, you might also try moving the float calculation out of the timer interrupt routine instead. Just set a variable with the current rotations/2.5 seconds instead and then do the calculation for actual windspeed using this variable when you actually use it.

Or, rather than try to keep windspeed in real-time, you might also just count rotations in a single 2.5 second interval in its own routine vs reading it every 2.5 seconds, and do this in between reading temperature, etc.

Basically.. attach the interrupt. zero the rotation count, wait 2.5 seconds the detach the interrupt, calculate windspeed using the new rotation count. This would eliminate the timer interrupt and avoid any conflict with code like ds.readSensor() that uses fixed delays. The rain gauge tip interrupt is fast enough I don't think it will conflict much with the one wire read.

I set up a DS18B20 here on pin 3 of a Teensy 3.2. A ds18b20_scanner and a ds18b20_test sketch both worked, the test script writing reasonable values for the temperature.
I then tried the cactus demo sketch. It fails miserably. All it prints is:

4095.94 *C 7404.69 *F
4095.94 *C 7404.69 *F
4095.94 *C 7404.69 *F

and it does this even if the DS18B20 isn’t connected. But adding ds.getSerialNumber() to the sketch, in setup(), shows that it does read the ROM address correctly so it is seeing the DS18B20, it just can’t read the temperature properly. It doesn’t matter whether I wire the DS18B20 for parasite power or not - same results.
FYI: the cactus library that I found always reads the DS18B20 with parasite power. If you have your DS18B20 wired for non-parasite power, you are going to have trouble.
I suggest that you try the Dallas Semiconductor library instead of cactus.

Pete

Thank you for your answers .... I'm testing tomorrow back home

I add the code proposed:

cli(); //turn off interrupts temporarily
ds.readSensor();
sei(); //turn back on interrupts

but very quickly I recorded a temperature in error with -.0.6 ° C

I am in the process of integrating the DallasTemperature library, but I have a hard time transforming the reading script of a single sensor, edited by the serial port to a web server output

I think el-supremo confirmed the cactus library was not working right. I would probably start by just getting some code to read and print the right temperature from the DS18B20. At least you can confirm that is working as expected. Then add code for getting good numbers from the BME280.

I am not sure what you mean by "transforming the reading script of a single sensor, edited by the serial port to a web server output"?

Just start by getting good numbers from the DS18B20 and the BME280. One-Wire library for the ds18b20 and I know Adafruit offers a library for the BME280 that worked for me. When you have them you can see where those go in the client.print statements so they show up correctly on a web page. bme.getTemperature_C() is the temp in Celsius, bme.getHumidy() is the humidity, etc.

Then add back in the interrupts for keeping up with the wind speed and rain tip gauge.

Save your code in stages with new names so you can go back to working versions if you need to.

Thank you for your help and sorry for my bad english which forces me to go through a translator …
So I installed the library Dallastemperature … Actually this solution has solved the problem of the temperatures of the DS18B20 … for the BME280 it seems to work, even if I did not validate using the continuous recording of minitemp and maxtemp …
I have attached my current code, because now I have a concern with the interruptions of the rain gauge, it does not record all the readings of the buckets, while with my old code, it worked. I think I need to improve my interruptions and I may need to simplify the DS18B20’s read code, with only the address of my sensor and not a search of the sensor at each reading …
cordially

AWS_Web_Server_Sketch_V6.ino (13.3 KB)

Yes ... just use ...
RequestTemperatures ();
GetTempCByIndex ();

and Drop GetAddress and Bitmap.setresolution calls.

I still don't think you need to keep the wind speed in real time.

The Isr_rotation routine continues to increment the rotations in proportion to the wind speed.

The Isr_timer routine marks 2.5 seconds of interval (5 interruptions of half a second) to see how many rotations occurred in that time frame.

How about storing the number of rotations that happened in the last 2.5 second interval and keeping it in real time instead of calculating the wind rotations * 1.448406. This is a timely floating-point calculation and takes too much time, you don't really need to spend every 2.5 seconds. Thus, change the volatile float varaiable to another unsigned volatile intervalRotationCount int. Now in the isr_timer you can simply move the rotations to IntervalRotationCount after 5 interruptions instead of doing the floating-point calculation.

When you are ready to actually need wind speed inside the loop just calculate before using it.

Wind speed = IntervalRotationCount * 1.448406;

Now your processor may have more time to actually capture the rain events. But it is just a suggestion.

In the rare case that you are actively servicing isr_timer and you get a pin3 change, interrupts have been disabled by the prior interrupt and you will miss the event.

You can add sei() to the start of isr_timer to prevent this. Worst case you might alter your wind speed by a fraction but they are not that accurate anyway as wind is not stable anyway.

Question... Do you need a pullup on pin 3?

============================================= Translated --> Traduit

Oui ... juste utiliser ...
RequestTemperatures ();
GetTempCByIndex ();

et Drop GetAddress et Bitmap.setresolution appels.

Je ne pense toujours pas que vous devez garder la vitesse du vent en temps réel.

La routine Isr_rotation continue d'incrémenter les rotations proportionnellement à la vitesse du vent.

La routine Isr_timer marque 2,5 secondes d'intervalle (5 interruptions d'une demi-seconde) pour voir combien de rotations ont eu lieu pendant cette période.

Que diriez-vous de stocker le nombre de rotations qui se sont produites dans le dernier intervalle de 2,5 secondes et de le garder en temps réel au lieu de calculer les rotations du vent * 1.448406. C'est un calcul en temps réel à virgule flottante et prend trop de temps, vous n'avez pas vraiment besoin de passer toutes les 2,5 secondes. Ainsi, modifiez le flottant volatil varaiable à un autre intervalRotationCount int volatile non signé. Maintenant, dans l'isr_timer, vous pouvez simplement déplacer les rotations vers IntervalRotationCount après 5 interruptions au lieu de faire le calcul en virgule flottante.

Lorsque vous êtes prêt à réellement avoir besoin de la vitesse du vent dans la boucle, calculez juste avant de l'utiliser.

Vitesse du vent = IntervalRotationCount * 1.448406;

Maintenant, votre processeur peut avoir plus de temps pour capturer les événements de pluie. Mais ce n'est qu'une suggestion.

Dans les rares cas où vous entretenez activement isr_timer et que vous obtenez un changement de pin3, les interruptions ont été désactivées par l'interruption précédente et l'événement vous manquera.

Vous pouvez ajouter sei () au début de isr_timer pour éviter cela. Dans le pire des cas, vous pourriez modifier la vitesse de votre vent d'une fraction, mais ils ne sont pas si précis que cela car le vent n'est pas stable de toute façon.

Question ... Avez-vous besoin d'un pullup sur la broche 3?

wzaggle:
Yes ... just use ...
RequestTemperatures ();
GetTempCByIndex ();

and Drop GetAddress

Trouble with that is ‘GetTempCByIndex ()’ then needs to call ‘getAddress()’ EVERY TIME, that’s wasteful. And, all the ‘GetTemp…()’ functions block by default.

And, don’t call the ‘sensor…()’ functions every time you need the temperature. Call it once per reading and save the value to use later.

I prefer this way:

In setup():

sensors.begin();
sensors.setWaitForConversion(true);  // Block only for first read in setup()
sensors.getAddress(sensorDeviceAddress, 0);
sensors.setResolution(sensorDeviceAddress, 10);
sensors.requestTemperatures();
minTemp = sensors.getTempC(sensorDeviceAddress);
maxTemp = minTemp;
sensors.setWaitForConversion(false);   // Don’t block on read any more;
sensors.requestTemperatures();   // Start temperature conversion process, don’t wait for completion

In loop():

// Check if measurement is done, don't block if not done
if (sensors.isConversionComplete()) {
  currentTemp = sensors.getTempC(sensorDeviceAddress);  // Get temperature only once for each measurement completion and then use it everywhere
  sensors.requestTemperatures();   // Start another temperature conversion process, don’t wait for completion
}

// Do useful stuff here because we're not waiting for temperature conversion process to finish

Even with this code you’re going to be reading from the DS18B20 WAY TOO OFTEN. Outside temperature just doesn’t change that fast!!! A reading every minute would be more than enough!!!. The best way to accomplish this is to use a State Machine / millis() Timer technique. The states would be something like: UsingPrevisouReading, WaitingForNewReading, GettingNewReading.

EDIT:
Not sure if this technique will work in parasite power mode. Everything works better with this device if you give it a real Vdd.

EDIT #2:
Minor correction to above 'setup()' code

Thank you for all your attention and advice. I have only to get to work taking into account your remarks … go … :slight_smile: :slight_smile:

I have this error ???

if (sensors.isConversionComplete()) {

'class DallasTemperature' has no member named 'isConversionComplete'

Check the DallasTemperature.h file. There should be a function prototype:

    // Is a conversion complete on the wire?
    bool isConversionComplete(void);

to the question ... Do you need a pullup on pin 3?
I have one of 4K7, but is it necessary ??? I do not know...

With isConversion, i have only " bool isConversionAvailable(const uint8_t*);"
is it the same???

Right out of the Datasheet:

richardpub:
With isConversion, i have only " bool isConversionAvailable(const uint8_t*);"
is it the same???

Don’t know. What version of library did you download and from where?

i have this one

name=DallasTemperature
version=3.7.6
author=Miles Burton miles@mnetcs.com, Tim Newsome nuisance@casualhacker.net, Guil Barros gfbarros@bappos.com, Rob Tillaart rob.tillaart@gmail.com
maintainer=Miles Burton miles@mnetcs.com
sentence=Arduino Library for Dallas Temperature ICs
paragraph=Supports DS18B20, DS18S20, DS1822, DS1820
category=Sensors
url=https://github.com/milesburton/Arduino-Temperature-Control-Library
architectures=*

wzaggle:
I think el-supremo confirmed the cactus library was not working right. I would probably start by just getting some code to read and print the right temperature from the DS18B20. At least you can confirm that is working as expected. Then add code for getting good numbers from the BME280.

I am not sure what you mean by "transforming the reading script of a single sensor, edited by the serial port to a web server output"?

Just start by getting good numbers from the DS18B20 and the BME280. One-Wire library for the ds18b20 and I know Adafruit offers a library for the BME280 that worked for me. When you have them you can see where those go in the client.print statements so they show up correctly on a web page. bme.getTemperature_C() is the temp in Celsius, bme.getHumidy() is the humidity, etc.

Then add back in the interrupts for keeping up with the wind speed and rain tip gauge.

Save your code in stages with new names so you can go back to working versions if you need to.

Quelle librairie moi conseillez-vous pour un BME280???

Looks like there's a newer version:

Now it's OK with the DallasTemperature bookstore that you offered me to use ...
little concern with onewire.h .. I had not seen that he was included in this library ...

How can I improve the reliability of the meter with its I.L.S. contact?
I regularly lose a bucket?