Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using a logic analyzer to analyze the runtime sequence routines #252

Open
mayjack0312 opened this issue Jun 18, 2024 · 4 comments
Open

Using a logic analyzer to analyze the runtime sequence routines #252

mayjack0312 opened this issue Jun 18, 2024 · 4 comments

Comments

@mayjack0312
Copy link

I want to use a logic analyzer to measure the relevant timing parameters:

  1. The time to initialize the DS18B20 and monitor the online information
  2. The time to wait for the DS18B20 to release the bus
  3. The time to trigger the temperature conversion
  4. The time to send the read data command
  5. The time to read the register value and obtain the temperature value

According to the datasheet, their units should be in microseconds (us), but my actual measurements are in milliseconds (ms).
How should I modify my measurement method?
Here is my code:

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

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

DeviceAddress DS18B20_ID;

void setup() {
  Serial.begin(9600);

  unsigned long initStartTime = micros();

  sensors.begin();

  unsigned long initEndTime = micros();

  Serial.print("Initialization Time: ");
  Serial.print(initEndTime - initStartTime);
  Serial.println(" us");
}

void loop() {
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    command.trim();

    if (command == "GET") {
      unsigned long waitStartTime = micros();

      delayMicroseconds(550);

      unsigned long waitEndTime = micros();

      unsigned long convStartTime = micros();

      sensors.requestTemperatures();

      unsigned long convEndTime = micros();

      unsigned long readCmdStartTime = micros();

      float temperature = sensors.getTempCByIndex(0);

      unsigned long readCmdEndTime = micros();

      unsigned long readRegStartTime = micros();

      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println(" C");

      unsigned long readRegEndTime = micros();

      Serial.print("Wait for Bus Release Time: ");
      Serial.print(waitEndTime - waitStartTime);
      Serial.println(" us");

      Serial.print("Trigger Conversion Time: ");
      Serial.print(convEndTime - convStartTime);
      Serial.println(" us");

      Serial.print("Send Read Command Time: ");
      Serial.print(readCmdEndTime - readCmdStartTime);
      Serial.println(" us");

      Serial.print("Read Register Value Time: ");
      Serial.print(readRegEndTime - readRegStartTime);
      Serial.println(" us");
    } else {
      Serial.println("Unknown command.");
    }
  }
}
f770f4ff34d1b538ee5ee64843ae5db
@RobTillaart
Copy link
Contributor

Two tips.

Flush serial before measurements
Do all your measurements before printing the results

@mayjack0312
Copy link
Author

mayjack0312 commented Jun 18, 2024

Two tips.

Flush serial before measurements Do all your measurements before printing the results

I tried both methods, but neither seems to work for me.

image

image

@RobTillaart
Copy link
Contributor

According to the datasheet, their units should be in microseconds (us), but my actual measurements are in milliseconds (ms).
How should I modify my measurement method?

Your code does measure in microseconds.


I tried both methods, but neither seems to work for me.

What is wrong with the numbers?
Are they different than you expect?
If so, what numbers do you expect?

Think you should read the datasheet carefully as it does mentions variation on the numbers.
E.g. the conversion time for 12 bit is max 750 ms which is based upon the worst case conversion (and maybe even a bit extra).


I slightly modified your code, as you do not take into account that printing variables and strings takes time and these affect your measurements. The code below is a bit more stable as it adds delays to wait until the serial output buffer is empty.

Note that there are always variations per call, so you might need to execute your tests 100 times and take the average.

Furthermore you need to know that micro() has a resolution of 4 us. So it will never return 550.
(and it will add the overhead of the function call).

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

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

DeviceAddress DS18B20_ID;


void setup() 
{
  Serial.begin(9600);
  while(!Serial);  //  wait until Serial device is ready.
  Serial.println(__FILE__);
  delay(100);  //  wait until output buffer of Serial is empty.
  
  unsigned long initStartTime = micros();

  sensors.begin();
  sensors.setResolution(12);  //  force an explicit resolution, 9..12

  unsigned long initEndTime = micros();

  Serial.print("Initialization Time: ");
  Serial.print(initEndTime - initStartTime);
  Serial.println(" us");
  delay(100);  //  wait until output buffer of Serial is empty.
}


