Why is my sketch running quite slowly?

Hi all,

I am hoping somebody can help me out with this one - I have made a sketch which basically gets a temperature reading from a digital sensor and activates one of three LEDs based on the temperature being low, okay or high, if the temperature is high it also activates a fan. Other than that there is another LED which is used as a “on” LED. The temperature is sent to an LCD display and also sent as serial data to a Raspberry Pi which then uploads the data to a database for viewing on a website. This all works fine however I also send what I will call the “loops per second” to the Raspberry Pi, the two forms of serial data are prefixed with three letters so the Raspberry Pi knows which is which. It could well be that my maths is wrong but essentially I am trying to calculate how many times the loop runs per second therefore how many times the temperature is sampled and analysed per second - this data is paramount to the project.

The problem is I am getting numbers between 1.27 and 1.5 which I feel is really slow for the Arduino? I am aware that I have a lot of digital writes which will slow things down but should it really be running this slowly? Any insight would be greatly appreciated!

#include <OneWire.h>              // Used for Temp Sensor
#include <DallasTemperature.h>    // Used for Temp Sensor
#include <LiquidCrystal.h>        // Used for LCD Display

// DEFINITIONS
#define ONE_WIRE_BUS 13 // Data wire is plugged into pin 2 on the Arduino
#define FAN_PIN 9       // Fan is attached to pin 9 on the Arduino
#define WHITE_LED 7     // White LED is attached to pin 7 on the Arduino
#define BLUE_LED 10     // Blue LED is attached to pin 10 on the Arduino
#define GREEN_LED 8     // Green LED is attached to pin 8 on the Arduino
#define RED_LED 6       // Red LED is attached to pin 6 on the Arduino

#define TEMP_LOW 18.00    // Dictates what is classified as a low temperature
#define TEMP_HIGH 27.00   // Dictates what is classified as a high temperature

// Initialize the LiquidCrystal library with the numbers of the interface pins
// Current using four data lines (rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 5, 4, 3, 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);

// Global Variables

int screenWidth = 16;     // 16x2 LCD Width
int screenHeight = 2;     // 16x2 LCD Height
String line1 = "TEMP";    // LCD Line one - STATIC
String line2 = " Low: < 18         OK: 18-27         High = 27+ "; // LCD Line Two - Scrolling
int stringStart, stringStop = 0;  // LCD Scrolling Variables
int scrollCursor = screenWidth;   // LCD Scrolling Variables

float currentTemp = 5.00;   // Current Temperature Value
bool manualFanStatus = false;   // Has the fan been requested manually?

// Timing Variables
unsigned long startTime;
unsigned long elapsedTime;
unsigned long runningTime;
long loops;

     
void setup(void) 
{
  // Set up baud rate of serial port 
  Serial.begin(9600);   
 
  // Initiate PINs 
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  pinMode(WHITE_LED, OUTPUT);
  pinMode(FAN_PIN, OUTPUT);

  // Set up LCD's number of columns and rows
  lcd.begin(screenWidth,screenHeight);

  // Start up the Dallas Temperature Library
  sensors.begin();

  // Set up timing variables
  startTime = millis();
  loops = 0;
}
     
     
void loop(void) 
{
  // Update Timing Variables
  loops++; 
  elapsedTime = millis();
  runningTime = elapsedTime - startTime;

  // Check Loops per Second
  if(elapsedTime >= 3000)
  {
      float timePerLoop = runningTime / loops;
      float loopsPerSecond = 1000 / timePerLoop;
    
      Serial.print("LPS: ");
      Serial.println(loopsPerSecond);

      // Reset Timing Variables 
      startTime = millis();
      elapsedTime = millis();
      loops = 0;
  }
  
  // Activate Status LED
  digitalWrite(WHITE_LED, HIGH);

  // Request Temperatures from Sensors
  sensors.requestTemperatures();

  // Can have multiple sensors on same bus - 0 = first IC on the wire
  currentTemp = sensors.getTempCByIndex(0);

  Serial.print("TMP: ");
  Serial.println(currentTemp);

  // Check if a serial communication has been received
  if(Serial.available())
  {
      // If communication is 1, fan has been requested, otherwise it has not.
      if(Serial.read() == '1')
      {
          manualFanStatus = true;
      }
      else if (Serial.read() == '0')
      {
          manualFanStatus = false;
      }
  }

  // Set LED's and update LCD based on current temperature
  if(currentTemp <= TEMP_LOW)
  {
      digitalWrite(BLUE_LED, HIGH);
      digitalWrite(GREEN_LED, LOW);
      digitalWrite(RED_LED, LOW);
      digitalWrite(FAN_PIN, LOW);
      
      line1 = "TEMP: ";
      line1 += currentTemp;
      line1 += "   LO";
  }
  else if(currentTemp >= TEMP_HIGH)
  {
      digitalWrite(RED_LED, HIGH);
      digitalWrite(GREEN_LED, LOW);
      digitalWrite(BLUE_LED, LOW);
      digitalWrite(FAN_PIN, HIGH);
      
      line1 = "TEMP: ";
      line1 += currentTemp;
      line1 += "   HI";
  }
  else
  {
      digitalWrite(GREEN_LED, HIGH);
      digitalWrite(BLUE_LED, LOW);
      digitalWrite(RED_LED, LOW);
      digitalWrite(FAN_PIN, LOW);
      
      line1 = "TEMP: ";
      line1 += currentTemp;
      line1 += "   OK";
  }
  

  // LCD Print
  lcd.setCursor(0,0);
  lcd.print(line1);
  lcd.setCursor(scrollCursor, 1);
  lcd.print(line2.substring(stringStart,stringStop));

  // LCD Scrolling
  if(stringStart == 0 && scrollCursor > 0)
  {
      scrollCursor--;
      stringStop++;
  } 
  else if (stringStart == stringStop)
  {
      stringStart = stringStop = 0;
      scrollCursor = screenWidth;
  } 
  else if (stringStop == line2.length() && scrollCursor == 0) 
  {
      stringStart++;
  } 
  else 
  {
      stringStart++;
      stringStop++;
  }
  
} // END OF VOID LOOP

