En gjennomgang av temperatur sensor prosjektet mitt som jeg har skrudd sammen hjemme ved hjelp av en Arduino modul og noen LM35 temperatursensorer.

Temperatursensorer med Arduino.

Dette prosjektet startet egentlig engang i vår da jeg bestemte meg for at jeg hadde fått nok av støyen fra datamaskinene mine, og bestemte meg for å plassere dem ute på lageret som ligger vegg-i-vegg med stuen bak en godt isolert vegg. Etter å ha kjøpt inn ekstra lange USB, skjerm og lydkabler og plagdes en del med å få USB signalet til å rekke 10 meter, noe som fremdeles ikke fungerer helt optimalt, og deretter lodden sammen noen av/på brytere som gjør at jeg kan slå av og på maskinene uten å springe ut på lageret, var det endelig stille i stuen (bortsett fra kjøleskapet som plutselig ble så altfor mer tydelig.)

En av tingene som derimot bekymret meg litt var temperaturen på det 6-8M^2 store lagerrommet, og et par dager etterpå, på selveste 17 mai, målte jeg 40’C der inne med et utendørstermometer var koblet trådløst til en Claes Ohlson værstasjon som jeg har i stuen. Det var helt klart at jeg måtte inn med kjøling. I utgangspunktet var lageret ventilert, så jeg trengte bare en vifte for å blåse varmlufta ut. Jeg dro innom Biltema og kjøpte en ventilasjonsvifte, disse bråker altfor mye, og etter noen stygge blikk fra naboene satte jeg inn en bordvifte som fungerte vel så bra som ventilasjonsviften, men uten vibrasjonsstøyen.


På dette tidspunktet bestemte jeg meg også for at jeg ville ha en mer permanent overvåkning av temperaturen på rommet, og jeg begynte å lete etter noe som kunne lage trend grafer på samme måte som Cricket, Cacti og MRTG. De jeg fant var enten for sære (proprietære) eller så krevde de at man kjørte noe som rart som kaltes for Windows. Det jeg dermed endte opp med var en løsning som baserte seg på Arduino som er en Italiensk open source platform hvor hardware delen består av et kretskort med en microkontroller med forskjellige innganger (analog/digital inn, 5V/12V ut, osv.) I tillegg til dette trengte jeg bare en LM35 sensor som er en temperatur sensor med +5V og jord inn, hvor den 3dje kontakten avgir voltstyrke alt etter hvordan temperaturen i rommet er. Jeg koblet sensoren opp mot Arduinoen på følgende måte:

Arduino LM35 sensor schematics

Jeg ønsket å koble til to temperatur sensorer til denne. Vel, egentlig tre, men det viste seg i ettertid at avlesningen ble uregelmessig når ledningen mellom Arduinoen og sensoren ble for lang. Så jeg begrenset meg til å måle av temperaturen i stuen og på lageret. I tillegg har jeg en graf som leser temperaturen på en av hard diskene, til dette bruker jeg ganske enkelt kommandoen ‘hddtemp /dev/sda’ for så å gi outputen videre til programvaren som tar seg av grafingen.

Når det gjelder grafene så finnes det mye programvare for å gjøre dette, MRTG, Cricket og Cacti. Hvis man har lyst til å plages litt med RRDtool så kan man sikkert også ordne dette selv direkte fra kommandolinjen. MRTG er veldig lett å sette opp men problemet med MRTG er blant annet at den ikke støtter negative nummer og flyttall. Cricket er fremdeles veldig knotete å sette opp, mens Cacti sliter med et ikke intuitivt web-grensesnitt og behov for egen MySQL server. Velg din demon med omhu, jeg endte opp med Cacti selv, men jeg hadde sikkert spart meg mye trøbbel med å bare bruke RRDtool direkte. Det er mulig at jeg kommer til å gjøre dette engang i fremtiden.

Koden som kjøres på Arduinoen ser slik ut:

int pin1=0;
int pin2=2;
int inc;
float gain=100; // sensor gain = 10mV/deg
float resolution=1024; // steps between max and min
float volt=5.0;
float temp1=0;
float temp2=0;

