Data difference Master Receiver vs Slave Sender

Hello,

I have created a program wherein Master Receiver ( ESP8266 Based Wemos D1R1 board) requests data from Slave Sender( Arduino Uno R3).

However the data received is different from what data is send by UnoR3.

Refer plots COM5 ( Master Receiver) COM6 (Slave Sender)

Is there something which I am not taking into account. From data sheets I found that R4 has avergae operating current of 50mA which for D1R1 has 80 mA.

Is there is a need to scale the received data or some other changes please suggest.

Image from Original Post so we don't have to download it. See this Simple Image Posting Guide

...R

Your question and your graphs make no sense without seeing the pair of programs and your connection diagram.

...R

Hello Robin2,

Thanks for the picture and guide.

The first graph is the data received by my Master Receiver while the second one shows data sent which is clearly different.

My question is why the difference in data. it should be the same in both serial monitors, isn’t it.

My best guess is that Master Receiver ( ESP8266 Based Wemos D1R1 board) has something which reads the data in a different way.

naik2408:
My best guess

post your code so we don't have to guess

Code for Master

#include <Wire.h>
#include <ESP8266WiFi.h>

#include “ThingSpeak.h”
#include “secrets.h”

char ssid = “"; // your network SSID (name)
char pass[] = "
”; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
WiFiClient client;

unsigned long myChannelNumber = ;
const char * myWriteAPIKey = "
";

// Define Slave I2C Address
#define SLAVE_ADDR 9

// Define counter to count bytes in response
int bcount;

// Define array for return data
byte vib[3];

void setup()
{
Wire.begin();
Serial.begin(9600);

WiFi.mode(WIFI_STA);
ThingSpeak.begin(client); // Initialize ThingSpeak
}

byte readI2C(int address) {
// Define a variable to hold byte of data
byte bval ;
long entry = millis();
// Read one byte at a time
Wire.requestFrom(address, 3);
// Wait 100 ms for data to stabilize
while (Wire.available() == 0 && (millis() - entry) < 100) Serial.print(“Waiting”);
// Place data into byte
if (millis() - entry < 100) bval = Wire.read();
return bval;
}

void loop()
{
// Connect or reconnect to WiFi
if (WiFi.status() != WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID: ");
Serial.println(SECRET_SSID);
while (WiFi.status() != WL_CONNECTED)
{

WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
Serial.print("\nConnecting…");
delay(5000);
}
Serial.println("\nConnected.");
Serial.println("The IP Address of ESP8266 Module is: ");
Serial.println(WiFi.localIP());// Print the IP address
Serial.println("Signal strength: ");
Serial.println(WiFi.RSSI());
}
/while (readI2C(SLAVE_ADDR) < 255) {
// Until first byte has been received print a waiting message
Serial.println(“Waiting for data”);
}
/

for (bcount = 0; bcount < 3; bcount++) {
vib[bcount] = readI2C(SLAVE_ADDR);
}
for (int i = 0; i < 3; i++) {

//float Ax= (( ( ( (float)(vib[0] * 5) / 1024) - 1.65 ) / 0.330 ) * 9.8) ;

int A = ThingSpeak.writeField(myChannelNumber, 1, vib[0], myWriteAPIKey);
// int B = ThingSpeak.writeField(myChannelNumber, 2, vib[1], myWriteAPIKey);
// int C = ThingSpeak.writeField(myChannelNumber, 3, vib[2], myWriteAPIKey);
Serial.println(vib[0]);

}
Serial.println();
Serial.println(“NEW”);

}

COde for SLave

/*
Acceleration sensors Test

*/

#include <Wire.h>
#include <math.h>
#define SLAVE_ADDR 9

const int x_out = A0; /* connect x_out of module to A2 of UNO board /
const int y_out = A1; /
connect y_out of module to A2 of UNO board /
const int z_out = A2; /
connect z_out of module to A3 of UNO board */

// Define return data array, one element per axis
int vib[3];

// Define counter to count bytes in response
int bcount = 0;

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

// Initialize I2C communications as Slave
Wire.begin(SLAVE_ADDR);

// Function to run when data requested from master
Wire.onRequest(requestEvent);

}
int x_adc_value, y_adc_value, z_adc_value;
int Gx, Gy, Gz;

void requestEvent() {

// Define a byte to hold data
byte bval;

// Cycle through data

switch (bcount) {
case 0:
bval = vib[0];
break;
case 1:
bval = vib[1];
break;
case 2:
bval = vib[2];
break;
}
// Send response back to Master
Wire.write(bval);

// Increment byte counter
bcount = bcount + 1;
if (bcount > 4) bcount = 0;

}

