ascii image


0010101000011111101001101010000010011000
1110101110110101011011111010010010001011
0001011100011101111001010011010010111110
0000010111101001100000110011101100001000
0011000000111010001111111000100110000001
1010110110000000000001011001000110001010
0101100010101100000100000010100100010101
0001011001011101100011000101110111101110
0110010100110100111101110100110011111101
0010111100110011010010110010101111011011
0100000000001001001011000010110100101001
1101000111100000110111011100110111000010
1111110001111111101101001010000111101100
0010110000100000111011000000101100010110
0101111000011100111010000000011111101111
0010010011110010011101001000110101000101
0000000001000100001111111100111010001111

Friday, 31 December 2010

VFD - Vacuum Fluorescent Display


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