Need Help with ESP8266 DNS Resolution for ThingSpeak (Newbie)

Hello Arduino Community,

I'm a newbie and I'm working on a project using an Arduino with an ESP8266 module to send ultrasonic sensor data to ThingSpeak. I have been facing an issue with DNS resolution when trying to connect to ThingSpeak. The connection fails with a "DNS Fail" error. Below are the details of my setup and the code I'm using.

Project Details:

  • Microcontroller: Arduino
  • WiFi Module: ESP8266
  • Sensor: Ultrasonic Sensor (HC-SR04)
  • Goal: Send distance data to ThingSpeak

Problem Description:

I can connect the ESP8266 to my WiFi network, but when attempting to resolve the DNS for api.thingspeak.com, it fails with a "DNS Fail" error. Below is the serial output I get:

rust

Copy code

00:36:09.298 -> Connecting to WiFi...
00:36:09.298 -> AT+CWJAP="wifi","12345678"
00:36:11.447 -> WIFI DISCONNECT
00:36:16.905 -> WIFI CONNECTED
00:36:16.948 -> WIFI GOT IP
00:36:18.301 -> 
00:36:18.301 -> OK
00:36:29.307 -> 
00:36:29.340 -> Response: AT+CWJAP="vivo1901","12345678"
00:36:29.372 -> WIFI DISCONNECT
00:36:29.372 -> WIFI CONNECTED
00:36:29.404 -> WIFI GOT IP
00:36:29.404 -> 
00:36:29.438 -> OK
00:37:32.598 -> 
00:37:32.598 -> ERROR
00:37:35.776 -> 
00:37:35.776 -> Response: AT+CIPSTART="TCP","AT+CIPDOMAIN="api.thingspeak.com"",80
00:37:35.844 -> busy p...
00:37:35.844 -> DNS Fail
00:37:35.877 -> 
00:37:35.877 -> ERROR
00:37:35.877 -> 
00:37:35.877 -> Connection to ThingSpeak failed.

Code:

cpp

Copy code

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX for ESP8266

const int Trig = 8;
const int Echo = 9;
const long MEASURE_INTERVAL = 5000; // Measure interval
const long THINGSPEAK_INTERVAL = 15000; // ThingSpeak update interval

const int DipSwitch1 = 10; // First switch
const int DipSwitch2 = 11; // Second switch
const int DipSwitch3 = 12; // Third switch
const int DipSwitch4 = 13; // Fourth switch

const int RED_LED = 7; // Red LED
const int GREEN_LED = 6; // Green LED

unsigned long lastThingSpeakUpdate = 0;
bool printData = true; // Variable to control printing

const char* ssid = "wifi"; // Replace with your WiFi SSID
const char* password = "12345678"; // Replace with your WiFi password
const char* apiKey = "AAAAAA"; // Your ThingSpeak API key

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);

  Serial.println("Starting setup...");

  // Initialize pins
  pinMode(Trig, OUTPUT);
  pinMode(Echo, INPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(DipSwitch1, INPUT_PULLUP);
  pinMode(DipSwitch2, INPUT_PULLUP);
  pinMode(DipSwitch3, INPUT_PULLUP);
  pinMode(DipSwitch4, INPUT_PULLUP);

  Serial.println("Pins initialized.");

  // Connect to WiFi
  connectToWiFi();
}

void loop() {
  long distance = measureDistance();
  int waterLevelThreshold = getWaterLevelThreshold();

  if (printData) {
    Serial.print("Ultrasonic Distance: ");
    Serial.print(distance);
    Serial.println(" cm");

    Serial.print("Current Water Level Threshold: ");
    Serial.print(waterLevelThreshold);
    Serial.println(" cm");
  }

  delay(MEASURE_INTERVAL);

  // Control LEDs based on distance
  if (distance <= 30) {
    digitalWrite(GREEN_LED, HIGH);
    digitalWrite(RED_LED, LOW);
  } else if (distance <= 80) {
    digitalWrite(GREEN_LED, HIGH);
    digitalWrite(RED_LED, LOW);
    delay(150); // Blink delay
    digitalWrite(GREEN_LED, LOW);
    delay(50); // Blink delay
  } else if (distance > waterLevelThreshold) {
    digitalWrite(GREEN_LED, LOW);
    digitalWrite(RED_LED, HIGH);
  } else {
    digitalWrite(GREEN_LED, LOW);
    digitalWrite(RED_LED, LOW);
  }

  // Update ThingSpeak at regular intervals
  if (millis() - lastThingSpeakUpdate > THINGSPEAK_INTERVAL) {
    updateThingSpeak(distance);
    lastThingSpeakUpdate = millis();
  }
}

// Measure distance using ultrasonic sensor
long measureDistance() {
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(Trig, LOW);

  long duration = pulseIn(Echo, HIGH);
  long distanceCm = duration / 29 / 2;
  return distanceCm;
}