void readvib()
{

x_adc_value = analogRead(x_out); /* Digital value of voltage on x_out pin /
Gx = ( ( ( (double)(x_adc_value * 5) / 1024) - 1.65 ) / 0.330 ); /
Acceleration in x-direction in g units */
vib[0] = Gx * 9.8;

y_adc_value = analogRead(y_out); /* Digital value of voltage on y_out pin /
Gy = ( ( ( (double)(y_adc_value * 5) / 1024) - 1.65 ) / 0.330 ); /
Acceleration in y-direction in g units */
vib[1] = Gy * 9.8;

z_adc_value = analogRead(z_out); /* Digital value of voltage on z_out pin */
Gz = ( ( ( (double)(z_adc_value * 5) / 1024) - 1.80 ) / 0.330 ); /Acceleration in z-direction in g units/
vib[2] = Gz * 9.8;

Serial.println();
Serial.print(vib[0]);
Serial.print("\t");
Serial.print(vib[1]);
Serial.print("\t");
Serial.print(vib[2]);
Serial.print("\t");

}

void loop()
{
// Refresh readings every half second
delay(500);
readvib();
Serial.println();
Serial.println(“NEW”);
}

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 
looks like this

and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor.

...R

You can send and request three bytes. When you send just one byte, then the data can be out of sync.

Do you use the newest Arduino IDE and the updated ESP8266 environment ?
The ESP8266 has been improved and the I2C functions match better the Arduino I2C functions.

How many times per second do you want to get data from the Arduino Slave ? The ESP8266 can ask so often, that the Arduino Slave will fail.

Sending three bytes in the Slave is this:

byte threeBytes[3];

void requestEvent() 
{
  Wire.write( threeBytes, 3);
}

Sending three 16-bit signed integers is this:

int16_t threeInt[3];

void requestEvent() 
{
  Wire.write( threeInt, 6);
}

I use 'int16_t' instead of 'int' because this is data between two different platforms. If you use 'int16_t' on the ESP8266 as well, then it should be okay.

Since you have problems, the Master should know if something went wrong:
This is requesting three bytes:

byte threeBytes[3];

Wire.requestFrom(address, 3);
if( Wire.available() == 3)
{
  Wire.readBytes( threeBytes, 3);
}
else
{
  Serial.println( "Request Failed");
}

The waiting with timeout and something with stabilize that you have now is not okay. I call that nonsense code.

i see the following which is i think is where data is being sent over a serial interface

   Serial.println();
    Serial.print(vib[0]);
    Serial.print("\t");
    Serial.print(vib[1]);
    Serial.print("\t");
    Serial.print(vib[2]);
    Serial.print("\t");

i don't see any corresponding serial reads in the master

Hello @ Koepel

Thanks for the 16int_t suggestion, i can try that.

But my problem is that the data send by my slave is completely different froim what is received by the master.

Here is the screenshot of serial monitor and code attached

/*
  //SLave


*/
#include "ADXL335.h"
#include <Wire.h>
#include <math.h>
#define SLAVE_ADDR 9


ADXL335 accelerometer;

// Define return data array, one element per axis
int vib[3];

// Define counter to count bytes in response
int bcount = 0;

void setup() {
  Serial.begin(9600);
accelerometer.begin();
  // Initialize I2C communications as Slave
  Wire.begin(SLAVE_ADDR);

  // Function to run when data requested from master
  Wire.onRequest(requestEvent);

}


void requestEvent() {

  // Define a byte to hold data
  byte bval;

  // Cycle through data

  switch (bcount) {
    case 0:
      bval = vib[0];
      break;
    case 1:
      bval = vib[1];
      break;
    case 2:
      bval = vib[2];
      break;
  }
  // Send response back to Master
  Wire.write(bval);

  // Increment byte counter
  bcount = bcount + 1;
  if (bcount > 4) bcount = 0;

}

void readvib()
{

 int x, y, z;
    accelerometer.getXYZ(&x, &y, &z);
    float ax, ay, az;
    accelerometer.getAcceleration(&ax, &ay, &az);
    
    Serial.println("accleration of X/Y/Z: ");
    Serial.print(ax);
    Serial.println(" g");
    Serial.print(ay);
    Serial.println(" g");
    Serial.print(az);
    Serial.println(" g");
   

vib[0]=ax;
vib[1]=ay;
vib[2]=az;


}

void loop()
{
  // Refresh readings every half second
  delay(500);
  readvib();
  Serial.println();
  Serial.println("NEW");
}

//Master

// Include Arduino Wire library for I2C
#include <Wire.h>
#include <ESP8266WiFi.h>

