Reading ds18b20 with force sensor

Hello,

I'm using 2 temperature sensors (ds18b20) to read foot temperature alongside force sensors.

my problem is that a high resolution temperature takes around 750ms according to the datasheet of the sensor. I don't mind a delay in the temp reading (even in minutes), but I have to read force values approximately every 50ms.
I saw that it's possible to read other sensors in background while the temp sensor requests and displays the value, probably using millis function. but due to my limited experience in programming, I don't know how to do it.

is there any clear way on how to do so? any help would be appreciated.

Thanks

Have you seen the WaitForConversion2 example from the examples in the Dallas temperature library.

Lots more pages with a search for "non blocking Reading ds18b20 arduino".

1 Like

You can include a count so that after every (say) twenty readings of the force sensor, you take a reading of the DS18B20. Then zero the counter.

1 Like

as the temperature seems to change slowly

How about a solution that uses one microcontroller for aquiring temperaturedata every 750 milliseconds and whenever the temperature changed sending it over a serial interface as a 16bit integer wher 12345 means 123.45 °C to the microcontroller that does the force-sensor-measurings?

Or maybe using this sensor 0,1°C accuray I2C-interface
https://www.tindie.com/products/ab-log/tmp117-high-accuracy-digital-temperature-sensor/

best regards Stefan

1 Like

I tried using this example after editing a little bit. I don't care about the minimum acquisition time at each resolution so I fixed the temp time at 1000ms, I can even change it to a whole minute later. then I used the text "Force" to indicate force values and it seems like it's working as it's supposed to.
could you please check my code and give me your feedback. Although it's working, but i would be more comfortable knowing that I'm utilizing the sensors functions correctly.
also, what is your personal experience with this sensor? I heard it's and accurate one, did you have any problems with it.
here's my code:

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;

float temperature;

int pause_t = 1000;
int pause_f = 100;

unsigned long lastTime_t = millis();
unsigned long lastTime_f = millis();

void setup()
{
  sensors.begin();
  sensors.setResolution(12);
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures(); 
  Serial.begin(115200);
}

void loop()
{

  String dataString = "";  // string to store measurements

  //temperature timing
  if ( millis() - lastTime_t > pause_t)
  {
    temperature = sensors.getTempCByIndex(0);
    sensors.requestTemperatures(); // ask for next reading 
    lastTime = millis();

    // process temperature here
    dataString += String(temperature);   
  }
  else{
    dataString += ("null");
  }

  // force timing
  if ( millis() - lastTime_f > pause_f)
  {
    dataString += ("|| Force_1");
    dataString += (" Force_2");
    dataString += (" Force_3");
    lastTime2 = millis();  

   Serial.println(dataString);
}
}

Me personal I do not use the variable-type String.

The variable-type String can be dangerous because repeated assigning new values to a variable of type String can eat up all memory and then start overwriting other data which might lead to corrupted data or a program-crash

I always use a library called SafeString which offers almost the same comfort as String but is safe to use and never eats up more memory than shown at compiling

here is a short demo-code how to use it

#include <SafeString.h>
createSafeString(myDemo_SS, 32);
createSafeString(mySecondDemo_SS, 32);

unsigned long myCounter;

// if program starts printout the source-code filename etc. to the serial monitor
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println(__FILE__);
  Serial.print( F("  compiled ") );
  Serial.print(__DATE__);
  Serial.print( F(" ") );
  Serial.println(__TIME__);  
}

//useful function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();  
  if ( currentMillis - periodStartTime >= TimePeriod )
  {
    periodStartTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}

unsigned long MyTestTimer = 0;                   // variables MUST be of type unsigned long
const byte    OnBoard_LED = 13; // Arduino-Uno Onboard-LED is IO-pin 13

// make onboard-LED blink to show: "program is running"
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}



void setup() {
  Serial.begin(115200);
  Serial.println( F("Setup-Start") );
  PrintFileNameDateTime();
  myCounter = 0;
  myDemo_SS = "Hello world!";
}


