Go Down

Topic: Wire.read returning constant stream of data (Read 184 times) previous topic - next topic

majhi

Hello everyone.  I'm having a tough time figuring out the error in my code.  I have a bluetooth module on a Nano, which will send data to a Mega using Wire.  Here is the code for the Nano+BT module:

Code: [Select]
char data = 0;

#define led 3
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);
   
}
void loop()
{
   if(Serial.available() > 0)      // Send data only when you receive data:
    {
      data = Serial.read();
      Serial.print(data);
      Serial.print("\n");       
      digitalWrite(led, HIGH); // flash LED when BT command received
      delay(150);
      digitalWrite(led, LOW);
      Wire.beginTransmission(A4); // SDA on Mega
      Wire.write(data);
      Wire.endTransmission();
      int x = Wire.endTransmission();
      Serial.println(x, DEC);
    }
}


This module receives BT commands just fine, but Serial.println returns 2 for Wire.endTransmission.

Here is the code for the mega:
Code: [Select]
#include <Wire.h>
#define lights 4

int data;

void setup() {
  Wire.begin(20); // SDA
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void receiveEvent(int bytes)
{
  data = Wire.read();
  Serial.print(data);
}

void loop()
{
  if (data = 1) {
    analogWrite(lights,255);
    Serial.println(data);
  }
}


With that code, the serial monitor for the Mega returns a constant stream of 1's.  I could change it to "if (data = 2)", but then it just returns a constant stream of 2's (even though the BT module is not sending a 2).  I can also remove the receiveEvent code, but it still returns 1's.  However if I change it to "if (data == 1)", then nothing is returned at all.

What am I doing wrong?  Thank you in advance.

wildbill

Not:
Code: [Select]

  if (data = 1) {

But:
Code: [Select]

  if (data == 1) {

majhi

Not:
Code: [Select]

  if (data = 1) {

But:
Code: [Select]

  if (data == 1) {

As I mentioned, having it be == instead of just = causes it to return nothing at all on the serial monitor.

johnwasser

Code: [Select]
      Serial.print(data);
      Serial.print("\n");

The traditional way to do that is "Serial.println(data);"
     
Code: [Select]
      Wire.beginTransmission(A4); // SDA on Mega
Why are you using the name of an analog input pins as a Wire address?!?  This should be the address of the remote device.  Since the code got the Mega says "Wire.begin(20);" this should say "Wire.beginTransmission(20);".  Since A4 is not defined as 20 that would explain why none of the transmissions get to the destination address.

Code: [Select]
      Wire.endTransmission();
      int x = Wire.endTransmission();

Why are you calling "Wire.endTransmission()" twice?!?
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

GolamMostafa

#4
Oct 05, 2019, 03:51 pm Last Edit: Oct 05, 2019, 04:44 pm by GolamMostafa
Your codes should be like:
Code: [Select]
char data = 0;

#define led 3
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);
  
}
void loop()
{
   if(Serial.available() > 0)      // Send data only when you receive data:
    {
      data = Serial.read();
      Serial.print(data);
      Serial.print("\n");      
      digitalWrite(led, HIGH); // flash LED when BT command received
      delay(150);
      digitalWrite(led, LOW);
      Wire.beginTransmission(20);//SlaveAddress(A4); // SDA on Mega
      Wire.write(data);
     // Wire.endTransmission();
      byte x = Wire.endTransmission();
      if (x != 0x00)
      {
         Serial.print("Transmission Problem...!");
         while(1); //wait for ever
      }
      Serial.println("Good Transmission.");//x, DEC);
    }

}


And:
Code: [Select]
#include <Wire.h>
#define lights 4
volatile bool flag1 = false;
int data;

void setup()
{
  Wire.begin(20); // SDA
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void receiveEvent(int bytes)
{
  //data = Wire.read();
  flag1 = true;//Serial.print(data);  //never ever issue print() command in this interrupt handler
}

void loop()
{
    if(flag1 == true)
    {
        data = Wire.read();
        if (data == 1)
       {
          analogWrite(lights,255);
          Serial.println(data);
          flag1 = false;
       }
       else
       {
          flag1 = false;
       }
    }
 }

majhi

Your codes should be like:
Code: [Select]
char data = 0;

#define led 3
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);
   
}
void loop()
{
   if(Serial.available() > 0)      // Send data only when you receive data:
    {
      data = Serial.read();
      Serial.print(data);
      Serial.print("\n");       
      digitalWrite(led, HIGH); // flash LED when BT command received
      delay(150);
      digitalWrite(led, LOW);
      Wire.beginTransmission(20);//SlaveAddress(A4); // SDA on Mega
      Wire.write(data);
     // Wire.endTransmission();
      byte x = Wire.endTransmission();
      if (x != 0x00)
      {
         Serial.print("Transmission Problem...!");
         while(1); //wait for ever
      }
      Serial.println("Good Transmission.");//x, DEC);
    }

}


And:
Code: [Select]
#include <Wire.h>
#define lights 4
volatile bool flag1 = false;
int data;

void setup()
{
  Wire.begin(20); // SDA
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void receiveEvent(int bytes)
{
  //data = Wire.read();
  flag1 = true;//Serial.print(data);  //never ever issue print() command in this interrupt handler
}

void loop()
{
    if(flag1 == true)
    {
        data = Wire.read();
        if (data == 1)
       {
          analogWrite(lights,255);
          Serial.println(data);
          flag1 = false;
       }
       else
       {
          flag1 = false;
       }
    }
 }


Just tried it and it still doesn't work.  In fact, upon booting the Nano, it will only read the first command and nothing more.  I send it the digit 1, it Serial.println's a 1, then prints "Transmission Problem..." as your code states.  Then it never prints another digit or flashes the LED until I reboot it, but the LED on the actual BT module itself flashes as if it received a digit.  As for the Mega, it still doesn't recognize anything.

johnwasser

The return value from Wire.endTransmission() is:
Quote
byte, which indicates the status of the transmission:
It might be helpful to display the actual value:
Code: [Select]
      byte x = Wire.endTransmission();
      if (x != 0x00)
      {
         Serial.print("Transmission Problem! Wire.endTransmission() returned ");
         Serial.println(x);
         while(1); //wait forever
      }
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

GolamMostafa

#7
Oct 05, 2019, 07:04 pm Last Edit: Oct 05, 2019, 07:09 pm by GolamMostafa
I have performed a setup using NANO(Master) and MEGA(Slave) where I have uploaded your sketches (with slight modifications); the results are OK. Please, check your I2C bus wiring as follows (MEGA has built-in 2x10k pull-up with I2C bus):
NANO (A4/SDA) --------> MEGA (SDA/20)
NANO (A5/SCL) --------> MEGA (SCL/21)
NANO (GND) <--------->  MEGA (GND)

NANO (Master) Sketch:
Code: [Select]
char data = 0;
#define led 3
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);

}
void loop()
{
  if (Serial.available() > 0)     // Send data only when you receive data:
  {
    data = Serial.read();
    Serial.println(data);
   // Serial.print("\n");
    digitalWrite(led, HIGH); // flash LED when BT command received
    delay(150);
    digitalWrite(led, LOW);
    Wire.beginTransmission(20);//SlaveAddress(A4); // SDA on Mega
    Wire.write(data);
    // Wire.endTransmission();
    byte x = Wire.endTransmission();
    if (x != 0x00)
    {
      Serial.print("Transmission Problem...!");
      while (1); //wait for ever
    }
    Serial.println("Good Transmission.");//x, DEC);
  }

}


MEGA(Slave) Sketch:
Code: [Select]
#include <Wire.h>
#define lights 4
volatile bool flag1 = false;
int data;

void setup()
{
  Wire.begin(20); // SDA
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void receiveEvent(int bytes)
{
  //data = Wire.read();
  flag1 = true;//Serial.print(data);  //never ever issue print() command in this interrupt handler
}

void loop()
{
  if (flag1 == true)
  {
    data = Wire.read();
    if (data == '1')
    {
      analogWrite(lights, 255);
      Serial.println((char)data);
      flag1 = false;
    }
    else
    {
      flag1 = false;
    }
  }
}


Screen shot: NANO


Screen shot: MEGA

majhi

I have performed a setup using NANO(Master) and MEGA(Slave) where I have uploaded your sketches (with slight modifications); the results are OK. Please, check your I2C bus wiring as follows (MEGA has built-in 2x10k pull-up with I2C bus):
NANO (A4/SDA) --------> MEGA (SDA/20)
NANO (A5/SCL) --------> MEGA (SCL/21)
NANO (GND) <--------->  MEGA (GND)

NANO (Master) Sketch:
Code: [Select]
char data = 0;
#define led 3
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);

}
void loop()
{
  if (Serial.available() > 0)     // Send data only when you receive data:
  {
    data = Serial.read();
    Serial.println(data);
   // Serial.print("\n");
    digitalWrite(led, HIGH); // flash LED when BT command received
    delay(150);
    digitalWrite(led, LOW);
    Wire.beginTransmission(20);//SlaveAddress(A4); // SDA on Mega
    Wire.write(data);
    // Wire.endTransmission();
    byte x = Wire.endTransmission();
    if (x != 0x00)
    {
      Serial.print("Transmission Problem...!");
      while (1); //wait for ever
    }
    Serial.println("Good Transmission.");//x, DEC);
  }

}


