Your CuPID as a PLC: Example Modbus Client with LabJack multifunction DAQ

Step 1: Choose a Modbus Server

Servers abound: other PLCs, touchscreens, temperature controllers, VFDs, DAQs, other Pis; nearly anything on the network these days has modbus functionality built in. It is, for better or worse, the least common denominator in device communication. We wrote a bit about this topic previously.

Here, we’ll demonstrate communication with a LabJack DAQ. They offer very reasonably priced hardware with some great functionality. We’ve used them for many years, built LabVIEW applications for them, and put them to test in industrial data acquisition environments. Bang for buck, you just can’t beat them.

Incredibly, outside of the well-written LJUD driver (which our LabVIEW applications are built on), each of their devices also acts as a modbus server for all available data. All you need is a map of registers and which values they correspond to, which they provide here.

Map out the values

With the modbus register map, all we need to do is decide what we want to read, choose the appropriate registers, read them, and make sure we interpret them properly into meaningful values.

We’ve got a couple LabJacks laying around. For this example, we’ll use our trusty UE9, which has plenty of IO for what we’re doing here. It’s on our LAN here at the shop, and we’ve set it up to take a static IP.

First, we’ll make sure that we’re talking properly to view the Analog Input (AIN) data. We’ll use AIN0-3 (why and where we’re probing is discussed below). Each value comes in as a float, which occupies four bytes. Each modbus register is a two-byte word, so each AIN will require two modbus registers. This means we can read two registers each from registers 1, 3, 5, and 7 for the four analog inputs. Note that the modbus maps provided by LabJack start at 0, but all modbus data layers start at 1. So all values are offset by one.

We pull up our basic modbus TCP viewer page to view devices. As we discussed previously, we use some ajax and wsgi to pass data back and forth between our browser and our server. In this case, the user initiates a request in the webpage by pressing a ‘data refresh’ button, which passes the register, clientIP, and length of the request to the server via ajax. A wsgi script on the server, in the case ‘wsgiactions.wsgi’, is run with the request information. It calls pymodbus to read our data from our LabJack, and happily returns it to our browser, as shown below:

Our basic MBTCP Viewer allows us to verify we're reading what we want, and the device is responding as we like
Our basic MBTCP Viewer allows us to verify we’re reading what we want, and the device is responding as we like

You can watch all of this magic happen using Firebug, which is how we diagnose all of our web behavior. See at the bottom how we log the data object as it comes from our wsgi script, and can examine the object structure and the DOM as we like. You can even execute js/jQuery on the fly. It’s seriously like magic.

Firebug: how we diagnose our client behavior and ajax queries (css too!). It's pretty amazing stuff.
Firebug: how we diagnose our client behavior and ajax queries (css too!). It’s pretty amazing stuff.

So we’re getting values, and they appear to be legitimate. Next, we need to make a decision about how to format them. These are four-byte float values, which need to be converted into something that resembles, you know, a number. We can do this in the web page itself,  or we can process them as we put them into a database that stores current values and datalogs. We’ll show both, just for fun. Inside the browser, we’ll add an option to select formatting. It will force us to build some formatting and byte-switching functions that we should probably have around anyway.

Float, anyone?

Javascript

First, we borrow this beautifully simple piece of code from here. It takes an array of bytes and converts it into a float, given a few other parameters that determine the type of conversion. It’s simple enough to plug and play, but flexible enough to allow conversion of 32 and 64 bit floats and varying endianness. First, we simply take our two 16-bit words and break them into bytes:

var byte2 = somedata.response.values[i] % 256
var byte1 = (somedata.response.values[i] - byte2)/256
var byte4 = somedata.response.values[i+1] % 256
var byte3 = (somedata.response.values[i+1] - byte4)/256
var bytes = [byte1, byte2, byte3, byte4]

Then we feed our bytes into our decoder, and out pop values:

var myfloat = decodeFloat(bytes ,1, 8, 23, -126, 127, false)

We’d also like to truncate the displayed values a little bit to make them easier to read. At best, the UE9 will give us 16-bit resolution over the +/-5V range, which comes out to 0.15mV. This means it’s totally safe to give ourselves 5 digits of precision without losing any information. And, while we’re at it, let’s add a widget to the panel to let us set this on the fly, should we want to fix it. We’ll also add a drop-down to allow selection of our float formatting. We add it in, an d presto: human-readable values! We have connected AIN0 to Vs and AIN1 to GND on the LabJack, so we know where our numbers should be. Everything looks pretty good.

Our basic modbus tcp/ip viewer, with float conversion and adjustable precision. We’ve got Vs on AIN0 and GND on AIN1, so everything looks proper.
Python

In python, our life is easier. Everything we need is built into standard packages, namely the struct package. First, we break the words into bytes as we did previously:

byte2 = somedata.response.values[i] % 256
byte1 = (somedata.response.values[i] - byte2)/256
byte4 = somedata.response.values[i+1] % 256
byte3 = (somedata.response.values[i+1] - byte4)/256

Next, we convert to characters that are string hexadecimal representations of the bytes:

byte1hex = hex(byte1)
byte2hex = hex(byte2)
byte3hex = hex(byte3)
byte4hex = hex(byte4)
hexstring = byte1hex + byte2hex + byte3hex + byte4hex

Finally, we use the struct package to convert a string representation, specifying that we are big-endian (>) and float (f):

import struct
myfloat = struct.unpack('>f',hexstring)

We’ll use this later when we build a general purpose importer for our database values. Easy peasy!

Read and log, please

Now we don’t want to have to keep pressing our data refresh button, so we’re going to set up our Modbus values as inputs for our CuPID. Besides our mouse finger getting tired, we want to datalog, and potentially use these values to trigger external actions, such as outputs, emails, etc.

We define all of the poll and read configuration through database tables, in a database aptly named ‘controldata.db’. A python daemon handles various system maintenance, data hygiene functions, web session management, and most important, our input/output polling and control algorithms. How this works is worth an article in itself, and it’s on the way. For now, suffice it to say that when we create an interface and define IO as below, our CuPID will periodically read and log values to our IO and log databases.

Each time the daemon cycles through and reads IO, it does so by interface. Each type of interface is handled depending on type. For example, 1Wire interfaces have their own routine, as do SPI, I2C, and so on. For the modbus interface type, if the interface is enabled, the ‘modbustcp’ table is searched for those bound to its interface id and processes them as dictated by the table entry.

