0

I have an Arduino Uno and an ESP8266, connected over serial through ESP8266 pin GPIO_2 (which is set as RX over espsoftwareserial) and 11 on Uno (which is set as TX over SoftwareSerial). I am trying to send data (for now just random numbers from 0 to 1000) from Arduino Uno to ESP8266. But ESP8266 shows messy chars.

I am using:

Arduino UNO code:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX    
int randnum;

void setup() {
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  Serial.begin(115200);
}

void loop() { // run over and over      
  randnum = random(0,1000);    
  mySerial.write(randnum);
  Serial.println(randnum);
  delay(2000);
}

ESP8266 code: (it's programmed with Arduino IDE)

#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>

SoftwareSerial ARD_ESP(2, SW_SERIAL_UNUSED_PIN); // RX, TX  |||| RX = ESP8266 = GPIO_2

const char* ssid     = "myssid";
const char* password = "mypassword";

const char* host = "www.myweb.com";
const char* value2 = "986.458";
const char* value1 = "150.0589";
long previousMillis = 0;
char indata;
String incomingData_from_ARD = "";
int i=0;

void setup() {
  Serial.begin(115200);
  ARD_ESP.begin(9600);
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("connecting to wifi: ");
  Serial.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
//int value = 0;

void loop() {
  //delay(1000);
  //++value;
  if (ARD_ESP.available() > 0) {
    Serial.write(ARD_ESP.read());
    indata = ARD_ESP.read();
    incomingData_from_ARD += String(indata);
  }
  if ((millis() - previousMillis) > 10000) {
    Serial.println("---------------------------------------------------------------------------------------");
    Serial.print("Requesting URL: ");
    Serial.println(host);
    Serial.println("-------------------------------");
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {
      Serial.println("Request failed");
      return;
    }
    // We now create a URI for the request
    String url = "/testesp.php";
    url += "?sensor_1_total_volume=";
    url += incomingData_from_ARD;
    url += "&sensor_2_total_volume=";
    url += value2;
    Serial.println("Sending data to URL: ");
    Serial.println(url);
    Serial.println("-------------------------------");
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
      "Host: " + host + "\r\n" +
      "Connection: close\r\n\r\n");
      unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 5000) {
        Serial.println(">>> Server Timeout!");
        client.stop();
        return;
      }
    }
    while(client.available()) {
      String line = client.readStringUntil('\r');
      Serial.print(line);
    }
    Serial.println();
    Serial.println("Closing connection with web");
    Serial.println("-----------------------------------------------------------------------------------");
    previousMillis = millis();
    incomingData_from_ARD = "";
  }
}

And this is the text that I am getting on Serial (on PC):

    -----------------------------------------------------------------------------------
        ›¸Ąě*Ű
 ---------------------------------------------------------------------------------------
Requesting URL: www.myweb.com
-------------------------------
Sending data to URL: 
/testesp.php?sensor_1_total_volume=Ĺ˙˙˙˙˙&sensor_2_total_volume=986.458
-------------------------------
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 13 Dec 2016 23:28:58 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.10

354
<div style=" background-color:#; font-size: px;"><div class="oznamy"><div class="eq"><i>„Čas si vymysleli lidé, aby věděli, od kdy do kdy a co za to.“ </i>Jan Werich</div></div></div><!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <meta name="description" content="TEST_ESP">
   <meta name="author" content="Vasekdvor">
   <meta name="robots" content="noindex">
   <title>TEST ESP 8266 POST A GET</title>

0


Closing connection with web
-----------------------------------------------------------------------------------

These messy chars at the beginning are the random numbers that Arduino Uno sends:

›¸Ąě*Ű

But Arduino sends real numbers, only the ESP8266 is interpreting them as this.

Can you please help me fix that? How can I receive numbers?

Thank you.

EDIT:

So i have made some changes based on chupo_cro recommendations

Now its Arduino:

void loop() { // run over and over

randnum = random(0,1000);

mySerial.write((byte*)&randnum, sizeof(randnum));
Serial.println(randnum);

delay(2000);
}

And ESP8266:

long previousMillis = millis();
char indata;
String incomingData_from_ARD = "";
int i=0;