MEGA(Slave) Sketch:
Code: [Select]
#include <Wire.h>
#define lights 4
volatile bool flag1 = false;
int data;

void setup()
{
  Wire.begin(20); // SDA
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void receiveEvent(int bytes)
{
  //data = Wire.read();
  flag1 = true;//Serial.print(data);  //never ever issue print() command in this interrupt handler
}

void loop()
{
  if (flag1 == true)
  {
    data = Wire.read();
    if (data == '1')
    {
      analogWrite(lights, 255);
      Serial.println((char)data);
      flag1 = false;
    }
    else
    {
      flag1 = false;
    }
  }
}


Thanks, I got it to work.  But I think I found out what the issue is.  For some reason, the Nano isn't sending a 1.  It's receiving a 1 via BT, but it's sending a 49 to the Mega.  This is my updated code because the "if (data == 1)" does nothing:
Code: [Select]
void loop()
{
  if(flag1 == true)
  {
    data = Wire.read();
    if (data == 49)
    {
      analogWrite(lights,255);
      Serial.println((char)data);
      flag1 = false;
    }
    else
    {
      flag1 = false;
    }
  }
}


But for some reason, the serial monitor is printing a 1 anyway...  Color me confused.

majhi

Oh okay, I did some research and it turns out that's the char/int conversion.  Instead of "char data = 0;" for the Nano, I put "int data = 0;" to see what would happen.  Now the BT module receives a 1, but prints 49 in the serial monitor, just like it sends to the Mega.

Danois90

#10
Oct 05, 2019, 08:56 pm Last Edit: Oct 05, 2019, 08:56 pm by Danois90
Now the BT module receives a 1, but prints 49 in the serial monitor.
Somewhere in your setup the character "1" is printed instead of the integral value "1". The character "1" has the ASCII value 49.

Code: [Select]
char one = '1';
Serial.print(one);
Serial.print(" - ");
Serial.println((int)one);


This should print "1 - 49".
Instead of mocking what's wrong, teach what's right! ;)
When you get help, remember to thank the helper and give some karma!
Please, do NOT send me any private messages!!

