====== Embedded Linux computer with 1-wire net ====== Linksys NSLU2 running Debian Linux off of flash memory, polls a 1-wire net every 5 minutes and records the data (temperature and humidity) to a remote SQL server. 1-Wire ===== PIC18 Microcontroller ===== PIC18F4523 reading an ADT7410 temperature sensor via I2C. ===== Web box on main page ===== Displays the following little info box about temperature, humidity, and atmospheric pressure. include("webinfo.php"); ===== Files ===== ==== ADT7410.asm ==== list p=18f4523 include GLOBAL INIT_I2C,READ_ID,READ_TEMP,Therm ; EXTERN SendChar #DEFINE ADDRESS_W 0x90 ; ADT7410 Address 0x48 shifted left by 1 #DEFINE ADDRESS_R 0x91 #DEFINE ADT7410_TEMPH 0x00 #DEFINE ADT7410_TEMPL 0x01 #DEFINE ADT7410_STATUS 0x02 #DEFINE ADT7410_CONFIG 0x03 #DEFINE ID 0x0B ; Obtain ID UDATA Temp RES 1 Therm RES 2 MyID RES 1 I2C_START MACRO BSF SSPCON2,SEN BTFSC SSPCON2,SEN GOTO $-2 ENDM I2C_STOP MACRO BSF SSPCON2,PEN BTFSC SSPCON2,PEN GOTO $-2 ENDM I2C_ACKCONF MACRO ; Confirm ACK BTFSC SSPCON2,ACKSTAT GOTO $-2 ENDM I2C_SendAck MACRO BSF SSPCON2,ACKEN BTFSC SSPCON2,ACKEN GOTO $-2 ENDM I2C CODE INIT_I2C ; BSF LATD,RD0 MOVLW 0x03 MOVWF SSPADD ; Baud Rate BSF TRISC,SDA ;Serial data (SDA) – RC4/SDI/SDA BSF TRISC,SCL ;Serial clock (SCL) – RC3/SCK/SCL BSF SSPSTAT,SMP BCF SSPSTAT,CKE MOVLW b'00001000' MOVWF SSPCON1 BSF SSPCON1,SSPEN I2C_START ; Send Start Bit ; Send Address for Write MOVLW ADDRESS_W MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK MOVLW ADT7410_CONFIG MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send Address for Write MOVLW b'11000000' MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send Stop I2C_STOP RETURN READ_ID I2C_START ; Send Start Bit ; Send Address for Write MOVLW ADDRESS_W MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send ID Byte MOVLW ID MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send Repeated Start Bit BSF SSPCON2,RSEN BTFSC SSPCON2,RSEN GOTO $-2 ; Send Address for Read MOVLW ADDRESS_R MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Receive Data BSF SSPCON2,RCEN BTFSC SSPCON2,RCEN GOTO $-2 MOVFF SSPBUF,MyID BSF SSPCON2,ACKDT ; NoAck for no more data I2C_SendAck ; Send Stop I2C_STOP RETURN READ_TEMP I2C_START ; Send Start Bit ; Send Address for Write MOVLW ADDRESS_W MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send ID Byte MOVLW ADT7410_TEMPH MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Send Repeated Start Bit BSF SSPCON2,RSEN BTFSC SSPCON2,RSEN GOTO $-2 ; Send Address for Read MOVLW ADDRESS_R MOVWF SSPBUF BTFSC SSPSTAT,BF GOTO $-2 I2C_ACKCONF ; Confirm ACK ; Receive Data BCF SSPCON2,ACKDT ; Ack for more data BSF SSPCON2,RCEN BTFSC SSPCON2,RCEN GOTO $-2 MOVFF SSPBUF,Therm+1 I2C_SendAck BSF SSPCON2,ACKDT ; NoAck for no more data BSF SSPCON2,RCEN BTFSC SSPCON2,RCEN GOTO $-2 MOVFF SSPBUF,Therm I2C_SendAck ; Send Stop I2C_STOP BCF LATD,RD0 RETURN END ==== Pic18poller.pl ==== #!/usr/bin/perl use Device::SerialPort; use DBI; # MySQL CONFIG VARIABLES $host = "hostname"; $database = "database"; $tablename = "pic"; $user = "username"; $pw = "password"; #Filename for when MySQL server is offline $file="pcontroller_cache.dat"; # Set up the serial port # 19200, 81N on the USB ftdi driver my $port = Device::SerialPort->new("/dev/ttyUSB0"); $port->databits(8); $port->baudrate(19200); $port->parity("none"); $port->stopbits(1); $port->read(255); $port->write("\$S1,Q#"); my $notFndCnt = 0; $data=""; while($data !~ /\$C0.*\#/) { $data.=$port->read(255); } $port->close(); @values=split(/,/,$data); $hex=$values[3]; $Temperature=hex($hex)/128; #if(!$hex) { #die(); #} print "$Temperature\n"; my ($s,$m,$h,$d,$mon,$yr,$wday,$yday,$isdst) = localtime time; if($dbh = DBI->connect('DBI:mysql:'.$database.":$host",$user,$pw)) { $sql = "INSERT INTO `1wire`.`$tablename` (`dt`, `hex`, `temp_c`, `misc`) VALUES (CURRENT_TIMESTAMP, \'$hex\', \'$Temperature\', NULL);"; $c = $dbh->do($sql); if(!$quiet) {print "Affected $c rows for table $tablename\n";} $dbh->disconnect(); } else { if(!$quiet) {print "Could not connect to database: $DBI::errstr";} $c=0; } if(!$c) { if(!$quiet) {print "Failure, writing to $file\n";} $stamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d", $yr+1900, $mon+1, $d, $h, $m, $s); open(FH,">>$file") || die("Cannot open $file."); print FH "$tablename,$stamp,$hex,$Temperature,0\n"; close(FH); } ==== pic.php ==== DATE_SUB(NOW(),INTERVAL $INTERVAL DAY) ORDER BY `dt` ASC"; # $sql="SELECT UNIX_TIMESTAMP(`dt`),avg(`temp_c`) FROM `pic` WHERE 1 AND `dt`> DATE_SUB(NOW(),INTERVAL 2 DAY) group by DATE_FORMAT(`dt`,'%j.%k') ORDER BY `dt` ASC"; $result=mysql_query($sql); fwrite($fp,"# PIC Controller\n# ".date("F j, Y, g:i a")."\n#unixtime\ttemperature\n"); while ($row = mysql_fetch_assoc($result)) { if(isset($row['temp_c'])) { fwrite($fp,$row['UNIX_TIMESTAMP(`dt`)']+$TZoffset."\t".$row['temp_c']."\n"); } else { fwrite($fp,"\n"); } } fclose($fp); } ==== webinfo.php ==== 0) { $icolor=$RED; } if($outdoortemp>0) { $ocolor=$RED; } else {$ocolor=$BLUE;} if($envcan['tendency']=='falling') $trend='↓'; elseif($envcan['tendency']=='rising') $trend='↑'; else $trend=''; if((is_numeric($indoortemp) AND is_numeric($outdoortemp) AND is_numeric($ihumid))) { $date=date('Y-m-d G:i',$oldest); #print "
\n"; printf('Indoor Temp: %0.1f°C
',$icolor,$indoortemp); printf('Outdoor Temp: %0.1f°C
',$ocolor,$outdoortemp); printf('Indoor humidity: %0.0f%%
',$ihumid); printf('Outdoor humidity: %0.0f%%
',$envcan['humidity']); printf('Pressure: %s kPa %s
',$envcan['pressure'],$trend); #print "Updated: $date\n"; #print "
\n"; } else { print "Offline\n"; } ?>
==== config.inc.php ====