mityakoval:
When I declare both of them and set them to listen to the ports they don't work.
Correct. The master code you have won't work. The current SoftwareSerial library is the NewSoftSerial library, which has some additional documentation here: NewSoftSerial
That page has a discussion about using two software serial ports, make sure you read it and understand it. For example, it clearly states this method won't work:
void loop()
{
device1.listen();
if (device1.available() > 0)
{
int c = device1.read();
...
}
device2.listen();
if (device2.available() > 0)
{
int c = device2.read();
...
}
}
That's pretty much what your code does.
It's important to understand that when you call .listen() on one of the software serial ports, it throws away any data and resets the software serial logic to start listening to data coming in on that port. The way you have the code, you are calling .listen() on one port, which resets things, and then immediately checking if there is data. That check will happen so quickly that there is absolutely no chance that any data could be received in that time. So you move on and do the same thing with the next serial port. You are spending all of your time resetting things and selecting ports, and never giving it a chance to receive anything.
You can't listen on two ports at the same time, you can only talk to one at a time. Once you call .listen() on one of the ports, you need to give it some time to actually receive some data. I described the way I did it earlier in this thread:
ShapeShifter:
There are some restrictions when using two SoftwareSerial ports - they cannot both listen at the same time. I came up with a simple polling protocol where the Yun is the master, and the slaves don't talk unless spoken to. The code sets one SoftwareSerial to listen, and sends a poll request. After getting a response or a timeout, it sets the other SoftwareSerial to listen, and sends a poll request to that unit. After a response or timeout, it's back to the first.
You have part of this scheme in your code: SlaveNode1 only talks after receiving a 'g' character. The MasterNode has some logic to send the poll character, but it doesn't wait for a response, it just goes immediately to the listen/check code that can't work.
What you need to do is before sending the poll character to a particular slave, you should first .listen() to that slave. Then you can send the poll character, and after that you should only be checking for data available from that slave that you last polled. Once you've received a complete message from that slave, or you timed out and waited long enough with no response, you can then .listen() to the other slave and send the poll request and wait for a response.
Basically, the sequence is listen to A, send a poll to A, and wait for a response from A. Then listen to B, send a poll to B, and wait for a response from B. Then go back to A.
The official TwoPortReceive Tutorial is seriously flawed. The general structure is very much like your code, but the only reason it might work at all is because there is a long message printed to the Serial port after the .listen() call and before the .available() call. Since the Serial port and both SoftwareSerial ports are running at the same 9600 speed, that Serial.println() call gives a delay of 20 character times where data can actually be received. So there is a chance it might actually receive something in that time period. In your code, there is nothing between the .listen() and .available() calls so you have no chance to receive anything. It's very unfortunate that the official example is so poorly designed and documented. It doesn't mention the simultaneous port limitations of the SoftwareSerial port, and it doesn't explain that there must be some time after the .listen() call to actually let some data come in. I think it's just sheer dumb luck that they happened to put the Serial.println() call after the .listen() call. Had they put the println() call before the .listen() (or not put it in at all) then it wouldn't work at all. Personally, I don't think sample code should be so fragile, and if it must be fragile like that, it should explain the consequences of doing something that seems so innocent as removing a println() call - it would be very easy to assume that such a call is merely for debugging, and is not the main key to getting it to work!