Does Loss of Client Reset the Counters?

Hello Arduino world. I have one heck of a bizarre problem.

I am using LabVIEW to TCP to my Arduino. All of this was working at one point. Now, it’s doing something absolutely bizarre. My arduino program is basically just watching digital reads and keeping track of time while cycling digital outputs based on the states. I am using micros() to keep track of time. My issue: the first state is on and the Arduino counts. My LabVIEW program can read and interpret how many seconds has taken place and what number the cycle is on. After the first ON cycle…it goes into stupid mode. For starters it randomly resets the second counter which apparently also resets the triggers. But the real big issue is that every time I reconnect my LabVIEW (thus saying yes I have a client) the triggers all reset! My question, does the client.connected reset the micros()?

#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>

// Network configuration.  gateway and subnet are optional.

// The media access control (ethernet hardware) address for the shield:
byte mac[] = { 
  Insert Your Own Mac };  
// The IP address for the shield:
byte ip[] = { 
  Insert Your Own IP };    
// The router's gateway address:


unsigned int cycle[6];
unsigned long trigger[6];

byte EE_cycle_MSB[6];
byte EE_cycle_LSB[6];

byte LEDS = 0;

boolean laststate[] = { 
  false, false, false, false, false, false };

// port 6340
EthernetServer server(6340);

void setup()  {

  Serial.begin(9600);

  // Read the EEPROM and interpret for all the plates and their corresponding cycles
  for (int i = 0; i <= 5; i++) {
    EE_cycle_LSB[i] = EE_cycle_LSB[i] | EEPROM.read(i*2);
    EE_cycle_MSB[i] = EE_cycle_MSB[i] | EEPROM.read((i*2)+1);
    cycle[i] = ((unsigned int)EE_cycle_MSB[i] << 8) | (unsigned int)EE_cycle_LSB[i];
    Serial.println(cycle[i]);
  }

  // Initialize the ethernet device
  Ethernet.begin(mac, ip);

  // Start listening for clients
  server.begin();
  Serial.print("Server is at ");
  Serial.println(Ethernet.localIP());

  // Initialize the digital Outputs, meant to trigger the relays
  for (int i = 3; i <= 8; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
  }

  // Initialize the digital inputs
  for (int i = 22; i <= 27; i++) {
    pinMode(i, INPUT);
  }

  // Start all the timers for each of the six individual plates
  for (int i = 0; i <= 5; i++) {
    trigger[i] = micros();
  }
}

void loop() {
  delay(10);
  // For all six plates (containing 8 valves)
  for (int i = 0; i <= 5; i++) {
    // Check to see if it has run for 50k cycles yet
    if (cycle[i] >= 50000) {
      // If so, turn the relay operator off...forever
      digitalWrite(8-i, LOW);
      delay(10);
    }
    else {
      // Check what the last state was, (On/Off?)
      if (!digitalRead(22+i)) { // Was last state Off?
        // Check to make sure the relay is in conjunction with the Last State
        if (!laststate[i]) {  // Should read Lo
          // If previous are true, then count for 90 seconds while the relay is On
          if (micros() - trigger[i] >= 90000000) {
            // After counting for 90 seconds, turn the relay off, reset the counter, and change the state
            trigger[i] = micros();
            digitalWrite((8-i), LOW);
            laststate[i] = true;
          }
        }
        // A relay is not in conjunction with the states and will display 0 until fixed
        else {
          trigger[i] = micros();
          delay(1);
        }
      }
      // Check what the last state was, (On/Off?)
      else if (digitalRead(22+i)) {  // Should Read Hi
        // Check to make sure the relay is in conjunction with the Last State
        if (laststate[i]) {  // Was last state on?
          // If previous are true, then count for 120 seconds while the relay is Off
          if (micros() - trigger[i] >= 120000000) {
            // After 120 seconds, turn the relay back on, 
            // add to the cyle counter (because one complete cycle has taken place), 
            // store the value in the EEPROM while also resetting the counter
            // and change the state
            trigger[i] = micros();
            digitalWrite((8-i), HIGH);
            cycle[i]++;
            EE_cycle_LSB[i] = cycle[i] & 0xFF;
            EEPROM.write((i*2), EE_cycle_LSB[i]);
            EE_cycle_MSB[i] = (cycle[i] >> 8) & 0xFF;
            EEPROM.write(((i*2)+1), EE_cycle_MSB[i]);
            laststate[i] = false;
          }
        }
        // A relay is no in conjunction with the states and will display 0 until fixed
        else {
          trigger[i] = micros();
          delay(1);
        }
      }
    }
  }
  byte seconds[6];
  // Calculate where the timers are in seconds
  for (int i = 0; i <= 5; i++) {
    seconds[i] = (micros() - trigger[i])/1000000;
    Serial.println(seconds[i]);
  }
  // Check for a TCP client
  EthernetClient client = server.available();
  // Do only if there is a client
  if (client) {
    byte empty = 0;  // Strictly meant for LabView .exe
    // Debug
    //Serial.print("You have a client (");
    //Serial.println(")");
    // LEDs meant for LED display on .exe client
    // The digital reads check whether or not current is flowing through valves
    if (client.connected()) {
      if (!digitalRead(22)) {
        LEDS = LEDS | 0x20;
        //Serial.println("DR 22");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xDF;
      }
      if (!digitalRead(23)) {
        LEDS = LEDS | 0x10;
        //Serial.println("DR 23");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xEF;
      }
      if (!digitalRead(24)) {
        LEDS = LEDS | 0x08;
        //Serial.println("DR 24");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xF7;
      }
      if (!digitalRead(25)) {
        LEDS = LEDS | 0x04;
        //Serial.println("DR 25");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xFB;
      }
      if (!digitalRead(26)) {
        LEDS = LEDS | 0x02;
        //Serial.println("DR 26");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xFD;
      }
      if (!digitalRead(27)) {
        LEDS = LEDS | 0x01;
        //Serial.println("DR 27");
        //Serial.println(LEDS);
      }
      else {
        LEDS = LEDS & 0xFE;
      }
      // Send the following data to the client
      for (int i = 0; i <= 5; i++) {
        server.write(EE_cycle_MSB[i]);
        server.write(EE_cycle_LSB[i]);
        server.write(empty);
        server.write(seconds[i]);
      }
      server.write(LEDS);
      delay(10);
    }
    // Debug
    Serial.println("You lost your client");
    client.stop();
  }
  delay(1);
}

