Send string via I2C for ESP communication from Node-RED

The ESP Arduino device receives strings from Node-RED.
How do I send those strings via I2C?

I tried following this post with these programs:

I2Cmaster

#include <Wire.h>

char shape_squence = "1, 1, 1, 4";

void setup()
{
  Wire.begin(); // Join I2C bus

  Serial.begin(57600);
  delay(10);
}

void loop()
{

  
  char buffer[shape_sequence.length()];
  shape_sequence.toCharArray(buffer, shape_sequence.length());
  
  Wire.beginTransmission(1); // transmit to device #1  
  Wire.write(buffer);
}

I2Cslave

#include <Wire.h>

String shape_sequence;

void setup()
{
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
    
  Serial.begin(115200);
  while (!Serial);    // Needed for native USB port only, 
                      // wait for serial port to connect.
  delay(500); // Necessary for clean Serial Monitor print
  Serial.print("this");
}

void loop()
{

}

void receiveEvent()
{
  shape_sequence = Wire.read();
  Serial.println(shape_sequence);

  
}

I am having trouble sending the string as chars. Any simple fixes?

Also made this, which I previously thought was needed:

http://cpp.sh/

#include <iostream>
#include <string>
using namespace std;

int numOfElements = 0;

int main()
{
    string shape_sequence = "1, 1, 1, 4\n";

    char receivedChars[4];
    int i = 0;
    for(int index = 0; index < shape_sequence.length(); index+= 3)
        receivedChars[i++] = shape_sequence[index];


    for(char c : receivedChars)
        cout << c << " ";
 
}

The idea is to put numbers in an array for the slave Arduino device to execute. And so "1" will execute one thing, "2" will execute another and so forth.

Oh, well for one, the Arduino devices got disconnected. :-[

That’s not correct in C++ if you want to represent a cString.

 char shape_squence = "1, 1, 1, 4";

you need to write

const char * shape_squence = "1, 1, 1, 4";

or

 char shape_squence[] = "1, 1, 1, 4";

It’s not an instance of the String class so you can’t call methods on this variable. It’s either just a pointer or an array.

This was my attempt to re-create a larger program with minimal code.

A string of varying length is sent to the master Arduino device. Then, I want that to be sent via I2C. The original (large) program does not have any scope errors.

Anyway, I don't follow what needs to change.

I2Cmaster change:

char shape_squence[] = "1, 1, 1, 4";

I2Cmaster full program

#include <Wire.h>

char shape_squence[] = "1, 1, 1, 4";

void setup()
{
  Wire.begin(); // Join I2C bus

  Serial.begin(57600);
  delay(10);
}

void loop()
{

  
  char buffer[shape_sequence.length()];
  shape_sequence.toCharArray(buffer, shape_sequence.length());
  
  Wire.beginTransmission(1); // transmit to device #1  
  Wire.write(buffer);
}

I2Cslave unchanged:

#include <Wire.h>

String shape_sequence;

void setup()
{
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
    
  Serial.begin(115200);
  while (!Serial);    // Needed for native USB port only, 
                      // wait for serial port to connect.
  delay(500); // Necessary for clean Serial Monitor print
  Serial.print("this");
}

void loop()
{

}

void receiveEvent()
{
  shape_sequence = Wire.read();
  Serial.println(shape_sequence);

  
}

Put this aside for the moment and read about cString and arrays in C++

J-M-L:
Put this aside for the moment and read about cString and arrays in C++

"Use string. cstring is so 1970's. string is a modern way to represent strings in c++. you'll need to learn cstring because you will run into code that uses it. but cstring is responsible for lots of unsafe code."

http://www.cplusplus.com/forum/general/38801/

Do you recommend any resource about this? I'm leery of using const for this minimal program (in light of what's going on in large program).

Was going off of Robin2's Serial Input Basics because this is too short:

In your sender, you seem to be missing a Wire.endTransmission. That is what starts the actual transmission over the bus.

That is how it works on Arduinos, ESP might be different (no experience).

Yes cStrings are so 70s but I’m not sure the C++ string class is supported in Wire.write(), is it ?

Thanks sterretje. Lost that when making new program from the old.

J-M-L, I'm not sure what else to read besides the ones I posted. Anyway, I'm trying just sending it like this:

I2Cmaster

#include <Wire.h>

char shape_squence[] = "1, 1";

void setup()
{
  Wire.begin(); // Join I2C bus

  Serial.begin(57600);
  delay(10);
//  Serial.print(shape_sequence.length());
}