#include "ThingSpeak.h"
#include "secrets.h"

char ssid[] = "***";   // your network SSID (name)
char pass[] = "***";   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;


unsigned long myChannelNumber = ***;
const char * myWriteAPIKey = "***";

// Define Slave I2C Address
#define SLAVE_ADDR 9

// Define counter to count bytes in response
int bcount;

// Define array for return data
byte vib[3];

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}


byte readI2C(float address) {
  // Define a variable to hold byte of data
  byte bval ;
 //long entry = millis();
  // Read one byte at a time
  Wire.requestFrom(address, 3);
  // Wait 100 ms for data to stabilize
//  while (Wire.available() == 0 && (millis() - entry) < 100)  Serial.print("Waiting");
  // Place data into byte
 // if  (millis() - entry < 100) bval = Wire.read();
  //return bval;
}

void loop()
{
  // Connect or reconnect to WiFi
  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while (WiFi.status() != WL_CONNECTED)
    {

      WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print("\nConnecting...");
      delay(5000);
    }
    Serial.println("\nConnected.");
    Serial.println("The IP Address of ESP8266 Module is: ");
    Serial.println(WiFi.localIP());// Print the IP address
    Serial.println("Signal strength: ");
    Serial.println(WiFi.RSSI());
  }
  /*while (readI2C(SLAVE_ADDR) < 255) {
    // Until first byte has been received print a waiting message
    Serial.println("Waiting for data");
    }*/


  for (bcount = 0; bcount < 3; bcount++) {
    vib[bcount] = readI2C(SLAVE_ADDR);
  }
  for (int i = 0; i < 3; i++) {

    //float Ax= (( ( ( (float)(vib[0] * 5) / 1024) - 1.65 ) / 0.330 ) * 9.8) ;

    float A = ThingSpeak.writeField(myChannelNumber, 1, vib[0], myWriteAPIKey);
    //  int B = ThingSpeak.writeField(myChannelNumber, 2, vib[1], myWriteAPIKey);
    // int C = ThingSpeak.writeField(myChannelNumber, 3, vib[2], myWriteAPIKey);
    Serial.println(vib[0]);

  }
  Serial.println();
  Serial.println("NEW");


}

I recently wrote this I2C Tutorial . I have not tested it with an ESP8266 but looking at your Master program my guess is that the examples should work.

The advantage of starting with my examples is that they are very simple and do nothing except send and receive messages. I suggest you try to get them working before you consider adding the extra code needed for your project.

If you have a second Uno so that you can verify that I2C works between the two Unos that will help to identify any problems that might be specific to the Wemos board

Separately, I don't understand why you are sending the values in the array vib one at a time. Why not send the complete array as one message?

...R

Hello Robin2,

Thanks for the tutorial, it helped.

It turns out that i was doing a silly mistake reading float from slave and not converting them to bytes.

But right now I am stuck at the conversion itself.

I get an error

Arduino: 1.8.12 (Windows Store 1.8.33.0) (Windows 10), Board: "Arduino Uno"

C:\Users\Rohit\Documents\Arduino\i2c_uno_Adxl_lib_new_try\i2c_uno_Adxl_lib_new_try.ino: In function 'void requestEvent()':

i2c_uno_Adxl_lib_new_try:41:22: error: invalid cast from type 'float' to type 'byte* {aka unsigned char*}'

   Wire.write((byte *)ax); // respond with x

                      ^~

i2c_uno_Adxl_lib_new_try:42:22: error: invalid cast from type 'float' to type 'byte* {aka unsigned char*}'

   Wire.write((byte *)ay); // respond with y

                      ^~

i2c_uno_Adxl_lib_new_try:43:22: error: invalid cast from type 'float' to type 'byte* {aka unsigned char*}'

   Wire.write((byte *)az); // respond with z

                      ^~

exit status 1
invalid cast from type 'float' to type 'byte* {aka unsigned char*}'

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Below is the new updated code

#include "ADXL335.h"
#include <Wire.h>
#include <math.h>
#define SLAVE_ADDR 9
ADXL335 accelerometer;

void setup() {
  Serial.begin(9600);
  accelerometer.begin();
  Wire.begin(SLAVE_ADDR); // Initialize I2C communications as Slave
  Wire.onRequest(requestEvent); // Function to run when data requested from master

}


void loop() {

  int x, y, z;
  accelerometer.getXYZ(&x, &y, &z);
  float ax, ay, az;
  accelerometer.getAcceleration(&ax, &ay, &az);

  Serial.println("accleration of X/Y/Z: ");
  Serial.print(ax);
  Serial.println(" g");
  Serial.print(ay);
  Serial.println(" g");
  Serial.print(az);
  Serial.println(" g");

  delay(100);

  // function that executes whenever data is requested by master
  // this function is registered as an event, see setup()
}