void loop() {
  BlinkHeartBeatLED(OnBoard_LED,500);
  myCounter++;
  
  // loop is running very fast counting up very fast
  // but only once every 1234 milliseconds print 
  if ( TimePeriodIsOver(MyTestTimer,1234) ) {
    mySecondDemo_SS = myDemo_SS;  // assigning a SafeString to another SafeString
    
    mySecondDemo_SS += " ";       // append a SPACE
    mySecondDemo_SS += myCounter; // append integer-number
    Serial.println(mySecondDemo_SS);    
  }  

}

you can install the library with the library-manager

My experience with DS18B20-sensors is: their accuracy is within the specs.
This means 0.5°C. So if you have two sensors at the exact same temperature one sensor can show 20.00°C and the other 20.25°C or another 19.75°C

Using the ```
setWaitForConversion(false);

command means start a measuring with the first requestTemperatures and retrieve the data on the next call.

best regards Stefan
1 Like

So you have called temperature a float. It comes as a float and all you need do is print the float. None of that String stuff is necessary, and is likely to cause you grief. Take the long view and seriously consider what you want to do, and do you really need all that text anyway. If you're serious about logging data, I'm betting you will probably delete it.

Both redundant, you get 12bit by default.

1 Like

Read the Evils of Strings page to see why members recommend not using the String class without knowing what you are doing.

1 Like

the line to set the resolution is there to check the validity of the sensor since I was getting weird readings at some point. that was because I didn't call the initializing commands for the sensor properly, so I can remove that line now.
Regarding the String format I'm hearing many negative comments on it. I used this format from the DataLogger example on SD library. Later in my application, these readings will be either written on an SD card or sent by Bluetooth. is it still better to ditch the string and print them directly in that case?

The problematic thing is repeated assigning values to a String-variable.

The difference in using String or SafeString isn't that big

String:

    dataString += String(temperature);    // needs a conversion with String()

SafeString:

#include SafeString.h

createSafeString(dataString , 256);  //256 is the length of characters the variable can hold can be any value until no RAM is left 
dataString = ""; 
dataString += temperature; // needs no conversion (the conversion is done by the SafeString-library

some functions will accept only a character-sequence that is defined as "c_string"
easy thing for the library SafeString.h
simply code

specialobject.write(  dataString.c_str() );

best regards Stefan

1 Like

Thanks for the explanation, I checked the description of the library, applied it to my code and got the same result as before. I initialized the safestring and kept the same structure as it was, except I wrote

dataString.clear();

instead of

dataString = "";

Can you please explain the last statement? what are these functions, and what does SpecialObject refer to in that case?

Regards

for example if you would like to use a library that is sending a "string" to a LCD or send a string via TCP/IP
these functions don't provide a variant for each type of variable like the
print-function of the serial-object

serial.print() works for all and any "simple" datatype like
byte, integer, char, unsigned int, long, unsigned long String etc.
because the library provides a special version for each datatype.

If a library does not provide a special version of a function for each datatype the compiler will complain "wrong data-type"
I encountered this problem for example for udp:

the udp-oject accepts only bytes.
This means sending a string needs a conversion and the conversion requieres a c_string to work

a simple

createSafeString(UDP_Msg_SS,MaxMsgLength); 

  Udp.write(UDP_Msg_SSUDP_Msg_SS.length() );

does not work

in this case it requieres two steps conversion to c_str() and additionally to (const uint8_t*)

Udp.write((const uint8_t*)UDP_Msg_SS.c_str(), UDP_Msg_SS.length() );

if you lok inside the library of the serial object you will find a lot of variants if the print-function.
If a library does not provide all these variants you have to use a certain type
And libraries that expect a character-sequence often expect datatype "c_str"

the name "SpecialObject" is just a place-holder for such libraries.

best regards Stefan

1 Like

It is always better to ditch the String.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.