Defining an interface

Our interfaces are defined in the ‘interfaces’ table, shown here in phpliteadmin:

Our interfaces table as viewed in phpliteadmin.
Our interfaces table as viewed in phpliteadmin.

and here in our interfaces screen:

Interfaces screen as viewed in the CuPID web interface.
Interfaces screen as viewed in the CuPID web interface.

You can see that all the defining parameters are present for our various interfaces. In the case of Modbus TCP/IP, we define the IP here and then individual registers in a separate table, aptly named modbustcp.

The modbustcp table

Each modbustcp table entry  specifies the unique interface ID of the modbus interface (created above), and are hence bound to this interface. In this way, if we change the client ID or basic read parameters, we can do it once in the interface table, rather than in a dozen places. It also enables us to take devices offline in one fell swoop. It has loads of benefits.

In the ‘modbustcp’ table, we specify the read memory locations and size, how to interpret the data, and a number of other options. In light of our work with float conversion above, we add a ‘format’ field, to which we can add our float specification. We add a piece to our IO read handler (see processMBinterface section here), and we’re set. We also add a catch-all ‘options’ field to which we can add any other number of flags and options, in object notation. So, for example, if we want to scale our values and set precision before the values are entered into the database, we can specify:

scale:1, precision:5

Our python control scripts can use a function to parse this into a dictionary and do with it as we see fit. More on this later. Now we just need to add and name our modbustcp entries for our analog input entries. We can do this from our ioedit page:

Adding modbus TCP IO entries for each of our analog inputs.

A little clicky-clicky, and we have four inputs named for the four analog inputs. To get them to show up in our list of inputs, we hit the refresh button. Remember, what shows up in the lists of inputs and outputs are what are actually generated when IO are read by the daemon. Notice that they have values in the right-hand column. Our first analog input (shown below) has a value shown in the bubble. To give them handy names, we edit them in place:

Renaming IO in place gives us handles that help us remember what is attached to what.
Renaming IO in place gives us handles that help us remember what is attached to what.

Now, when we make new  connections, we rename them and they’ll pop up with the names we’ve given them. It’s otherwise quite inconvenient to have to remember what “AIN0” or “MBTCP1_400001_2R” mean. The colloquial names we make are stored in a special table called “ioinfo”, and key an ID to a text name. The IDs are automatically created in such a way as to make them unique, and the labels are stored even after the IO is removed. If you add it back in again, the label will still be there.

See the Data

Now, we want to see the data. First, we verify that it’s being recorded as we wish. We won’t get into the details (we’ll do that elsewhere), but default parameters dictate that each input that is read is logged with the same regularity it’s read. We can specify how much is retained. The default here is 100 points. Either using phpliteadmin or our ‘dataviewer’ page, we can see they indeed exist, and we select them to be viewed using the toggles:

Logs show up with the number of points indicated by the bubbles. We select the logs we wish to view.
Logs show up with the number of points indicated by the bubbles. We select the logs we wish to view.

Now, we pop over to our datalogviewer to see them in plot form. Using the plot controls at left, we select our newly-created short names and refresh the plot. Like magic, they pop up with our names:

Selected datalogs, viewed in our plot window.

Next, on to a practical example!

Reference

The above makes use of the open source libraries available on github here:

Explanation and installation here:

Your CuPID as a PLC: Modbus TCP Client

The PLC Pi as a Communicator

As we discussed in a previous post, one of the most important  functions of a PLC is as a communication swiss army knife. A given control system might have devices that speak half a dozen or more languages on as many interfaces that need to be read and written. If the central control device cannot interface with a device, different hardware must be specified to resolve compatibility. Obviously, the fewer languages your PLC speaks, the fewer options you have when it comes to selecting instrumentation and acquisition hardware.

The Modbus Protocol

One of the most common formats in use in the industry is Modbus, which has been around since 1979. It’s a simple and somewhat archaic protocol, but one that you’ll find everywhere as a least common denominator for inter-device communication. While it’s quite limited in structure, the fact that it is well-defined makes it an easy drop-in format that’s easy to configure.

We won’t get into the nitty gritty of frame and bit by bit message format, but the protocol has the following properties:

  • A Modbus transaction has two participants: a Master (Client) and Slave (Server)
  • Members on a multi-drop Modbus network are identified by a Node number (address), and in the case of Modbus TCP/IP, an IP Address. In the case of TCP/IP, the node number is unnecessary except in unusual cases where the Slave acts as a gateway for multiple devices.
  • Data exist in a Modbus slave in banks of data locations referred to as Registers
  • Data transactions consist of a Function Code, which specifies a read or write transaction, as well as which bank of registers to act on, a specific register number, and any data required to complete the request
  • There is no way to encode metadata, except in adhoc systems. Datamaps must be defined outside of the protocol itself. Most devices will have a map that says “data A is in register X, in format Y”
Registers and Function Codes
Name Registers Datatype Mode Read FC Write FC
Coils 000001-065535 bit RW 1 5
Discrete Inputs 100001-165535 bit R 2 -
Input Registers 300001-065535 bit R 4 -
Holding Registers 400001-165535 bit RW 3 6

The Physical Layer

The above defines the communication format, i.e. where the bytes and bits go. It does not define, however, how that information is physically communicated. Typically, Modbus is employed in serial formats such as RS232, RS485, and over TCP/IP. The first two are what might be considered legacy, in particular RS232, but they are still in widespread usage in industry today. TCP/IP is the go-to format for most networks today, and what new designs are built around, at least as far as Modbus is concerned. In general, where the overhead of the TCP/IP layer is not a killer for transfer efficiency or power considerations, it’s a good way to go, if for no other reason that so many network infrastructures are built on it.

Although it is possible to interface the Pi with devices on RS485 and RS232, using level-shifting transceivers depending on the voltage levels of the host devices, what we will cover here is Modbus TCP/IP, for the fact that it is the most widely used moving forward, and that the standard is so well defined. Plus, we’ve got some great toys laying around that talk it, which make great demos!

How does Pi talk Modbus?

There are many options available for speaking modbus on  a linux box. We’ll demonstrate a Python implementation, for the reasons that it is the default language for Pi projects and because it’s what we write all of our server-side code in here. We use a nice little library called Pymodbus, which is quite easy to use. On top of it, we build in some error-handling and user-friendliness. You can find that here. Thumbing down a bit, you can find the function below, which is the workhorse for our MB TCP/IP reads:

