Arduino Ethernet Shield 2 Web-client to control Relay. DigitalWrite Breaks code

Hello,

I have a very strange problem.

Using the JSON Webclient example i can communicate with my Webservice application, i can retrieve the JSON information.

Based on the result of this information i want to set a digital Pin to High.

This is where the code breaks down.

As soon as i call digitalWrite(RELAY_1, HIGH); after executing the Webclient query, the HTTP GET request fails with a HTTP404 error.

I cant understand why this happens, surly executing the digital write after the HTTP GET request would have no implications on the HTTP GET request.

I have re-written my code several times, i have researched and tried to debug this for 2 straight days. i don’t come asking for help without trying myself.

Please see the code snippet below.

Thank you.

#include <ArduinoJson.h>
#include <Ethernet2.h>
#include <SPI.h>

//DEFINE GLOBALS

const char*  _machine_id = "001";   //Unit Machine ID
unsigned long v_update_time = 3000;     //Webservice Polling Time (ms)
unsigned long v_last_update_time = 0;  //Place holder for Last Refresh Time
String v_state;                        // Current Machine State
IPAddress v_WebService(<REDACTED>);  //Webservice IP

#define  RELAY_1 5    //Relay 1 ID RED
#define  RELAY_2 6    //Relay 2 ID ORANGE
#define  RELAY_3 7    //Relay 3 ID GREEN
#define  RELAY_4 8    //Relay 4 ID BLUE
 
EthernetClient client;  //Ethernet client connection

void setup() {
  //Disable the SD Card
  pinMode(4, OUTPUT);  
  digitalWrite(4, HIGH);  
   //Setup the relays
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);
  pinMode(RELAY_3, OUTPUT);
  pinMode(RELAY_4, OUTPUT);
  //Inital Set Relays Low
  digitalWrite(RELAY_1, HIGH);  
  digitalWrite(RELAY_2, HIGH);  
  digitalWrite(RELAY_3, HIGH);  
  digitalWrite(RELAY_4, HIGH);
  //Initialise the serial port
  Serial.begin(9600);
  while (!Serial) continue;

  Test_Lights(); //Initialise Lights

  // Initialize Ethernet library
  byte mac[] = {<REDACTED>};
  if (!Ethernet.begin(mac)) {
    Serial.println(F("Failed to configure Ethernet"));
    return;
  }
  delay(1000);

  Serial.println(F("Connecting..."));

  // Connect to HTTP server

  client.setTimeout(10000);

  // Disconnect
  //client.stop();
}

void loop() {

  delay(3000);

  v_state = GetMCStatus(); // Call Inital Status UpDate
  Serial.println(F("Status Update Done"));
  Serial.println(F("Updating Relay..."));

   digitalWrite(RELAY_2, HIGH);  //*TEST* THIS BREAKS THE HTTP GET!!!!!!!! HELP!!!
   //SetRelays();  //THIS ALSO BREAKS THE HTTP GET!!!!!!!! HELP!!!
  
}


String GetMCStatus() {

  char* v_temp_state;
  client.stop();
  client.setTimeout(10000);

   if (!client.connect(v_WebService, 80)) {
    Serial.println(F("Connection failed"));
    return;
  }

  Serial.println(F("Connected!"));

  // Send HTTP request
  client.println(F("GET <REDACTED> HTTP/1.0"));
  client.println("Host: " + v_WebService);
  client.println(F("Connection: close"));
  if (client.println() == 0) {
    Serial.println(F("Failed to send request"));
    return;
  }

  // Check HTTP status
  char status[32] = {0};
  client.readBytesUntil('\r', status, sizeof(status));
  if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
    Serial.print(F("Unexpected response: "));
    Serial.println(status);
    return;
  }

  // Skip HTTP headers
  char endOfHeaders[] = "\r\n\r\n";
  if (!client.find(endOfHeaders)) {
    Serial.println(F("Invalid response"));
    return;
  }

  // Allocate JsonBuffer
  // Use arduinojson.org/assistant to compute the capacity.
  const size_t capacity = JSON_OBJECT_SIZE(2) + 30;
  DynamicJsonBuffer jsonBuffer(capacity);

  // Parse JSON object
  JsonObject& root = jsonBuffer.parseObject(client);
  if (!root.success()) {
    Serial.println(F("Parsing failed!"));
    return;
  }

  // Extract values
  v_temp_state = root["State"].as<char*>();
  
  Serial.println(F("Response:"));
  Serial.println(root["MachineID"].as<char*>());
  Serial.println(root["State"].as<char*>());

  delay(500);

  v_last_update_time = millis(); //Set to current system timeer value

  return String(v_temp_state);
}





