1

I'm trying to create a setup with which an Arduino UNO sends out a tweet (one random quote) every time a button is pressed. I want to use it as a Mailbox Watcher.

I'm not new to Arduino but ESP8266 is all new to me, so I'm trying to figure things out from how-to articles, youtube videos, etc.

My current setup is an ESP8266-01 attached to an Arduino UNO and I adapted the code found here (link) to my needs. I ended up with something that resembles this:

#include <SoftwareSerial.h>
#include <Bounce.h>

#define DEBUG true

#define APIKEY "THING_SPEAK_KEY" //  api key ThingSpeak
#define TARGET_IP "184.106.153.149"///         //local  direccion IP o Hosting  ThingSpeak
#define TARGET_PORT "80"          ///  port 80
#define ID "WIFI_NAME"  //name of wireless access point to connect to   
#define PASS "WIFI_PASSWORD"  //wifi password                        

#define BUTTON_PIN 8

#define RX_PIN 10
#define TX_PIN 11

SoftwareSerial esp8266(RX_PIN,TX_PIN);      



Bounce button=Bounce(BUTTON_PIN, 5);


void setup() {
    Serial.begin(115200);
    esp8266.begin(9600);

    pinMode(BUTTON_PIN, INPUT);

    initializeModem();

    Serial.println("ready player One");
 }


void initializeModem(){

     sendData("AT+RST\r\n",1000,DEBUG); // 

     sendData("AT+CWMODE=1\r\n",1000,DEBUG); // 

      String cmd="AT+CWJAP=\"";  
      cmd+=ID;
      cmd+="\",\"";
      cmd+=PASS;
      cmd+="\"";      
     sendData( cmd+"\r\n",1000,DEBUG); //     

     sendData("AT+CIPMUX=0\r\n",1000,DEBUG); 


  }


boolean buttonState(){

  if (button.update() && button.read()==HIGH){


      return true;


    }else {
      return false;
      }
  }

void loop() { 

if (buttonState()) {


   //  String con tweet
   String  updateTwitterStatus = "The best and most beautiful things in the world cannot be seen or even touched - they must be felt with the heart. Helen Keller #quoteoftheday";      
   Serial.println(updateTwitterStatus);

    String webpage = "AT+CIPSTART=\"TCP\",\""; 
    webpage += TARGET_IP;
    webpage += "\",80\r\n";         
    sendData(webpage,1000,DEBUG);        

    // Create HTTP POST Data   

    String tsData = "api_key=" APIKEY "&status=" + updateTwitterStatus ;    

    String webpage1 = "POST /apps/thingtweet/1/statuses/update HTTP/1.1\n";
    webpage1+="Host: api.thingspeak.com\n";
    webpage1+="Connection: close\n";
    webpage1+="Content-Type: application/x-www-form-urlencoded\n";
    webpage1+="Content-Length: ";
    webpage1+=tsData.length();
    webpage1+="\n\n";
    webpage1+=tsData;

     //// envia   comando AT + cantidad de caracteres   

     String cipsend = "AT+CIPSEND=";     
     cipsend+= webpage1.length();
     cipsend+="\r\n";     

     sendData(cipsend,1000,DEBUG);
     sendData(webpage1,1000,DEBUG);   

      //// comando AT de cierre de conexion            
     sendData("AT+CIPCLOSE=0\r\n",1500,DEBUG);


              /// DELAY para reenvio de datos a twitter
     delay(10000);  //3 seg
}

}


 //// rutina de depuracion via puerto serial


String sendData(String command, const int timeout, boolean debug) {
    String response = "";

    esp8266.print(command); // send the read character to the esp8266

    long int time = millis();

    while( (time+timeout) > millis()) {
      while(esp8266.available()) {
        // The esp has data so display its output to the serial window 
        char c = esp8266.read(); // read the next character.
        response+=c;
      }  
    }

    if(debug) {
      Serial.print(response);
    }

    return response;
}

The setup works more or less as expected. It connects ok to the WiFi and so on, but it is only able to publish a tweet if it is not very long. As example, the quote on this example code will no be published whereas if it is half as long, it will be no problem.

In the end, I want to clean up the code and make use of private libraries to tidy things up and leave as few lines of codes as possible on the .ino file, but for testing and debugging purposes, I'm working on the code above.

I realize that a short text should be sufficient for my needs, but the fact of knowing that something is off bothers me to great extend. I have been dealing with this for three long days, so if anyone has an idea it would be much appreciated...

Thanks in advance

EDIT: It seems as the longest tweet I can send is 108 characters long. Together with the AT code to sent it, tha serial monitor gives the following feedback:

AT+CIPSEND=302

  • 2
    Have you tested to find out at what length it doesn't work? "short" and "long" are not specific values, but if you can find out the maximum tweet length that doesn't work, you have made a lot of progress in determining the problem and solution. – jose can u c Nov 28 '17 at 17:08
  • that's the next thing I wanted to do, yes. It'll take a while – Felix Hauser Nov 28 '17 at 17:19
  • 1
    Edited with the length of the longest tweet possible. Thanks. – Felix Hauser Nov 28 '17 at 18:21
  • wouldn't it be better using a library? – Juraj Nov 28 '17 at 18:28
  • it would be MUCH easier to program the ESP and leave the UNO out of the equation: far more RAM+CPU, only one sketch, no messy serial parsing, better error handling, etc. – dandavis Nov 28 '17 at 19:12
1

It's plausible and likely that you are running out of RAM on the Uno by making extensive use of the String object and it's concatenation function (overloaded + operator).

Every time you + a String object, a new block of RAM is allocated to hold the new string, and that RAM is nearer the "ceiling" of RAM than the previous block. The old blocks are de-allocated, but since they are smaller than the new one, they can't be re-used for new allocations of your continually-larger String, so you eventually run out of contiguous blocks of RAM into which to put your new, longer String object.

One solution here, and pretty much everywhere on an Arduino, is to avoid using the String object, and go with the classic C string handling routines.

I would allocate one buffer char array char buf[512] or whatever you compute your maximum desired total string length to ever be. Then use strncat() to repeatedly concatenate your other parts into that one buffer.

Also consider putting static strings in PROGMEM as described at https://www.arduino.cc/reference/en/language/variables/utilities/progmem/, so you won't be holding all static strings in RAM the whole time, but can copy each as you use it to working RAM as you build up your HTTP request string.

The real killer is += used repeatedly with a String object. Arduino Uno has only 2k of RAM.

  • Thank you for your answer. As I began to read I understood that all together was over my head, but you explained it very well. I'll see to it tomorrow, but your explanation seems more than plausible. Thanks again! – Felix Hauser Nov 28 '17 at 20:48
  • Well, it has taken me long enough, but thanks to your indications I made it work. Thanks! – Felix Hauser Nov 30 '17 at 16:32

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.