Raspberry Pi HD44780 LCD Display Perl Script

I just ported this python script  to Perl using Device::BCM2835 from cpan in order to display text on a HD44780 compatible LCD using the GPIO pins of a Raspberry Pi. The LCD I used is the C0802-04 from Pollin.

My Perl script displays the time and temperature, using a 1-wire temperature sensor (DS18S20) using the 4 bit mode. RS is on GPIO14, E on GPIO 15, Data4 on GPIO 24, Data5 on GPIO 10, Data6 on GPIO 9 and Data7 on GPIO 11. Additionally it let a LED blink on GPIO 25.


#!/usr/bin/perl

use Device::BCM2835;

use strict;
use warnings;

# call set_debug(1) to do a non-destructive test on non-RPi hardware
 #Device::BCM2835::set_debug(1);
 Device::BCM2835::init()
 || die "Could not init library";

use constant DISPLAY_RS => 14;
use constant DISPLAY_E => 15;
use constant DISPLAY_DATA4 => 24 ;
use constant DISPLAY_DATA5 => 10;
use constant DISPLAY_DATA6 => 9;
use constant DISPLAY_DATA7 => 11;

use constant DISPLAY_WIDTH => 8; # Zeichen je Zeile
use constant DISPLAY_LINE_1 => 0x80; # Adresse der ersten Display Zeile
use constant DISPLAY_LINE_2 => 0xC0; # Adresse der zweiten Display Zeile
use constant DISPLAY_CHR => 1;
use constant DISPLAY_CMD => 0;
use constant E_PULSE => 0.005;
use constant E_DELAY => 0.005 ;
use constant LED => 25;

sub display_init();
sub lcd_string($);
sub lcd_byte($$);

my @temp_sensor;
my $temp;
my $repeat = 1;

# Outputs
Device::BCM2835::gpio_fsel(DISPLAY_RS,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
Device::BCM2835::gpio_fsel(DISPLAY_E,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
Device::BCM2835::gpio_fsel(DISPLAY_DATA4,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
Device::BCM2835::gpio_fsel(DISPLAY_DATA5,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
Device::BCM2835::gpio_fsel(DISPLAY_DATA6,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
Device::BCM2835::gpio_fsel(DISPLAY_DATA7,Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
# Blink 25:
Device::BCM2835::gpio_fsel(LED,&Device::BCM2835::BCM2835_GPIO_FSEL_OUTP);
&display_init;

print "LCD Test\n";
do {
 if(open(W1, "</sys/devices/w1_bus_master1/w1_master_slaves") == 0) {
 &lcd_byte(DISPLAY_LINE_1, DISPLAY_CMD);
 &lcd_string("Test 1");
 }
 else {
 Device::BCM2835::gpio_write(LED, 1);
 my $i=0;
 while(<W1>) {
 $temp_sensor[$i]=$_;
 $i++;
 }
 close(W1);

 chomp(@temp_sensor);

 open(TEMP, "</sys/bus/w1/devices/".$temp_sensor[0]."/w1_slave") || die "couldn't read $temp_sensor[0]";

 while(<TEMP>) {
 $temp=$_;
 $i++;
 }

close TEMP;

 $temp=sprintf("%4.2f",substr($temp,index($temp,"t=")+2)/1000);
 lcd_byte(DISPLAY_LINE_1, DISPLAY_CMD);
 lcd_string("$temp ßC");
 Device::BCM2835::gpio_write(LED, 0);
 }
 for (my $i=0;$i<4;$i++) {
 my ($sec,$min,$hour) = localtime(time);
 $hour = sprintf "%02d",$hour;
 $min = sprintf "%02d",$min;
 $sec = sprintf "%02d",$sec;
 lcd_byte(DISPLAY_LINE_2, DISPLAY_CMD);
 lcd_string($hour.+":".$min.":".$sec);

Device::BCM2835::delay(250);
 }

} while($repeat);



sub display_init() {
 lcd_byte(0x33,DISPLAY_CMD); #8 bit 8 bit
 lcd_byte(0x32,DISPLAY_CMD); #8bit 4bit
 lcd_byte(0x28,DISPLAY_CMD); #2lines 5*7
 lcd_byte(0x08,DISPLAY_CMD); #off
 lcd_byte(0x0C,DISPLAY_CMD); #on no cucrsor no blink
 lcd_byte(0x06,DISPLAY_CMD); #cusor increment
 lcd_byte(0x01,DISPLAY_CMD); #display clear
 Device::BCM2835::delay(100);

}
sub lcd_string($) {
 my $message = shift;
#$message = sprintf("%*s", DISPLAY_WIDTH, $message) ; #rechtsbündig
 $message = sprintf("%-*s", DISPLAY_WIDTH, $message) ;
for (my $i=0;$i<DISPLAY_WIDTH;$i++) {
lcd_byte(ord(substr($message,$i,1)),DISPLAY_CHR);
}

}
sub lcd_byte($$) {
 my $bits = shift;
 my $mode = shift;
 Device::BCM2835::gpio_write(DISPLAY_RS, $mode);
 Device::BCM2835::gpio_write(DISPLAY_DATA4, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA5, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA6, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA7, 0);
 if (($bits & 0x10)==0x10) {
 Device::BCM2835::gpio_write(DISPLAY_DATA4, 1);
 }
 if (($bits & 0x20)==0x20) {
 Device::BCM2835::gpio_write(DISPLAY_DATA5, 1);
 }
 if (($bits & 0x40)==0x40) {
 Device::BCM2835::gpio_write(DISPLAY_DATA6, 1);
 }
 if (($bits & 0x80)==0x80) {
 Device::BCM2835::gpio_write(DISPLAY_DATA7, 1);
 }
 Device::BCM2835::delay(E_DELAY);
 Device::BCM2835::gpio_write(DISPLAY_E, 1);
 Device::BCM2835::delay(E_PULSE);
 Device::BCM2835::gpio_write(DISPLAY_E, 0);
 Device::BCM2835::delay(E_DELAY);
 Device::BCM2835::gpio_write(DISPLAY_DATA4, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA5, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA6, 0);
 Device::BCM2835::gpio_write(DISPLAY_DATA7, 0);
 if (($bits & 0x01)==0x01) {
 Device::BCM2835::gpio_write(DISPLAY_DATA4, 1);
 }
 if (($bits & 0x02)==0x02) {
 Device::BCM2835::gpio_write(DISPLAY_DATA5, 1);
 }
 if (($bits & 0x04)==0x04) {
 Device::BCM2835::gpio_write(DISPLAY_DATA6, 1);
 }
 if (($bits & 0x08)==0x08) {
 Device::BCM2835::gpio_write(DISPLAY_DATA7, 1);
 }
 Device::BCM2835::delay(E_DELAY);
 Device::BCM2835::gpio_write(DISPLAY_E, 1);
 Device::BCM2835::delay(E_PULSE);
 Device::BCM2835::gpio_write(DISPLAY_E, 0);
 Device::BCM2835::delay(E_DELAY);
}