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

PIC18F4523 reading an ADT7410 temperature sensor via I2C.

Displays the following little info box about temperature, humidity, and atmospheric pressure.

<php>include(“webinfo.php”);</php>
ADT7410.asm
	list p=18f4523
	include <P18f4523.INC>
 
 
	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
<?
# Jeff Brown
# November 1th, 2010
# Version: 2.3
# http://photonicsguy.ca/nslu2

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
 
date_default_timezone_set("America/Toronto");
 
include('config.inc.php');
$INTERVAL=2;
$TZoffset=-3600*4;
$link = mysql_connect($MYSQL_HOST,$MYSQL_USER,$MYSQL_PASS);
if (!$link) {
	echo "Unable to connect to DB: " . mysql_error();
	exit;
}
 
if (!mysql_select_db($MYSQL_DB)) {
    echo "Unable to select mydbname: " . mysql_error();
    exit;
}
plot_picdata();
 
header('Content-Type: image/jpeg');
$file=$datadir."pic.gnuplot";
	$fp=fopen($file,'w');
	$tfrom=time()+$TZoffset-($INTERVAL*24*3600);
	$tto=(time()+$TZoffset);
#Blackberry size: 480,360

	$plot='set terminal jpeg nocrop size 1000,800
set xdata time
set timefmt "%s"
#set format x "%d/%m\n%I:%M"
set format x "%a %d\n%I:%M %p"
set grid nopolar
set grid xtics mxtics ytics mytics noztics nomztics \
 nox2tics nomx2tics noy2tics nomy2tics nocbtics nomcbtics
#set grid layerdefault   linetype 0 linewidth 1.000,  linetype 0 linewidth 1.000
set key inside right bottom vertical Right noreverse enhanced autotitles box
set title "'.date("F j, Y, g:i a").'"
#set style data fsteps
#set xlabel "Date\nTime"
#TZoffset='.$TZoffset.'
#set xrange ["'.$tfrom.'":"'.$tto.'"] noreverse nowriteback
set ylabel "Temperature"
#set yrange ['.$YRANGE.']
set yrange [0:30]
#set xtics 1*3600
#set mxtics 4
#set mytics 1
plot \'data/_sql_pic.dat\' using 1:2 t \'PIC\' with lines lw 2';
$t=',\
\'data/_sql_3.dat\' using 1:2 t \'Sensor 1\' with lines lw 1,\
\'data/_sql_3.dat\' using 1:2 t \'Sensor 2\' with lines lw 1,\
\'data/_sql_3.dat\' using 1:2 t \'Sensor 3\' with lines lw 1
';
fwrite($fp,$plot);
fclose($fp);
	passthru($gnuplot.' '.$datadir.'pic.gnuplot');
 
 
function plot_picdata() {
	global $datadir;
	global $INTERVAL;
	global $TZoffset;
	$file=$datadir."_sql_pic.dat";
	$fp=fopen($file,'w');
	$sql="SELECT UNIX_TIMESTAMP(`dt`),`temp_c` FROM `pic` WHERE 1 AND `dt`> 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
<?PHP
# Jeff Brown
# November 5th, 2010
# Version: 1.0
# http://photonicsguy.ca/nslu2

# Because my webhost is in another timezone...
date_default_timezone_set("America/Toronto");
 
include('config.inc.php');
 
$link = @mysql_connect($MYSQL_HOST,$MYSQL_USER,$MYSQL_PASS);
@mysql_select_db($MYSQL_DB);
 
# Indoor Temperature
#$sql='SELECT `temp_c`  FROM `pic` WHERE 1 ORDER BY `dt` DESC LIMIT 1';
#$result=mysql_query($sql);
#$row=mysql_fetch_assoc($result);
#$indoortemp=$row['temp_c'];

# Indoor Temperature & humidity
$sql='SELECT UNIX_TIMESTAMP(`dt`),`temp_c`,`humidity`  FROM `Humidity` ORDER BY `dt` DESC LIMIT 1';
$result=@mysql_query($sql);
$row=@mysql_fetch_assoc($result);
$ihumid=$row['humidity'];
$indoortemp=$row['temp_c'];
$oldest=$row['UNIX_TIMESTAMP(`dt`)'];
 
# All Enviroment Canada Stuff
$sql='SELECT *  FROM `TorWeather` WHERE 1 ORDER BY `dt` DESC';
$result=@mysql_query($sql);
$row=@mysql_fetch_assoc($result);
$outdoortemp=$row['temperature'];
$envcan=$row;
 
 
$RED="#FF0000";
$BLUE="#0000FF";
 
if($indoortemp>0) { $icolor=$RED; }
if($outdoortemp>0) { $ocolor=$RED; } else {$ocolor=$BLUE;}
if($envcan['tendency']=='falling')
	$trend='&darr;';
  elseif($envcan['tendency']=='rising')
	$trend='&uarr;';
  else
	$trend='';
 
if((is_numeric($indoortemp) AND is_numeric($outdoortemp) AND is_numeric($ihumid))) {
$date=date('Y-m-d G:i',$oldest);
#print "<DIV CLASS=\"rbox\">\n";
printf('Indoor Temp: <font color="%s">%0.1f&deg;C</font><BR>',$icolor,$indoortemp);
printf('Outdoor Temp: <font color="%s">%0.1f&deg;C</font><BR>',$ocolor,$outdoortemp);
printf('Indoor humidity: %0.0f%%<BR>',$ihumid);
printf('Outdoor humidity: %0.0f%%<BR>',$envcan['humidity']);
 
 
printf('Pressure: %s kPa&nbsp;%s<BR>',$envcan['pressure'],$trend);
#print "<font size=1>Updated: $date</font>\n";
#print "</DIV>\n";
} else {
	print "Offline\n";
}
?>
config.inc.php
<?
$MYSQL_HOST='hostname';
$MYSQL_USER='username';
$MYSQL_PASS='password';
$MYSQL_DB='database';
$MYTABLE='table'; # used for Temperature.php only

$INTERVAL=1; # used for Temperature.php only
$YRANGE="0:70"; # used for Temperature.php only

$datadir='data/'; # used for Temperature.php only

#Path to gnuplot
$gnuplot='/usr/bin/gnuplot';
?>
  • archive/nslu2.txt
  • Last modified: 2017/11/12 10:33
  • by photonicsguy