Using variables in if statements

Hello,

I am trying to use a variable in an if statement. I have a master and a slave device, the slave saves data into a variable (x) and then prints it.

why doesn’t this work? note: this is located at the very bottom

   if (x == 110 ) {
    Serial.println("HI");     
   }

Here is the full code for the slave:

#include <Wire.h>
#include <Mouse.h>
#include <HID.h>

int incomingByte = 0;   // for incoming serial data

 void mouse_to_corner() {                                       //use command "mouse_to_corner" (it means what it says)
   int i;
   for (i=0; i<15; i++){
        Mouse.move(-128, -128); 
        delay(5);
  }
}

void setup() {
 Wire.begin(8);                // join i2c bus with address #8
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600);           // start serial for output
}

void loop() {
 delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
 while (1 < Wire.available()) { // loop through all but the last
   char c = Wire.read(); // receive byte as a character
   Serial.print(c);         // print the character
 }
 int x = Wire.read();    // receive byte as an integer
 Serial.println(x);         // print the integer

//==================
   if (x == 110 ) {
    Serial.println("HI");     
   }
}

Slave1.ino (1.1 KB)

You need to put html code tags around your code so it prints right, woops

Wire.begin(8); // join i2c bus with address #8

as opposed to

  Wire.begin(8);                // join i2c bus with address #8

If you Quote my post in reply, you will see code tags around the second example.

If you had read the Read Before Posting thread then you would have known about code tags and other helpful tips.

Thanks, I was previously unaware of this. I have since read the Read Before Posting thread, and updated my original post

why doesn’t this work?

if (x == 110 ) {
Serial.println(“HI”);
}

void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer

//==================
    if (x == 110 ) {
     Serial.println("HI");     
    }
}

It doesn’t work here because you read into x only when no chars are available, will always == -1 if wire works as does serial.

Also consider that receiveEvent() runs at the end of loop() and usually there is none, it gets optimized out.
In your case with that delay(100) in void loop, I’d expect problems.

Thanks, im still new to Arduino, so an example code would be much appreciated :slight_smile:

Even if you get the code right, there’s a good chance it still doesn’t work properly.

receiveEvent() won’t be optimised out as it’s registered in setup().

It’s an actually an ISR and should be treated as such: when it runs, interrupts are disabled, and the Serial.print() function needs interrupts to work properly. Furthermore, it being an ISR you should not do any real work there beyond reading the input, storing it somewhere, and setting a flag or so telling there’s data.

The proper way to do this: save the value of x in a global volatile variable, set a flag, then check in loop() for this flag and act upon it.

#include <Wire.h>
#include <Mouse.h>
#include <HID.h>

int incomingByte = 0;   // for incoming serial data

const byte MAX_SIZE = 5; // Set the maximum data size you may receive here.

volatile byte data[MAX_SIZE];
volatile byte receivedBytes;

 void mouse_to_corner() {                                       //use command "mouse_to_corner" (it means what it says)
   int i;
   for (i=0; i<15; i++){
        Mouse.move(-128, -128); 
        delay(5);
  }
}

void setup() {
 Wire.begin(8);                // join i2c bus with address #8
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(9600);           // start serial for output
}

void loop() {
  if (receivedBytes) {
    for (byte i = 0; i < receivedBytes; i++) {
      Serial.print(data[i]);
    }

    for (byte i = 0; i < receivedBytes; i++) {
      if (data[i] == 110) {
        Serial.print("HI");
      }
    }
    receivedBytes = 0; // Reset for the next use.
  }
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  if (howMany <= MAX_SIZE) {
    for (byte i = 0; i < howMany; i++) {
      data[i] = Wire.read(); // receive byte as a character
    }
    receivedBytes = howMany;
  }
  else {
    // invalid: too many bytes.
  }
}

May include typos, not tested.

Expects to finish the processing of incoming data before the next transmission arrives, or odd things may happen. At 9600 bps it takes about 1 ms to print one character, that’s a significant time. Increase your Serial speed to 115200 or so to speed that up.

There are many examples already in your IDE through File->Examples.

You should be studying from here: https://www.arduino.cc/en/Tutorial/Foundations

Then you have a chance at reading code and looking up new-to-you terms and commands.

I have been doing some research,

You should be studying from here: https://www.arduino.cc/en/Tutorial/Foundations

after a bit of work i was able to get the example code posted by GoForSmoke semi-working. its receiving data, but printing it in the wrong format. when I send 18, I get 498. and when i send 19 i get 499.

I tried switching the if statement to:

  if (receivedBytes) {
    for (byte i = 0; i < receivedBytes; i++) {
      Serial.print(data[i]);
    }

    for (byte i = 0; i < receivedBytes; i++) {
      if (data[i] == 498) {
        Serial.println("HI");
      }
    }
    receivedBytes = 0; // Reset for the next use.
  }
}

This still doesn’t work,
any ideas?

Snippets are quite useless. The problem is no doubt in the part you didn't post.
What is the type of that array data, and how is that array populated?
As it's about Serial communications I expect byte, but then the comparison with a number >255 doesn't make sense.
Also know the difference between Serial.print() and Serial.write(), that may be another cause of issues.

Heres the full code

*note: theres only 2 or 3 changes from your original post

#include <Wire.h>
#include <Mouse.h>
#include <HID.h>

int incomingByte = 0;   // for incoming serial data

