http://qs1969.pair.com?node_id=1170366

Well, I've finally released RPi::WiringPi. This uses the WiringPi::API wrapper that wraps the C-based wiringPi Raspberry Pi hacking software.

Anyway, I thought I'd throw something together that's kind of silly to play around with it. A couple of points: a) I know this isn't the proper way to web-scrape, it's just an example ;) b) forgive the global variables. The interrupt code in wiringPi library does not allow you to pass in any parameters, so until I submit a possible patch, globals are all I have. This was not meant to be prod code :D

The following code, infinitely looping every 60 seconds, scrapes my number of posts and XP from PerlMonks (in a *very* crude way), collects up the current time, then prints the data out onto an LCD display attached to my Pi:

p: 1293 18:15 x: 10361

Number of posts and then the time on the top line, XP on the bottom.

We introduce a button connected to a pin, when pressed, triggers an interrupt, and the interrupt handler rewrites the bottom line with the amount of XP remaining until my next PM level, instead of current XP (changes from x: 10361 to r: 1638. Every button press flips this back and forth.

Pics: before button press, and after button press.

use warnings; use strict; use LWP::Simple; use RPi::WiringPi; use RPi::WiringPi::Constant qw(:all); # catch a sigint. This allows us to # safely exit the while() loop and perform # emergency LCD/pin cleanup. The main class # catches die() my $continue = 1; $SIG{INT} = sub { $continue = 0; }; # initialize a Raspberry Pi object using the # BCM GPIO pin numbering scheme my $pi = RPi::WiringPi->new(setup => 'gpio'); # prepare and initialize the LCD my $lcd = $pi->lcd; # the following list of args looks daunting, but # it's very straightforward, and the docs are # pretty clear my %args = ( cols => 16, rows => 2, bits => 4, rs => 21, strb => 16, d0 => 12, d1 => 25, d2 => 24, d3 => 23, d4 => 0, d5 => 0, d6 => 0, d7 => 0, ); $lcd->init(%args); # set up a pin with a button, and set an # interrupt handler to do something when # the button is pressed my $button_pin = $pi->pin(26); # we're going to interrupt when the pin # goes LOW (off), so we'll pull it HIGH # with the built-in pull up resistor. # only when the button is pressed, will the # pin briefly go LOW, and this triggers # an interrupt $button_pin->pull(PUD_UP); # the second arg to interrupt_set() is the # name of the perl sub I've defined below # that I want handling the interrupt $button_pin->interrupt_set( EDGE_FALLING, 'button_press' ); my $button_presses = 0; my ($posts, $xp, $next); while ($continue){ my ( $sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst ) = localtime(); $min = "0$min" if length $min == 1; # get my post and xp count from PM ($posts, $xp) = perlmonks(); # manually get xp needed for next level $next = 12000 - $xp; # set the LCD cursor to top row, first # column, and print my num of PM posts $lcd->position(0, 0); $lcd->print("p: $posts"); # sub for bottom line, because the # code needs to be called also in our # interrupt handler. What's printed depends # on the cumulative number of button presses display_xp(); # on top row of the LCD at column 12, # we print the time $lcd->position(11, 0); $lcd->print("$hour:$min"); print "$hour:$min posts: $posts, " . "xp: $xp, next lvl: $next\n"; # rinse, repeat every minute sleep 60; } # wipe the LCD clean $lcd->clear; # reset pins to default state $pi->cleanup; sub button_press { # this is the interrupt handler print "button pressed\n"; $button_presses++; display_xp(); } sub display_xp { # this is the manager for the bottom LCD # row. It'll update things even when the # main program is sleeping in the while() # loop # print XP for 0 and even number of button # presses, and print XP remaining to next level # on odd number of presses $lcd->position(0, 1); if ($button_presses % 2){ $lcd->print("r: $next"); } else { $lcd->print("x: $xp"); } } sub perlmonks { my $url = "http://perlmonks.org/?node_id=789891"; my $page = get $url; my @content = split /\n/, $page; my ($xp, $posts); my $i = 0; for (@content){ if (/Experience:/){ my $line = $i; $line += 2; $xp = $1 if $content[$line] =~ /(\d+)/; } if (/Writeups:/){ my $line = $i; $line += 2; $posts = $1 if $content[$line] =~ />(\d+)/; } $i++; } return ($posts, $xp); }

Here's the code without all of the comments....

use warnings; use strict; use LWP::Simple; use RPi::WiringPi; use RPi::WiringPi::Constant qw(:all); my $continue = 1; $SIG{INT} = sub { $continue = 0; }; my $pi = RPi::WiringPi->new(setup => 'gpio'); my $lcd = $pi->lcd; my %args = ( cols => 16, rows => 2, bits => 4, rs => 21, strb => 16, d0 => 12, d1 => 25, d2 => 24, d3 => 23, d4 => 0, d5 => 0, d6 => 0, d7 => 0, ); $lcd->init(%args); my $button_pin = $pi->pin(26); $button_pin->pull(PUD_UP); $button_pin->interrupt_set( EDGE_FALLING, 'button_press' ); my $button_presses = 0; my ($posts, $xp, $next); while ($continue){ my ( $sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst ) = localtime(); $min = "0$min" if length $min == 1; ($posts, $xp) = perlmonks(); $next = 12000 - $xp; $lcd->position(0, 0); $lcd->print("p: $posts"); display_xp(); $lcd->position(11, 0); $lcd->print("$hour:$min"); print "$hour:$min posts: $posts, " . "xp: $xp, next lvl: $next\n"; sleep 60; } $lcd->clear; $pi->cleanup; sub button_press { print "button pressed\n"; $button_presses++; display_xp(); } sub display_xp { $lcd->position(0, 1); if ($button_presses % 2){ $lcd->print("r: $next"); } else { $lcd->print("x: $xp"); } } sub perlmonks { my $url = "http://perlmonks.org/?node_id=789891"; my $page = get $url; my @content = split /\n/, $page; my ($xp, $posts); my $i = 0; for (@content){ if (/Experience:/){ my $line = $i; $line += 2; $xp = $1 if $content[$line] =~ /(\d+)/; } if (/Writeups:/){ my $line = $i; $line += 2; $posts = $1 if $content[$line] =~ />(\d+)/; } $i++; } return ($posts, $xp); }

Replies are listed 'Best First'.
Re: Displaying my PM post count and XP on an LCD with RPi::WiringPi
by LanX (Saint) on Aug 26, 2016 at 17:34 UTC

      Thanks LanX,

      Although this q&d example was just for fun, I have periodically been interested in being able to gather information from PM, so yep, this is great!

Re: Displaying my PM post count and XP on an LCD with RPi::WiringPi
by jmlynesjr (Deacon) on Aug 25, 2016 at 19:54 UTC

    stevieb

    Nice work!

    Check RPi::WiringPi::LCD init(%args) section. The comments eg: 16 or 20 and eg: 2 or 4 are flipped.

    And yes, I'm a picky proof reader...

    James

    There's never enough time to do it right, but always enough time to do it over...

      Thanks! :)

      There are a few issues in the docs that I missed before release, but I've been cleaning them up today. That's one I've missed again.

      There are certainly some issues remaining, particularly with interrupts. Although they work properly most of the time, in certain situations they fail and don't halt the main app, but do hinder it. I'll debug this over the next few days.

      Other than that, it seems to work quite well so far. I'm going to test it out on some more complex applications and see how it fares.

      If you get a chance to test it out, I'm all ears for feedback for certain. Very soon I'll want to discuss the points you brought up on the other thread, so I'll ping you via email when I've got the time.

        stevieb

        "Call" anytime...

        I see a lot of RPi/Python discussions in the amateur radio world, so, I like to see some Perl alternatives becoming available.

        James

        There's never enough time to do it right, but always enough time to do it over...