Skip to content
View Categories

Arduino Library for Input duinoNodes

3 min read

DNIN8 and DNIN8K boards are 8-bit parallel in, serial out shift register device. However, the Arduino shiftin() library function is not compatible with shift register used by this board. You need the duinoNodes Library to use these devices.

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/inputNodesDemo/ and load inputNodesDemo.ino. Attach some buttons and switches to the ports and use the Serial Monitor to see responses to inputs.

Basic Usage #

To use the library, explicitly include it at the top of your main sketch:

#include <duinoNodes.h>

The default value of NUM_INPUT_NODES is 1; override by defining it before including the header file.

#define NUM_INPUT_NODES 2 
#include <duinoNodes.h>

After including the header, define a global variable that will point to the input nodes:

inputNodes *inputs;

In setup(), initialize the input duinoNodes with this way:

inputs = new inputNodes(NUM_INPUT_NODES, INPUT_CLOCK, INPUT_LATCH, INPUT_DATA);

This will instantiate the inputNodes object using the default CLOCK, LATCH and DATA pins — D5, D7 and D8 respectively. To change the defaults define INPUT_CLOCK, INPUT_LATCH and INPUT_DATA with different pin values before including the library header, like this:

#define INPUT_CLOCK A1
#define INPUT_LATCH A2
#define INPUT_DATA 6
#define NUM_INPUT_NODES 2
#include "duinoNodes.h"
inputNodes *inputs;  

Retrieving and Interpreting Inputs #

In loop() of you main sketch, call the inputs->poll() method to read the inputs. Poll() reads the current state of the inputs by retrieving one byte from each DNIN8 board. Each bit represents the state of one of the 8 input ports. If a port is HIGH — current is flowing into the port because of a button press, switch position or digital sensor device — the bit for the port will be set to 1; otherwise the bit is 0.

inputs->poll() returns true if the state of any input port has changed, otherwise it returns false indicating no changes were detected allowing you to selectively decide when to examine individual port states.

It is advisable to call inputs->poll() fairly frequently in order to respond to input changes accurately. I suggest at least 10 reads per second, or every 100 milliseconds.

To determine whether buttons/switches/sensors have been triggered, examine the bits stored in inputNodes to determine which inputs are on and off:

if(inputs->poll()){
   // if poll() returns true, find out which inputs are on
   // traverse the nodes
   for (int n=0; n < inputs->numNodes(); n++) {
     // traverse the ports on each node
     for(int i = 0; i < 8; i++){ 
     // Most of the time you only want to act if an input has changed
       if(inputs->isChanged(n, i)) {
         Serial.print("nnInput " + String(i) + " on NODE " + String(n) + " changed state. It is now ");
         if (inputs->nodeGetPin(n, i) == 1){
           Serial.println("ON.n");
         } else {
           Serial.println("OFF.n");
         }
       }
     }
     for(int i = 0; i < 8; i++){
       // You can also examine every input
         if (inputs->nodeGetPin(n, i) == 1){
           //port is active, do something
           Serial.println("Input " + String(i) + " on NODE " + String(n) + " is on");
         } else {
           //port is inactive, do something
           Serial.println("Input " + String(i) + " on NODE " + String(n) + " is off");
         }
       }
     }
   }

Input “Bounce” #

By design the board is resistant to input “bounce” because the shift register monitors the parallel inputs continuously (asynchronously with respect to the microcontroller), rejects low voltage signals and renders the data in a 2 step process triggered by inputs->poll(). When the latch is pulsed, the parallel inputs are momentarily frozen and stored, and a byte whose bits represent the state of each port can then be transferred serially.

The polling interval is another factor to consider. I find that 100 microseconds (polling 10 times per second) picks up even brief button presses without making the system sensitive to spurious signals.

The easiest way to set up interval polling is to wrap your call to inputs->poll() in a millisecond timer, as shown here:

  static unsigned long lastRead;
  unsigned long curMillis;
  curMillis = millis();
  if(curMillis - lastRead >= 100){
    lastRead = curMillis;
    if(inputs->poll()){
      ... read inputs ...
    }
  }

You can experiment with the interval to see what works best for you.

You still have to contend with things like multiple, or contradictory, button presses. You can overcome user errors with internal rules. For example if a turnout is already in motion when a control button is pressed, it has to be allowed to complete the current motion cycle before triggering a new one. The best strategy is to code your “action” objects (turnouts, for example) in a way that controls those kinds of problems, rejecting any control messages that are contextually inappropriate.

UPDATED: 1/18/23

Powered by BetterDocs