Onewire DS18B20 can't report minus degrees

Hello!
I have an Arduino + enc28j60 -based ethernet shield + two DS18B20 sensors connected and I am using the webserver from this page: http://blog.thiseldo.co.uk/?p=344
I am not using the pachube updater as it doesn't work anymore but the sketch also outputs the values in csv format as a normal webserver. Then I use my server to fetch the values with wget on the server and it works fine - but the Onewire library used doesn't support minus degrees, it just outputs the right value but no minus sign. What should be added to get the minus to work?

The onewire library from that sketch looks like this:

/*
 * Arduino OneWire functions
 */

#define TEMP_PIN  3
void OneWireReset(int Pin);
void OneWireOutByte(int Pin, byte d);
byte OneWireInByte(int Pin);


// Initialise OneWire
void initOneWire() {
  // Temp Pin input
  digitalWrite(TEMP_PIN, LOW);
  pinMode(TEMP_PIN, INPUT);      // sets the digital pin as input (logic 1)
}

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
  digitalWrite(Pin, LOW);
  pinMode(Pin, OUTPUT); // bring low for 500 us
  delayMicroseconds(500);
  pinMode(Pin, INPUT);
  delayMicroseconds(500);
}

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
  byte n;

  for(n=8; n!=0; n--)
  {
    if ((d & 0x01) == 1)  // test least sig bit
    {
      digitalWrite(Pin, LOW);
      pinMode(Pin, OUTPUT);
      delayMicroseconds(5);
      pinMode(Pin, INPUT);
      delayMicroseconds(60);
    }
    else
    {
      digitalWrite(Pin, LOW);
      pinMode(Pin, OUTPUT);
      delayMicroseconds(60);
      pinMode(Pin, INPUT);
    }

    d=d>>1; // now the next bit is in the least sig bit position.
  }
}

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
  byte d, n, b;

  for (n=0; n<8; n++)
  {
    digitalWrite(Pin, LOW);
    pinMode(Pin, OUTPUT);
    delayMicroseconds(5);
    pinMode(Pin, INPUT);
    delayMicroseconds(5);
    b = digitalRead(Pin);
    delayMicroseconds(50);
    d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
  }
  return(d);
}

// Return temp * 100, need to /100 for main part and % 100 for decimal part
int readOneWireTemp() {
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  int temp;

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0xbe);

  LowByte = OneWireInByte(TEMP_PIN);
  HighByte = OneWireInByte(TEMP_PIN);
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;

  return Tc_100;
}

So as you see there is a " if (SignBit) // negative" place but it is not used after that.
I have found (here: Using a DS18B20 Temperature sensor with an Arduino- ar3ne1tt) another similar code which ends like this:

void loop(){
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0xbe);

  LowByte = OneWireInByte(TEMP_PIN);
  HighByte = OneWireInByte(TEMP_PIN);
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;


  if (SignBit) // If its negative
  {
     Serial.print("-");
  }
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
  {
     Serial.print("0");
  }

  Serial.print(Fract);

      Serial.print("\n");
  delay(5000);      // 5 second delay.  Adjust as necessary
}

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
}

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n=8; n!=0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
      }
      else
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         pinMode(Pin, INPUT);
      }

      d=d>>1; // now the next bit is in the least sig bit position.
   }

}

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for (n=0; n<8; n++)
    {
        digitalWrite(Pin, LOW);
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        b = digitalRead(Pin);
        delayMicroseconds(50);
        d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}

That code clearly has code for adding the minus sign but it doesn't work at least directly as it is for the serial port.

And on nuelectronics.com which makes the ethernet shield, I have found this in the webserver temperature example sketch:

