Arduino Library for Output duinoNodes

Output duinoNodes (DNOU1 & DNOU8) are 8-bit serial in, parallel out shift register logic devices. Accordingly, board ports can be turned on or off using the Arduino library function shiftout(). The duinoNodes software library provides an addressing system and additional functionality you may find useful.

The library — duinoNodes-biuvvo.zip — should have been automatically added to your cart when you purchased your duinoNode product, and is now available through your Lew’s Duino Gear account.

Download the file and install it by unzipping it into your Arduino/libraries directory. Navigate to Arduino/libraries/duinoNodes/examples/outputNodesDemo/ and load outputNodesDemo.ino. You can attach LEDs and/or relays to the outputs of your boards to see the sketch demo the use of the board(s).

Basic Usage

To use the library, add #include <duinoNodes.h> at the top of your main sketch:

#include <duinoNodes.h>

You must set the number of nodes in use. To do that, define NUM_OUTPUT_NODES before including the header file. Finally, create a global variable for the “outputNodes” object used to reference the boards; in the demo sketch the variable is called “outputs”:

#define NUM_OUTPUT_NODES 2
#include "duinoNodes.h"
outputNodes *outputs;

In setup(), initialize the duinoNodes with this call:

outputs = new outputNodes(NUM_OUTPUT_NODES, OUTPUT_CLOCK, OUTPUT_LATCH, OUTPUT_DATA);

This will instantiate the outputNodes object using the default CLOCK, LATCH and DATA pins — D2, D3 and D4 respectively. To change the defaults define OUTPUT_CLOCK, OUTPUT_LATCH and OUTPUT_DATA with different pin values before including the library header, like this:

#define OUTPUT_CLOCK A1
#define OUTPUT_LATCH A2
#define OUTPUT_DATA 6
#define NUM_OUTPUT_NODES 2 
#include "duinoNodes.h" 
outputNodes *outputs; 

Addressing and Manipulating Ports

Each port can be addressed by its sequential ID. With one board (Board 0), the available sequential IDs are 0 to 7. Each board you add to the chain adds additional sequential IDs. So, ports on board 1 can be addressed by IDs 8 – 15, ports on board 2 can be address by IDs 16 – 23, and so on.

The Sequential ID can be calculated this way, where the Board Number can be from 0 – 64, and the Port Number ranges from 0 – 7:

Sequential ID = (Board Number x 8) + Port Number

To facilitate using ports in groups, each port can also be referenced by a nodeAddress structure, defined as follows:

typedef struct nodeAddress {
  word node;
  byte pin;
};

Addresses in this form can be grouped into a nodeList, allowing all member nodes to be turned on or off at the same time.

typedef struct nodeList {
  int elements; // number of nodes in the list
  nodeAddress *nodes;
};

Methods

The outputsNodes object offers multiple methods for manipulating the ports. Any individual port can be turned on or off using the nodeWrite() method with the sequential ID of the port:

outputs->nodeWrite(ID, 1); //turns port on
outputs->nodeWrite(ID, 0); //turns port off

Sometimes you want to switch multiple ports in parallel, such as where you have a group of lights you want to go on and off at the same time. To do that, you first create an array of nodeAddress objects. In the following example with two nodes, an array of nodeAddresses includes two random ports from each board.

nodeAddress a_group[4] = {
   {word(0, 0), 0},
   {word(0, 0), 4},
   {word(0, 1), 2},
   {word(0, 1), 3}
  };

Next create a nodeList with the array and the number of addresses in the array:

nodeList list_of_items = {4,  a_group};

There are two methods that can be applied to a nodeList:

outputs->nodesOn(list_of_items); // turns all ports on

outputs->nodesOff(list_of_items); // turns all ports off

Pin states are manipulated and maintained in RAM; pin state data is pushed out to the boards whenever there is a change that needs to be communicated. The foregoing methods all set pin states and automatically refresh the outputs to reflect changes.

Sometimes, you may want to manipulate pin states without refreshing the output ports right away. Use the nodeSetPin() method to do this:

outputs->nodeSetPin(ID, state [0 or 1]);

You can also get the current state of a pin using the nodeGetPin() method which returns the pin state as either true (1) or false (0):

outputs->nodeGetPin(ID);

This makes it easy to flip the state of a port:

 outputs->nodeSetPin(ID,  !outputs->nodeGetPin(ID) ); 

You can get or set the pin byte of a node (board) instead of addressing its individual ports; this eliminates address calculations and results in the maximum possible rate of change of port states. This is also useful where you want to manipulate ports asynchronously relative to refresh calls.

Three helper methods are available:

outputs->nodeGet(node) – returns the pin byte for the node. The state of each port is represented by a bit in the pin byte.
outputs->nodeSet(node, pins) – sets the pins byte of the node. Change the value of "pins" bits to turn ports on or off.

Any time you want to refresh the outputs, call the nodesRefresh() method:

outputs->nodesRefresh() – pushes current pin data out to the nodes and refreshes outputs.