void requestEvent() {

  float ax, ay, az;
  accelerometer.getAcceleration(&ax, &ay, &az);
  Wire.write((byte *)ax); // respond with x
  Wire.write((byte *)ay); // respond with y
  Wire.write((byte *)az); // respond with z
}

Can someone help me with it.

naik2408:
But right now I am stuck at the conversion itself.

Why are you bothering with a conversion? Just put the floats into a struct (as in my I2C tutorial) and send the struct.

Also, be careful to check whether a float on an Arduino is stored internally the same way as a float on an ESP8266

...R

Hello Robin2,

I am not very good at programming that’s why sending struct gets complicated for me.

Although I found another way of converting float into char and pass to master as a string which is later converted back to float which solves the purpose.

However the problem now is that for 3 sensors i have created 3 char arrays but my master reads only first array and other two sensor data is blank.

Here is the master code

#include <Wire.h>
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
#include "secrets.h"

char X[10] = {}; //empty array where to put the numbers comming from the slave
char Y[10] = {};
char Z[10] = {};
float V;
char ssid[] = "****";   // your network SSID (name)
char pass[] = "****";   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;

unsigned long myChannelNumber = ****;
const char * myWriteAPIKey = "****";

#define SLAVE_ADDR 9

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);  // Initialize ThingSpeak
}
void loop()
{
  // Connect or reconnect to WiFi
  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while (WiFi.status() != WL_CONNECTED)
    {

      WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print("\nConnecting...");
      delay(5000);
    }
    Serial.println("\nConnected.");
    Serial.println("The IP Address of ESP8266 Module is: ");
    Serial.println(WiFi.localIP());// Print the IP address
    Serial.println("Signal strength: ");
    Serial.println(WiFi.RSSI());
  }

  {
    Wire.requestFrom(9, 6);

    int i = 0; //counter for each bite as it arrives
    while (Wire.available()) {
      X[i] = Wire.read(); // every character that arrives it put in order in the empty array "t"
      i = i + 1;
    }

    int j = 0; //counter for each bite as it arrives
    while (Wire.available()) {
      Y[j] = Wire.read(); // every character that arrives it put in order in the empty array "t"
      j = j + 1;
    }

    int k = 0; //counter for each bite as it arrives
    while (Wire.available()) {
      Z[k] = Wire.read(); // every character that arrives it put in order in the empty array "t"
      k = k + 1;
    }

    Serial.print(X);
    Serial.print("\t");
    Serial.println(Y);
    Serial.print("\t");
    Serial.println(Z);

    
    V = atof (X);

    float VA = V*9.8;
    

    float A = ThingSpeak.writeField(myChannelNumber, 1, VA, myWriteAPIKey);
    Serial.println("\nChannel update successful.");
    delay(1000);
    Serial.println();
    Serial.println("NEW");


  }
}

The slave code

#include "ADXL335.h"
#include <Wire.h>
#include <math.h>
#define SLAVE_ADDR 9
ADXL335 accelerometer;

char X[10];
char Y[10];
char Z[10];



void setup() {
  Serial.begin(9600);
  accelerometer.begin();
  Wire.begin(SLAVE_ADDR); // Initialize I2C communications as Slave
  Wire.onRequest(requestEvent); // Function to run when data requested from master

}


void loop() {

  int x, y, z;
  accelerometer.getXYZ(&x, &y, &z);
  float ax, ay, az;
  accelerometer.getAcceleration(&ax, &ay, &az); //Acceleration G's

   dtostrf(ax, 3, 3, X); //convers the float or integer to a string. (floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, empty array);
  dtostrf(ay, 3, 3, Y);
  dtostrf(az, 3, 3, Z);

  Serial.print("Acceleration in G's");
  Serial.println(X);         // print the character
  Serial.println(Y);
  Serial.println(Z);
  // respond with x
  delay(1000);



  // function that executes whenever data is requested by master
  // this function is registered as an event, see setup()
}

void requestEvent() {

  
  Wire.write(X);
  Wire.write(Y);
  Wire.write(Z);
}

Serial monitor here

Robin2:
Why are you bothering with a conversion? Just put the floats into a struct (as in my I2C tutorial) and send the struct.

Also, be careful to check whether a float on an Arduino is stored internally the same way as a float on an ESP8266

…R

The ESP8266 does store the float values

naik2408:
I am not very good at programming that's why sending struct gets complicated for me.

Why not just start with one of my example programs?

...R