Loop speed on power up

First post. Picked up an Uno Rev 3 last week, and I am officially hooked.

So, I have a fairly simple sketch at the moment. It pulls some temperature readings from some one-wire style ic sensors, does a few floating point calculations and prints them to a parallel lcd. I am using the led on pin 13 as a sort of heartbeat indicator. The led is switched on at the beginning of loop() and switched off at the end before a half second delay, then it starts over. The loop is noticeably slower (the led is on for more time) when the arduino is powered on for the first time. After pressing the reset button once, the heartbeat blinks significantly faster.

Actually, I think I am going to modify it to print the duration of the loop to see if it's just me. Anyway, has anyone else noticed this? Is it normal?

Lets see the code you are running.
Also, I think the bootloader is smart enough to distinguish between a power-up reset vs a reset-button reset and can skip certain start up actions.

The LED on pin 13 blinks a few times during the bootloader processing. Once that is over (a second or so later) everything should run at the same speed.

Try a LED on a different pin, to see for sure.

On power up, the loop takes ~800ms. After a reset, either by uploading or pressing reset on the board, the loop only takes 135ms. It has something to do with the onewire sensors. If I comment out the part where the temperatures are retrieved, this behavior is gone. It must be something to do with the libraries and comm rate of the sensors.

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

OneWire oneWire(4);
DallasTemperature sensors(&oneWire);
DeviceAddress waterThermometer = { 0x28, 0x6F, 0x3B, 0x4B, 0x04, 0x00, 0x00, 0xE7 };
DeviceAddress airThermometer = { 0x28, 0x1D, 0x74, 0x4B, 0x04, 0x00, 0x00, 0x97 };

LiquidCrystal lcd(12, 11, 9, 8, 7, 6);

void setup() {
  pinMode(13, OUTPUT);
  sensors.begin();
  sensors.setResolution(waterThermometer, 9);
  sensors.setResolution(airThermometer, 9);
  lcd.begin(16,2);
}

float tempH2O = 0;
float tempAir = 0;
int delta = 0;
long duration = 0;

void loop() {
  duration = millis();
  digitalWrite(13, HIGH);
  sensors.requestTemperatures();
  tempH2O = sensors.getTempC(waterThermometer);
  tempAir = sensors.getTempC(airThermometer);
  delta = tempH2O - tempAir + 0.5;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Air ");
  lcd.print((int)tempAir);
  lcd.print("C H2O ");
  lcd.print((int)tempH2O);
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Duration ");
  lcd.print(millis() - duration);
  lcd.print("ms");
  digitalWrite(13, LOW);
  delay(500);
}

The problem seems to be setting the resolution of the sensors. The default is 12 bit which takes ~750ms. I don't need that kind of accuracy, so I set the resolution to 9 bit which is significantly faster. For some reason, the resolution is not being set correctly for each sensor on a fresh power up. I tried a delay in case the sensors needed a little time, but that did not work either.

I looked over the info for the dallas temp library and decided to try setting a global resolution instead of setting each sensor individually. That fixed the issue. It must be a bug in the library.

It is possible that directly after power-up the sensors themselves haven't powered up fully, and ignore the resolution change. Hitting reset resends the change, and now the sensors are powered.

Try adding a 1 second delay at the start of setup, before configuring the sensors. That should simulate that.

As I stated in my previous reply, I tried adding a delay up to 5 seconds. It did not help. I even moved the setResolution call to loop(), and that did not work either. The call to set the resolution globally does not suffer from this issue.

Where did you get that library? My copy doesn't have setResolution in it.

http://milesburton.com/Dallas_Temperature_Control_Library

Relevant portion:

// set resolution of all devices to 9, 10, 11, or 12 bits
// if new resolution is out of range, it is constrained.
void DallasTemperature::setResolution(uint8_t newResolution)
{
  bitResolution = constrain(newResolution, 9, 12);
  DeviceAddress deviceAddress;
  for (int i=0; i<devices; i++)
  {
    getAddress(deviceAddress, i);
	setResolution(deviceAddress, bitResolution);
  }
}

// set resolution of a device to 9, 10, 11, or 12 bits
// if new resolution is out of range, 9 bits is used. 
bool DallasTemperature::setResolution(uint8_t* deviceAddress, uint8_t newResolution)
{
  ScratchPad scratchPad;
  if (isConnected(deviceAddress, scratchPad))
  {
    // DS18S20 has a fixed 9-bit resolution
    if (deviceAddress[0] != DS18S20MODEL)
    {
      switch (newResolution)
      {
        case 12:
          scratchPad[CONFIGURATION] = TEMP_12_BIT;
          break;
        case 11:
          scratchPad[CONFIGURATION] = TEMP_11_BIT;
          break;
        case 10:
          scratchPad[CONFIGURATION] = TEMP_10_BIT;
          break;
        case 9:
        default:
          scratchPad[CONFIGURATION] = TEMP_9_BIT;
          break;
      }
      writeScratchPad(deviceAddress, scratchPad);
    }
	return true;  // new value set
  }
  return false;
}

I note that the variable bitResolution is not changed when you set up individual sensors, but only when you do the lot. That might explain it, because the rest looks the same.

Looking at this piece of code, I would say you've hit the nail on the head.

void DallasTemperature::requestTemperatures()
{
  _wire->reset();
  _wire->skip();
  _wire->write(STARTCONVO, parasite);

  // ASYNC mode?
  if (!waitForConversion) return; 
  blockTillConversionComplete(&bitResolution, 0);

  return;
}

If you read the temperatures of all sensors at once using requestTemperatures(), it uses the global resolution to decide how long to wait. The per-sensor resolution only seems to be used when reading an individual sensor.

Yes. Though it is weird how it only works incorrectly after a power cycle and not a regular reset.

I don't know how much internal state the sensors have but it would be reasonable for them to remember what resolution they have been set to, and perhaps that setting is not lost when the Arduino is reset.