const byte MAX_SIZE = 50; // Set the maximum data size you may receive here.

volatile byte data[MAX_SIZE];
volatile byte receivedBytes;

void mouse_to_corner() {                                       //use command "mouse_to_corner" (it means what it says)
  int i;
  for (i=0; i<15; i++){
       Mouse.move(-128, -128); 
       delay(5);
 }
}

void setup() {
Wire.begin(8);                // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600);           // start serial for output
}

void loop() {
 if (receivedBytes) {
   for (byte i = 0; i < receivedBytes; i++) {
     Serial.print(data[i]);
   }

   for (byte i = 0; i < receivedBytes; i++) {
     if (data[i] == 498) {
       Serial.println("HI");
     }
   }
   receivedBytes = 0; // Reset for the next use.
 }
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
 if (howMany <= MAX_SIZE) {
   for (byte i = 0; i < howMany; i++) {
    data[i] = Wire.read(); // receive byte as a character
  }
 receivedBytes = howMany;
 }
}

Heh. It’s nice that you’re following peoples’ advice rather than complaining that your original code was AN EXACT COPY of the Wire slave example! (it’s good advice - the example is awful. Although “print” in an ISR was fixed a long time ago.)

     if (data[i] == 498) {

Serial.println(“HI”);
     }

So what is actually sending the data? If this is one of those “xxx joystick to mouse” conversion programs, you might need to be aware that checking for an exact value can be problematic. For various reasons, you might never see exactly 110. You will for sure never see 498, since data is a byte array, and bytes can only hold values up to 255.
It would be safer to use a range:

if (data[i] > 100 && data[i] < 120) { ...

Have you played with your device with the original example? Does it print the sort of values you are expecting to see?

I have a few ultrasonic sensors, they send distances to my pro micro (im working on detecting an object such as a finger on a board).

my Mega2560 is acting as a master (this has my ultrasonic sensors connected to it)
and my Pro Micro is acting as a slave

the reason im sending the data to the Pro Micro is because it can act as a mouse or keyboard

if sensor #1 gives a result of “10cm”
it will print “110” on the mega2560

if sensor #4 gives a result of “8cm”
it will print “48” on the mega2560

when the data (example: 110) is sent to the pro micro, the formatting changes. so if I send 110, i will receive 4910

anyways, I hope this answers your questions :slight_smile:

Heres what i have now:

#include <Wire.h>
#include <Mouse.h>
#include <HID.h>

int incomingByte = 0;   // for incoming serial data

const byte MAX_SIZE = 50; // Set the maximum data size you may receive here.

volatile byte data[MAX_SIZE];
volatile byte receivedBytes;

 void mouse_to_corner() {                                       //use command "mouse_to_corner" (it means what it says)
   int i;
   for (i=0; i<15; i++){
        Mouse.move(-128, -128); 
        delay(5);
  }
}

void setup() {
 Wire.begin(8);                // join i2c bus with address #8
 Wire.onReceive(receiveEvent); // register event
 Serial.begin(19200);           // start serial for output
}

void loop() {
  if (receivedBytes) {
    for (byte i = 0; i < receivedBytes; i++) {
      Serial.print(data[i]);
    }

  for (byte i = 0; i < receivedBytes; i++) {
      if (data[i] >= 496 && data[i] <= 499) {                         // if sensor 1 gives a distance of 6-9cm
        Serial.println("HI");
      }
    }
    receivedBytes = 0; // Reset for the next use.
  }
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  if (howMany <= MAX_SIZE) {
    for (byte i = 0; i < howMany; i++) {
     data[i] = Wire.read(); // receive byte as a character
   }
  receivedBytes = howMany;
  }
}

if sensor #4 gives a result of "8cm"
it will print "48" on the mega2560

Check out the ASCII value of '8'. You are sending characters and interpreting them as numbers

That was part of my take. The OP is also not printing spaces between outputs with some other mistake mixed in.

When you want to see what you got, print separated 2-digit hex values (use a leading zero for values < 16) and use an ASCII table to see what is and not what some algorithm turned it into.

Am I seeing something you don’t?!

Treating the data in the loop is a bad idea as you most likely have concurrency issues. The receiveEvent(int) could called at the most inconvenient places in your main loop(), as it is asynchronous event.

Why not try to treat the data inside the even handler.

Let me know if this improves your results. (I didn’t test it for correctness besides compile)

Such as:

#include <Wire.h>
#include <Mouse.h>
#include <HID.h>

int incomingByte = 0;   // for incoming serial data

const byte MAX_SIZE = 50; // Set the maximum data size you may receive here.

volatile byte data[MAX_SIZE];
volatile byte receivedBytes;

void mouse_to_corner() {                                       //use command "mouse_to_corner" (it means what it says)
  int i;
  for (i = 0; i < 15; i++) {
    Mouse.move(-128, -128);
    delay(5);
  }
}

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  //loop does nothing as the events are treated by the handler SYNCHRONIUSLY
  delay(1);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  //first you record the bytes
  if (howMany <= MAX_SIZE) {
    for (byte i = 0; i < howMany; i++) {
      data[i] = Wire.read(); // receive byte as a character
    }
    receivedBytes = howMany;

    //here you treat the received data
    for (byte i = 0; i < receivedBytes; i++) {
      Serial.print(data[i]);
      if (data[i] == 498) {
        Serial.println("HI");
      }
    }
  }

}