Now that we have considered what ball valves to connect to what outputs and sensor inputs we can start programming the Arduino TapHat.

Overview of all steps:
1. Preparing Raspberry Pi
2. Testing the TapHat / Pi connection – Arduino side
3. Testing the TapHat / Pi connection – Pi side
4. Connecting your Hardware
5. Configuring your TapHat and valves
6. Tap Control from the Internet
7. Finishing our Python Tap Control program

First we need to create a basic protocol for controlling the valves. We at least have three parameters:

  • a module address
  • a tap number
  • a tap state (On/Off or Open/Closed)We could make our simple protocol something like module:0x10 message:”1=0;”. We don’t send the address over i2c but we send four bytes directly to the selected module using it’s address. Byte 1 is the tap number, 0 will close the tap and 1 will open the tap.

See our “BasicTapControl” example for the Arduino side.

/*
   J.A. Korten
   JKSOFT Educational
   BasicTapControl.ino

   Example: Arduino side i2c communication
   V1.0 July 12, 2017

*/

#include <Wire.h>

int currentTap = 0;
boolean tapMoving = false; // one tap at a time
unsigned long timerStart = 0;
int nextTap = 0;
int nextTapState = 0;
boolean showDebugMsg = false; 

void setup()
{
  initLEDs();                   // See second tab (download our library)

  Wire.begin(0x10);             // Pi will see the TapHat on 0x10
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(115200);         // start serial for output
  delay(3000);
  if (showDebugMsg) Serial.println("TapHat Communication Example");
}

void loop() {
  delay(100);
  heartBeat();
  if (tapMoving) {
    checkTapTimer(currentTap, timerStart);
  } else {
    if (nextTap > 0) {
      // set tap
      setTapInMotion(nextTap, nextTapState);
      nextTap = 0;
    }
  }
}

void receiveEvent(int howMany) {
  char bufferIn[100];
  int index = 0;

  while (Wire.available() > 0) // make sure we still can read...
  {
    char input    = Wire.read();
    //Serial.print(input);
    bufferIn[index] = input;
    index++;

    if (input == ';' || index > 4) {
      if (index == 5) {
        char tapNum    = bufferIn[1];
        char separator = bufferIn[2];
        char tapState  = bufferIn[3];
        char terminal  = bufferIn[4];

        if (separator == ':' && terminal == ';') {

          byte tap    = tapNum - '0'; // convert '0' to 0
          byte state  = tapState - '0'; // convert '0' to 0
          if (state == 0 || state == 1) {
            // at least for now we only allow one tap changing at the time
            // ignoring other tap messages while tapMoving is true
            // we will remember one next tap change only
            if (!tapMoving) {
              setTapInMotion(tap, state);
            } else {
              rememberTap(tap, state);
            }
          }
        }
      }
      Serial.println();
      index = 0;
    }
  }
}

void rememberTap(int tap, int state) {
  nextTap = tap;
  nextTapState = state;
}

void setTapInMotion(int tap, int state) {
  if (showDebugMsg) {
    Serial.print("Setting tap ");
    Serial.print(tap);
    Serial.print(" to state ");
    Serial.println(state);
  }
  setTap(tap, state);
  currentTap = tap;
  timerStart = millis();
  tapMoving = true;
}

In the above example we see how we could make and deal with a protocol to set taps of the TapHat board using a simple but effective protocol. You can find the entire example with the setTap implementation (see “TapControl” Tab) in our library.

The protocol consists of four bytes: “1:1;”. The first byte is the number of the tap we want to set: it can be either tap 1, tap 2 or tap 3. The colon (“:”) separates the tap number with the state. The state is the second number: 0 closes the tap, 1 opens the tap. The final token is a semicolon “;”.

Next step: 6. Tap Control from the Internet