def readMBcodedaddresses(clientIP,address,length=1)

The function takes a server IP, register, and read length, chooses the appropriate function code, and returns the read value(s). Some basic coded error functions are included.

>>> import netfun
>>> netfun.readMBcodedaddresses('192.168.1.202',400001,2)
ReadRegisterResponse (2)
{'message': 'status ok', 'values': [16544, 20890], 'statuscode': 0}
>>>

We’re working on an analogous write routine.

One thing to keep in mind, however, is that each transaction has an overhead involved with establishing the connection. If you are carrying out multiple reads, it’s much more efficient to intelligently group register reads into blocks. We’ve written a young piece of code that will do this for you, given you have a datamap that has the correct structure for it. The main function is datamaptoblockreads, and interprets an sqlite table of reads, groups them into blocks, and parses the data. This ends up saving loads of time for large read operations. We’ll cover this later.

What to do with it?

So we’ve got some server-side python that reads clients on the network. What do we do with it? Well, a few things:

  • Read data from LAN/WAN host devices
  • Log and database it
  • Expose it on a web server
  • Accept and process write requests

We’ll explore the topics above in a miniseries:

Reference

The above makes use of the open source libraries available on github here:

Explanation and installation here:

 

Your CuPID/Pi as a PLC: What does that even mean?

The PLC

What is a PLC? What does it mean to be a PLC? These are interesting and open-ended questions indeed.

The Programmable Logic Controller (PLC) hearkens back to the days of control panels that used relay logic to define the electrical operation of control systems. Powered mechanical relays connected in series or parallel defined ANDs, ORs, and more complex logic was built on top of these basic elements. With the advent of cheap and accessible microcontrollers, hardwired logic was replaced with as many ones and zeroes, and power-handling was passed on to relays or transistors. Operational logic became more compact, inexpensive, and best of all, reconfigurable with a program change to the chip. The programming language typically used to this day for your average PLC reflects that they are, in fact, replacements for relay control logic. They use what is referred to as ‘ladder logic’, a series of virtual contacts and coils that if printed out and wired as it appears, would be a functional circuit. A bizarre abstraction for those of that grew up writing linear code, but an interesting one nonetheless.

These days, the PLC does so much more. Often, the most important function a PLC performs is as an air traffic controller of sorts. A content and data aggregator. In many or most control and/or monitoring systems, you’ve got a handful of devices that speak many different languages. They need to be read and written, and by something that knows how to talk to them. You have the interface transmission protocols and physical layer, such as RS-232, RS-485, RS-422, I2C, SPI, and communication formats such as MODBUS (which has three variants in itself), CAN, and many other standard and proprietary formats. The point is that the PLC talks to all the things, processes the data, and decides what to do about it. These days, most have some web functionality built in, and can operate as a data server on several different interfaces. With the addition of these higher-level functions, along with more memory, tags, and advanced data structures, they have in recent years also been called Programmable Automation Controllers (PACs). The lines are blurred, for sure, and the names are not really important.

Two other key features of a PLC – or a device that functions as one – are speed and reliability. Ideally, it should be as reliable and fast as the hardwired relay logic it replaces. How close depends on the application, of course, but at a minimum the speed should be consistent over time. This is what makes PLCs suitable for mission-critical processes and those that have safety considerations – they are bulletproof. Compare this to your average PC, which is susceptible to malicious attacks, corrupted operating system data and files, and insists upon updating itself daily, and it’s pretty clear why you would choose a PLC. It’s bad enough when you walk by a display monitor in a retail store and see a blue screen of death. Imagine one that risks others’ lives. No bueno.

So … no OS?

Until recently, the above two factors have ruled out anything that runs an operating system. Reliability and consistency just haven’t been possible at a level that makes them even a remote consideration. With the widespread use of linux servers to run the world, however, it may be time to reconsider. Even Windows Embedded is in widespread use in things like touchscreen HMIs.

So why use an operating system? On top of what a PLC does, an OS can do so much more. Established libraries and coding tools that greatly simplify putting control strategies into action are available. Databasing, email, advanced web services, and many many other facilities extend the controller far beyond your typical PLC. Hardware options and communications protocols are effectively limitless, another improvement over existing PLC platforms. Memory is no longer a consideration, which is a huge bonus. Even typical advanced PLCs work with as little as 256kb! With orders of magnitude more memory, trajectory data can be stored without concern, a killer feature for many applications. Data structures are not as strict and offer a higher level of abstraction, including object-oriented programming. All of these advantages justify a hard look at a better piece of hardware running something like Ubuntu for control needs.

Is it good enough?

As should be obvious from the discussion above, whether a control device is good enough is clearly a function of who you ask and which application you’re talking about. For a very simple but mission critical app, for example, you would gladly sacrifice some functionality for reliability. These days, we’d choose something like an ATTiny or ATMega microcontroller (what goes into Arduinos). If you want a rich user experience, databasing, and web/internet functionality, you could go with something like a CuPID, plain-jane Raspberry Pi, Beagle Bone, or other microcomputer. Or homebrew your own using combinations of them.

In any case, our point here is not to decide what is right for everybody, but to really explore what functionality we can bring to the Pi/CuPID to make it the best it can be, and evaluate it from the context of the key performance metrics above:

  • Connectivity, communication, and interfacing
  • Reliability
  • Speed
  • Functionality

We’ll show some neat tricks and applications for Pi/CuPID/microcontrollers, and you may do with it what you like!

Cheers!

See Also

CuPID Controls are Open Source Hardware

Hello there.

We are pleased to announce that CuPID Controls web and control libraries are now available on github under a GPL-compliant Apache 2 license. They’re young, but actively developed and in constant use. They’re what we deploy on our CuPID Controls line of home automation gateways/controllers.

Get the libraries here

Take a look at how the interface and control model works here, along with some screenshots and features

So jump in, see what you like and don’t like, and let us know in the issues. Fork it, add to it, as you please.

Happy coding!

Colin

Raspberry Pi / CuPID WebIO by database: Javascript/jQuery, Apache, & Python