If anybody is interested in why the loop timer needs to be accurate it is because I intend to rewrite the sketch in another language, perhaps ASM to see if I can achieve a performance gain, although my initial thoughts are that the digital writes are my bottleneck! This is part of my dissertation.

Many Thanks!

if(elapsedTime >= 3000)This will always be true three seconds after reset.

You are correct. It was running a little quicker than three seconds, I have altered it as follows

void loop(void) 
{
  // Update Timing Variables
  loops++; 
  elapsedTime = millis();
  runningTime = elapsedTime - startTime;

  // Check Loops per Second
  if(runningTime >= 3000)
  {
      float timePerLoop = runningTime / loops;
      float loopsPerSecond = 1000 / timePerLoop;
    
      Serial.print("LPS: ");
      Serial.println(loopsPerSecond);

      // Reset Timing Variables 
      startTime = millis();
      //elapsedTime = millis();
      elapsedTime = 0;
      loops = 0;
  }
  
  // Activate Status LED
  digitalWrite(WHITE_LED, HIGH);

However the data doesn't change as you can see;

TMP: 20.69
TMP: 20.75
TMP: 20.69
TMP: 20.75
LPS: 1.26
TMP: 20.75
TMP: 20.75
TMP: 20.69
TMP: 20.75
LPS: 1.26
TMP: 20.69
TMP: 20.75
TMP: 20.69
TMP: 20.75
LPS: 1.26

If LPS is printed every three seconds and I am getting four temperature readings in that time therefore 4 / 3 = 1.33 which is pretty close to the LPS reading. Which appears to confirm the speed of the sketch, can anybody tell me if this is a normal operating speed and if not how it could be improved?

Thanks again

The temperature sensor is slow. Read the Dallas datasheet.

aarg: The temperature sensor is slow. Read the Dallas datasheet.

Thanks for the information. That is a shame! Are you aware of any alternatives? I was using an analogue temperature sensor originally but this was more suitable as it came with a 1m cable and is waterproof allowing me to quickly change the temperature for testing.

I don't have one myself but I believe (from other Threads) that the library for reading the Dallas sensor can be slow.

Writing to an LCD (or to the Serial Monitor) is slow and does not need to be done in every iteration of loop(). Once per second may be sufficient.

For measuring performance I would record the start time, then count (say) 100 loops and then record the end-time.

...R

Following on from Reply #4, I think it may be possible to start the Dallas sensor and come back later for the answer rather than wait around for it to do its thing.

Robin2: I don't have one myself but I believe (from other Threads) that the library for reading the Dallas sensor can be slow.

Writing to an LCD (or to the Serial Monitor) is slow and does not need to be done in every iteration of loop(). Once per second may be sufficient.

For measuring performance I would record the start time, then count (say) 100 loops and then record the end-time.

...R

Following on from Reply #4, I think it may be possible to start the Dallas sensor and come back later for the answer rather than wait around for it to do its thing.

Thanks Robin. I was originally limiting the frequency that the LCD and Serial was written too however I want the system to function as quickly as possible end to end, so the delay between me touching the sensor and then seeing that data on the webpage doesn't take too long. Currently I have a dynamic graph that is refreshed via AJAX every second based on the latest temperature entry in the database, I would say that there is a 2-3 second delay at the minute between altering the temperature and then seeing it live on the internet although it does vary.