I'm trying to connect two Arduino Uno (let's call them A and B) to a Mega (C) through serial (Tx Rx).
A and B would generate numbers and send them to C.
C would read the numbers and process them.
An example: A and B generate simultaneously numbers between 0 and 10 and send them to C.
C reads these number simultaneously and if the numbers are the same a LED will go on.
if (number A==number B) then LED High
I know how to make A and B generate random numbers, but don't know how to send them to C. And how to set C so that he can receive these numbers.
The process is really simple but I really don't know how to make communicate the three Arduino, and how to start writing a proper code. Do you think it would be a too difficult job for a beginner like me?
Any advice on how to manage the thing would be appreciated.
I know how to make A and B generate random numbers
Let's start with that. How random do your numbers have to be and how are you generating them ?
As to
C reads these number simultaneously
It can't actually do that, but it can do one after the other very quickly. How will C know that the numbers are a pair to be compared ?
The process is really simple but I really don't know how to make communicate the three Arduino
So start with just A and C and a serial connection between them. Serial.print() a number from A, receive it on C using Serial.read() once you know that there is something to read using Serial.available() and display it on C's serial monitor.
The Mega has 4 hardware serial ports so you are well placed to use 2 of them to receive data from the Unos and to display received data on the serial monitor.
Let's start with that. How random do your numbers have to be and how are you generating them ?
The random number would be generated by the two Arduino Uno with a simple code that I've found in the examples library.
I don't have the code with me now because I'm not writing from my computer. I will post it soon.
What do you mean "how random the number have to be"? Are you meaning how big the numbers, or how fast the generation of numbers?
It can't actually do that, but it can do one after the other very quickly.
Ok
How will C know that the numbers are a pair to be compared ?
That's the problem. I thought about the "if" protocol: if (the number sent by A==the number sent by B) then turn a LED on.
But I don't know:
1- how to send the number from A and B to C;
2- how to make possible for C to read and recognize those number.
So start with just A and C and a serial connection between them. Serial.print() a number from A, receive it on C using Serial.read() once you know that there is something to read using Serial.available() and display it on C's serial monitor.
I did already try it but it is not so easy, at least not for me. I will try again tomorrow.
The Mega has 4 hardware serial ports so you are well placed to use 2 of them to receive data from the Unos and to display received data on the serial monitor.
Yes I know, that's why I've been suggested to use a Mega and two Uno. But I thought Serial communication to be much easier, and I was wrong
How frequently do you want the Unos to generate their random numbers? Is it triggered by some external event or do you want them to do it on a timer?
If it is the second option, then you could turn the problem around and make the Mega the controller. Along these lines ...
Every n milliseconds (say), the Mega sends a specific character or a string via serial ports to each of the Unos. Each Uno is in a loop checking for this control character to arrive. When it does, it generates the random number and sends it back to the Mega over the serial port.
After sending the control character to each Uno, the Mega has been waiting for a response from the Uno. When it gets the numbers from each Uno, it carries on processing them and then loops around (after a delay, I guess?) to send the next control character to the Unos.
If you take this approach, you need to decide what happens in certain possible error conditions. For example, what if the Mega gets no response to its message to one of the Unos - does it give up, or try again after a delay, or report an error condition somehow? You want to avoid the sketch getting stuck waiting for a response that never arrives.
I've got code that does something very like this, but will need to dig it out. Let me know if that would help.
How frequently do you want the Unos to generate their random numbers? Is it triggered by some external event or do you want them to do it on a timer?
No external interaction, A and B just generate numbers by them selves and send to C.
A and B should generate random numbers any 0,5 sec (more or less).
So i guess it is "on a timer".
If it is the second option, then you could turn the problem around and make the Mega the controller. Along these lines ...
It is, I guess.
Every n milliseconds (say), the Mega sends a specific character or a string via serial ports to each of the Unos. Each Uno is in a loop checking for this control character to arrive. When it does, it generates the random number and sends it back to the Mega over the serial port.
So the Mega would be the "timer" and the two Unos will respond to the Mega's inputs and requests.
Seems like a good solution.
After sending the control character to each Uno, the Mega has been waiting for a response from the Uno. When it gets the numbers from each Uno, it carries on processing them and then loops around (after a delay, I guess?) to send the next control character to the Unos.
Ok
If you take this approach, you need to decide what happens in certain possible error conditions. For example, what if the Mega gets no response to its message to one of the Unos - does it give up, or try again after a delay, or report an error condition somehow? You want to avoid the sketch getting stuck waiting for a response that never arrives.
Why would the Unos not respond to the Mega's request? Can there be that error possibility?
In this case, I would say, the Mega should just ignore that not response has been received, and go on with the process (requesting the next number and so on).
I've got code that does something very like this, but will need to dig it out. Let me know if that would help.
I did already try it but it is not so easy, at least not for me.
Post the code that you tried, even if it did not work. That way we can see what you did and offer advice to fix or improve it. Please read the sticky at the start of this forum before posting any code and note and follow the advice given.
If the Mega and the Unos are connected through short cables, there should be virtually no chance of a response from the Unos being corrupted. But just in case something goes wrong, it is good to handle the exception rather than ending up with the whole application hanging waiting for something that will never arrive.
Here are the examples I mentioned, edited down from a larger application. Hope they are useful. They are event driven rather than using delay(). So they set timeouts and check them against millis() to decide when it is time to do something, and check if a character has arrived from the Unos before trying to process it.
Please note, the data we used only needed to be one byte long. If your numbers need more than 0 .. 255, then you will need to change the code to handle this.
This is the controlling sketch which runs on the Mega. The original sketch polls more than two devices, which is why we used for loops to iterate through them.
/////////////////////////////////////////////////////////////////////////////////////////
// Sensor polling definitions
/////////////////////////////////////////////////////////////////////////////////////////
#define NUM_SENSORS 2
const uint32_t pollCycleInterval = 1000; // Interval between the start of consecutive cycles of polling (ms)
const uint32_t responseWait = 100; // // Timeout for response from sensor before declaring it unavailable (ms)
boolean sensorActive[NUM_SENSORS] = { }; // True if response received before timeout
boolean awaitingResponse[NUM_SENSORS] = { }; // Flag to show if response "timer" is running
uint32_t pollTimeout = 0;
uint32_t responseTimeout[NUM_SENSORS] = { };
uint8_t sensorByte[NUM_SENSORS] = { };
/////////////////////////////////////////////////////////////////////////////////////////
// Sensor serial definitions
/////////////////////////////////////////////////////////////////////////////////////////
HardwareSerial sensorPort[NUM_SENSORS] = {
Serial1, // RX = pin 19, TX = pin 18
Serial2 // RX = pin 17, TX = pin 16
// Can add more here
};
void setup()
{
for (uint8_t i = 0; i < NUM_SENSORS; i++)
{
sensorPort[i].begin(9600);
sensorActive[i] = false;
awaitingResponse[i] = false;
}
pollTimeout = millis() + pollCycleInterval;
}
void loop()
{
if (millis() > pollTimeout)
{
for (uint8_t i = 0; i < NUM_SENSORS; i++)
{
sensorPort[i].write('P');
responseTimeout[i] = millis() + responseWait;
awaitingResponse[i] = true;
}
pollTimeout = millis() + pollCycleInterval;
}
for (uint8_t i = 0; i < NUM_SENSORS; i++)
{
if (sensorPort[i].available())
{
sensorByte[i] = sensorPort[i].read();
sensorActive[i] = true;
awaitingResponse[i] = false; // Stop the "timer"
}
}
for (uint8_t i = 0; i < NUM_SENSORS; i++)
{
if (awaitingResponse[i] && (millis() > responseTimeout[i]))
{
sensorActive[i] = false;
awaitingResponse[i] = false; // Stop the "timer"
}
}
// NEED TO ADD CODE HERE ...
// to check that awaitingResponse is false for all sensors
// to check for any (sensorActive[] == false) which means response not received
// and then to process the sensorByte[] received
// Because the sketch does not use delay(), you can do other processing here
// so long as you finish quick enough for next poll cycle
}
And this is the sketch that ran on the remote sensor. We were using ATTinys rather than Unos, so had to use SoftwareSerial, but the same structure should work with Unos.
/////////////////////////////////////////////////////////////////////////////////////////
// SoftwareSerial definitions
/////////////////////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
#define RECEIVE_PIN 3
#define TRANSMIT_PIN 4
SoftwareSerial portOne(RECEIVE_PIN, TRANSMIT_PIN);
uint8_t inByte = 0;
uint8_t outByte = 0;
void setup()
{
portOne.begin(9600);
}
void loop()
{
if (portOne.available())
{
// Read incoming byte to clear buffer
inByte = portOne.read();
// NEED TO ADD CODE HERE ...
// to generate the number to send back, in outByte
// Send number
portOne.write(outByte);
}
}
Ray. Whilst what you suggest and illustrate may be a good idea I can't help think that it is way beyond what the OP will understand and be able to adapt at this stage.
Let's wait and see what code he/she posts so that we can see what has been tried and how and build on that. I would still like to see something simple such as serial transmission between the Mega and a single Uno before expanding on that.
Apart from anything else there are still questions to be answered such as generation of a random number, simply using random(255); will not do, how often this is to happen and how the mega will know which pairs of numbers to compare if each Uno is sending a stream of numbers.
Actually comparing the numbers and turning on an LED is the least of the problems at the moment.
So start with just A and C and a serial connection between them. Serial.print() a number from A, receive it on C using Serial.read() once you know that there is something to read using Serial.available() and display it on C's serial monitor.
So here's my attempts:
The Arduino Uno (A) generates random number through the following code and I can visualize the number on Serial Monitor when connected via USB, so it should work:
long randNumber;
void setup(){
Serial.begin(9600);
// if analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
}
void loop() {
// print a random number from 0 to ..
randNumber = random(3000);
Serial.println(randNumber);
delay(500);
}
Now I want the Arduino Mega (C) to read that random number sent from A via serial, and that's the problem.
I've tried a lot of different sketches. I can post this but it didn't work:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600);
Serial2.begin(9600);
// opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
I have connected the Mega to my computer via USB while the Uno is connected to a power adapter.
They have a common Ground (GND) and the TX1 of the Uno is connected to the RX2 of the Mega.
It's not working though.
any suggestion?
thanks
Hackscribble:
If the Mega and the Unos are connected through short cables, there should be virtually no chance of a response from the Unos being corrupted. But just in case something goes wrong, it is good to handle the exception rather than ending up with the whole application hanging waiting for something that will never arrive.
Here are the examples I mentioned, edited down from a larger application. Hope they are useful. They are event driven rather than using delay(). So they set timeouts and check them against millis() to decide when it is time to do something, and check if a character has arrived from the Unos before trying to process it.
Please note, the data we used only needed to be one byte long. If your numbers need more than 0 .. 255, then you will need to change the code to handle this.
This is the controlling sketch which runs on the Mega. The original sketch polls more than two devices, which is why we used for loops to iterate through them.
Regards
Ray at Hackscribble
Thanks for the code Ray,
I will try to work on it, even though It seems too advanced for my level to understand.
But I'll give a try.
Don't dump your code in favour of mine just yet Robin2 makes a very good point.
And to echo something Robin2 raised about the code you posted ...
Serial.begin(9600);
Serial2.begin(9600);
I'm guessing you are using Serial (i.e. Serial0) to talk to your PC via USB, and Serial2 to talk to the Uno?
If so, the following code is waiting on your PC rather than the Uno ...
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
I think it should be Serial2.available and Serial2.read in the above code to get it to wait for the Uno and then read a byte from the Uno.
If you try changing that, let us know if you then see anything on the Mega.
Then, the next thing to look at is your Uno code seems to be sending the random number as a string of characters i.e. it displays OK on your PC. But your Mega code is currently reading the incoming data one byte at a time and displaying that. OK for testing but maybe not what you intended?
So start with just A and C and a serial connection between them. Serial.print() a number from A, receive it on C using Serial.read() once you know that there is something to read using Serial.available() and display it on C's serial monitor.
So here's my attempts:
The Arduino Uno (A) generates random number through the following code and I can visualize the number on Serial Monitor when connected via USB, so it should work:
long randNumber;
void setup(){
Serial.begin(9600);
// if analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
}
void loop() {
// print a random number from 0 to ..
randNumber = random(3000);
Serial.println(randNumber);
delay(500);
}
Now I want the Arduino Mega (C) to read that random number sent from A via serial, and that's the problem.
I've tried a lot of different sketches. I can post this but it didn't work:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600);
Serial2.begin(9600);
// opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
I have connected the Mega to my computer via USB while the Uno is connected to a power adapter.
They have a common Ground (GND) and the TX1 of the Uno is connected to the RX2 of the Mega.
It's not working though.
any suggestion?
thanks
Firstly do not initially try to send a random number because you need to know what is being sent in order to know that it is being received correctly. You can add random number generation later and discuss whether what you are generating is truly random.
So, send a fixed number, say 1234 from the Mega.
Now look at the receiving code. Each byte that is received by the Mega will have a value between 0 and 255, so how can you ever receive a number like 1234 ? What the Uno is actually sending is '1' then '2' then '3' then '4', so you must receive each byte and assemble the full number on the receiving side either as an integer of a string. Note that a String is not the same as a string.
I expect that what you are seeing on the screen as a result ofSerial.println(incomingByte, DEC);is a series of numbers between 48 and 5, which is the ASCII code for each single digit. Remove the DEC parameter and try again. What do you see ?
Hey guys, following your advices I have made a couple of changes and now the communication is working.
-- heres the two new sketches --
Arduino Uno sketch: I have change the random number broad to 0-255
long randNumber;
void setup(){
Serial.begin(9600);
// if analog input pin 0 is unconnected, random analog
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.
randomSeed(analogRead(0));
}
void loop() {
// print a random number from 0 to ...
randNumber = random(255);
Serial.println(randNumber);
delay(500);
}
Arduino Mega, I have properly adjusted the the serial connections code:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600);
Serial2.begin(9600);
// opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial2.available() > 0) {
// read the incoming byte:
incomingByte = Serial2.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
}
}
The Mega is connected to my PC and the Serial MOnitor gives these numbers (randomly?):
I received: 50
I received: 51
I received: 52
I received: 13
I received: 10
I received: 57
I received: 50
I received: 13
I received: 10
I received: 49
I received: 53
I received: 13
I received: 10
I received: 50
I received: 56
I received: 13
I received: 10
I received: 49
I received: 48
I received: 54
I received: 13
.......
.......
Hackscribble:
In your Mega sketch, try changing the Serial2.read to be ...
Serial2.parseInt()
Does that improve things?
did it and it's working.
it's giving real random number (or I guess they are) from 0 to 255.
Arduino Mega sketch:
int incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(9600);
Serial2.begin(9600);
// opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial2.available() > 0) {
// read the incoming byte:
incomingByte = Serial2.parseInt();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte);
}
}
do you think I should try to add the third Arduino (Arduino Uno) with the same code and see what happen?
I would add a new serial port for the Mega.
let's see