Real communication between arduino and NodeMCU

For Serial connections between Uno/Mega and 3V3 boards see my
Arduino to Arduino/PC which has circuits and code for sending a line at a time (includes adding a check sum for error checking)
If you are sending less the 60chars to UNO or 125chars to Mega at a time, the code will cope with very long delays on either side.

1 Like

It is unbelievable what crap people have uploaded.
As for error sensitivity, it does depend a little on what you think you need to send back and forth.
If you are sending whole webpages or major parts thereof, you are doing something wrong.
The board with the biggest memory and fastest CPU should be in charge, and some information can be fetched and sent. Serial Input basics is very reliable, but a method that sends a header of a few bytes + length of transmission and optional CRC check can also be very efficient. Still if it is just for lack of pins, port expanders or even multiplexer or bitshifters are usually enough of a solution.

I want to order several output digital pins to switch on and off , read a few sensors values which are obviously input analog and optionally control a few pwm pins. Additionally, i have a plan to connect a clock (ds3231) to my board , an oled display and a keyboard and maybe more. (Im trying to scheme a flexible, modular and expandable base for the future)

But as far as i know (maybe Im wrong), if i use the above items there are not enough pins to do it, for example a multiplexer for input analog values will consume 4 digital pins aside from the only analog pin on wemos, and also ds3231 will take two pins and display … Etc.

Unfortunately i know very little things about combining some elements together by i2c or UART or …
Is it possible to handle all of these items by expanders on wemos?

1 Like

By UART i can send simple data from arduino to wemos but at the same time no value transfered from weons to arduino. I have no idea about how to sync and how to stop at a suitable time to receive data from opposite side an also so many other things. I’m very beginner at this stage but my search through different forums and related sites has been pointless up to know … :confused:

Do you know a comprehensive tutorial about this issue?

Why not? People do this all the time. Start on this forum with Serial Input Basics.

It is pretty simple to design your own command/communications protocol. For example, serial commands could look something like this:

<s4,1> set digital output pin 4 to 1
<p9,150> set PWM on pin 9 to 150
<g2,0> get analog input on A2

The MCP23017 will give you 16 digital ports
The PCF8574 will give you 8 digital ports
The PCA9685 will give you 16 PWM ports
The ADS1115 will give you 4 analog pins

all on just two pins - which you might already use for your i2c display. That’s what I2C is used for: a bus where you connect multiple ICs.

Tnx a lot jremington, the link seems great :+1:

Hi again,