void setup()
{
  Serial.begin(19200);
}

void loop()
{
  if (Serial.available() > 0)
  {
      inc=Serial.read(); // accept data from the server
      temp1=(((analogRead(pin1)/resolution)*volt)*gain);
      temp2=(((analogRead(pin2)/resolution)*volt)*gain);

      Serial.print ("X:");
      Serial.print (temp1,DEC);
      Serial.print (":");
      Serial.print (temp2,DEC);
      Serial.println (":Y");
  }
}

Scriptet venter på data ifra serieporten, og når data mottas, leses sensordataene og skrives tilbake. Jeg bruker X:temp1:temp2:Y for å lettere kunne parse og verifisere at dataene er rett i scriptet som mottar dataene. Dette scriptet kjøres på kortet og det kreves at du installerer en IDE + noen bibliotek for å kunne gjøre dette. Jeg anbefaler at man kjører et av de OSene som er offisielt støttet av Arduino for å gjøre dette så enkelt som mulig.

Dette er koden som kjøres på serveren som kortet er koblet til, når dataene skal hentes ut:

#!/usr/bin/perl

# read temperature sensor data from the Arduino.

use Device::SerialPort;

# connect to the USB port
my $port = Device::SerialPort->new("/dev/ttyUSB0");
$port->databits(8);

$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);

