no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | atmel:ds18b20-2313 [2009/11/27 17:53] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Temperature logger ====== | ||
+ | Monitor up to 7x DS18b20 1-wire devices using the [[http:// | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Two DS18b20 shown, one directly attached to the PCB via a 3pin socket others can be connect via additional pins. | ||
+ | |||
+ | The current draw from this device is 25mA. This is too much to drive from the RS232 port however a USB port can drive up to 500mA at 5v. Perfect. | ||
+ | |||
+ | How to save current: | ||
+ | * if we went for an interrupt driven approach rather then a tight loop we could idle down the chip in the meantime. | ||
+ | * Using a lower frequency chip say 4Mhz. | ||
+ | |||
+ | Alas its already built now. | ||
+ | |||
+ | < | ||
+ | 2313 Temperature monitor | ||
+ | Found 2 1-wire devices | ||
+ | 28A83FF6010000DB28 22 | ||
+ | 28EA31F60100006228 22 | ||
+ | 28A83FF6010000DB28 23 | ||
+ | 28A83FF6010000DB28 22 | ||
+ | </ | ||
+ | |||
+ | Reference: | ||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
+ | {{: | ||
+ | |||
+ | <code vb> | ||
+ | ' | ||
+ | '* 2313temp.bas | ||
+ | '* | ||
+ | '* Measure temperature using up to 4 1-wire 18b20 or 18s20 devices | ||
+ | '* BASCOM | ||
+ | ' | ||
+ | |||
+ | $regfile = " | ||
+ | $crystal = 10000000 | ||
+ | $baud = 9600 | ||
+ | |||
+ | Config 1wire = Pd.4 | ||
+ | |||
+ | ' DS18x20 ROM ID | ||
+ | Const Ds18s20_id = &H10 | ||
+ | Const Ds18b20_id = &H28 | ||
+ | |||
+ | ' COMMANDS | ||
+ | Const Ds18x20_convert_t = &H44 | ||
+ | Const Ds18x20_read = &HBE | ||
+ | |||
+ | Declare Sub Convallt | ||
+ | Declare Sub Meas_to_cel(id As Byte , Offset As Byte) | ||
+ | Declare Sub Monitor | ||
+ | Declare Sub Disp_temp(cnt As Byte , Offset As Byte) | ||
+ | |||
+ | ' 1-wire devices | ||
+ | Const Max1wire = 7 | ||
+ | ' Up to 7 each having an 8 byte ROMID | ||
+ | Dim Dsid(56) As Byte ' Dallas ID 64bit inc. CRC | ||
+ | Dim Dsvalue(max1wire) As Byte ' | ||
+ | Dim Dssign As Byte ' If max1wire > 7 make this a word | ||
+ | Dim Cnt1wire As Byte ' Number of 1-wire devices found | ||
+ | |||
+ | Dim I As Byte | ||
+ | Dim J As Byte | ||
+ | Dim K As Byte | ||
+ | Dim Meas As Word | ||
+ | Dim Sc(9) As Byte ' | ||
+ | 'Sc(1) ' | ||
+ | 'Sc(2) ' | ||
+ | 'Sc(3) ' | ||
+ | 'Sc(4) ' | ||
+ | 'Sc(5) ' | ||
+ | 'Sc(6) 'res | ||
+ | 'Sc(7) 'res | ||
+ | 'Sc(8) 'res | ||
+ | 'Sc(9) '8 CRC | ||
+ | |||
+ | ' | ||
+ | Print "2313 Temperature monitor" | ||
+ | |||
+ | ' Gather ROM ID for all 1-wire devices | ||
+ | Cnt1wire = 1wirecount() | ||
+ | Print "Found " ; Cnt1wire ; " 1-wire devices" | ||
+ | If Cnt1wire = 0 Then | ||
+ | Idle | ||
+ | End If | ||
+ | |||
+ | If Cnt1wire > Max1wire Then | ||
+ | Cnt1wire = Max1wire | ||
+ | End If | ||
+ | |||
+ | I = 1 | ||
+ | Dsid(i) = 1wsearchfirst() | ||
+ | For J = 1 To Cnt1wire | ||
+ | I = I + 8 | ||
+ | Dsid(i) = 1wsearchnext() | ||
+ | Next | ||
+ | |||
+ | Do | ||
+ | Convallt | ||
+ | Waitms 750 | ||
+ | Monitor | ||
+ | Loop | ||
+ | |||
+ | End | ||
+ | |||
+ | Sub Monitor | ||
+ | J = 1 | ||
+ | For I = 1 To Cnt1wire | ||
+ | 1wverify Dsid(j) | ||
+ | If Err = 0 Then | ||
+ | 1wwrite Ds18x20_read | ||
+ | Sc(1) = 1wread(9) | ||
+ | If Sc(9) = Crc8(sc(1) , 8) Then | ||
+ | Call Disp_temp(i , J) | ||
+ | End If | ||
+ | End If | ||
+ | |||
+ | J = J + 8 | ||
+ | Next | ||
+ | End Sub | ||
+ | |||
+ | |||
+ | 'Makes the Dallas " | ||
+ | 'WAIT 200-750 ms after issued, internal conversion time for the sensor | ||
+ | 'SKIPS ROM - so it makes the conversion on ALL sensors on the bus simultaniously | ||
+ | 'When leaving this sub, NO sensor is selected, but ALL sensors has the actual | ||
+ | ' | ||
+ | |||
+ | Sub Convallt | ||
+ | | ||
+ | | ||
+ | | ||
+ | End Sub | ||
+ | |||
+ | |||
+ | ' Store WHOLE degree' | ||
+ | ' Display if the value has changed since last polled. | ||
+ | Sub Disp_temp(cnt As Byte , Offset As Byte) | ||
+ | Meas = 0 | ||
+ | Meas = Makeint(sc(1) , Sc(2)) | ||
+ | |||
+ | ' 18S20 is only 9bit upscale to 12bit | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | |||
+ | If Meas.15 = 1 Then ' | ||
+ | Set Dssign.cnt | ||
+ | ' convert to +ve, (two's complement)++ | ||
+ | Meas = Meas Xor &HFFFF | ||
+ | Incr Meas | ||
+ | Else | ||
+ | Reset Dssign.cnt | ||
+ | End If | ||
+ | |||
+ | Shift Meas , Right , 4 | ||
+ | ' If this value different from the stored value ? | ||
+ | If Dsvalue(cnt) <> Meas Then | ||
+ | ' Dump ROMID of 1-wire device followed by temperature | ||
+ | K = Offset + 8 | ||
+ | Do | ||
+ | Print Hex(dsid(offset)); | ||
+ | Incr Offset | ||
+ | Loop Until Offset > K | ||
+ | Print " "; | ||
+ | If Dssign.cnt = 1 Then | ||
+ | Print " | ||
+ | End If | ||
+ | Print Meas | ||
+ | Dsvalue(cnt) = Meas | ||
+ | End If | ||
+ | |||
+ | End Sub | ||
+ | </ | ||
+ | |||
+ | To read the device from a linux box we can use the following snippet of perl. Now that we have a data value in a file we can use this value to feed my [[: | ||
+ | |||
+ | I guess I could have changed the firmware to send a value every (x) mins, however if you want different polling frequencies then you now need to change the firmware to suit, which is more difficult than adjusting your CRON that reads this file!. | ||
+ | |||
+ | <code perl> | ||
+ | # | ||
+ | use Device:: | ||
+ | |||
+ | # Map 1-wire ROMID to a location | ||
+ | %rommap=( | ||
+ | " | ||
+ | " | ||
+ | ); | ||
+ | |||
+ | # setup SERIAL port | ||
+ | my $port = Device:: | ||
+ | $port-> | ||
+ | $port-> | ||
+ | $port-> | ||
+ | $port-> | ||
+ | $port-> | ||
+ | $port-> | ||
+ | |||
+ | # Read from serial device | ||
+ | my $buffer = ""; | ||
+ | while(1) { | ||
+ | while ($string_in = $port-> | ||
+ | $buffer .= $string_in; | ||
+ | while ($buffer =~ m/\n/) { | ||
+ | ($buffer, $rest) = split(' | ||
+ | process_temp($buffer); | ||
+ | $buffer = $rest; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | exit; | ||
+ | |||
+ | sub process_temp() { | ||
+ | my ($output) = @_; | ||
+ | my ($romid, $temp) = split(' | ||
+ | |||
+ | my $location = $rommap{$romid}; | ||
+ | if ($location eq "" | ||
+ | | ||
+ | } | ||
+ | # We update the temperature when a new value is received. | ||
+ | # This file will be polled and logged by another | ||
+ | $temp =~ s/ | ||
+ | $file = "/ | ||
+ | open(FH,"> | ||
+ | print FH " | ||
+ | close(FH); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | We run this PERL code in a cron job that poll every 5 mins and transmits the value to the RRD server. | ||
+ | < | ||
+ | */5 * * * * / | ||
+ | </ | ||
+ | |||
+ | <code perl> | ||
+ | # | ||
+ | # | ||
+ | # rrd_hddtemp.pl | ||
+ | |||
+ | use IO::Socket; | ||
+ | use File:: | ||
+ | |||
+ | # Remote RRD server and port | ||
+ | my $host = " | ||
+ | my $port = 13900; | ||
+ | |||
+ | my $socket = IO:: | ||
+ | PeerPort=> | ||
+ | Proto=> ' | ||
+ | Type=> SOCK_STREAM) | ||
+ | or die " | ||
+ | @files = </ | ||
+ | foreach $file (@files) { | ||
+ | & | ||
+ | } | ||
+ | |||
+ | close $socket; | ||
+ | |||
+ | sub ProcessHDD | ||
+ | { | ||
+ | my($socket, | ||
+ | open(FH, | ||
+ | $temp = <FH>; | ||
+ | close FH; | ||
+ | |||
+ | $loc = basename($file); | ||
+ | $temp =~ s/[\n ]//g; | ||
+ | # print "$loc : $temp degrees C\n"; | ||
+ | |||
+ | print $socket " | ||
+ | $answer = < | ||
+ | print $answer; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | {{tag> |