The IoT is coming! The IoT is coming! If you’re anything like me, you hate buzzwords like the Internet of Things (IoT). The concept behind this one, however, is simply hard to deny. EVERYTHING should be networked and controllable by a mobile device, even if only on a local network. It’s inarguably the future. Now, while some will argue there is still a place for developing platform specific applications for things like iOS and Android, we ignore all that and go with 100% HTML5. In the age of media queries, we don’t think there is any reason everything shouldn’t be cross-platform compliant and beautiful everywhere.

Coding for the Raspberry Pi was no exception. People are doing all sorts of crazy stuff, from node.js, websockets, calls to C from php, you name it, just to be able to control the Pi from a web interface. A noble undertaking for sure, and one might argue that desperate times call for desperate measures. One of the core problems is that reading and writing from the GPIO requires access to /dev/mem, which can create all sorts of problems. You don’t want www-data (web apps) to have direct access to this stuff. On other platforms (and with other languages), you can wrap up your script in a way that will allow you access to these features without running as full-blown root, but with debian there is simply no way to do this for python scripts. This is sad, in a way, as RPi.GPIO, the most popular, widely used, and easily to implement API for controlling and reading GPIO, must be run as root … which means no web GPIO. On the other hand, the reason that wsgi and other web functions don’t let you run as root is because it’s dangerous. BAD THINGS CAN HAPPEN.

A way around this that solves many many other control issues at the same time is to use an intermediate database to store commands and data. This brings with it all sorts of bonus features like logging (necessary for things like PID), foreign key constraints, restricting which combinations of conditions can exist at one time, group disable/enable, fail-safe conditions, and all sorts of other goodies. It’s moderated access to very important things on our little Pi. So this is what our model looks like:

software_model_flat
Full MVC for control of IO on the Raspberry Pi, as used in CuPID Controls

We’ll also discuss a stripped down version of this that you can try very quickly to give yourself an interface to your Pi IO, much like WebIOPi. We show the specific files here, and it’s instrumental to get the hang of how these gears turn together.

CuPID MVC Model for IO Control on the Raspberry Pi

 

The idea is pretty simple. Use css to make a pretty web page, jQuery to make interactive elements and to send the data by POST, pick it up in Apache/wsgi in Python, and read/write from/to a database (we use sqlite here). Asynchronously, run a Python script in the background that both updates io with set values from the database and also reads back read values into it. Simple, right? It really is. Here’s a screenshot of what you get with a super-simple example, and take a demo here (yes, that’s running on a Pi)>

Simple rawio web page for Raspberry Pi : all jQuery and Apache no node or websockets.
Simple rawio web page for Raspberry Pi : all jQuery and Apache no node or websockets.

 

We’ll drop some more knowledge in here, but for a quick run-down of the install, check here: http://interfaceinnovations.org/ccbarebonesinstall.html

CuPID Power Output : Control power where you need it

Why

Most control applications require powering things. Refrigerators, heaters, LEDs, thermoelectrics, motors, and solenoids are all examples of things that require power that the Raspberry Pi cannot (or should not) supply.

Now, our philosophy with the CuPID is that it is a lightweight IO board. It’s not loaded with every power output, switch relay, and sensor that you could need. We wanted to keep it small and cheap, so we only added what we thought was really necessary. We may change our mind and isolate the GPIO with mosfets at some point, but the point is still the same: a flexible device that you add IO to as you need it. The other advantage to this approach is that you put power and sensors where you need them, not in the box with the Pi. Run Cat5 wherever you want (and over RF soon enough), and expand wherever you want, leaving your Pi in place. IO are daisy-chainable, so one run of cable can connect multiple devices in the same place!

What

What we’re building here is the basic powered control output. With a Cat5 cable from the CuPID, it can supply AC (wall power), DC (by swapping out the relay), or anything that will operate on 5V or less. It also accepts an auxiliary control voltage, so you can switch pretty much anything you want. It performs the switching with a 2n7000 mosfet, so whatever you’re switching won’t fry your Pi if it fails. It’s got two COM ports on it, so you can daisy chain several of these guys. Here is the EAGLE layout.

EagleCAD layout file of the output board.
EagleCAD layout file of the output board.

First, let’s start with the input. We’ll go ahead and reprint the CuPID IO here. COM2 and COM3 each have four GPIO on them. An internal DIP switch on the output board will allow you to select one of the GPIO to use. Alternatively, if you need to control multiple devices with one GPIO, just make the same DIP selection on each.

CuPID IO listing for RJ45 ports. COM2 and COM3 each have four GPIO. The output unit has an internal DIP selector to choose which to use for control.
CuPID IO listing for RJ45 ports. COM2 and COM3 each have four GPIO. The output unit has an internal DIP selector to choose which to use for control.

The board

Shown are the ingredients. If you’re going to use the 5V on the com cable to do your switching, you will only need one screw terminal. If you are using a SSR as we are here, then the only reason you really need a current-limiting resistor is to diminish the fail if you manage to short the coil. Remember that a CuPID has an isolated 5V on the COM cable, so you won’t worry about frying your Pi.

Ingredients for a CuPID output.
Ingredients for a CuPID output.
  1. IO Board
  2. 2 x 8P8C Jacks
  3. 4 position DIP switch
  4. 2 x 3.5mm pitch screw terminals
  5. 2 x 2.54mm (0.1″) two-position jumpers
  6. Current-limiting resistor (47ohms here)
  7. 2N7000 NPN mosfet
  8. Pull-down resistor (10kohm here)

We’re not ones for glorifying soldering in pictorial fashion, so here’s what you get when you’re all done:

All soldered and ready.
All soldered and ready.

The box

Alright. So now we need to get it into a box. What box you use of course depends on what you need to put into it. For this project, we’re going to use a pretty standard solid-state relay (SSR) to switch AC power. This works for a refrigerator, a heater, anything that you can power with single-phase power. Our relay is rated for 25A, but our cable is only 16awg, so you want to keep it under 13A to be safe. This is in line with most household circuits. Our relay and our board fit quite well into the case we use for the CuPID, so we use one of those. It’s a polycase WC23F, which we’ve raved about before. The top is clear, so we can see the nice little LED on the top of our relay. So we head over to the mill and put a couple holes in this thing and see how our board fits.

Our standard ‘cutting holes in the box’ picture with our handy mill. This is one of the easier jobs.

Even before filing out the cutouts a bit, the fit is pretty good.

 