void SetRelays()
{
  int v_run_state = -1; //Set runs code to integer
  if(v_state == "RUN")
    {
      v_run_state = 1;
    }
    else if (v_state == "WAIT")
    {
      v_run_state = 2;
    }
    else if (v_state == "STOP")
    {
      v_run_state = 0;
    }
    else if (v_state == "TEST")
    {
      v_run_state = 3;
    }

    switch(v_run_state) //set becon light based on status
    {
      case 2:
        digitalWrite(RELAY_4, LOW);  
        digitalWrite(RELAY_3, LOW);  
        digitalWrite(RELAY_2, HIGH);  
        digitalWrite(RELAY_1, LOW);  
        Serial.println("Relay 2 set.");
      break;
      case 1:
        digitalWrite(RELAY_4, LOW);  
        digitalWrite(RELAY_3, LOW);  
        digitalWrite(RELAY_2, LOW);  
        digitalWrite(RELAY_1, HIGH);  
        Serial.println("Relay 1 set.");
      break;
      case 0:
        digitalWrite(RELAY_4, LOW);  
        digitalWrite(RELAY_3, HIGH);  
        digitalWrite(RELAY_2, LOW);  
        digitalWrite(RELAY_1, LOW);  
        Serial.println("Relay 3 set.");
      break;
      case 3:
        digitalWrite(RELAY_4, HIGH);  
        digitalWrite(RELAY_3, LOW);  
        digitalWrite(RELAY_2, LOW);  
        digitalWrite(RELAY_1, LOW);  
        Serial.println("Relay 4 set.");
      break;
      default:
        digitalWrite(RELAY_4, LOW);  
        digitalWrite(RELAY_3, LOW);  
        digitalWrite(RELAY_2, LOW);  
        digitalWrite(RELAY_1, LOW); 
    }

}

void Test_Lights()
{
  delay(1000);
  //Turn all Relays off
  digitalWrite(RELAY_4, LOW);
  digitalWrite(RELAY_3, LOW);  
  digitalWrite(RELAY_2, LOW);
  digitalWrite(RELAY_1, LOW); 
  //Sequence test
  digitalWrite(RELAY_4, HIGH);
  delay(100);
  digitalWrite(RELAY_4, LOW);
  delay(100);
  digitalWrite(RELAY_3, HIGH);
  delay(100);
  digitalWrite(RELAY_3, LOW);
  delay(100);
  digitalWrite(RELAY_2, HIGH);
  delay(100);
  digitalWrite(RELAY_2, LOW);
  delay(100);
  digitalWrite(RELAY_1, HIGH);
  delay(100);
  digitalWrite(RELAY_1, LOW);
  delay(1000);
  //Turn all Relays on
  digitalWrite(RELAY_4, HIGH);  
  digitalWrite(RELAY_3, HIGH);
  digitalWrite(RELAY_2, HIGH);
  digitalWrite(RELAY_1, HIGH);
  delay(1000);
  //Turn all Relays off
  digitalWrite(RELAY_4, LOW);
  digitalWrite(RELAY_3, LOW);  
  digitalWrite(RELAY_2, LOW);
  digitalWrite(RELAY_1, LOW); 
}
  //Inital Set Relays Low
  digitalWrite(RELAY_1, HIGH); 
  digitalWrite(RELAY_2, HIGH); 
  digitalWrite(RELAY_3, HIGH); 
  digitalWrite(RELAY_4, HIGH);

For some definition of Low...

What is connected to these pins?

  delay(3000);

WHY?