If the Arduino is connected to USB it will reset when the host computer opens the serial port connection, unless you have modified the hardware to inhibit the reset. You can see this using the serial port monitor - every time you open the monitor window, the Arduino will reset.

TCP is not Serial. (Least I don't believe it is) If it were doing a Hard Reset like it does when you Open the Com port, I should expect all values to reset as well as the state. This is not the case. The only thing resetting are my triggers apparently. My code only resets the triggers if the state does not match the digital read or it completes the task. So I'm wondering then...is there something in the ethernet libraries that resets the micro counter or kills the digital pins?

Oh, Labview isn't connecting via the serial port? Sorry, I had misunderstood.

I haven't looked into your code in detail but you seem to be using micros() to derive a number of seconds. That's not a good idea because the value of micros() will wrap after quite a short time (I think it's around thirty seconds). If all you want is a seconds counter then just use millis()/1000 instead. The value of millis() will wrap too, but only after about 50 days, and if you code your time comparisons correctly using subtraction and unsigned longs as you have don so far then it will work correctly when millis() wraps.

I see you have code in a loop that writes to EEPROM. Presumably you have noticed that the EEPROM has a limited write life so I suggest you make absolutely certain your logic to control those writes is bulletproof before you let it actually do the writes. It would only take a few seconds to use up the working life of your EEPROM if your code is faulty.

PeterH: Oh, Labview isn't connecting via the serial port?

It's TCP connection with LabVIEW. So it's communicating over the network.

PeterH: I haven't looked into your code in detail but you seem to be using micros() to derive a number of seconds. That's not a good idea because the value of micros() will wrap after quite a short time (I think it's around thirty seconds).

Per Arduino Reference: "This number will overflow (go back to zero), after approximately 70 minutes."

PeterH: I see you have code in a loop that writes to EEPROM. Presumably you have noticed that the EEPROM has a limited write life so I suggest you make absolutely certain your logic to control those writes is bulletproof before you let it actually do the writes. It would only take a few seconds to use up the working life of your EEPROM if your code is faulty.

My code writes to EEPROM once every 210 seconds. With that, EEPROM life span prob die in something like 3 years?

I think I found the problem. The code is made to reset the trigger values if the digital reads are wrong. The problem however, even with the pull down resistors, they still appear to be floating and will occasionally show a high thus causing the triggers to reset. I just went ahead and commented those out. Still doesn't quite explain why every time I reconnected with LabVIEW the timer would reset. My guess is something to do with the Libraries for Ethernet and the pins I'm using. Oh well. The world may never know.