Feed on
Posts
Comments

As discussed last week the Standalone Temperature Logger has now been updated to v3.0.

The PCB works well, with a few more parts needing top layer soldering it was a bit trickier.

The improvements made were:

  • Added external I2C EEPROM support with automatic EEPROM size checking
  • Updated 10K resistor divider to 1% tolerance
  • Added 28 seconds to delay options available
  • Updated temperature resolution to be 0.65C which is rounded up or down in 0.5 – 1C increments thanks to the suggestion made by tytower

Download SATL_v3.0 or view the updated Standalone Temperature Logger project page.

Increasing the resolution of data saved to EEPROM

A user named tytower left me a comment about increasing the resolution range that the SATL uses when saving to the EEPROM from my value 90 to 255 to use 1 to 255 which has prompted me to include his suggestions in the SATL v3.0. Tytower explained that the temperature range is -40C to 125 which is 165 data points and if we take the maximum value of data stored in the EEPROM 255 (minus 1 for the value 0 being our stop bit) and divide by 165, we get 1.545 which means we can increase our resolution by 1.5x. If we divide 165 by 255, our new resolution is 0.65C degrees (before I just had it as 1C) and to keep things nice I’ll round up or down to 0 or 0.5.

The formula we use to convert a temperature to a value is (temp * 1.545) + 63 and to convert it back to a temperature it’s (value- 63) / 1.545. Below I show some examples of temperature converted to a data value and then back again including rounding.

-40.12140
-39.48239.5
-38.833
30
4.53
704.5
5.17
715
5.82
726
107.44
229107.5
108.09230108
108.73231108.5
124.27255124.5

What you’ll note is that sometimes it won’t show the 0.5 value, like it skipped from 5 to 6 which is a draw back of just using 1.5x resolution and rounding.

Updated code

PORTB |= (1<<ledPin); // Turn on LED which also turns on the thermistor<br />
_delay_us(50); // Wait a little while before reading thermistor</p>
<p>// Calculation to store -40C to 125C to a single byte = (temperature * 1.545) + 63<br />
int tempValue = (int) floor((((thermistorTemp(analogRead(thermistorPin))) * 1.545) + 63) + 0.5);<br />
PORTB &= ~(1<<ledPin); // OFF

Above is the updated code the the thermistor reading, floor (x + 0.5) is like using round().

Next is taking the value, converting to a temperature and displaying in HID values.

c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: main.elf section .text will not fit in region text<br />
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: region text overflowed by 64 bytes

I thought I could use the dtostrf function to convert an double to string (like I did in the SAVL) however what I found is that took up too much program space! It’s time to make our own way to convert a double to HID values.

// Calculations to restore value to temperature = (value - 63) / 1.545
double tempDouble = (value - 63) / 1.545;

// Check if value is less than 0, if so convert it to positive number and include the negative sign at the end
boolean isNegative = false;
if (tempDouble < 0) {
  tempDouble = tempDouble - (tempDouble * 2);
  isNegative = true;
}

// Split the value into 2 parts and doing some rounding, e.g a reading of 123.45762 would give 123 and 5
int beforeDecimalpoint = (int) tempDouble; // Before the decimal point
int afterDecimalpoint = (int) ((tempDouble - beforeDecimalpoint) * 100); // After the decimal point
if (afterDecimalpoint < 25 || afterDecimalpoint > 75) { // Round to 0 or 5
  if (afterDecimalpoint > 75) { // Round up
    beforeDecimalpoint++;
  }
  afterDecimalpoint = 0;
}
else {
  afterDecimalpoint = 5;
}

nextDigit = &valueBuffer[sizeof(valueBuffer)];
*--nextDigit = 0xff;
*--nextDigit = 0;
*--nextDigit = KEY_RETURN;

// Break up the number and convert to USB HID values.
if (afterDecimalpoint == 5) { // If there is number after decimal point, it's a 5
  *--nextDigit = 0;
  *--nextDigit = KEY_5;

  // Dot
  *--nextDigit = 0;
  *--nextDigit = KEY_DOT;
}

// First part
value = beforeDecimalpoint;
do {
  digit = value % 10;
  value /= 10;
  *--nextDigit = 0;
  if (digit == 0) {
    *--nextDigit = KEY_0;
  }
  else {
    *--nextDigit = KEY_1 - 1 + digit;
  }
} while (value != 0);

// Negative
if (isNegative == true) {
  *--nextDigit = 0;
  *--nextDigit = KEY_MINUS;
}

First we check if the number is negative and then we split the number up before and after the decimal point. First we convert the number to an int which gives us the first half and then we minus the int from the original number and times by 100 and convert that to an int which gives us the 2 digits after the decimal point. Next we check if we need to round up or down and lastly we convert each part to HID values and only send the decimal point and second part if the second part is 5 (to give 0.5).

My next step is to integrate both the temperature and voltage capabilities and make a Standalone Temperature/Voltage Logger which was suggested in a comment made by Steve which is a good idea. I think I’ll skip making the home made PCB and try my luck at sending it to a PCB fab.

9 Responses to “Standalone Temperature Logger updated to v3.0”

  1. lochnessduck says:

    great work! I love this site for it’s updates to products. Really helps show how products can be improved over time

  2. I suggest that when yo go to the fab, you’d better have some stock of components needed for assembly. Sometimes it’s easier to get everything from one place.
    What’s more – this gadget needs some neat plastic(?) case.
    It could become a nice substitute to dallas chronoterms…

  3. tytower says:

    Thanks for the mention -hope it helps . I believe the map function also does similar stuff.

    Do you have an eagle file for the schematic (.sch) and /or a board file (.brd) for this . I know little of Eagle , I’m just learning this again after not using it for a few years. I could not work out how to convert the png file to something in eagle and I hoped to use it to practice on . Thanks again for the logger.

  4. tytower says:

    Thanks always better to relearn on something interesting
    Here is that map function for you to try
    //Map Example

    /* Map an analog value to temp (-40 to 125) */
    void setup() {
    Serial.begin(9600);}
    void loop()
    {
    int val = analogRead(0);
    val = map(val,0, 1023, -40, 125);
    Serial.println(val);
    delay(1000);
    }

  5. Naveen says:

    Hi,

    I have a need to add RTC to EasyLogger. Do you have any suggestions on. How to configure RTC time form Personal computer? . I need to lot RTC time when the logger starts and stops.

    RTC log should be reported back to PC.

    Thanks
    Naveen

Leave a Reply to Alex