Sensor2

multiple temp sensors


Edsard Boelen, 02-march-2007
this project is to record the CPU, room and outside temperature and show it in one graph. This time, the digital, factory calibrated DS1820 IC's are used.

see past week graph
see past 24 hours
see all time graph

the idea

the ds1820 uses the dallas 1wire protocol, the time window of the data is 50us, which is just too fast for a non-realtime multitasking OS. These days, microcontrollers are very cheap and advanced, so let them do the task of converting the 1wire data to simple rs232 digits with the temp.
the data is logged in a plain text file, and phplot can draw nice graphs from it.

the interface

I used quozl's temp sensor project with the PIC12C509, see http://quozl.us.netrek.org/ts/
a picture of the board:

the outside sensor


the temp logger

At the moment the device is connected to the serial port, and the serial port is enabled, it will send the data at 2400 baud. So in fact cat /dev/ttyS0 or /dev/ttyUSB0 will show you a readout every second. If not, then check the com port. for example run comtest or set the tty speed with stty -F /dev/ttyS0 2400

I wrote quickly a C app which will be run every 30 minutes by the cron daemon
templog.c
#include <stdio.h>   /* required for file operations */
#include <stdlib.h>
#include <pthread.h> // compile with -lpthread 
#include <time.h>

FILE *fr;            /* declare the file pointer */
void *readlines();

main()
{
   pthread_t thread1;
   int  iret1;

   iret1 = pthread_create( &thread1, NULL, readlines,NULL);
   sleep(20);
   exit(0);
   
}

void *readlines()
{
   int n,cnt=0,number;
   char line[80];
   char *lch;
   float temp1,temp2,cputemp;
   
   FILE *output = NULL, *i2c = NULL;
   time_t now;
   struct tm *tm;
     
   fr = fopen ("/dev/ttyS0", "rt");  /* open the file for reading */
   /* "rt" means open the file for reading text */

   while ((fgets(line, 80, fr) != NULL) && cnt < 8)
   {
   	 /* get a line, up to 80 chars from fr.  done if NULL */
    	//  sscanf (line, "%s", &lch);
	 /* convert the string to a long int */
 	 //printf ("%s\n", lch);
	 
	  // remove trailing \n 
	  lch = line + strlen(line) - 1;
          while (*lch == '\r' || *lch == '\n') {
            *lch-- = '\0';
            if (lch < line) break;
          }

	  /* remove preceeding lf or cr */
	  lch = line;
	  while (*lch == '\r' || *lch == '\n') lch++;

          /* ignore any other packet header other than sensor reports */
          if (!isdigit(*lch)) continue;

	  /* decode the sensor number */
          number = atoi(lch)-1;
         if (number < 0 || number > 3) continue;
	 
         lch++; // skip space
         if (*lch != ' ') continue;
	 if (strlen(lch) > 9) lch += 11;
	 lch++;
	
	 //printf(lch);
	 //printf(" %d \n ",number);
	 // scan data
	 if (number == 0)
	 sscanf(lch, "%f", &temp1);
	 
	 if (number == 1)
	 sscanf(lch, "%f", &temp2);	 
		 
	 
	 cnt++;
   }
   
      /* establish timestamp for this sample */
      now = time(NULL);
      tm = localtime(&now);
   
   fclose(fr);  /* close the file prior to exiting the routine */
  
   i2c = fopen("/sys/bus/i2c/devices/0-002d/temp2_input", "r");
   if (i2c == NULL) { perror("i2c bus"); exit(1); }
   if (fgets(line,10,i2c) != NULL)
   {
     sscanf(line, "%f", &cputemp);
     if(cputemp > 1000)
	     cputemp = cputemp /1000;
   }
   fclose(i2c);
   
   output = fopen("xxx.log", "a");
   if (output == NULL) { perror("xxx.log"); exit(1); }
   fprintf(output,"%04d|%03d|%02d|%02d|%0.2f|%0.2f|%0.2f\n",  tm->tm_year+1900,tm->tm_yday+1,
                         tm->tm_hour, tm->tm_min, temp1 , temp2 , cputemp);
   fclose(output);
} 


the image generator

I used phplot for the image generation, the source codes are:

<?php
  
include("phplot.php");
  
$timep $_GET["timep"];

  if(
$timep == "24h")
     
$graph = new PHPlot(500,400);
  else
      
$graph = new PHPlot(800,400);
  
$mode "silent";
 
  include(
"read_data.php");

  
$graph->SetXDataLabelAngle(90);
  
$graph->SetDataValues($stack);
  
$graph->SetYLabel("Temp C");
  
$graph->SetPlotType("lines");
  
$graph->SetDrawXDataLabels(true);
  
$graph->SetLineStyles("solid");
  
$graph->SetDataColors(array("red","blue",array(00,166,00),array(166,166,0)),"");
  
$graph->SetLegend(array("room","outside","cpu","room2"));
  
$graph->SetLegendPixels(50,10);
  
$graph->DrawGraph();

?>






and read_data is
<?php
  $stack 
= array();
  
$lfile "***.log";
  
$data file($lfile);
 
  
$cend count($data);
  
$cbegin 0;
  if ((
$timep=="24h") && ($cend 100))
  { 
    
$cbegin $cend-48;
  } 
  if ((
$timep=="week") && ($cend 400))
  {
    
$cbegin $cend-336;  
  }

  
$step = ($cend-$cbegin)/30;
  
$lcnt $step;
  
$i=$cbegin;
  for(
$i$i<$cend;$i++)
  {
    
$line $data[$i];

    
$expl explode("|",$line);
    if (
$lcnt >= $step)
    {
      
      
$outformat '%d %B %H:%M';
      
$tstamp mktime($expl[2], $expl[3],0,1,$expl[1],2007);   
      
$dd strftime($outformat$tstamp);
      
array_push($stack, array($dd,$expl[4],$expl[5],trim($expl[6])));  
      
$lcnt=0;
    }
    else
    { 
       
array_push($stack, array(" ",$expl[4],$expl[5],trim($expl[6])));
      
$lcnt++;
    }
    if (
$mode != "silent")
      echo 
"$step $expl[4]  -  $expl[5] - $expl[6] <br> ";
  } 
?>