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.12 | 1 | 40 |
---|---|---|
-39.48 | 2 | 39.5 |
-38.83 | 3 | 30 |
4.53 | 70 | 4.5 |
5.17 | 71 | 5 |
5.82 | 72 | 6 |
107.44 | 229 | 107.5 |
108.09 | 230 | 108 |
108.73 | 231 | 108.5 |
124.27 | 255 | 124.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.
great work! I love this site for it’s updates to products. Really helps show how products can be improved over time
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…
By fab I just mean getting 10 boards done by Seedstudio/Itlead. Yes I have thought about the case – http://australia.rs-online.com/web/p/plastic-boxes/5135375/, this one could do but you would need to remove the “two inside holes” that would hold the PCB shown on the PDF and then you’d have to cut a hole at the top for the thermistor.
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.
Sure, here are the sch/brd files: http://www.insidegadgets.com/wp-content/uploads/2012/03/SATL_v3.0_Eagle.zip
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);
}
Thanks, I knew I saw that somewhere before (Arduino AnalogInOutSerial). I’ve tested the map function and the existing one and both give about the same results – https://docs.google.com/spreadsheet/ccc?key=0AjdPcLyofyusdGFIbW9XTmxNV2Q1UW5IUG1JOVZBcGc
The only downside to map is that it takes a bit more program size.
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
Hi Naveen,
I think you should look at the Powerswitch example which shows how to send data from the PC to the microcontroller, so you would modify the PC side code to send the date – http://www.obdev.at/products/vusb/powerswitch.html
Then you could have the microcontroller send the logged details via the HID ‘keyboard’ way that EasyLogger does.