void getCurrentTemp(char *temp)
{  
  int HighByte, LowByte, TReading, Tc_100, sign, whole, fract;

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(TEMP_PIN);
  OneWireOutByte(TEMP_PIN, 0xcc);
  OneWireOutByte(TEMP_PIN, 0xbe);

  LowByte = OneWireInByte(TEMP_PIN);
  HighByte = OneWireInByte(TEMP_PIN);
  TReading = (HighByte << 8) + LowByte;
  sign = TReading & 0x8000;  // test most sig bit
  if (sign) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  whole = Tc_100 / 100;  // separate off the whole and fractional portions
  fract = Tc_100 % 100;


	if(sign) temp[0]='-';
	else 		 temp[0]='+';
	
        if(whole/100==0)
           temp[1] =' ';
        else
	  temp[1]= whole/100+'0';
	temp[2]= (whole-(whole/100)*100)/10 +'0' ;
	temp[3]= whole-(whole/10)*10 +'0';
	
	temp[4]='.';
	temp[5]=fract/10 +'0';
	temp[6]=fract-(fract/10)*10 +'0';
	
	temp[7] = '\0';


	
}

But that doesn't either seem to work, I guess as it begins with "void getCurrentTemp(char *temp)" and the same part of the code from the link in the beginning of this post begins with "int readOneWireTemp() {".

I could also use the nuelectronics example code (from http://www.nuelectronics.com/estore/?p=12) but that one shows a "Get Temperature" button on the html page and I would need it to show the value directly so that I can fetch it directly to my server without needing it to press any button on any html page.

So my question would be, how to add the minus degree part to the first code in this post? I am also ready to try a totally different code but this is also working really fine apart from that the minus sign is missing..

To fix the problem, just remove this part:

  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }

That part is taking the absolute value of TReading. It is a roundabout way of saying:

if (TReading < 0)
    TReading = -TReading;

That explains why your result is always positive.

You can also get rid of the Whole and Fract values,too, since they are just thrown away.

Hey thanks a lot, it actually works. Still there is one problem, the output looks like "-2.-18", it puts in the minus also after the decimal comma, but that is no big problem, for me it is easier to remove that on the server with a simple command.

Well, it seems to work for the first minus value, I have set it to read the value and refresh the csv output every 2 minutes, and after the first minus output the webserver doesn't even reply to ping anymore. Could it be a problem with the "main" sketch that it can't handle minus values? The code looks like this, I don't use pachube/twitter, only the local csv output:

/*
 * Arduino ENC28J60 Ethernet shield pachube client
 * Supports CSV method only due to buffer size limitations.
 * with option to tweet every hour
 *
 * Written by Andrew Lindsay, July 2009.
 * Portions of code taken from examples on nulectronics.com (oneWIre and sht11 code)
 * TCP/IP code originally from tuxgraphics.org - combined with ethershield library by me.
 *
 */

#include "etherShield.h"

// Code compilation options
// define TWEET to include twitter calls
#define TWEET

// define FULLWEB to display just a full webpage with values or a simple 1 line csv output
#define FULLWEB

// ** Local Network Setup **
// Please modify the following lines. mac and ip have to be unique
// in your local area network. You can not have the same numbers in
// two devices:
static uint8_t mymac[6] = {
  0x54,0x55,0x58,0x10,0x00,0x25};

// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
// The IP address of the arduino.
static uint8_t myip[4] = {
  10,0,0,25};

// Default gateway. The ip address of your DSL/Cable router.
static uint8_t gwip[4] = {
  10,0,0,1};

// ** pachube.com setup **
// IP address of the www.pachube.com server to contact (IP of the first portion of the URL):
static uint8_t pachubeip[4] = {
  209,40,205,190};

// The name of the virtual host which you want to contact at pachubeip (hostname of the first portion of the URL):
#define PACHUBE_VHOST "www.pachube.com"

// setup yor feed url and API keys here.
#define PACHUBEAPIURL "/api/xxxx.csv"
#define PACHUBEAPIKEY "X-PachubeApiKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

#ifdef TWEET
// ** Twitter setup **
// IP address of the twitter server to contact (IP of the first portion of the URL):
static uint8_t twitterip[4] = {
  128,121,146,228};

// The name of the virtual host which you want to contact at twitterip (hostname of the first portion of the URL):
#define TWITTER_VHOST "twitter.com"
#define TWITTERAPIURL "/statuses/update.xml"

