I found some VFDs on ebay and i thought, that would be a great replacement to the USB LCD - bigger and brighter.
These were NCR 5972s, these are great as they are RS232 controlled (which is why i needed to add some extra RS232 ports in an earlier post).
I used this document i found for the pinouts. www.maltepoeggel.de/html/vfd/vfd_ncr5972.pdf
Initially i wrote the code below on the Mac, but the serial to usb dongles i had didnt like the length of time they were running and died/crashed after a few hours runtime. On the linux box it has been running for days no problem.
#!/usr/bin/perl -w use FileHandle; #use LWP::Simple qw/get/; #my $serialport="/dev/tty.usbmodemfd631"; # mac my $serialport="/dev/ttyS1"; # linux my $displaydelay=5; # how long before each messages is displayed my $DEBUG=0; ##################################################################### # # the display updates only on a serialport flush # this is notmally done when you close the port # if we try and auto flush the serial port after a time # the serial port crahed and the process become # uninterruptable ps state=U, and you cant kill it unless # you reboot ! URGH # so open teh port each time, send the data and then close it # again. our @list=(); # list of strings to display my $DEGREES=chr(248); # ascii 248 for degrees symbol my $SYM_UP=chr(24); # trend up symbol my $SYM_DOWN=chr(25); # trend down symbol our $outside="-" x 20; our %data; our $datafile="/opt/weather/html/weather-data.js"; $|=1; my $continue = 1; #$SIG{TERM} = sub { $continue=0; }; #$SIG{INT} = sub { $continue=0; }; $SIG{INT} = 'handler'; $SIG{TERM} = 'handler'; $SIG{QUIT} = 'handler'; sub handler { # 1st argument is signal name local($sig) = @_; print localtime()." Caught a SIG$sig--shutting down\n"; cursor_top_line(); blank_display(); write_text("shutting down"); close(SERIAL); exit(77); } sub send_serial($) { local $data=shift; # # open serial port # if (! -e "$serialport" ) {die "no port $!";}; print "send_serial: opening...\n" if ($DEBUG>1); eval { local $SIG{ALRM} = sub { die("alarm\n"); }; alarm(10); open(SERIAL, ">$serialport") || die("cant open $serialport"); #sysopen(SERIAL, $serialport, O_RDWR | O_EXCL ) || die("cant open $serialport : $!"); alarm(0); }; if ($@) { if ($@ eq "alarm\n") { die ("Serial port open timed out\n"); } else { die ("ugh some other error at serial port open : $@\n"); }; }; print "send_serial: opened\n" if ($DEBUG>1); #SERIAL->autoflush(1); if (!defined(SERIAL)) { warn "serial port handle not defined"; }; # now set baud rate - VERY IMPORTANT on OSX $msg=`stty -F $serialport 9600 2>&1`; $ERR=$?; if ($ERR != 0) { die("cant set baud on $serialport : $msg"); }; ## IMPORTANT to autoflush the serial port #http://perldoc.perl.org/perlfaq8.html#How-do-I-read-and-write-the-serial-port%3f # we dont use this now, as it is what zombies the process ##select((select(SERIAL), $| = 1)[0]); print "send_serial: 0x".unpack("H*", $data)."\n" if ($DEBUG>1); print SERIAL $data; print "send_serial: sent\n" if ($DEBUG>1); close(SERIAL); }; sub send_command($) { local $cmd=shift; send_serial pack("cc",0x1B, $cmd); }; sub send_commandEx($) { # send a 3 byte command local $cmd=shift; #print "cmdEx: 0x".unpack("H*",pack("n",$cmd))."\n"; # for debugging send_serial pack("cn",0x1B, $cmd); }; sub init_display { send_command(0x05); sleep(5); # catch up with display blank_display(); }; sub clear_display { send_command(0x02); }; sub write_text { local $text=shift; print "writing: >>$text<<\n" if ($DEBUG>0); send_serial $text; }; sub blank_display() { write_text(" " x 40); # clear any blinking etc }; sub blank_line() { write_text(" " x 20); # write 20 blanks, careful that you are at pos 0, 0x14 first }; sub char_blink($) { #The only way to cause an existing character to start or stop blinking #is to set up the character blink operator, move the cursor to the #correct character, and resend the individual character code. # 0 = off # 1 = on local $b = shift; if ($b==1) { send_command(0x0D); } else { send_command(0x0E); }; }; sub display_brightness($){ local $b=shift; if ($b>0 && $b<6) { $b=0x17<<8 | $b; send_commandEx($b); }; }; sub enable_screensaver($) { # after 5mins blank or walk # 0 = blank # 1 = walk local $b = shift; if ($b==1) { send_command(0x0A); } else { send_command(0x09); }; }; sub disable_screensaver() { send_command(0x0C); }; sub start_screensaver() { # start immediately send_command(0x0B); }; sub cursor_to_position($) { local $b = shift; if ($b>=0 && $b<=0x27) { $b=0x13<<8 | $b; send_commandEx($b); }; }; sub cursor_top_line() { cursor_to_position(0); }; sub cursor_bottom_line() { cursor_to_position(0x14); }; sub display_item($) { local $item=substr(shift,0,20); #cursor_top_line(); #blank_line(); cursor_top_line(); $outside .= " " x ( 20 - length( $outside ) ); write_text($outside); #cursor_bottom_line(); #blank_line(); cursor_bottom_line(); $item .= " " x ( 20 - length( $item ) ); write_text($item); }; sub populateList() { # # push your data into the list - some how # # initialise the list @list=(); # get from DB %data=(); #@datafile=split(/\n/,get("http://someserver/weather-data.js")); open(DATA,"<$datafile") || warn("cant open data file : $!"); while (<DATA>) { my $line =$_; #var outsideT=-2.1;//C $data{"$1"}=$2 if ($line=~m/var\s+(\S+)=(.*?);/); print "$1 = $2\n" if ($DEBUG>0); }; close(DATA); if (scalar(keys %data)==0) { $outside = substr(localtime()." ",0,20); push @list, "Server Down!"; } else { $data{wind_dscr}=~s/\"//g; # remove my quotes $ght=($data{greenhouseTD}=~/up/)?$SYM_UP:$SYM_DOWN; $ot=($data{outsideTD}=~/up/)?$SYM_UP:$SYM_DOWN; $outside="Outside: ".$data{outsideT}.$DEGREES."C ".$ot; push @list, "Greenhouse: ".$data{greenhouseT}.$DEGREES."C ".$ght; push @list, "Humidity: ".$data{humidity}."%"; push @list, "Rain in 24hrs: ".$data{rainlastday}."mm"; push @list, "Wind speed: ".$data{windspeed}." mph"; push @list, "Wind: ".$data{wind_dscr}; push @list, "Cloudbase: ".$data{cloudbase}."m"; }; }; ################################################################################## # MAIN print "starting...\n"; init_display(); disable_screensaver(); display_brightness(1); populateList(); # get initial values # # display and rotate # my $index=0; my $then=time(); while ($continue==1) { local $hour=(localtime())[2]; if ($hour>=6 && $hour<23) { # display only between 6am and 11pm print "loop..." if ($DEBUG>0); $item=$list[$index]; display_item($item); $index++; if ($index>scalar(@list)-1) { $index=0; }; $now=time(); if ($now - $then > 7) { populateList(); $then=$now; }; } else { blank_display(); sleep(300); # 5mins }; # end display only between hours sleep($displaydelay); }; # it can take a while to get here, sometime it zombies. (used to) print "exiting...\n";
No comments:
Post a Comment