0

I have an Arduino Uno connected to an ESP8266 via an ESP-01 adapter. The adapter is powered from the Arduino 3.3V and GND pins and the Tx/Rx to the Adapter use Arduino pins 2/3.
The purpose of the sketch is to trigger an event at IFTTT (If This Than That)
My sketch uses a lot of String objects but works perfect.
Now, given the advice by @Juraj better to use char arrays instead of String, I started to replace the ESP receive String with a char buffer[512] and it doesn't work anymore.
To make things easy, I #defined USE_BUFFER When USE_BUFFER is commented out, String is used, otherwise char[512]
I really don't have a clue what's wrong with this.

#include "Arduino.h" // Needed for Sloeber Eclipse Plugin
#include <SoftwareSerial.h>

//#define USE_BUFFER

SoftwareSerial esp8266(2,3); // RX, TX
const boolean dbg_mode = true;

const String HOST="maker.ifttt.com";
const String PORT="80";

// WIFI
const String SSIDstring = "\"SSID\"";
const String PASSstring = "\"PASSWORD\"";

// IFTTT
const String IFTTT_EVENT = "EOD_PV";
const String IFTTT_APIKEY = "Complex_IFTTT_Key";

#ifdef USE_BUFFER
char buf[512];
#endif

void setup()
{
  Serial.begin(19200);
  esp8266.begin(19200);

  Serial.println("----- [ RESET ESP8266 (RST) ] -----");
  sendData("AT+RST", 1000, dbg_mode);

  Serial.println("----- [ CONFIGURE ESP (CWMODE) ] -----");
  sendData("AT+CWMODE=1", 500, dbg_mode); // Configure ESP in "station mode" (1=Station, 2=AP, 3=Station+AP).

  Serial.println("----- [ CONNECT (CWJAP) ] -----");
  sendData("AT+CWJAP=" + SSIDstring + "," + PASSstring, 5000, dbg_mode); // Connect to WiFi

  Serial.println("----- [ CONNECTION STATUS ] -----");
  sendData("AT+CIPSTATUS", 500, dbg_mode);

  Serial.println("----- [IP ADRES] -----");
  sendData("AT+CIFSR", 500, dbg_mode); // Get given IP address

  trigger("{\"value1\":\"123\",\"value2\":\"v2\",\"value3\":\"v3\"}");
}

void trigger(String data)
{
  String postData = "POST /trigger/" + IFTTT_EVENT + "/with/key/" + IFTTT_APIKEY;
  postData += " HTTP/1.1\r\n";
  postData += "Host: " + HOST + "\r\n";
  postData += "Accept: */*\r\n";
  postData += "Content-Type: application/json\r\n";
  postData += "Content-Length: " + String(data.length()) + "\r\n";
  postData += "\r\n" + data;

  sendData("AT+CIPMUX=0", 500, dbg_mode);

  Serial.println("----- [ Establish TCP Connection ] -----");
  sendData("AT+CIPSTART=\"TCP\",\"" + HOST + "\"," + PORT, 1500, dbg_mode);

  Serial.println("----- [ Send Data ] -----");
  sendData("AT+CIPSEND=" + String(postData.length()+4), 1500, dbg_mode);

  Serial.println("Sending " + postData);

  Serial.println("----- [ POST ] -----");
  sendData(postData, 500, dbg_mode);

  Serial.println("----- [ Close TCP Connection ] -----");
  sendData("AT+CIPCLOSE", 5000, dbg_mode);

  Serial.println("----- [ DONE ] -----");
}

int sendData(String command, unsigned int timeout, boolean debug)
{
#ifdef USE_BUFFER
  int idx = 0;
#else
  String response = "";
#endif
  Serial.println("Sending " + command);
  esp8266.println(command);
  unsigned long time = millis();
  while((time + timeout) > millis())
  {
    while(esp8266.available())
    {
#ifdef USE_BUFFER
      buf[idx++] = esp8266.read();
#else
      response += esp8266.readStringUntil('\n');
      response += '\n';
#endif
    }
  }

#ifdef USE_BUFFER
  buf[idx] = 0;
#endif

  if(debug)
  {
#ifdef USE_BUFFER
    Serial.print(buf);
#else
    Serial.print(response);
#endif
  }

  return 0;
}

void loop()
{
  Serial.print(".");
  delay(60000);
}

