MikeL's FreeBSD Socket Controller project

For many years, I've been running a 110V socket controller via the parellel port on a PC. The program accepts console commands, txt msg commands, and html commands. It also accepts inputs from assorted status pins on the parallel port, and can act on those, e.g. sending a txt msg, or triggering the outlets, etc.

This is written as a (believe it or not) Perl script, and the code is straightforward, simple, and reliable. It's running on Windows XP, as it requires a computer that's so old that it still has a parallel port! This has become as problem as Win XP is long out of maintenance, and can no longer be used reliably for a permanent server. (It's still running rock-steady, but I'm afraid of it's vulnerability to viruses.)
Unfortunately, I have not been able to get Win10 to run on this ancient computer. I did buy a parallel port card for a newer computer, but the only one I could find uses a non-standard I/O setting instead of 0x378 and I can't seem to get the Perl Device:: library to work with it. Note that I was able to find a test app DowntownDougBrown Perallel Port Tester (local copy) that shows that it physically works, I simply can't get the Perl code to talk to it. But that's Ok, it's time to get rid of that entire computer, screen, keyboard and mouse mess, for a nice little power-efficient standalone Raspberry Pi.

So the goal of this page is to document my upgrade to using an RPi as a controller. If I get a chance, I'll put in data here on the old Parallel port project as I go.

Note that this page is shown in archeological order, namely newest first. If you want to understand the events in order, start at the bottom.

Working on getting I2C working with 4 ch relay hat this evening.
I took the trouble to find out how to enable I2C from command line -- without having to dig up video/kbd/mse (see 22020308 below).
From superuser
Arrow down, take Interfaces, take I2C, take Enable, take Yes.

Built trivial Perl tester program, download here. The program increments through the 4 relays in binary. We now have everything needed to rebuild with relay hat board.

Finally got some time to upload photos. (click on small photo for full sized photo.)
Parallel port version.
This is an old APC Backups-350 unit. I ripped out the old charger board and battery. The DB-25 connector goes into the IBM PC parallel port (printer connector). The ribbon cable with the pin connector goes to a cable that connects to the relays of a wireless driveway sensor (Dakota DCMA-2500 setup to be specific). My control program is written in Perl, and used the Device::ParallelPort library.
Another photo.
Closeup of relay board "Mains" wiring.
This is the SunFounder 4 Ch Relay Shield (at Amazon.com), I think I got mine from RobotShop.com or SparkFun.com.
The "NO" connections go to the hot side of each of the outlets already built in to the box. The "common" goes to the red wire-nut, which goes to the main hot input. Come to think of it, I should have taken the hot to the NO connection as that way there would be less availability of it on the board, oh well. The neutral and ground of the builtin outlets are connected via the old builtin wiring, tracable in the upper photo. BTW also note that the main power line coming into the unit goes through a resettable circuit breaker (visible in top right of 2nd photo above) - I kept this intact for safety's sake.
Parallel port connector.
Note the bottom left, there's a 7.5VDC wallwart power supply that I had available - it's wired directly into an LM7805 to provide 5VDC for the relay board with no heat sink, just free hanging and protected with tape. The remaining connections are just passthrough from the ribbon connector (inputs), or passthrough to the relay board connector (outputs).
Final version, redone with RPi. No more DB-25 cable. RPi uses WiFi for connectivity, but if necessary, an RJ-45 ethernet cable could be run out the ribbon cable hole. This RPi is an older Canakit 3B+ that I was given by a friend; it's hidden underneath the ribbon cable junction. Relay board is just visible under that.

ssh in, then su
apt-get install xterm
apt-get install x11-apps (for xload)
apt-get install ftp (ftp client is not installed by default)
apt-get install tcsh (my preferred shell)
apt-get install emacs (my preferred editor)
vipw update my usernumber, make sure group is staff (50 on raspbian)
cd /home/[me]
chown [me] . update to new usernumber
chgrp staff .
Now back as [me], mkdir bin
ftp [home domain]. Download the usual login files like .cshrc and .profile, and get the bin directory.
Log all the way out, login, make sure your basic world is now there.
gosub below 20220228 to install RPi::Pin.

Got the system all set up and working. Will document later. Right now I'm setting up a new RPi so will doc here.

Obviously plug in screen, mouse, keyboard.
Power up.
Choose "noobs".
Wade through install.
Give it WiFi info, let it update.
Go into preferences->Raspberry Pi Configuration, click Interfaces tab, and enable SSH and I2C.
Start a command line.
sudo passwd root
Change root password to something you can deal with.
edit /etc/dhcpcd.conf
Comment in the sample static block and fix with your addr.
If you're using WiFi, don't forget to change to "wlan0" from "eth0".
Edit /etc/hostname and change to your full hostname and domain
adduser and create your personal account
shutdown -r now
Start a command line, enter ifconfig -a to confirm
Check for ssh from outside world. From here on out you can do everything via ssh and xterm, no more need for kbd/mse/mon on the pi itself.

Finally got my Geeekpi 4 channel relay board (here shown at RobotShop). (Been waiting since last Nov/Dec!).

I had assumed this would simply trigger off a set of output pins, but no, it uses the I2C bus.

[Note! See 22020319 above to do the following from command line.]
This requires additional setup at the console screen using the default UI. I have been running headless for months, so I had to dig up the micro-dmi/dmi adapter, borrow a screen/mouse/keyboard from another computer, just to go in and enable this. (I'm sure there's a way to do it from the commandline, but this was easier than trying to figure it out.) See the following website: wiki.52pi.com EP-0099. In a nutshell, on the main screen Raspi desktop, take Settings->Preferences->Interfaces. Find the I2C interface option, hit Enable. It'll say "do you wanna turn on Arm I2C?", take yes.

From this website, you'll find how to check for success: Seeed 4 ch relay RPi Hat.
In a nutshell: use the following to verify success:
i2cdetect -y -r 1
You'll get a screen with a grid that shows all your I2C devices, you'll only see the one relay board you have installed, the rest will be "--". This number is the offset your board is set at, mine defaults to 0x10 with no jumpers. Above EP-0099 doc explains how to change this.

I then proceeded to try the other python libraries and test programs on the Seeed page, but was unable to get any to work. (Yes, I changed the hard-coded relay address in the code to match mine, but no relay activity.)

Next I tried the latter steps on the EP-0099 page, and was able to make the relays trip.
In short (from superuser):
i2cset -y 0x10 0x01 0xff turn on rly 1
i2cset -y 0x10 0x01 0x00 turn off rly 1
i2cset -y 0x10 0x02 0xff turn on rly 2
etc. So now I know the hardware works, and I'm done with the remote scrn/kbd/mouse and can go back to ssh/x-windows.

Note that in the end, I decided not to change over to this board for the project. I already had the existing relay board in place and had the mains connections wired into the box, and the software was already able to control it. It wasn't worth the effort to mechanically remount and rewire the new board, and I'd have to get the software working doing I2C. I'll get to that someday, and use this board for some other future project.

A few notes on software...
FYI: My next step was to try to get RPi::WiringPi to work. Am having problems installing. Now trying:
Giving up for now as I can do what I need right now with just the RPi::Pin module.

A few notes on software...
In order to handle txt msgs, I use http://www.plivo.com/. I had to struggle to get the Plivo incoming interface to work as doocumented, as they don't have a published Perl interface. Eventually I got it to work by ignoring their documentation (which is incorrect), and instead by looking carefully at the Python API that they do provide. I'm giving you this code fragment so as to save you the hassle of figuring it out yourself: plivointerface.pl. I've also included the outgoing code as well.
The following list of libraries I used to build my server should also help you:
use strict;

use HTTP::Daemon;
use HTTP::Status;
use HTML::Entities;

use Net::Domain;
use HTTP::Date;
use HTTP::Request;
use LWP;
use JSON;
use Net::SMTP;
use URI::Escape;
use URI::Encode qw(uri_encode uri_decode);
use Digest::SHA qw(hmac_sha256);
use MIME::Base64;
use Date::Parse;
use Sys::HostAddr;

use Errno qw(EAGAIN EIO);
use Socket;
use Net::Ping;
use IO::Socket;

One of those minor annoyances is that on the RPi board, they don't mark pin 1 of the GPIO connector! DUH! Doing a quick google search shows that pin 1 is the corner of the connector closest to the SD card end - the end that's away from the ethernet and USB connectors (see SparkFun GPIO diagram). BTW: I strongly recommend getting an RPi starters/experimenters kit like the "Adeept Ultimate Starter" for $49. At least get the "GPIO extender/header expander" and a breadboard as shown in the photo.

(click on image for full-size image)

MetaCpan RPI::Pin documentation.

Click here for my gpiotest.pl simple demo program.

This demonstrates toggling an output (blue LED and you can hear relay clicking), polling style read, and interupt on input change. These actions are independent - the button push is only displayed on the computer screen, the relay and blue led are simply toggling at 1 second interval. Red LED simply indicates power connected.

Here's a 21 sec video showing program in action. Notice the keybounce the second time I release the button - two entries into the interupt handler. This is something that you'll have to be able to handle in your code as this can easily happen in the real world.

So there's the basics of the input/output control functions, now it's up to you to write the code to do what you want!

I found the following instructions, and have been able to get through them successfully. The test program reports "pin 4 mode 0 state 1" over and over again when run, which I guess is what's supposed to happen until I get into the GPIO port and start connecting things up...

(Directions to get Perl access to GPIO found here: https://forums.raspberrypi.com/viewtopic.php?t=147514)
as root:
cd ~
mkdir bcm2835
cd bcm2835
wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.59.tar.gz
tar xvfz bcm2835-1.59.tar.gz
cd bcm2835-1.59/
make install

apt-get install wiringpi

cpan -i Device::BCM2835
cpan -i WiringPi::API
cpan -i RPi::Pin

And sample code as follows:
use RPi::Pin;
use RPi::Const qw(:all);
my $pin = RPi::Pin->new(4);
$pin->set_interrupt(EDGE_RISING, "main::pin4_interrupt_handler");
while (1) {
     my $num = $pin->num;
     my $mode = $pin->mode;
     my $state = $pin->read;
     print "pin number $num is in mode $mode with state $state\n";

sub pin4_interrupt_handler {
     print "in interrupt handler\n";

Get RPi running. I used NOOBS (Linux). See LED Array program for info on this (and why I used noobs instead of FreeBSD, which I'd prefer). You may also get some hints from my various FreeBSD howto pages.

At this point you no longer need the scrn/kbd/mouse, everything can be done via command line ssh and x-windows with putty on your PC.

NOTE! If you're using an external relay board, see above 20220308 notes.

Copyright © 1995-2023 Mike Lempriere (running on host pedicel)