// The TWITTERACCOUNT Authorization code can be generated from 
// username and password of your twitter account 
// by using this encoder: http://tuxgraphics.org/~guido/javascript/base64-javascript.html
// Replace the string after the space after Basic with your authurization string
#define TWITTERACCOUNT "Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

// how many pachube updates to do before tweeting, currently updating vert 30s, so 120 is after about an hour.
#define UPDATES_TO_TWEET 120
#endif

// End of configuration 

// listen port for tcp/www:
#define MYWWWPORT 80

static volatile uint8_t start_web_client=0;  // 0=off but enabled, 1=send update, 2=sending initiated, 3=update was sent OK, 4=diable updates
static uint8_t web_client_attempts=0;
static uint8_t web_client_sendok=0;
static uint8_t resend=0;

int temp = 0;
int outTemp = 0;
int humid = 0;
int dewpoint = 0;
int lightValue = 0;

#ifdef TWEET
#define STATUS_BUFFER_SIZE 200
int updatesSinceTweet = UPDATES_TO_TWEET;
#else
#define STATUS_BUFFER_SIZE 20
#endif

#define BUFFER_SIZE 650
static uint8_t buf[BUFFER_SIZE+1];

// global string buffer for twitter message:
static char statusstr[STATUS_BUFFER_SIZE];

// Instantiate the EtherShield class
EtherShield es=EtherShield();

// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
{
  uint16_t plen;
  char vstr[5];

  plen = es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"));
#ifdef FULLWEB
  // Display full info 
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1>Arduino Monitoring</h1><pre>\n"));
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("Inside Temp: "));
  itoa(temp/100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("."));
  itoa(temp%100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);

  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("C\nRel Humidity: "));
  itoa(humid/100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("."));
  itoa(humid%100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);
  
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("%RH\nDew Point: "));
  itoa(dewpoint/100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("."));
  itoa(dewpoint%100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);

  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("C\nOutside Temp: "));
  itoa(outTemp/100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("."));
  itoa(outTemp%100,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);

  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("C\nLight Level: "));
  // convert number to string:
  plen=es.ES_fill_tcp_data(buf,plen,vstr);

#ifdef TWEET
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("%\nUpdates since tweet: "));
  itoa(updatesSinceTweet,vstr,10);
  plen=es.ES_fill_tcp_data(buf,plen,vstr);

  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\n</pre>"));
#else
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("%\n</pre>"));
#endif
  plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<a href=\"http://www.pachube.com/feeds/xxxx/\">Pachube Feed</a>"));
#else  
  // Display just the csv data
  plen=es.ES_fill_tcp_data(buf,plen,statusstr);
#endif
  return(plen);
}

// Browser callback, where we get to after receiving a reply to an update, should really 
// do somthing here to check all was OK.
void browserresult_callback(uint8_t statuscode,uint16_t datapos){

  if (statuscode==0){
    web_client_sendok++;
  }
  // clear pending state at sucessful contact with the
  // web server even if account is expired:
  if (start_web_client==2) start_web_client=3;
}

// Perform setup on etherent and oneWire
void setup(){

  initOneWire();

  // initialize enc28j60
  es.ES_enc28j60Init(mymac);
  //init the ethernet/ip layer:
  es.ES_init_ip_arp_udp_tcp(mymac,myip, MYWWWPORT);
  // init the web client:
  es.ES_client_set_gwip(gwip);  // e.g internal IP of dsl router
}