// Get water level threshold based on DIP switch settings
int getWaterLevelThreshold() {
  int threshold = 40; // Default threshold
  bool switch1 = (digitalRead(DipSwitch1) == LOW);
  bool switch2 = (digitalRead(DipSwitch2) == LOW);
  bool switch3 = (digitalRead(DipSwitch3) == LOW);
  bool switch4 = (digitalRead(DipSwitch4) == LOW);

  if (switch1) threshold = 50;
  if (switch2) threshold = 60;
  if (switch3) threshold = 70;
  if (switch4) threshold = 80;

  if (printData) {
    Serial.print("DIP Switch 1: ");
    Serial.println(switch1 ? "ON" : "OFF");
    Serial.print("DIP Switch 2: ");
    Serial.println(switch2 ? "ON" : "OFF");
    Serial.print("DIP Switch 3: ");
    Serial.println(switch3 ? "ON" : "OFF");
    Serial.print("DIP Switch 4: ");
    Serial.println(switch4 ? "ON" : "OFF");
  }

  return threshold;
}

// Send AT commands to the ESP8266
bool sendCommand(const char* command, unsigned long timeout) {
  mySerial.println(command);
  unsigned long time = millis();
  String response = "";
  while (millis() - time < timeout) {
    while (mySerial.available()) {
      char c = mySerial.read();
      response += c;
      Serial.write(c); // Echo the response to Serial Monitor
    }
  }
  Serial.println(); // Print a new line after the response
  Serial.println("Response: " + response); // Debugging line
  return response.indexOf("OK") != -1 || response.indexOf("WIFI CONNECTED") != -1;
}

bool sendCommand(String command, unsigned long timeout) {
  return sendCommand(command.c_str(), timeout);
}

// Connect to WiFi
void connectToWiFi() {
  Serial.println("Resetting module...");
  sendCommand("AT+RST", 10000);
  delay(10000); // Additional delay to ensure reset

  Serial.println("Setting WiFi mode...");
  sendCommand("AT+CWMODE=1", 5000);
  delay(2000); // Ensure command is processed

  Serial.println("Connecting to WiFi...");
  if (sendCommand("AT+CWJAP=\"" + String(ssid) + "\",\"" + String(password) + "\"", 20000)) {
    Serial.println("Connected to WiFi");
  } else {
    Serial.println("Failed to connect to WiFi");
  }
}

// Perform DNS lookup to resolve the IP address of ThingSpeak
String resolveDNS(String host) {
  String cmd = "AT+CIPDOMAIN=\"" + host + "\"";
  mySerial.println(cmd);
  unsigned long time = millis();
  String response = "";
  while (millis() - time < 5000) {
    while (mySerial.available()) {
      char c = mySerial.read();
      response += c;
      Serial.write(c); // Echo the response to Serial Monitor
    }
  }
  Serial.println(); // Print a new line after the response
  Serial.println("Response: " + response); // Debugging line
  int startIndex = response.indexOf(":") + 1;
  int endIndex = response.indexOf("\r", startIndex);
  return response.substring(startIndex, endIndex);
}

// Update ThingSpeak with distance data
void updateThingSpeak(long distance) {
  String ipAddress = resolveDNS("api.thingspeak.com");
  Serial.println("Resolved IP: " + ipAddress);

  if (ipAddress.length() == 0) {
    Serial.println("Failed to resolve IP address.");
    return;
  }

  String cmd = "AT+CIPSTART=\"TCP\",\"" + ipAddress + "\",80";
  if (sendCommand(cmd.c_str(), 5000)) {
    Serial.println("Connected to ThingSpeak.");
  } else {
    Serial.println("Connection to ThingSpeak failed.");
    return;
  }

  String httpRequest = "GET /update?api_key=" + String(apiKey) + "&field1=" + String(distance) + " HTTP/1.1\r\n" +
                       "Host: api.thingspeak.com\r\n" +
                       "Connection: close\r\n\r\n";

  cmd = "AT+CIPSEND=" + String(httpRequest.length());
  if (sendCommand(cmd.c_str(), 5000)) {
    Serial.println("Sending data to ThingSpeak...");
    mySerial.print(httpRequest);

    // Wait for the response
    unsigned long time = millis();
    String response = "";
    while (millis() - time < 5000) {
      while (mySerial.available()) {
        char c = mySerial.read();
        response += c;
        Serial.write(c);
      }
    }
    Serial.println("Response: " + response);

    // Check if the response indicates success
    if (response.indexOf("OK") != -1 || response.indexOf("SEND OK") != -1) {
      Serial.println("ThingSpeak update sent successfully.");
    } else {
      Serial.println("Failed to send data to ThingSpeak, retrying...");
    }

    // Close the connection
    if (sendCommand("AT+CIPCLOSE", 5000)) {
      Serial.println("Connection closed successfully.");
    } else {
      Serial.println("Failed to close connection, retrying...");
    }
  } else {
    Serial.println("Failed to initiate data send.");
  }
}