# attempt to read from the serial port a few times
$cnt=0; $str="";
while (($cnt++write("1n"); # any data will do
    $str=$port->lookfor();
    sleep (3);
}

# check the data we received from the arduino
$chk=0;
$_=$str;
# integrity check on return string
if ((/^X/) && (/Y/)) { $chk=1; }

# the format on the return string is:
# X:TEMP1(float):TEMP2(float):Y
if ($chk)
{
    ($foo,$t1,$t2,$bar)=split /:/,$_;

    $temp1=sprintf ("%1.1f",$t1);
    $temp2=sprintf ("%1.1f",$t2);
    print "temp1:".$temp1." temp2:".$temp2."n";

    # since data from the arduino device sometimes fail
    # store the current data for future use
    if ($temp > 0)
    {
        open TXT,">/tmp/temperature2.dta";
        print TXT $temp1."n";
        print TXT $temp2."n";
        close TXT;
    }
} else {
    # reading temperature from sensor failed, get previous reading
    open TXT,"</tmp/temerature2.dta";
    $temp1=;
    $temp2=;
    close TXT;
    print $temp1;
    print $temp2;
}

Scriptet kobler seg ganske enkelt opp mot serieporten NB! Cacti må ha lesetilgang til /dev/ttyUSB0 noe som gjør at du må skrive ‘chown cacti /dev/ttyUSB0‘ hver gang du kobler inn Arduinoen, nok en grunn til å ikke bruke Cacti. Etter at scriptet har koblet seg opp mot USB porten sender den et ett tall og venter på retur data. Dette blir litt som UDP trafikk slik at garantien for at pakkene kommer korrekt igjennom er ikke helt 100%, jeg har derfor kodet inn litt feilhåndtering.

Cacti mottar dataene på formatet:
temp1:verdi1 temp2:verdi2

Når det gjelder installasjon av Cacti så er det ganske rett frem – yum install diverse rpm pakker. Konfigurasjon av systemet er heller lite intuitivt med feilmeldinger som får Harry Hurt til å gråte. For å gjøre det enkelt anbefaler jeg at du holder deg unna templates og går rett på Data Input Methods:
Input Type=script/command
Input String=Perl scriptet over, med full path
Ouput Fields:
temp1 og temp2 (over to linjer) Det som er viktig her er at field output er temp1/temp2 siden du ønsker å referere dataene seinere.

Deretter går du på data sources og legger til to kilder. temp1 og temp2 brukes her som Internal Data Source Name.

Under graph management legger du inn Temperature Sensors, jeg har brukt følgende oppsett på selve grafen:

Temperatur Sensor grapher configuration

Når det gjelder grafen så kan man enten se den i Cacti som krever login, eller generere den on-the-fly når web-siden lastes slik som jeg gjør det. I tillegg har Cacti en eksport funksjon som krasjet spektakulært når jeg testet den. Her er PHP koden jeg bruker for å lage grafen basert på rrdtool dataene.

    // generate a picture in the date/ folder 
   // for later inclusion using <img
  // src tags

    gengraph ("Temperatures for the past 24 hours",
                       "graph01.png",-86400,-300);

    function gengraph ($otitle,$ofile,$start,$end)
    {
        $cmd='/usr/bin/rrdtool graph data/'.$ofile.' 
--imgformat=PNG 
--start='.$start.' 
--end='.$end.' 
--title=''.$otitle.'' 
--base=1000 
--height=120 
--width=500 
--alt-autoscale-max 
--lower-limit=10 
--vertical-label='degrees C' 
--slope-mode 
--font TITLE:12: 
--font AXIS:8: 
--font LEGEND:10: 
--font UNIT:8: 
DEF:a="/usr/share/cacti/rra/temp1_16.rrd":temp1:AVERAGE 
DEF:b="/usr/share/cacti/rra/temp2_17.rrd":temp2:AVERAGE 
DEF:c="/usr/share/cacti/rra/hdtemp_15.rrd":hdtemp:AVERAGE 
LINE2:a#3D168BFF:"Sensor 1: Storage Room n"  
GPRINT:a:MIN:"Min:%8.2lf %s"  
GPRINT:a:AVERAGE:"Average:%8.2lf %s"  
GPRINT:a:MAX:"Max:%8.2lf %s"  
GPRINT:a:LAST:"Last:%8.2lf %sn"  
LINE2:b#007283FF:"Sensor 2: Living Room  n"  
GPRINT:b:MIN:"Min:%8.2lf %s"  
GPRINT:b:AVERAGE:"Average:%8.2lf %s"  
GPRINT:b:MAX:"Max:%8.2lf %s"  
GPRINT:b:LAST:"Last:%8.2lf %sn"  
LINE2:c#FF5700FF:"Sensor 3: Fileserver HDn"  
GPRINT:c:AVERAGE:"Min:%8.2lf %s"  
GPRINT:c:AVERAGE:"Average:%8.2lf %s"  
GPRINT:c:MAX:"Max:%8.2lf %s"  
GPRINT:c:LAST:"Last:%8.2lf %sn"';
        exec ($cmd);
    }

Dette er nesten en cut-n-paste av koden som kommer opp når man slår på debugging under graph management i Cacti.

Koden som leser av temperaturen i harddisken er avhenging av at man har hddtemp installert (yum install hddtemp i Fedora) og scriptet under gjør at det eneste som skrives ut er temperaturen.

#!/usr/bin/perl

$ic='/usr/bin/hddtemp /dev/sda';
open TXT,$ic."|";
$io=;
chomp $io;
close TXT;
($foo,$foo,$io)=split /:/,$io;
$io=~s/s|C|°//g;
$dtemp1=$io;

print $dtemp1;

Det kan virke som om Arduino er litt overkill for enkel temperaturavlesing, alternativet er å koble sensoren direkte på en IO port, men Arduino er beregnet på eksperimentelle ting, blant annet så ødelegges den ikke når du tar feil av + og jord kontakten. Den kan uansett brukes til mye annet også, jeg har boken “Programming Interactivity” liggende på kontoret hvis det er noen som har lyst til å låne den for å lese mer om hva man kan gjøre med kortet.

Ca. pris for alt, mellom 3-400 NOK, når Arduinoen bestilles fra USA og man allerede har loddebolt. Resultatet kan du se på http://ekran.homeip.net/

Lenker:
Arduino – http://www.arduino.cc/
Cacti – http://www.cacti.net/
Fedora Linux – http://fedoraproject.org/
Perl – http://www.perl.org/
RRDtool – http://oss.oetiker.ch/rrdtool/
Hjemmeserveren min – http://ekran.homeip.net/

One response to “Temperatursensorer med Arduino.”

  1. RF says:

    Tøft! Skal igang selv med Arduino-basert fuktmålerløsning i gammelt hus. Blir moro!

Leave a Reply

Your email address will not be published. Required fields are marked *