// The business end of things
void loop(){
  uint16_t dat_p;
  int8_t cmd;
  start_web_client=1;
  unsigned long lastSend = millis();
  unsigned long time;

  while(1){
    // handle ping and wait for a tcp packet
    dat_p=es.ES_packetloop_icmp_tcp(buf,es.ES_enc28j60PacketReceive(BUFFER_SIZE, buf));
    if(dat_p==0){
      // Nothing received, jus see if there is anythng to do 
      
      // update every 30s
      time = millis();
      if( time > (lastSend + 30000) ) {
        resend=1; // resend once if it failed
        start_web_client=1;
        lastSend = time;
      }
      
      if (start_web_client==1) {
        start_web_client=2;
        web_client_attempts++;

        // Here is where we make the reading and build the csv data
        takeSHTReading();
        temp = readSHTemp();
        humid = readRelHumidity();
        dewpoint = readDewPoint();
        outTemp = readOneWireTemp();
        lightValue = readLight();

        // Decide to update pachube or tweet
#ifdef TWEET
        if( updatesSinceTweet > UPDATES_TO_TWEET ) {
          // Build tweet message - just build up here and slap in values should be encoded ok.
          sprintf( statusstr, "status=Inside+Temp+%d.%dC,+Rel+Humidity+%d.%d,+Dew+Point+%d.%dC,+Outside+Temp+%d.%dC,+Light+Level+%d", temp / 100, temp % 100, humid / 100, humid % 100, dewpoint / 100, dewpoint % 100, outTemp / 100, outTemp % 100, lightValue );
          es.ES_client_set_wwwip(twitterip);
          es.ES_client_http_post(PSTR(TWITTERAPIURL),PSTR(TWITTER_VHOST),PSTR(TWITTERACCOUNT), PSTR("POST "),statusstr,&browserresult_callback);
          updatesSinceTweet = 0;
        } 
        else {
#endif
          // Pachube update
          sprintf( statusstr, "%d.%d,%d.%d,%d.%d,%d.%d,%d", temp / 100, temp % 100, humid / 100, humid % 100, dewpoint / 100, dewpoint % 100, outTemp / 100, outTemp % 100, lightValue );
          es.ES_client_set_wwwip(pachubeip);
          es.ES_client_http_post(PSTR(PACHUBEAPIURL),PSTR(PACHUBE_VHOST),PSTR(PACHUBEAPIKEY), PSTR("PUT "), statusstr ,&browserresult_callback);
#ifdef TWEET
          updatesSinceTweet++;
        }
#endif
      }

      continue;
    }

    dat_p=print_webpage(buf);
    es.ES_www_server_reply(buf,dat_p); // send data
  }
}
// Thats all folks!!

mekano:
Hey thanks a lot, it actually works. Still there is one problem, the output looks like "-2.-18", it puts in the minus also after the decimal comma, but that is no big problem, for me it is easier to remove that on the server with a simple command.

The function you provided (readOneWireTemp()) returns a signed integer. It's your conversion from signed integer to text that mangles the value.

Change:

          sprintf( statusstr, "status=Inside+Temp+%d.%dC,+Rel+Humidity+%d.%d,+Dew+Point+%d.%dC,+Outside+Temp+%d.%dC,+Light+Level+%d", temp / 100, temp % 100, humid / 100, humid % 100, dewpoint / 100, dewpoint % 100, outTemp / 100, outTemp % 100, lightValue );

To:

         sprintf( statusstr, "status=Inside+Temp+%d.%dC,+Rel+Humidity+%d.%d,+Dew+Point+%d.%dC,+Outside+Temp+%d.%dC,+Light+Level+%d", 
temp / 100, (temp<0 ? -temp % 100 : temp%100),
humid / 100, (humid < 0 ? -humid % 100 : humid % 100), 
dewpoint / 100, (dewpoint<0 ? -dewpoint % 100 : dewpoint % 100), 
outTemp / 100, (outtemp<0 ? -outTemp % 100 : outTemp % 100), 
lightValue );

That wil get you closer but will probably display 5005 as "50.5", not "50.05". That's why the original code had a check for value < 10 and inserting the leading 0.

I have now started from the beginning, as the pachube code was useless for me I used the nuelectronics sample code and just copied the onewire reading part from it, and changed its name to "twowire". It reports the values just fine, but then after 5-10 page refreshs the whole thing just locks - no response even to ping. Ping commands don't make it to hang, only page reloads which makes me think that the reading of values or the webserver crashes in some way because of the modifications I have done.