USE_BUFFER NOT defined: Using String -> OK "Congratulations! You've fired the EOD_PV event"

Sending AT+RST
AT+RST

OK
Ai-Thinker Technology Co. Ltd.

----- [ CONFIGURE ESP (CWMODE) ] -----
Sending AT+CWMODE=1
AT+CWMODE=1


OK
----- [ CONNECT (CWJAP) ] -----
Sending AT+CWJAP="SSID","PASSWORD"
AT+CWJAP="SSID","PASSWORD"

WIFI CONNECTED
WIFI GOT IP
----- [ CONNECTION STATUS ] -----
Sending AT+CIPSTATUS

OK
AT+CIPSTATUS

STATUS:2

OK
----- [IP ADRES] -----
Sending AT+CIFSR
AT+CIFSR

+CIFSR:STAIP,"192.168.1.41"
+CIFSR:STAMAC,"18:fe:34:e6:14:0b"

OK
Sending AT+CIPMUX=0
AT+CIPMUX=0 

OK
----- [ Establish TCP Connection ] -----
Sending AT+CIPSTART="TCP","maker.ifttt.com",80
AT+CIPSTART="TCP","maker.ifttt.com",80

CONNECT

OK
----- [ Send Data ] -----
Sending AT+CIPSEND=222 
AT+CIPSEND=222


OK
> 
Sending POST /trigger/EOD_PV/with/key/Complex_IFTTT_Key HTTP/1.1
Host: maker.ifttt.com
Accept: */*
Content-Type: application/json
Content-Length: 44

{"value1":"123","value2":"v2","value3":"v3"}
----- [ POST ] -----

----- [ Close TCP Connection ] -----
Sending AT+CIPCLOSE 
+CIPCLOSE

busy s...

Recv 222 bytes

SEND OK 

+IPD,336:HTTP/1.1 200 OK
Date: Wed, 22 Apr 2020 19:32:50 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 46
Connection: keep-alive 

Server: web_server

Congratulations! You've fired the EOD_PV event
----- [ DONE ] -----

USE_BUFFER defined: Using char[512] -> NOT OK

Sending AT+RST
AT+RST

OK
Ai-Thinker Technology Co. Ltd.

invalid
----- [ CONFIGURE ESP (CWMODE) ] -----
Sending AT+CWMODE=1
AT+CWMODE=1


OK
----- [ CONNECT (CWJAP) ] -----
Sending AT+CWJAP="SSID","PASSWORD" 
AT+CWJAP="SSID","PASSWORD"

WIFI CONNECTED
WIFI GOT IP 
----- [ CONNECTION STATUS ] -----
Sending AT+CIPSTATUS

OK 
AT+CIPSTATUS

STATUS:2

OK
----- [IP ADRES] -----
Sending AT+CIFSR
AT+CIFSR 
+CIFSR:STAIP,"192.168.1.41"
+CIFSR:STAMAC,"18:fe:34:e6:14:0b"

OK 

AT+CIPMUX=0


OK
----- [ Establish TCP Connection ] ----- 

",80

ERROR
----- [ Send Data ] -----

AT+CIPSEND=85

link is not valid

ERROR

----- [ POST ] -----



ERROR
----- [ Close TCP Connection ] ----- 

AT+CIPCLOSE


ERROR
----- [ DONE ] -----
  • 1
    When you are using String you are using readStringUntil to read in the string. That function has a timeout, it will wait while characters come in. When you are using the buffer you are just reading as long as the line says available(). That just reads what's in the buffer at that point, but reading is faster so eventually you run out in the buffer and since you don't wait for another character you end up with only part of the string. You need a way to know when you've got the whole string, either by having a character that marks the end or by knowing how long the string is. – Delta_G Apr 22 at 20:37
  • In your second output (the one with the buffer) I don't see the "Sending ..." line from CIPMUX=0 on, as if command is empty. Please check, if that is the case. Also: you still are using tons of Strings in your code, ehich can still break your code through heap fragmentation. You have to remove it from the complete code to rule that out – chrisl Apr 22 at 21:31
  • Finally had some time to dig into this... @Delta_G: Since the timeout loop is completely wrong, it will wait the complete timeout, even if available() is false for a moment. The issue was indeed related to the heavily usage of String class like @chrisl pointed out. Still don't understand why adding an extra String makes it work. – SBF May 5 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.