Serial comm between 2 Arduinos (Now with XBee)

Solved - see below

Hello,

I am teaching myself all about the Arduino (with your help). The project I am working on right now seemed simple but I'm having problems. I simply want to press a button attached to Arduino #1, and have it turn on a LED attached to Arduino #2. When I release the button, I want the LED to extinguish. I have a LED on Arduino #1 also to verify that the button press was received.

Results: When I press the button, both the LED on Arduino #1 (hardwired) and the LED on Arduino #2 (serial) come on; however when I release the button, LED#1 goes out and LED#2 stays on. I've tried several things but always get the same result.

Below is my code for both Arduinos:

Arduino 1: int button = 10; int ledPin = 12; int val = 0;

void setup() { pinMode(button, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); }

void loop() {

val = digitalRead(button); if (val == HIGH) { digitalWrite(ledPin, HIGH); Serial.print(1); } else { digitalWrite(ledPin, LOW); }

}

Arduino 2: int ledPin = 12; //led is on pin 12 int val = 0; //variable to store the serial read data

void setup() {

pinMode(ledPin, OUTPUT); //led pin is an output, duh Serial.begin(9600); //open the serial port }

void loop() {

val = Serial.read(); if (val = 1) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }

Help... lol

Your sender needs to send 1 when the button is pressed, and 0 when the button is released, rather than sending nothing when the button is released.

Your receiver needs to use == in the if test:

  if (val = 1)

should be

  if (val == 1)

Your receiver should also be testing that there is data to read:

void loop()
{
  if(Serial.available() > 0)
  {
     int val = Serial.read();
     if(val == 1)
        // Turn LED on
     else if(val == 0)
        // Turn LED off
  }
}

I tried your code and it still didn't work. I fiddled with it and got it to work; however I do not understand WHY it works this way.

Arduino1: int button = 10; int ledPin = 13; int val = 0;

void setup() { pinMode(button, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); }

void loop() {

val = digitalRead(button); if (val == HIGH) { digitalWrite(ledPin, HIGH); Serial.write(1); //it only works with "write" and not "print" } else if (val == LOW) { digitalWrite(ledPin, LOW); Serial.print(0); //it only works with "print" and not "write" }

}

Arduino2: int ledPin = 13; //led is on pin 12 int val = 0; //variable to store the serial read data

void setup() {

pinMode(ledPin, OUTPUT); //led pin is an output, duh Serial.begin(9600); //open the serial port }

void loop() { if(Serial.available() > 0) { int val = Serial.read(); if(val == 1) // Turn LED on { digitalWrite(ledPin, HIGH);

} else if(val != 1) // Turn LED off it only works with "!=1" and not "==0" { digitalWrite(ledPin, LOW); } } }

Thank you.

Try this;

// Arduino1

int button = 10;
int ledPin = 13;
int val = 0;

void setup()  
{
  pinMode(button, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() 
  {
  val = digitalRead(button);
  if (val == HIGH) 
    {
    digitalWrite(ledPin, HIGH);
    Serial.print(1); // This should print the ascii value for '1' - 49
    }
  else if (val == LOW)  
    {
    digitalWrite(ledPin, LOW);
    Serial.print(0); // This should print the ascii value for '0' - 48
    }
  }
//Arduino2

int ledPin = 13; //led is on pin 12
int val = 0; //variable to store the serial read data

void setup()  {
  
  pinMode(ledPin, OUTPUT); //led pin is an output, duh
  Serial.begin(9600); //open the serial port
}


void loop()
  {
  if(Serial.available() > 0)
    {
    char val = Serial.read();
    if(val == '1')  // if received 49 (ASCII for '1')
      { 
      digitalWrite(ledPin, HIGH);
      }
    else if(val == '0') // if received 48 (ASCII for '0')
      {
      digitalWrite(ledPin, LOW);
      }
     else
      {
      // shouldn't get here
      }
    }
  }

Serial.print and Serial.write aren’t the same. Stick to one and you should be fine. I find .print easier to predict, so I use that.

Also remember that you’ll have to hold the button down for this to work - it won’t toggle or latch.

The reason for your confusion of "else if(val != 1) // Turn LED off it only works with "!=1" and not "==0""

is because you're using Serial.write for the 1, which literally sends a 1, as in 0x01. As opposed to the ASCII representation of a 1, which is 0x31 (49 decimal). The reason you had to say != for the 0 is because no matter how you sent it... what you sent was NOT equal to 1. It was equal to 0x30 (48 decimal) or... if you had used Serial.write, it would be equal to 0... which also not equal to 1.

Thank you so much for your help. It appears that I need to really dig into the ASCII conversion rules.

0x is simply the prefix for HEX numbers so

0x10 --- HEX 16 --- Decimal B00010000 --- Binary

Are all the same value.


Rob

Graynomad: 0x is simply the prefix for HEX numbers so

0x10 --- HEX 16 --- Decimal B00010000 --- Binary

Are all the same value.


Rob

are

Ah, so for example "0xEE" [u]Format Value[/u] binary B11101110 decimal 238 hexidecimal 0xEE

Awesome. Thank you. I understood the hex, just wasn't sure what 0x meant.

even the code I listed above -- which was working -- is now not working

Then something else has changed. Have you knocked a wire out or something? Or is this the classic programmer's "I didn't change anything, honest" line :)

The number of times I've said that only to then remember I made a small mod that "shouldn't affect anything".

Do you have any test equipment? You need to have a good look at what exactly is emanating from Arduino 1.

Once you are happy that the transmitter is working OK then you look at the receiver.

You need to know what is being received. Just expecting a LED to go on or off doesn't help when it's not working. The code only works for '1' and '0', you have no way of telling if any of the other 254 possibilities are being received.

Put some debug code in the receiver, like

char val = Serial.read(); Serial.print (val, BYTE);

and look at the results.

Embedded processing can be very frustrating, no doubt about that, but moving to another platform won't help. They're all the same horse, just different colours.


Rob

Ok... I feel like an idiot now. In my transmitter program, I have variable "val" declared as an integer, but in my argument, I put "HIGH" and "LOW" as opposed to "1" and "0". As soon as I changed this it started "working" again. At least I'm back to where I started so I can now move forward.

he he, what did I say :)

Or is this the classic programmer's "I didn't change anything, honest" line


Rob

Just to be thorough, here is the "finished" sketch that works. I added a second button and some logic that turns on different LED's based on which button(s) are pressed. I also switched to newSoftSerial for my serial connection between the arduinos.

Thanks to everyone for their help. I was getting pretty frustrated. :blush: I did find out that the 9V wall wart's I bought are unregulated therefore put out closer to 14V which is no bueno. For some reason, the serial interface would not work when using the wart.

// Arduino 1 Transmitter

include "NewSoftSerial.h"

define txPin 6 //Xmit pin

define rxPin 7 //Rcv Pin

int greenButton = 9; //green pushbutton input int redButton = 10; //red pushbutton input int greenLed = 11; //green LED output int blueLed = 13; //blue LED output int redLed = 12; //red LED output int greenVal = 0; //Value of green button int redVal = 0; //vaklue of red button NewSoftSerial mySerial(rxPin, txPin);

void setup() { pinMode(greenButton, INPUT); pinMode(redButton, INPUT); pinMode(greenLed, OUTPUT); pinMode(redLed, OUTPUT); pinMode(blueLed, OUTPUT);

mySerial.begin(38400); }

void loop() { greenVal = digitalRead(greenButton); redVal = digitalRead(redButton); //****************************************************** if ((greenVal == 1) && (redVal ==0))// is the green button pressed (and not the red)? { digitalWrite(greenLed, HIGH); // Only the green LED should come on digitalWrite(redLed, LOW); digitalWrite(blueLed, LOW); mySerial.print(1); // This should print the ascii value for '1' - 49 } //****************************************************** else if ((greenVal == 0) && (redVal == 1))// is the red button pressed (and not the green)? { digitalWrite(redLed, HIGH); //only the red LED should come on digitalWrite(greenLed, LOW); digitalWrite(blueLed, LOW); mySerial.print(2); // This should print the ascii value for '2' - 50 } //****************************************************** else if ((greenVal == 1) && (redVal == 1)) { digitalWrite(blueLed, HIGH); //only the blue LED should come on digitalWrite(greenLed, LOW); digitalWrite(redLed, LOW); mySerial.print(3); // This should print the ascii value for '3' - 51 } //****************************************************** else if ((greenVal == 0) && (redVal == 0)) { digitalWrite(greenLed, LOW); //All LEDs off digitalWrite(redLed, LOW); digitalWrite(blueLed, LOW); mySerial.print(0); // This should print the ascii value for '0' - 48 } }

//Arduino 2 Receiver

include "NewSoftSerial.h"

define txPin 6

define rxPin 7

int greenLed = 11; //green led is on pin 11 int redLed = 12; //red led is on pin 12 int blueLed = 13; //blue led is on pin 13 //int val = 0; //variable to store the mySerial read data NewSoftSerial mySerial(rxPin, txPin);

void setup() {

pinMode(greenLed, OUTPUT); //green led pin is an output pinMode(redLed, OUTPUT); //red led pin is an output pinMode(blueLed, OUTPUT); //blue led pin is an output Serial.begin(38400); //open the serial port mySerial.begin(38400); //open the newSoftSerial port }

void loop() { if(mySerial.available() > 0) { char val = mySerial.read(); Serial.print("recieved:"); Serial.println(val); //Print what Arduino 1 is sending //************************************************************ if(val == '1') // if received 49 (ASCII for '1') { digitalWrite(greenLed, HIGH);// Only the green LED should come on digitalWrite(redLed, LOW); digitalWrite(blueLed, LOW); } //************************************************************ else if(val == '2') // if received 50 (ASCII for '2') { digitalWrite(redLed, HIGH);//only the red LED should come on digitalWrite(greenLed, LOW); digitalWrite(blueLed, LOW); } //************************************************************ else if(val == '3') // if received 51 (ASCII for '3') { digitalWrite(blueLed, HIGH);//only the blue LED should come on digitalWrite(greenLed, LOW); digitalWrite(redLed, LOW); } //************************************************************ else if(val == '0') // if received 48 (ASCII for '0') { digitalWrite(greenLed, LOW);//All LEDs off digitalWrite(redLed, LOW); digitalWrite(blueLed, LOW); } //************************************************************ } }

And the final update: I have replaced the twisted pair for my serial bus between Arduinos with my XBee radios and it works like a champ! Now I can get down to writing a program that is actually useful. :)

PS: If anyone wants me to post my XBee configurations let me know.

See, it’s good when something finally works, worth the frustration IMO.

The code could be reduced a lot, but if it’s working I think we’ll let that sleeping dog lie.


Rob

By all means, if you have suggestions on how to make the code better, please share. :)

There are always a 100 ways to write code for a given problem, but here's one example that I think will do the same job.

  //                            RGB       RGB       RGB       RGB
  byte bit_patterns [] = {B00000000,B00000010,B00000100,B00000001};


void loop()
    {
    if(mySerial.available() > 0)
        {
        char val = mySerial.read();   
        char b = bit_patterns[val - '0']; // note, no bounds checking, we could get a 'Z'

        Serial.print("recieved:");
        Serial.println(val); //Print what Arduino 1 is sending

        digitalWrite(blueLed, b & 1);
        b >>= 1;
        digitalWrite(greenLed, b & 1);
        b >>= 1;
        digitalWrite(redLed, b & 1);
        }
    }
}

Rob

Grendel: ... PS: If anyone wants me to post my XBee configurations let me know.

Us the Newbies would like to see them, Ayyuuppp! (VermontSpeak)

[quote author=Terry King link=topic=56318.msg422055#msg422055 date=1302975811]

Grendel: ... PS: If anyone wants me to post my XBee configurations let me know.

Us the Newbies would like to see them, Ayyuuppp! (VermontSpeak) [/quote] Ask and ye shall receive...

I guess I should clarify that I am using the XBee Series 2 radios

Oh, and thank you Mr. Nomad. I'd actually like to come visit in Australia and stay a few... years 8)

I'd actually like to come visit in Australia and stay a few... years

You're most welcome, the country is about the same size as the 'States but with the population of NY so we've got plenty of room :).


Rob