PaulS:   //Inital Set Relays Low   digitalWrite(RELAY_1, HIGH);   digitalWrite(RELAY_2, HIGH);   digitalWrite(RELAY_3, HIGH);   digitalWrite(RELAY_4, HIGH);

For some definition of Low...

What is connected to these pins?

  delay(3000);

WHY?

  delay(3000);

For Testing only. Im implementing millisn final solution

Yes i set the relays to high to test as well.

Two answers to three questions is the wrong ratio.

HI Paul,

Sorry i missed that, The pins are connected to a 4 12v+ Relay board.

https://www.mikroe.com/relay4-board which controls 4 24v Lights.

I understand the code may not be ideal, i have torn the code up trying to diagnose the issue and i understand the code is not ideal r production ready at the moment. i am just trying to identify the issue and resolve it before i can re-code the sections ready for a production environment.

If you disconnect that board, does that affect whether the GET request works?

I could see how the board might interfere with the ability to make GET requests. I can't see how it could possibly interfere with the server's response (a valid reply vs. a "that file doesn't exist" reply).

Hi Paul.,

Indeed the GET request works fine without or with the board, it only seems to be effected by conditional relay updates. please see the GIF attached where i run though the code twice, once with and once without the Relay update test code. This may give you a better understanding of the issue.

Thanks

please see the GIF attached where i run though the code twice, once with and once without the Relay update test code. This may give you a better understanding of the issue.

That picture is like taking a picture of the trunk of your car to illustrate how beautiful the Grand Canyon is.

It didn't tell me a thing.

The relay board, with relays doing nothing, could be interfering with pins that have dual purpose, though I can't see where/how. On the other hand, I can't see what Arduino, or not-exactly-an-Arduino, you are running that code on...

The relays, controlling things, could be causing electrical interference, but I can't see how that would affect the server's ability to find a resource.

So, you need to start at the beginning. Disconnect the relay board. Run the code, manipulating the relay pins. If that works, the problem is NOT the code. If not, the problem is NOT the hardware.

Having determined if the problem is hardware or software, we can begin fixing it.

Thank you Paul,

I am using a Arduino Uno, and Ethernet Shield 2.

I disconnected the relay board and the code runs fine.

I must admit i never thought that the relay board could e causing interference. Relay signals?

Thank you,

I disconnected the relay board and the code runs fine.

The next step, then, is to connect the relay board, with NOTHING connected to the output side of the relays, to the Arduino.

What does that do to the program's execution?

If that works, and the relays useless click on and off, then the problem is the load they control causing interference.

One step at a time, though.

HI Paul,

After further Testing i have found out the following.

Firstly, i replaced the Relay completely with an Velleman 5v 4 relay board.

I tested this with a digitalWrite(RELAY_4, HIGH); line in the Loop, this worked ok!

However, when i added an IF Statement like below, the code failed. resulting in the HTTP 404 error as mentioned earlier. after more testing i can confirm the issue seems to be related to the comparison using v_state.

I gate the same issue whether the relay board is connected or not.

  if(v_state == "WAIT")//set beacon light based on status
    {
        digitalWrite(RELAY_4, LOW);  
        digitalWrite(RELAY_3, LOW);  
        digitalWrite(RELAY_2, HIGH);  
        digitalWrite(RELAY_1, LOW);  
        Serial.println("Relay 2 set.");
    }

Can anyone help with this? i have tested more and its definitely related to setting any pins to high while inside an IF statement or a switch/case statement.

I get a HTTP 400 error if the code is compiled with a digitalwrite as mentioned above. i have tried this with different UNO boards and Relays and i am testing without a relay attached. only the Ethernet shield 2.

In your code

IPAddress   v_WebService;
...
... 
client.println("Host: " + v_WebService);

There are 2 problems : - You can't concatenate char* with + ("Host : " is char* and not string object) - v_WebService is not a string but an IPAddress object The line is not printed to the modem and you receive a 400 error (bad request)

IPAddress   v_WebService;
...
... 
client.print("Host: ");
client.println(String(v_WebService[0]) + '.' + String(v_WebService[1]) + '.' + String(v_WebService[2]) + '.' + String(v_WebService[3]));

Host is generaly a hostname and not an IP address if your HTTP server serves multiple hosts.