As I told you above, I need to send and receive a big JSON between Arduino and Weoms at one code, but at first, I started to send a moderate size string of about 75 characters ( 75 doesn’t matter, I just want to send a not short string.
According to Serial Input Basics - updated (which you guys had recommended) I tried to send the string from UNO to Wemos D1 (as shown in the picture) but apparently, there are just only 64 characters could pass through serial communication.

whats is the problem?

Arduino Side:

#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial s(5,6);

void setup() {
  Serial.begin(115200);
  s.begin(115200);
}
 
void loop() {

  s.write("<");
  s.write("1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890");
  s.write(">");


  delay(2000);
}

Wemos Side:

#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial s(D6,D5);

const byte numChars = 1000; 
char receivedChars[numChars];
String stringBuffer;
boolean newData = false;

void setup() {
    Serial.begin(115200);
    s.begin(115200);
}

void loop() {
    Serial.println(SerialReceiver());
    delay(2000);
}

char* SerialReceiver()
{
    memset(receivedChars, 0x00, sizeof(receivedChars));     // i ssuppose this code clear the 
    receivedChars each loop
    newData = false;
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (s.available() > 0 && newData == false) {
        rc = s.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                //stringBuffer +=String(rc);
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
    return receivedChars;
}


Wiring

Received char A in Wemos Serial Side
What Wemos get is only 64 characters of what Arduino sent

Hi again
What is your idea about my latest question above?
tnx for your attention jremington

Your problem is here

void loop() {
    Serial.println(SerialReceiver());
    delay(2000);   // here
}

That means that you only start reading once the buffer is already overflowing.
your SerialReceiver function is in essence ‘non-blocking’ (or could be)
Your return the pointer to the input buffer, but there is no need for that, the buffer receivedChars[]
is global, so we know where it is.
The problem is that you decide right there and then that you want to print it.

    memset(receivedChars, 0x00, sizeof(receivedChars));     // i ssuppose this code clear the 
    receivedChars each loop

So that we should remove,

All you need to do is the following.

void loop() {
  SerialReceiver();
  if (newData) {
    Serial.println(receivedChars);
  }
}

Now how big is your buffer ?

Actually let me expand on that a little. This code is a copy of one of Robin2’s Serial Input Basics examples, that someone altered. This someone didn’t know what he was doing, Where did you get this code ? Because like this it doesn’t work.

s.begin(115200);

Keep in mind that on an UNO that BAUD rate is not reliable for reception (it is for transmission)
Apparently it is on the Wemos, (faster CPU) But you are planning to use hwSerial in the end anyway i guess.

If you change to an ESP32 the RTC is onboard
As soon as you connect to a WLAN-router time-information is obtained over WiFi
best regards Stefan

Tnx a lot deva,
As you told me, I changed the code to the original (Robin2’s Serial Input Basics) and everything went as should be. But for the next step I’d like to transfer a JSON. I used the ArduinoJSON-6, I made a JSON object in loop () :

StaticJsonDocument<1000> doc;

then I started creating its children and related nested objects, then convert the JSON to something that able to put in software serial by:

  s.write("<");
  serializeJson(doc, s);  // s: declared as sowtware serial by: SoftwareSerial s(5,6);
  s.write(">");

But on Wemos’s side, I couldn’t receive the complete message, actually, if i consider a very small and simple size JSON from arduino everything will go well but as soon as I change the JSON to a moderate JSON (for example a JSON with 4 objects and each object has more than 2 or 3 nested children) the message in Wemos’s side will be received incomplete and corrupted.

Do you know what the problem is?

Tnx Stephan
ESP32?
You mean something like NodeMCU?
if so, I tested it and get the same problems …

Nope, what is your receive buffer size ?
Have you tried a lower BAUD-rate ?

Yeah, i figured, but you know it is not the first time this happens, and usually the code you posted originally was found somewhere on the internet, I would like to know where so these things can be prevented (well prevented…) in the future, so can you tell me where you got it from ?

Looks like, but has 2 cores and all sorts of other features, many m,ore pins, more expensive too.

Check out this post which completely solves this issue (using JSON messages)
Arduino mega to esp8266 communication via TX RX
But you can send lines of plain text just as easily.

The 64 char problem is the RX buffer overflow on the Wemos side
The solution in the post referenced above is to allocate a bigger SoftwareSerial buffer
I used 256 bytes but see no reason you cannot increase that.

The SerialComs software is tolerant of long delay() on either side. It will just reconnect.
It also works well with SoftwareSerial as it does not allow send/receive to happen at the same time.

About baud-rate and buffer size I tested a few scenarios, but nothing changed.

The code won’t be found somewhere else instead here, because I altered it myself after a lot of changes on the original code (because the troubles that i had with json transmission) and i didn’t share it anywhere.

I know that I’m very beginner in this area and maybe I’m wrong but i realized that transfer a moderate size JSON (not even a long one) in a clean way and extendable code is too complicated, not rubost and also dirty code somehow for sending and receiving by I2C , SPI or other serial communication, due to some problems: corrupted transfered data, no be able to sync, sensitive against delay function and , and…And also i couldn’t find a tutorial or any sample to read and write for both side at the same code.

Deva as far as i realized, the best way i found is to use ESP32, thank you and everyone who introduce this wonderful device to me.

I purchased a ESP32 and i will start wiring and coding in the next few days, i let you all know about the results.

btw, i probably guess that such tutorial is old for you but I’ll start from here and try to combine this tutorial with my requirements:

I’ll try it and let you know
Tnx alot drmpd

there are two libraries

and

With the ESP-DASH-library creating a webinterface boils down to a few lines of code

here is an example-code with which you can switch ON/OFF the onboard-LED to blink with a button
and adjusting the blinkfrequency with a slider with user-pre-defined min-max-limits

#include <Arduino.h>
#if defined(ESP8266)
  /* ESP8266 Dependencies */
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
  /* on ESP8266 LED is connected to Vdd => HIGH = LED off */
  #define  LEDStateOff HIGH 
#elif defined(ESP32)
  /* ESP32 Dependencies */
  #include <WiFi.h>
  #include <AsyncTCP.h>
  #include <ESPAsyncWebServer.h>
  #define  LEDStateOff LOW
#endif
#include <AsyncElegantOTA.h> // manual https://randomnerdtutorials.com/esp32-ota-over-the-air-arduino/
#include <ESPDash.h>

const char *ssid     = "FRITZ!Box 7490";
const char *password = "";

unsigned long MyTestTimer = 0; // variables used with millis() MUST be of type unsigned long
const byte    OnBoard_LED = 2;

bool DoBlink = true;

unsigned long BlinkFreq = 500;
int Slider2Pos = 5;

AsyncWebServer MyServer(80);

ESPDash MyDashboard(&MyServer); 

//  Button Card Format - (Dashboard Instance, Card Type, descriptive Text)
Card MyButton(&MyDashboard, BUTTON_CARD, "Blink On / Off");

//  Slider Card Format - (Dashboard Instance, Card Type, descriptive Text, Card Symbol(optional), int min, int max)
Card MySlider1(&MyDashboard, SLIDER_CARD, "Blink-Period in Milliseconds", "", 50, 1000);
Card MySlider2(&MyDashboard, SLIDER_CARD, "2ndSlider", "Testtext", 0, 10);

void PrintFileNameDateTime() {
  Serial.println("Code running comes from file ");
  Serial.println(__FILE__);
  Serial.print("  compiled ");
  Serial.print(__DATE__);
  Serial.print(" ");
  Serial.println(__TIME__);  
}

boolean TimePeriodIsOver (unsigned long &expireTime, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();  
  if ( currentMillis - expireTime >= TimePeriod )
  {
    expireTime = currentMillis; // set new expireTime
    return true;                // more time than TimePeriod) has elapsed since last time if-condition was true
  } 
  else return false;            // not expired
}


void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}


void setup(){
  Serial.begin(115200);
  delay(200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  pinMode(OnBoard_LED, OUTPUT);
  digitalWrite(OnBoard_LED, LOW);
  
  Serial.print("Trying to connect to WiFi..");
  Serial.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("connected \r\n type this IP-Adress into your browser ");
  Serial.println(WiFi.localIP() );
  Serial.println("to see the ESP-Dash-Board");

  // Attach Button Callback this function gets executed every time the Button is clicked 
  MyButton.attachCallback([&](bool MyButtonState){
    DoBlink = MyButtonState;
    Serial.println("Button Triggered: " + String((MyButtonState)?"true":"false"));
    MyButton.update(MyButtonState); //Make sure we update our button's value and send update to dashboard */
    MyDashboard.sendUpdates();
  });

  // Attach Slider Callback this function gets executed every time the slider is adjusted to a new value
  MySlider1.attachCallback([&](int MySliderValue){
    BlinkFreq = MySliderValue;
    Serial.println("MySlider1 Triggered: " + String(MySliderValue));
    MySlider1.update(MySliderValue); // Make sure we update our slider's value and send update to dashboard */
    MyDashboard.sendUpdates();
  });

  MySlider2.attachCallback([&](int MySliderValue){
    Serial.println("slider2 Triggered: " + String(MySliderValue));
    Slider2Pos = MySliderValue;
    MySlider2.update(MySliderValue);
    MyDashboard.sendUpdates();
  });

  AsyncElegantOTA.begin(&MyServer);   // Start ElegantOTA
  MyServer.begin();                   // Start server
  MyButton.update(DoBlink); 
  
  MySlider1.update( int(500) );
  MyDashboard.sendUpdates();
}

void loop() {
  AsyncElegantOTA.loop(); // this line enables the OTA-updating
  if (DoBlink) {
    BlinkHeartBeatLED(OnBoard_LED,BlinkFreq / 2); // half and half On/Off
  }
  else {
    digitalWrite(OnBoard_LED,LEDStateOff); 
  }

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {
    Slider2Pos++;
    if (Slider2Pos > 10) {
      Slider2Pos = 0;
    }
    MySlider2.update( int(Slider2Pos) ); // your code can change the sliders value too
    MyDashboard.sendUpdates();
  }  
}

The Webinterface looks like this:

and if you type ipadress/update you get a standard select file-dialog to upload a new binary-file
as update of your code

The ESP-DASH-library does all the html-stuff in the backround.
This is very effective to create webinterfaces that can interact with an arduino-code

best regards Stefan