Even before filing out our ethernet cutouts, the fit is pretty good. The holes in our board allow mounting to the existing panel mounts.
Even before filing out our ethernet cutouts, the fit is pretty good. The holes in our board allow mounting to the existing panel mounts.

Since we’ve got a good fit, now we’ll mount the relay to the bottom of the box. We want to attach this and get our cable entries in place before we mount the board, as it’s a bit of a pain to work around the board and connect to the screw terminals once it’s installed. In the picture below you can see our relay, and following that a multiframe of our cord grip installation process.

Our solid-state relay and attachment hardware, two 6-32 socket cap screws and locknuts.
Our solid-state relay and attachment hardware, two 6-32 socket cap screws and locknuts. If we want DC output, we just have to replace our relay.

For those unfamiliar with cord grips (also cable glands, cable entries, strain relief, and a few more), they are watertight entry points that cinch down on a range of cable sizes. They resist pulling through, so even if you don’t need the weather-resistance, they’re great for keeping everything stationary and exactly where you put it. They’re offered in a variety of sizes and are <$1 for anything but very large sizes. Installation is easy. There are two parts (sometimes with a rubber washer), and you simply need a hole in the surface you are passing through. Check the spec sheet or take a measurement with some calipers of the threads, and put a hole in your surface with a spade bit. All done. The entry holes need not be perfect (and they won’t be with a spade bit and soft plastic), but you should take a quick round file to the edges to at least makes sure that burrs on the surface won’t prevent the flat side of the cord grip from pressing completely against the surface. This will diminish their security and weather resistance. After you have your holes, simple insert them and tighten them up. All done. Here we first drill and countersink two holes from the underside and insert a couple flathead screws, leaving a flush bottom for mounting. After, we slip our power cables through each side. We attach our hot side (we’re using AC here) to the relay contact, connect ground to ground and neutral to neutral with some solderless connectors, and secure the relay with a couple locknuts.

Installation of cord grips for power entry, mounting of the relay to the bottom of the enclosure, and connection of our power wiring.
Installation of cord grips for power entry, mounting of the relay to the bottom of the enclosure, and connection of our power wiring.

All we have left is to install our board and connect our control wiring to the coil of the relay. Piece of cake. We just connect our load high and low to our control board and to the relay, and reinstall our mounting screws. Short 4-40 screws self-tap into the PCB mounts quite nicely, and we’re done!

Our output unit, complete without top. All we need to do is set the DIP switch to our GPIO of choice and we're ready to power whatever we like.
Our output unit, complete without top. All we need to do is set the DIP switch to our GPIO of choice and we’re ready to power whatever we like.

And here is what we like like all-together with our top on. We’ll show you some simple applications with this that we have around the house in just a bit.

Completed powered io, from the top.
Completed powered output, from the top.
Completed powered IO unit, from the side.
Completed powered output, from the side.

 

CuPID Touchscreen II : Make it work, and make it usable

Ok, so we got a CuPID built and a touchscreen installed in Part I. The next step is installing the software to run it, and making some adjustments to make the small screen size usable for human fingers and eyes.

Adafruit’s tutorial is a good place to start. Let’s go to there. We download the five files as instructed, and follow the directions (we do that sometimes, honestly). When we’re done, including adding export FRAMEBUFFER=/dev/fb1 to our ~/.profile configuration file, we can run startx to get our desktop on the touchscreen.

What this gives us is a desktop that, well, works, but isn’t optimized for this tiny little display. Take a look: the background doesn’t fit, the text isn’t suitably sized, and the icons are pretty much a mess.

Startx with no modification. Needs some work.
Startx with no modification. Needs some work.

So we start futzing with the lxde environment. On the Pi, pcmanfm is used to control the desktop, and the configuration for this can be found at ~/.config/pcmanfm/LXDE/pcmanfm.conf. The ~ here means your home directory, which by default (and here) is /home/pi
. Taking a look at the file, we can see all sorts of options, at least a couple of which we want to change. First, we change the desktop image to one that’s the correct size, and also within our git repo at /var/www so we can update it when we like, with, say, version information. This is the wallpaper parameter, and we simply set the path:

wallpaper=/var/www/images/splash.png

We’ve got an image there that’s 320×240, but we can set copy any image we want to the path (say, by a shell or python script) if we change resolution.

We go ahead and scale down the font a bit as well:

desktop_font=Sans 8

This helps a lot:

Resized wallpaper and desktop icons font.
Resized wallpaper and desktop icons font.

The icons are still everywhere (and huge). Let’s reorganize them. We’ll do it manually here, but there are other ways. This method also allows us to do it programmatically if we wish. Now, if we poke around in .config/pcmanfm/LXDE/ , we find a file that defines our desktop icons’ positions. We can see the icons present in ~/Desktop (which is how we created our desktop icons. more on that later). So looking at the file, we see a list of icons, a few of which look like this:

[updatecupidweblibs.desktop]
x=20
y=10

[updateiicontrollibs.desktop]
x=20
y=60

[lxterminal.desktop]
x=20
y=110

[wpa_gui.desktop]
x=20
y=160

We can change their coordinates, and move them around as we see fit. With a little tweaking, we get this:

Lined up icons with text. Only the icons we want.
Lined up icons with text. Only the icons we want.

Not too bad. We could probably just do without the icon text. So we set the icon text size to 0. And, realistically, we probably won’t be using the terminal from the touchscreen, and if we decide we need it we’ll have a mouse and keyboard plugged in, so let’s just move it off the window. We can do that by moving the icons we don’t want out of the range of the visible window. This is nice, too, as we can make the icons visible on a larger screen (when we have a keyboard and mouse present). Or we can copy a particular screen configuration file into place. Here are the final icon settings:

[updatecupidweblibs.desktop]
x=-20
y=0

[updateiicontrollibs.desktop]
x=-20
y=70

[lxterminal.desktop]
x=-200
y=140

[wpa_gui.desktop]
x=-20
y=140

And the result:

Finished screen with text-less icons.
Finished screen with text-less icons.

Now we’ve got a nice, clear screen with clickable update icons. Next, we want to design an interface for what we’re controlling. We’ll drop that down here in juuuust a minute. It will look a little bit like this.

CuPID Touchscreen I : Touchscreen in a box

What are we doing?

