Slow Digital Read

Hello guys,

I'm using Arduino UNO with an ethernet shield to read relay values. I'm using the internal pull up resistors and passing ground from the board to the relay contacts to read the returns.

This seems to be very unstable and reliable and has a latency of about 2 seconds. I thought initially that the delay was added when reading the TCP packets but I was able to verify through serial monitor that this is not the case.

My code is very simple and my ethernet shield is Arduino certified (no knock off hardware used):

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

#define DEBUG_MODE 1

static const int pin_S0 = 2;
static const int pin_S1 = 3;
static const int pin_S2 = 4;
static const int pin_S3 = 5;

// Set values below to match your network needs:
byte MAC[] = {0x90, 0xA2, 0xDA, 0x00, 0xD7, 0xFC};   // MAC Address
byte IP[] = {192, 168, 1, 17};                       // Network Address
byte gateway[] = {192, 168, 1, 1};                   // Gateway Address
byte subnet[] = {255, 255, 255, 0};                  // Subnet Mask
EthernetServer server(80);                           // Set Server Port
EthernetClient client;                               // Define client
const int MAX_LEN = 10;                              // Maximum length of a command

static int c = 0;

char command[MAX_LEN];
char response[MAX_LEN];
char state[4];

void setup()
{ 
  #ifdef DEBUG_MODE
  Serial.begin(9600);
  #endif
  
  Ethernet.begin(MAC, IP, gateway, subnet);          
  server.begin();                                   
  
  //Set up input pins as active low using internal pullup
  pinMode(pin_S0,INPUT_PULLUP);
  pinMode(pin_S1,INPUT_PULLUP);
  pinMode(pin_S2,INPUT_PULLUP);
  pinMode(pin_S3,INPUT_PULLUP);                                                
}                                                   

void loop()
{                  
  char inByte;                  

  client = server.available(); 
  if(client){
    inByte = client.read();    
    switch (inByte)             
    {
    case 13:                    //CR: process the command
      command[c] = 0;           //Make the current position a terminating null byte
      receiveTCP(command);	    //Process the command
      c = 0;                    //Reset counter for next time
      break;                    
    case 10:			              //LF
      break;                    
    default:                    
      if (c < (MAX_LEN - 1)){
        command[c] = inByte;    
        c++;                   
      }
      break;
    }                           
  }                             
}                               

void receiveTCP(char* command)
{
  int relay = command[2] - '0';
  char response[4] = "[0]";

  //Read inputs and invert 
  state[0] = !digitalRead(pin_S0);
  state[1] = !digitalRead(pin_S1);
  state[2] = !digitalRead(pin_S2);
  state[3] = !digitalRead(pin_S3);

  if(command[1] != 'S' || relay >= 4)
  {
    #ifdef DEBUG_MODE
    Serial.println(response);
    #endif   
    return;    
  }

  response[1] = (state[relay] == 0) ? 48 : 49;
  
  #ifdef DEBUG_MODE
  Serial.println(response);
  #endif

  client.println(response);
}

Any thoughts on what could be the cause of this? Could it be that the internal pull up resistors are not reliable?

Cheers!

Schematic please!

Internal pull-up resistors are reliable.

How long are the wires between the relay and the Arduino?

I don't see your code checking client.available() before using client.read(). Perhaps the latency is caused by a timeout waiting to read a character from the client?

Try adding client.setTimeout(1) in setup() and later try client.setTimeout(5000). Does this affect the latency problem?

Sure, here is a doodle of my connections. I'm passing Arduino ground to the relay COMs and reading NO on digital pins 2 & 3 (4 & 5 are not physically connected). The relays are on an RF receiver which is bascially a black box to me with relay outputs.

The cable is about 5 feet long but I've verified the same results with short cables.

Hmm. I'll try that and update you!

This won't fix your problem, as you already figured out by testing with short wires. But...

It's probably not wise to rely on the internal pull-up resistors alone with such long wires, they will tend to act as antennas and pick up electrical interference which could result in "false positive" detections. Add stronger external pull-ups (1K~10K).

Add a 0.1uF ceramic cap wired from the input to ground to help to decouple the noise from the input.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.