void loop()
{
  
  
//  char bufferArr[shape_sequence.length()];
//  shape_sequence.toCharArray(bufferArr[], shape_sequence.length());
  
  Wire.beginTransmission(1); // transmit to device #1  
  Wire.write(shape_squence);
  Wire.endTransmission();
}

I think the issue is in the receiving or slave program, but there are multiple things that could be wrong anywhere:

How is the length of the string found? I tried with .length() and strlen(). Always amazed by the lack of examples about this basic stuff. I mean, spent days now just trying to send any string using I2C!

I2Cslave

#include <Wire.h>

String shape_squence = "";

void setup()
{
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
    
  Serial.begin(115200);
  while (!Serial);    // Needed for native USB port only, 
                      // wait for serial port to connect.
  delay(500); // Necessary for clean Serial Monitor print
  Serial.print("This");
}

void loop()
{

}

void receiveEvent()
{
  shape_sequence += (char)Wire.read();
  Serial.println(shape_sequence);


//  Serial.println("Event - Recieve");
//  while(Wire.available() > 0) // loop through all but the last
//  {
//    char c = Wire.read(); // receive byte as a character
//    shape_squence.concat(c);
//    delay(10);
//    Serial.print("Data in - ");         // print the character
//  }
  
}

Error: "'shape_sequence' was not declared in this scope"

Why doesn't this compile?

#include <Wire.h>

//char shape_squence[] = "1, 1";
String shape_squence = "1, 1";
byte leng = 0;

void setup()
{
  Wire.begin(); // Join I2C bus

  Serial.begin(57600);
  delay(10);
}

void loop()
{
  
  
  leng = 3;       //    strlen(shape_sequence);
                  //    shape_sequence.length();
  char bufferArr[leng];

  shape_sequence.toCharArray(bufferArr, leng);
  
  Wire.beginTransmission(1); // transmit to device #1  
  Wire.write(shape_squence);
  Wire.endTransmission();
}

Error: 'shape_sequence' was not declared in this scope

general info Arduino - Strings
(char)Wire Send string via I2C for ESP communication from Node-RED - #12 by adamelli - Programming Questions - Arduino Forum
+= stuff Send text string over i2c between two arduinos - Programming Questions - Arduino Forum
useless toCharArray() - Arduino Reference
convoluted Using wire to send strings of numbers and letters from one uno to another - Programming Questions - Arduino Forum

What is sending and what is receiving ?
There is no ESP Arduino and there is not device called Node-RED.

Does it have to be I2C ? Can you use Serial/UART communication ?
I wrote this page to disappoint Arduino users who think that the I2C bus is good bus to communicate between Arduino boards: How to make a reliable I2C bus · Koepel/How-to-use-the-Arduino-Wire-library Wiki · GitHub.

Ya, I just found out a maximum example cable length between devices can only be 2.5 feet (2.25m): Maximum I2C Bus Length? - Electrical Engineering Stack Exchange

So I'll just go back to using Serial. I'll probably encounter I2C again though and have the same question on how to merely send a string.

The I2C bus works better with fixed size packages of binary data.
However, if that is possible depends on which Arduino boards are used.

The length of 2.25 meters is a theoretical calculation for a certain speed with a certain cable, and even then that number does not make much sense.

@OP

1. What is your device at the Master Side? Is it Arduino UNO/NANO/MEGA/DUE or ESP (Node MCU)?

2. What is your device at the Slave Side? Is it Arduino UNO/NANO/MEGA/DUE or ESP (Node MCU)?

3. How much is the separating distance between the Master and Slave?

GolamMostafa:
@OP

1. What is your device at the Master Side? Is it Arduino UNO/NANO/MEGA/DUE or ESP (Node MCU)?

2. What is your device at the Slave Side? Is it Arduino UNO/NANO/MEGA/DUE or ESP (Node MCU)?

3. How much is the separating distance between the Master and Slave?

  1. ESP32

  2. Right now it's an Uno, but could be Nano. It can be anything.

  3. Too much distance for I2C to be feasible.

adamelli:

  1. ESP32

  2. Right now it's an Uno, but could be Nano. It can be anything.

  3. Too much distance for I2C to be feasible.

  1. Then use UART Communication Port which can convey digital data upto 80 feet with "RS232 Level" and upto 10 feet with "TTL Level".

I have ESP8266 (not ESP32) and UNO setup to test your project

@adamelli, the ESP32 can not have signals with 5V on its pins. That means you may not connect a ESP32 with a Uno or Nano. Either I2C or UART. A level shifter will solve that, but a level shifter will also make the signal a little weaker.

Ya, I'm using a level shifter.