We’re taking a CuPID and adding one of the new touchscreen displays offered on Adafruit.com. They’re reasonably priced, have functional resolution (320×240), and can give some basic HMI functionality to a CuPID controller project. The downside is that they occupy both SPI outputs and two GPIO, so you sacrifice a bit of controller functionality. This is obviously not compatible with our SPI board. If you’re doing your IO on only a few GPIO, or using other interfaces like UART, I2C, or 1Wire, this doesn’t present a problem. The only other downside to this display is that it compromises the element-resistance of the case, but if you were concerned you could easily seal this up with some silicone.

Preparing the enclosure

This is the lion’s share of the work. If you don’t have a mill, it’s simply going to be tedious dremel and file work, which we used to do. It never ends up perfect and takes loads of time. As we have mentioned previously, we like the WC line of cases from Polycase. They’re NEMA and IP-rated, until we put holes in them, a clear top so we can see all the goodies, and they’re pretty easy to mill. They are also reasonably priced and can be custom-machined and printed at small quantities without breaking the bank. They also have flanges for mounting, internal panel mounts, and they sell panels for mounting components (although these are pricy).

To mill our outline in the clear top of the case, we CAD up an outline on top of the outline of the case top and print it out at full size. The case, stencil, and screen are all shown here. I’ll get up a download of this at some point so you can try at home.

Our stencil, enclosure, and touchscreen, ready for construction.
Our stencil, enclosure, and touchscreen, ready for construction.

We mount the stencil to the top of the case, and go over our screen outline with a razor. Absolute location is not critical here; the most important thing is that the holes and cutout be accurate relative to one another, so the stencil needs to be flat.

Scoring our outline on the stencil. First, we tape on the stencil to ensure it is flat, then cut out the screen outline using a razor blade. We also use the point to mark the hole locations. Once we've completed this, we can remove the stencil.
Scoring our outline on the stencil. First, we tape on the stencil to ensure it is flat, then cut out the screen outline using a razor blade. We also use the point to mark the hole locations. Once we’ve completed this, we can remove the stencil.

Next, we get to milling. We mount up the board in the vise and get to work. The polycarbonate on the top is pleasantly hard and easy to mill with a nice finish without any work. It doesn’t heat up and melt at all, which can be a problem with plastics. We run over it once with a 3/8″ bit to remove material and then with a 1/32″ to clean up and square the corners. We test the screen and enlarge the cutout slightly to make the fit a bit easier. We’ll need to go back and update our stencil to account for this. We then drill though-holes for the M2.5mm screws. Checking our drill and tap chart, we see that we want a 7/64″, but 1/8″ will be fine. We give her a good soap and dry and prepare for mounting.

Milling out the cutout and mounting holes. First we remove material with a 3/8" bit, and then come back with a 1/32" to clean up the corners and give nice edges.
Milling out the cutout and mounting holes. First we remove material with a 3/8″ bit, and then come back with a 1/32″ to clean up the corners and give nice edges.

Here is the completed top. Pictures are a bit weird since we’re doing clear on white background, but you can see the screen fits nicely. At this stage, the screen is only attached by ribbon cable, so we are careful to support it whenever we’re moving it around.

Completed top and fit with screen.
Completed top and fit with screen. Don’t mind the chips on the screen. It’s just plastic around the shop from milling out the base.

Solder the board

This part is pretty straightforward, and described on Adafruit’s tutorial.  See the part on soldering the male header, but note that the boards seem to be shipping with a shrouded header. Being careful to support the board, solder your headers. The one important point I will mention here is that you need to populate the correct header on the included board. If you are going to mount this directly on your Pi (or CuPID), you don’t need to solder a male header. (you’ll solder the stacking headers provided) If you plan to use a cable, as we are here, make sure to only populate the header on the short side of the board. THIS MATTERS. These are reversed, so if you mount the box header to the wrong pins and connect your ribbon cable, you’re gonna have a bad time. Taking a look at the RPi IO, you’ll notice that connecting it backward will put all sorts of incorrect voltage level logic into play and will do all sorts of very bad things. We mention this because, being lazy and apt to not read directions, we mounted our box header in the incorrect position at first, and when we went to double-check our connections discovered we were all kinds of reversed. Luckily we’re paranoid and did this prior to powering up the unit, so no harm and no foul. We’ve got all sorts of headers laying around, so we just did up some plain double-row headers and moved on.

If you're going to use a ribbon cable, make sure you use the header on the short side. If you don't, you'll be sorry. They're reversed!
If you’re going to use a ribbon cable, make sure you use the header on the short side. If you don’t, you’ll be sorry. They’re reversed!

Mount the Screen

Alright, so now we just need to put it together. Our goal was to get the screen almost flush, but just barely recessed, by a mm or so. This took some futzing with hardware, and we ended up with the following approach. It’s obviously specific to this case panel thickness. We use steel screws and nylon spacers and nuts. The nylon gives us a bit of compression when we tighten, and we know the nylon will give before anything we care about. In other words, if we get too aggressive with the tightening, the nylon threads will strip before we crack a board or the case. We have a steel 8mm M2.5 screw, washers on either side of the case, and a nut between the case and the touchscreen board. Any nut will do on the other side of the PCB; we’ve got a nylon nut.

Case top with hardware on front and back. Steel M2.5 8mm screws, washers on either side, with a nut on the underside.
Case top with hardware on front and back. Steel M2.5 8mm screws, nylon washers on either side, with nylon nuts on the underside to give the correct height for the enclosure top.

Next we mount the touchscreen. Before we do so, we attach some more cushy double-sided tape to the board underneath the screen, on both sides of the ribbon cable to give it full support.

Touchscreen board with tape on either side of the ribbon cable for attachment and support.
Touchscreen board with tape on either side of the ribbon cable for attachment and support.

Now we line up the screen board on the screws and put nuts on the underside. After it’s in the opening, we need to attach it to the board, as it is still only connected by the ribbon cable. As such, it’s important to keep it supported to not stress the cable connection.

Attaching the screen. First, pull back and then take adhesive off of tape. Using the backing on the larger side to keep it from sticking, first attach to area behind ribbon, and then pull out from underneath the remainder. Result: attached and aligned touchscreen.
Attaching the screen. First, pull back and then take adhesive off of tape. Using the backing on the larger side to keep it from sticking, first attach to area behind ribbon, and then pull out from underneath the remainder. Result: attached and aligned touchscreen.