groundFungus

https://www.arduino.cc/en/Reference/ASCIIchart    for more info on character codes.

GolamMostafa

#12
Oct 06, 2019, 05:51 am Last Edit: Oct 06, 2019, 09:57 am by GolamMostafa
1.  You have entered digit 1 in the InputBox (Fig-1) of Serial Monitor and then has clicked on the Send Button. As a result, the data byte 0x31 (ASCII Code of 1, Fig-2) is moving towards UNO.

Figure-1:


Figure-2:

2.  UNO has received the data byte and has saved it in a char type variable named data, which now also holds 0x31 (it holds 31; 0x is not saved; it is shown to mean that 31 is in hex). The decimal equivalent of 0x31, which a human likes is: 49 (0x31 = 3x16 + 1x1).

3.  You executed this I2C code: Wire.write(data); to send 0x31 to I2C Slave; as a result, 0x31 is transmitted to Slave.

4.  The Slave has received the data and now it makes comparison using one of the following codes which are equivalent:
Code: [Select]
if(data == 0x31)

or

Code: [Select]
if(data == 49)

or

Code: [Select]
if(data == '1')

and NOT
Code: [Select]
if(data == 1)


GolamMostafa

#13
Oct 06, 2019, 06:48 am Last Edit: Oct 06, 2019, 07:51 am by GolamMostafa
Quote
https://www.arduino.cc/en/Reference/ASCIIchart    for more info on character codes.

majhi

Y'all are awesome, thanks a ton!  I was beating my head against the wall here.

Go Up