What would be the corresponding MPI receive routine of the broadcast routine, MPI_Bcast.
Namely, one processor broadcasts a message to a group, let's say all world, how I can have the message in these processes?
Thank you.
Regards
SRec
MPI_Bcast is both the sender and the receiver call.
Consider the prototype for it.
int MPI_Bcast ( void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm )
All machines except for the machine with id = root are receivers. The machine that has the id = root is the sender.
Related
I am making a system where I have a Pi that will send a string over UDP to an Arduino that has Wifi. The Arduino will then send some data back to the Pi. This part works flawlessly. Then the Pi will relay this same data over Serial to an Arduino Mega that has no Wifi. This is my problem. I am able to receive all the data over UDP but when I try to receive data and then send this over Serial, it glitches and nothing works. It just receives null values. I know this because on the Arduino Mega, I have setup a system where it will simply take the data it received and just send it back with the letters "ACK" signed on them so that I know that it was successfully received. All I get is null things. But when I just send the string "HI" over the Serial port and disable the UDP stuff, it magically works... sometimes. What could be going wrong?
Code on the Pi
#!/usr/bin/env python3
import serial
import time
import socket
serialData = 'null \n'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
message = b'pi'
addr = ("192.168.71.146", 2390)
def wifirecv():
global serialData
s.sendto(message, addr)
data, address = s.recvfrom(10240)
#print(data.decode())
angle = data.decode()
serialData = angle + ' \n'
while(True):
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)
ser.flush()
ser.close()
ser.open()
while True:
try:
wifirecv()
print(serialData)
ser.write(serialData.encode('utf-8'))
#ser.write(b'hi')
line = ser.readline().decode('utf-8').rstrip()
print(line)
except(KeyboardInterrupt):
ser.close()
print("Serial Closed")
exit()
Code on the Mega
void setup() {
Serial.begin(115200);
}
void loop() {
while(Serial.available() != 0){
String data = Serial.readStringUntil('\n');
Serial.println(data + ": ACK");
}
}
Despite you mention that the response from the Arduino works fine, I believe that you should use the SerialEvent interrupt callback rather than polling for the .available method. It is a much more reliable way to detect when data is present in the input buffer. I would form the input string char by char, as done in the official tutorial.
I think that the approach you opted for might be causing timing issues on the serial port since you said:
I am able to receive all the data over UDP but when I try to receive data and then send this over Serial, it glitches and nothing works
those glitches might also be a consequence of the selected baudrate or (again) the polling approach. This is reinforced by your statement:
Serial port and disable the UDP stuff, it magically works... sometimes
Have you tried using read_until(LF, None) instead of readline()? I've had better results with the first one in some acquisition routines. Check this for reference
Are you using any other resources from the Pi or the Arduino? I am not sure if the UDP messes up with the serial communication from the RPi. I would seriously doubt it, but just check if there are no reported issues with the socket library.
Finally, a tiny time.sleep(ms) between the write() and the read() in your RPi might not hurt the communication too much. For instance, in my recent experience with the I2C protocol, a tiny delay makes a huge difference for reliable communication.
The bottom line is: you have timing issues.
I have a Bluetooth module connected to my RX(0) pin on the Arduino through which I am receiving data.
I am then printing that data using a Serial.write().
These two pins correspond to COM16 in my computer.
I am now able to receive these values into processing and print them again in processing after I set the COM port to 16 in processing.
Now I want to send a particular value out from processing back to Arduino again via serial communication. I figured I could do this with the software serial.
However, I have a few questions as to how the software serial works:
If I setup a software serial, what is the COM port for the software serial for which I can send values out from processing to the Arduino?
This is the command to set the COM port in processing.
String portName ="COM16";
myPort = new Serial(this, portName, 57600);
I then use myPort.write() to send some values back to the Arduino but how do I capture the values in the soft serial?
The best way is to use Serial Event
Minimal code:
void setup() {
Serial.begin(9600); // initialize serial
}
void loop() { // you need to define a loop function even
// if not used at all.
}
// This is an interrupt.
// Code below will only execute when something is received in the RX pin.
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read(); // get the new byte
// here you can process the received byte
}
}
If you want to receive several bytes before processing them check the example in the link provided, where it concatenates the chars into a string until the \n byte is received
The advantage of this approach is that it uses interruptions, so you don't need to constantly check if something is received in the serial port.
PD: I see that in your code you use a baudrate of 57600. Just modify the code above to make sure you use the same speed, otherwise you will not receive anything (or even worse, you will receive garbage)
I would do it the other way around: use SoftSerial / AltSoftSerial for the Bluetooth module comms and the Hardware Serial for comms with Processing.
Bare in mind SoftSerial may not be as robust as a proper hardware serial port.Baud rate 57600 should work, but bare in mind higher baud rates may be unreliable.
Alternatively, if the budget/time allows it, you could use an Arduino that has multiple Serial ports (such Arduino Mega, Due, etc. which have Serial, Serial1, etc.)
The wikipedia entry states:
In computer system programming, an interrupt handler, also known as an interrupt service routine or ISR, is a callback function in microcontroller firmware, an operating system or a device driver, whose execution is triggered by the reception of an interrupt.
How is ISR a callback. Is it the PC value stored on stack itself is the callback function?
I.e., the ISR calls the interrupted function back. Hence the interrupted function is a callback.
A bit of setup code stores the address of the ISR function in the interrupt vector table to say "call me back at this address when the interrupt occurs".
To be clear, the ISR itself is the function that is "called back". The interrupted code is not the callback; it is merely "interrupted" and later "resumed".
ISR calls the interrupted function back
No, it doesn't, the program counter register is restored from stack like the return instruction does. ISR is a 'callback' because it is called via its address (stored in an interrupt vector table), and not directly.
Micro-controllers have an interrupt vector table in their flash memory at a known location. The table contains the addresses of all the ISR (reset interrupt, timer interrupts, GPIO interrupts, etc.). When an interrupt is enabled, on a specific trigger the ISR function is called: the application program is interrupted, the program counter and the processor registers are saved in the stack and the interrupt code is called. When the interrupt code is finished, the application is restored and the application program is resumed.
There is a simple example about network broadcasting in QtSDK. It is easy to send and receive broadcast information. And in the receiver side, I want to know whose broadcast packet I just received. I try QUdpSocket.peerName() in readyRead signal callback function,but I get empty string. Any clue?
You can retrieve the sender's IP address when reading the packet with QUdpSocket::readDatagram(). You need to pass to readDatagram() a pointer to a QHostAddress in which to store the address:
QHostAddress senderAddress;
yourSocket->readDatagram(&data, size, &senderAddress);
// senderAddress now represents the sender address
You can get the address as a QString or integer from senderAddress if you need to, see the documentation for QHostAddress.
If you want a host name, you can use QHostInfo to do a reverse lookup (but you are not guaranteed to get a name).
From the docs:
Returns the name of the peer as specified by connectToHost(), or an empty QString if connectToHost() has not been called.
So, if you've called connectToHost() you should get a result. You might also try peerAddress(). Unless you always connect via a name, I wouldn't expect that you'll always be able to do a reverse lookup and get a name.
If a socket is bound to IN6ADDR_ANY or INADDR_ANY and you use a call such as recvfrom() to receive messages on the socket. Is there a way to find out which interface the message came from?
In the case of IPv6 link-scope messages, I was hoping that the from argument of recvfrom() would have the scope_id field initialized to the interface Id. Unfortunately it is set to 0 in my test program.
Anybody know of a way to find out this information?
dwc is right, IPV6_PKTINFO will work for IPv6 on Linux.
Moreover, IP_PKTINFO will work for IPv4 — you can see details in manpage ip(7)
I've constructed an example that extracts the source, destination and interface addresses. For brevity, no error checking is provided. See this duplicate: Get destination address of a received UDP packet.
// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
// at this point, peeraddr is the source sockaddr
// pi->ipi_spec_dst is the destination in_addr
// pi->ipi_addr is the receiving interface in_addr
}
Apart from binding to each interface, I'm not aware of a way with IPv4, per se.
IPv6 has added the IPV6_PKTINFO socket option to address this shortcoming. With that option in effect, a struct in6_pktinfo will be returned as ancillary data.
Its been a while since I've been doing C/C++ TCP/IP coding but as far as I remember on every message (or derived socket) you can get into the IP headers information. These headers should include the receiving address which will be the IP of the interface you are asking about.
Outside of opening a separate socket on each interface as Glomek suggested, the only way I know to do this definitively on Windows is to use a raw socket, e.g.,
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
Each receive from this socket will be an IP packet, which contains both the source and destination addresses. The program I work on requires me to put the socket in promiscuous mode using the SIO_RCVALL option. Doing this means I get every IP packet the interface "sees" on the network. To extract packets expressly for my application requires me to filter the data using the addresses and ports in the IP and TCP/UDP headers. Obviously, that's probably more overhead than you're interested in. I only mention it to say this - I've never used a raw socket without putting it in promiscuous mode. So I'm not sure if you can bind it to INADDR_ANY and just use it as a regular socket from that point forward or not. It would seem to me that you can; I've just never tried it.
EDIT: Read this article for limitations regarding raw sockets on Windows. This biggest hurdle I faced on my project was that one has to be a member of the Administrators group to open a raw socket on Windows 2000 and later.