void loop() 
{
  if (Serial.available() > 0) 
  {
    String command = Serial.readStringUntil('\n');
    command.trim();
    if (command == "GET") 
    {
      delay(100);  //  wait for Serial output empty.
      
      //  why measure this?
      unsigned long waitStartTime = micros();
      delayMicroseconds(550);
      unsigned long waitEndTime = micros();


      unsigned long convStartTime = micros();
      sensors.requestTemperatures();
      unsigned long convEndTime = micros();


      unsigned long readCmdStartTime = micros();
      float temperature = sensors.getTempCByIndex(0);
      unsigned long readCmdEndTime = micros();

      //  here you measure the time to put the strings
      //  in the serial output buffer. not the print time.
      unsigned long readRegStartTime = micros();
      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println(" C");
      unsigned long readRegEndTime = micros();
      

      Serial.print("Wait for Bus Release Time: ");
      Serial.print(waitEndTime - waitStartTime);
      Serial.println(" us");

      Serial.print("Trigger Conversion Time: ");
      Serial.print(convEndTime - convStartTime);
      Serial.println(" us");

      Serial.print("Send Read Command Time: ");
      Serial.print(readCmdEndTime - readCmdStartTime);
      Serial.println(" us");

      Serial.print("Read Register Value Time: ");
      Serial.print(readRegEndTime - readRegStartTime);
      Serial.println(" us");
    } else {
      Serial.println("Unknown command.");
    }
  }
  delay(1000); // wait for all output to be done 
}

@mayjack0312
Copy link
Author

According to the datasheet, their units should be in microseconds (us), but my actual measurements are in milliseconds (ms).
How should I modify my measurement method?

Your code does measure in microseconds.

I tried both methods, but neither seems to work for me.

What is wrong with the numbers? Are they different than you expect? If so, what numbers do you expect?

Think you should read the datasheet carefully as it does mentions variation on the numbers. E.g. the conversion time for 12 bit is max 750 ms which is based upon the worst case conversion (and maybe even a bit extra).

I slightly modified your code, as you do not take into account that printing variables and strings takes time and these affect your measurements. The code below is a bit more stable as it adds delays to wait until the serial output buffer is empty.

Note that there are always variations per call, so you might need to execute your tests 100 times and take the average.

Furthermore you need to know that micro() has a resolution of 4 us. So it will never return 550. (and it will add the overhead of the function call).

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

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

DeviceAddress DS18B20_ID;


void setup() 
{
  Serial.begin(9600);
  while(!Serial);  //  wait until Serial device is ready.
  Serial.println(__FILE__);
  delay(100);  //  wait until output buffer of Serial is empty.
  
  unsigned long initStartTime = micros();

  sensors.begin();
  sensors.setResolution(12);  //  force an explicit resolution, 9..12

  unsigned long initEndTime = micros();

  Serial.print("Initialization Time: ");
  Serial.print(initEndTime - initStartTime);
  Serial.println(" us");
  delay(100);  //  wait until output buffer of Serial is empty.
}


void loop() 
{
  if (Serial.available() > 0) 
  {
    String command = Serial.readStringUntil('\n');
    command.trim();
    if (command == "GET") 
    {
      delay(100);  //  wait for Serial output empty.
      
      //  why measure this?
      unsigned long waitStartTime = micros();
      delayMicroseconds(550);
      unsigned long waitEndTime = micros();


      unsigned long convStartTime = micros();
      sensors.requestTemperatures();
      unsigned long convEndTime = micros();


      unsigned long readCmdStartTime = micros();
      float temperature = sensors.getTempCByIndex(0);
      unsigned long readCmdEndTime = micros();

      //  here you measure the time to put the strings
      //  in the serial output buffer. not the print time.
      unsigned long readRegStartTime = micros();
      Serial.print("Temperature: ");
      Serial.print(temperature);
      Serial.println(" C");
      unsigned long readRegEndTime = micros();
      

      Serial.print("Wait for Bus Release Time: ");
      Serial.print(waitEndTime - waitStartTime);
      Serial.println(" us");

      Serial.print("Trigger Conversion Time: ");
      Serial.print(convEndTime - convStartTime);
      Serial.println(" us");

      Serial.print("Send Read Command Time: ");
      Serial.print(readCmdEndTime - readCmdStartTime);
      Serial.println(" us");

      Serial.print("Read Register Value Time: ");
      Serial.print(readRegEndTime - readRegStartTime);
      Serial.println(" us");
    } else {
      Serial.println("Unknown command.");
    }
  }
  delay(1000); // wait for all output to be done 
}

Oh, thank you so much! After reading your reply, I realized that my consideration was indeed not very comprehensive. Below is the table representing the results I expect to achieve:

data time (us)
The time to initialize the DS18B20 and monitor the online information 610
The time to wait for the DS18B20 to release the bus 550
The time to trigger the temperature conversion 887
The time to send the read data command 886
The time to read the register value and obtain the temperature value 560

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants