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");
}
}
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.
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.
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.
}
}
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.
*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
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;
}
}
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.
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");
}
}
}
}