void setup() {

.................................

void loop() {
  //delay(1000);
  //++value;

  if (ARD_ESP.available() > 0) {
    //Serial.write(ARD_ESP.read());
    indata = ARD_ESP.read();
    incomingData_from_ARD += indata;
  }

  Serial.println(incomingData_from_ARD); 

  if ((millis() - previousMillis) > 10000) {

Its still doesnt work.

2

There are a few issues in your code.

First, you have if (ARD_ESP.available() > 0) to check if the data arrived but what is going to happen if the data still haven't arrived? Instead of waiting for the data to arrive the program will continue through the loop and it will send a request every 10 seconds even if there is no data.

Second, you initialized previousMillis to zero. You should initialize it to millis() so you can count from the present moment in time.

Third, in the loop where you are reading the input:

if (ARD_ESP.available() > 0) {
    Serial.write(ARD_ESP.read());       // <-- 1st read
    indata = ARD_ESP.read();            // <-- 2nd read
    incomingData_from_ARD += String(indata);
}

when something arrives, you are reading it twice so the second read indata = ARD_ESP.read(); gets -1 (no data available) when there is less than two chars in the buffer. Even if you sent more than one character there is no time for new data to arrive in the buffer and even if there is more than one character you miss every second one because of the 1st read.

Fourth, you cannot send the number greater than 255 (one byte) with mySerial.write(randnum); because write() sends only one byte. And even if you could in a such way send more than one byte, you cannot display these bytes as a string representing the number. You could send all bytes using:

mySerial.write((byte*)&randnum, sizeof(randnum));

but, as I said, these bytes are not a string representing the number contained in a variable. For example, if randnum = 1000, that is 0xe8, 0x03 and "1000" is 0x31, 0x30, 0x30, 0x30. 0x31 is ASCII for 1 and 0x30 is ASCII for 0.

So, you have a lot of things to improve.

EDIT:
Try this, I don't have a time to check the code but it should work:

int length = 4;
char to_send[length];
itoa(randnum, to_send, 10);
mySerial.write((byte*)&to_send, sizeof(to_send));
Serial.println(to_send);

EDIT:
Unfortunately I don't have Arduino (I've even never had one :-)) so you'll have to try the code and report back if it works. I have a few ESP8266s but they are all logging some data at the moment.

Now for the ESP8266 code:

You have at least two choices when deciding how to read the data. The first choice would be 'your way', something like:

void loop() {

    char input;
    if(ARD_ESP.available()) {
        input = (char)ARD_ESP.read();       // you can try even without (char)
        Serial.print(input);                // send char to terminal
        incomingData_from_ARD += input;     // concatenate the new char
    }

    if ((millis() - previousMillis) > 10000) {
        // if there was something received until now
        if(incomingData_from_ARD.length()) {
            // ...
            incomingData_from_ARD = "";
        }
        previousMillis = millis();
    }
    // ...
}

The second way could be:

void loop() {
    char input;
    // wait for the data
    while(!ARD_ESP.available())
        yield();                          // to prevent WDT reset
    // read everything that has been sent
    while(ARD_ESP.available()) {
        input = (char)ARD_ESP.read();
        Serial.print(input);
        incomingData_from_ARD += input;
        delay(120);                       // 100 or a bit more for 9600 Bd
    }

    // remove 'if' to send immediately
    if ((millis() - previousMillis) > 10000) {
        // ...
        previousMillis = millis();
    }
    // ...
}

There is a significant difference between these two ways of reading the incoming data. When reading the data as in the first example then in every pass through the loop you either read or don't read exactly one byte. Since there is a possibility 10 seconds will pass before we received some data, there has to be a check if the data in the meantime arrived or not. If there was some data then every 10 seconds everything received until that moment would be sent - even if that was in the middle of the string. You probably don't want to send just one part of the string to the server.

In the second example there is a while loop waiting for the data from serial port. When the data arrives there is another while loop to read all bytes one by one. Without delay the loop would end before receiving the second and all subsequent bytes so the received string would be cut in 1-character chunks. Now, when the whole string is received, we don't have to check if something arrived because we already know it did.

I've left 10 seconds delay between sending the GET requests but you have to decide if that is what you really want. You have to be aware that if the next data arrive in between sending the GET requests, the next string (number) will be concatenated with the previous one - and you do not want that to happen because such data wouldn't be meaningful. To avoid concatenation of the new with the old data, you have to remove if which is checking millis() to send the received data immediately.

Note: As I said, I can't test the code so I cannot guarantee it is 100% error free but you can check if it works so I can correct the mistakes if there are any.

  • Thanks for your reply, but first issue doesn´t solve the problem with serial data. I have edited the code, but still it doesn´t work. – Vasekdvor Dec 14 '16 at 13:28
  • Of course it does not resolve the issue, as I explained you cannot send raw numbers and have string representation. When you send number 1000, that is 0xe8, 0x03 (232, 3) because 1000 = 3*256 + 232. 232 and 3 is not 0x31, 0x30, 0x30, 0x30 which is String("1000"). To have string "1000" you have to send 0x31, 0x30, 0x30, 0x30. I will give you the code in an hour or two as I don't have time at the moment. – Chupo_cro Dec 14 '16 at 16:16
  • Here you are the code to send the number as a string. I'll take a look at other things later when I have time. – Chupo_cro Dec 14 '16 at 16:24
-2

Check the Softwareserial library, it is not from Arduino but a guy, Peter Lerup. I tested two Uno board Softwareserial and they works fine. But then, when I use a Wifi-uno-look-alike board, I don't get any serial signal.

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.