The end result is a nicely aligned and slightly recessed screen.

The end result: a slightly recessed screen, firmly attached.
The end result: a slightly recessed screen, firmly attached.

The last step: hook it up and put it in a box.

Hook it up

The last step is to hook it up. Here we show connections to a CuPID base unit using the ribbon cable connector. Ignore the box header you see in the photos that we connected to the header designed to stack directly on the Pi, and watch the connection to the side header.

Attaching the screen to the CuPID. Side header, ribbon cable, pretty basic.
Attaching the screen to the CuPID. Side header, ribbon cable, pretty basic. If you’re paranoid, take a look at the traces on the touchscreen board to make sure you have the proper orientation relative to the Pi connections.

Screw in the case, and we’re all done. We’ll fire up some software and show you what this can do in a bit.

Touch screen CuPID. All done.
Touch screen CuPID. All done.

Making of a CuPID : Raspberry Pi, better.

What are we doing?

We’re making a CuPID control unit. A networked monitor, controller, and otherwise omnipotent member of our new IoT. You can read a blog post about it here or here, check out the details here, and some of the software and other hardware.

The parts

Here’s what we need to make our CuPID, numbered in the picture as below. Not pictured are power supply filter capacitor(s), which are typically installed as here.

All the parts necessary for a CuPID board
All the parts necessary for a CuPID board
  1. CuPID control board PCB
  2. Shielded RJ45 jack (3)
  3. DS2483 i2C 1Wire chip
  4. Surface mount fuse and fuse holder
  5. Through-hole PCB Mount Female USB A (2)
  6. SMT USB Micro
  7. 2-pin 3.5mm pitch male/female pair (2)
  8. Extrashort male USB A connector (2)
  9. Extra-extralong Raspberry Pi 2×13 stacking header
  10. WiFi dongle
  11. Short SD Card holder
  12. For SPI indicator board option : box header

The board

Let’s put this guy together. First, we put on the surface mount components and do a short reflow. The DS2483 and USB micro ports are pretty small.

Board with SMD parts. They are, well, not too big. We could probably hand-solder, but it wouldn't be fun.
Board with SMD parts. They are, well, not too big. We could probably hand-solder, but it wouldn’t be fun.

We could probably get away with doing them by hand, but we put on some paste and let another Pi run a reflow on them, as we did previously. These SMD USB micros are a pain to get right, but fortunately we didn’t connect the data lines on the board, so you can add on plenty of paste and not worry about having to go one-to-one, as long as we get our high and low power terminals. Before placing them, you’ll want to flip them over and take a quick blade to the short plastic posts on the underside. When we make a board again, we’ll create recesses for these. On the other hand, we may go with USB mini since we can get a through-hole version and it’s a bit more robust. Although USB micro is the ‘standard of the future’ on the roadmap, USB mini is just as easy to find and is rated for more connections.

Next, place the DS2483 on the board, taking care to orient the chip as shown in the figure, using the plus to indicate the proper direction. After placing,  we run a short reflow and go.

We test afterward with our voltmeter to make sure we got it right.

Next, we put on the surface-mount replaceable fuse. We’ve found these get a bit melty if we’re not super-careful on the reflow profile, so we do them by hand. It’s pretty easy with the large pads as long as we tin both sides.

Mounting of the replaceable fuse. Tin the pads, heat the pad to attach the fuse, and spot reflow if you're picky like me or it's not sitting quite right. I find the back of my tweezers helpful here.
Mounting of the replaceable fuse. Tin the pads, heat the pad to attach the fuse, and spot reflow if you’re picky like me or it’s not sitting quite right. I find the back of my tweezers helpful here.

Next we put in all of our through-hole components. I prefer to mount all of them and do some marathon soldering rather than doing them one by one. The shield/mount posts on the USB connectors need to be flattened prior to insertion:

The pins on these ports need straightening before insertion.
The pins on these USB ports need straightening before insertion.

We place our parts and do our soldering:

Through-hole component soldering. First, we mount them, shown top and bottom here. We do a mess of soldering, and we're ready to go.
Through-hole component soldering. First, we mount them, shown top and bottom here. We do a mess of soldering, and we’re ready to go.

Now that the board is done, it’s time to mount it to a Pi.

Marrying the Pi

Now that we’ve prepared our board, let’s get it ready for mounting on the Pi. We need to connect the USB ports and connect the header. First, we take our super-short USB connectors and solder a couple paired wires. We crimp female pins and mount into connectors:

We use these short USB connectors to pull data to the CuPID USB ports, so we can power them directly from our power supply. It also allows one port to be inside the enclosure and one outside.
We use these short USB connectors to pull data to the CuPID USB ports, so we can power them directly from our power supply. It also allows one port to be inside the enclosure and one outside.

Now we mount our superlong header. This is similar to the ones that Adafruit sell … except it’s much longer. In addition to allowing us to mount a board on top of the Pi, it extends far enough to allow us to attach a ribbon connector on top of that! This is great for anything you want to put on top, like a touch-screen. You can see how much bigger it is here:

Our extra-extralong headers, next to those from Adafruit. They're so long, we can mount the CuPID and still have room on top for.. more stuff.
Our extra-extralong headers, next to those from Adafruit. They’re so long, we can mount the CuPID and still have room on top for.. more stuff.

Before we mount it, we throw a couple pieces of thick double-sided tape to the ethernet and to the audio jack to give the board a bit of stick and cushion. We mount the CuPID board, solder our headers, and plug in our USB connectors:

Mounting the board to the Pi. A couple of pieces of thick double-sided tape give some stick and cushion to the combination. We solder the headers and connect our USB cable, and we're done.
Mounting the board to the Pi. A couple of pieces of thick double-sided tape give some stick and cushion to the combination. We solder the headers and connect our USB cable, and we’re done.

Put it in a box

Now that we’ve got the business end of our CuPID complete, let’s put it in a box to protect it. We really like the line of WC cases from Polycase. They’re water-tight (until we put holes in them), durable, and reasonably priced. They have flanges, panel mounts, and optional back panels. They’re fairly easy to mill, and when your design is complete you can have them CNC machine and label them for you, at pretty decent prices even at rather small quantities. Once we absolutely nail down our openings, we’ll definitely go this route. For the moment, we mill them by hand. For prototyping, we CAD up our openings as best we can estimate them, print them in real size, and compare them with the boards, components, and previously iterated enclosures. When we find one we like, we tape it to the enclosure, run a razor blade over the lines to score the plastic, remove the stencil, and then mill out the openings. We take a first pass with a 1/4″ or 3/8″ bit to remove material, and then go back with something small like a 1/32″ mill to reduce the radius on the corners. We sometimes go back with a file to sharpen them up.