Here is my code:

I guess the problematic part is here where the values are printed out on the web page, but I'm not sure:

uint16_t print_webpage(uint8_t *buf)
{
        char temp_string[10];
        int i=0;
        //char *temp_string="100";
       
        uint16_t plen;
       
        getCurrentTemp(temp_string);
       
           char tempout_string[20];
        int j=0;
        //char *temp_string="100";
       
       // uint16_t plen;
       
        getCurrenttempout(tempout_string);
       
       
       plen=es.ES_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
  //      plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<center><p><h1>Welcome to Arduino Ethernet Shield V1.0  </h1></p> "));
         
 //       plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<hr>
<form METHOD=get action=\""));
        plen=es.ES_fill_tcp_data(buf,plen,baseurl);
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("\">"));
  //      plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h2> Current Temperature is </h2> "));
 //     plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<h1><font color=\"#00FF00\"> "));
         
     plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("
,") );  
        while (temp_string[i]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=temp_string[i++];
                plen++;
        }
 
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("  ,&#176C in,
, ") );
 while (tempout_string[j]) {
                buf[TCP_CHECKSUM_L_P+3+plen]=tempout_string[j++];
                plen++;
        }
 
        plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("  ,&#176C out,</font></h1>
 ") );
   //     plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
   //     plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=submit value=\"Get Temperature\"></form>"));
  //      plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("</center><hr> <p> V1.0 <a href=\"http://www.nuelectronics.com\">www.nuelectronics.com<a>"));
 
        return(plen);
}

I guess the parts that print out the values are wrong, but how should they look? Do they fill up some buffer or what happens? If there is some way to not have to have the onewire code two times, it would be really nice to see how, but it works fine in that way too, making the board not hang is my main issue now. Using one pin for each sensor is ok.

Anyone knows what the problem could be? Something has to be wrong with my code, but I don't know what.. It works fine for around 5-10 (it varies from time to time) http page loads (=measurings), and then it crashes and doesn't reply to ping until the hardware is resetted.

Could someone please just take a look at the code.. I guess the problem is not that big.. The code is here: Arduino DS18B20 code not working - Pastebin.com

My guess would be that you are running off the end of a buffer.

One way to check for that is to pass the buffer length along with the buffer pointer and have functions check that they have not gone off the end of the buffer.

Another possibility is to use "String" instead of fixed-length character buffers but that often causes its own problems.

mekano:
Anyone knows what the problem could be? Something has to be wrong with my code, but I don't know what.. It works fine for around 5-10 (it varies from time to time) http page loads (=measurings), and then it crashes and doesn't reply to ping until the hardware is resetted.

If I was facing this problem, I'd dive the problem into two parts.

Separate the rear temperature reading code from the webserver code. Change the web server to return a constant value instead of reading it from the temp sensor. Do you still get the problem after a few requests? If so this points to a problem in your web server code.

Yes I still get the problem after a few http requests, and I also think the problem happens because some buffer is filled. I think the #define BUFFER_SIZE 500 and #define STR_BUFFER_SIZE 22 cannot be increased because the enc28j60 ethernet chip can't handle much more.

And yes, I know it would be better to split the temperature reading part separately and just use a variable in the web server code, but the problem is that I don't know how to do that, so I guess I need to find some workaround. Maybe it could be resetted after each reading. Now I have used a 230V timer to reset the board a few times per day but it would be awesome to be able to read the temperature more often XD Even 20 readings per hardware reset would be really nice..

Have you tried running a simple example web server sketch? Just to prove that it's possible to do this reliably for a large number of requests. Once you can achieve that, you can gradually evolve that to implement your solution. If it stops working reliably, you know you've got a memory overflow or buffer overflow or memory leak or whatever.

Try using wireshark or equivalent to see what network activity is going on - I've had issues in the past with large packets being broadcast by my ISP that caused a buffer overflow in the ethernet library.