Milling out the enclosure cutouts. For prototypes, patterns are transferred from a stencil using a razor blade, and milled out in two steps: material removal and finishing.
Milling out the enclosure cutouts. For prototypes, patterns are transferred from a stencil using a razor blade, and milled out in two steps: material removal and finishing.

After the cutouts are complete, we install standoffs on both the bottom of the board and also on the bottom of the enclosure. On the bottom of the board, we use male/female 2.5mm threaded 6mm long standoffs, which keep the board at a consistent height and solid footing. These are not in the parts list above, as we recently added them. Their installation with a couple nylon nuts are shown below.

Installation of standoffs on the board to keep the board level.
Installation of standoffs on the board to keep the board level.

To keep the boards in position, in particular to reinforce it against pushes on the inputs when cables and/or power is connected, we put some 2.5mm thread, 8mm length standoffs in the bottom of the enclosure. From the backside, we insert a couple brass 2.5mm screws. We countersink them to keep the bottom flush, and if needed, thin layer of silicone will keep this waterproof.

Installation of standoffs in enclosure to hold board in place.
Installation of standoffs in enclosure to hold board in place.

Once we clean out the enclosure, insert our SD Card in our low-profile connector, and plug in our WiFi, we slip it into the cutouts. Almost done.

Mounting of board into enclosure with standoffs.
Mounting of board into enclosure with standoffs.

Let it be seen!

At this point, we have a couple options for indicators. We can go with an indicator board we made specifically to fit in this enclosure, as we reflowed and demonstrated previously. It mounts to the internal panel mounts with standoffs and connects with an 6-conductor IDC and box connector, and has 4RGBs and 4 single-color (R,G,B,Y) LEDs. Best of all, it uses only one SPI port, employing a couple shift registers.

CuPID with indicator panel, including 4RGB and 4 single-color (R,G,B,Y) programmable indicator LEDs, all on a single SPI output.
CuPID with indicator panel, including 4RGB and 4 single-color (R,G,B,Y) programmable indicator LEDs, all on a single SPI output.

Alternatively, we can throw a nice little touchscreen on top. We’re working on that write-up currently, but the result is here:

CuPID with touchscreen. Runs on SPI outputs and two GPIO.
CuPID with touchscreen. Runs on SPI outputs and two GPIO.

Moteino + II = CuPID Remote

We at II have been poking around for some time looking for the best remote IO solution. Well, solutions. There are a lot of different wireless applications. The one we’ll address here is one with the following criteria:

  • Low-power : battery-powered for up to a year, depending on sampling frequency
  • Small form factor
  • Low cost
  • Flexibility and capability in IO
  • Preferably open-source

While we don’t want to conclude that our search is over, we’ve for the moment chosen to look at the Moteino line of wireless products. They’re sub-1Ghz, offering a good mix of range/penetration while staying out of the crowded 2.4Ghz range. They offer an on-board ATMega328p, something we’d planned on coupling with the modules from, for example, XBee or Ciseco. While the API isn’t quite as built as XBee in the context of traffic management, their community is active and full of Arduino enthusiasts. The code is open-source, so it’s sure to continually develop. The onboard AVR is Arduino IDE compatible, and best of all, it’s a nicely built board with with what we want without having to do our own board design and SMD soldering. As a bonus, it’s open-source. It’s also competitively priced at about $20 per transceiver/uC combo. And, yeah, the developer cares about his product and gives excellent customer service.

So let’s get on with it. What we want to demonstrate here is a tiny IO unit with an onboard battery or externally with room for a few basic sensors.

We start with our components. A moteino R4 with RFM69W. We also elected to use a perma-proto min tin breadboard. We love these things. Well-made plated breadboards in a tiny package. It will leave us some space to wire sensors and whatnot to the ATMega IO and give us a good physical mount for the RF unit. We can even mount a through-hole mini USB if we want to power it externally. Standard headers, when soldered long side through the protoboard, will still leave enough room to attach female jumpers, which we will use to power it from the battery here.

Moteino and protoplate
Moteino and protoplate

For the enclosure, we use a little weather-proof enclosure by Polycase, the WC20F. This thing is IP65 rated, which means that it’s dust-tight and immune to, you know, waterjets. It’s also attractively priced at about $7 and has flange mounts.

Polycase WC-20F IP65 rated enclosure.
Polycase WC-20F IP65 rated enclosure.

The base of the enclosure will be reserved for the battery, and potentially sensors that we want to slide in there. Because the lid is fairly tall and about the right size (and because we want our RF module at the top), we can mount it inside the lid.

It doesn't quite fit. Pretty close.
It doesn’t quite fit. Pretty close.

We do a tiny bit of dremel work and get it to nicely wedge into the top of the enclosure. The fit result is no fasteners required.

Board fit from top side - no fasteners required.
Board fit from top side – no fasteners required.

After we make it fit, we do the rest of the soldering with our headers and wireless unit. We attach the antenna, and the internal rails nicely line up with our ground and 3.3V lines. You either get the pretty board size up or color-labeled rails on the underside. We chose ugly side up here.

Board after soldering from bottom.
Board after soldering from bottom.
Board after soldering from top.
Board after soldering from top.
Board all done. Super.
Board all done, view from the top, nothing holding it in. Super.

We do a bit of splicing on a 9V battery to put female end and jam it into the bottom of the enclosure. If you’re trying this at home, we did mill off the panel mounts to allow the battery a bit more room.

All ready to close. Long wires, plenty of room.
All ready to close. Long wires, plenty of room.
All done! It's just that easy.
All done! It’s just that easy.

And there you have it. A tiny little enclosure with an RF module for remote monitoring. If you want an external PS or sensor, just throw in some cord grips. We’ll show you this in another post, along with how to jam some sensors in this box and read it.

See here for our install, configuration, and communication of our remote 1Wire temperature sensor.

Reference

The above makes use of the open source libraries available on github here:

Explanation and installation here: