Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 7:51 pm

Hey there,

I'm fairly new with the raspberry pi and would like help from anyone willing to take their time. I'm attempting to use a single Raspberry Pi as a server to communicate with multiple Arduinos acting as clients. It would have to be a bidirectional communication.

My question is what is the easiest way to get this done. I'm basically looking for the best programming language to use on the Raspberry Pi to communicate with the Arduinos.

If someone could point me out to the right direction that would be awesome.

Thanks,

Zach

SurferTim
Posts: 1769
Joined: Sat Sep 14, 2013 9:27 am
Location: Miramar Beach, Florida

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 8:05 pm

What equipment are you planning on using? Ethernet? WiFi? USB?

I guess it will depend on how far apart each client will be from the server.

Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 8:27 pm

SurferTim wrote:
Sat Oct 14, 2017 8:05 pm
What equipment are you planning on using? Ethernet? WiFi? USB?

I guess it will depend on how far apart each client will be from the server.
Ah yes, I should have specified that in the post. I need to use the Ethernet connection. There are Ethernet wires already running through the walls of the section in our school we need to install our little project.

SurferTim
Posts: 1769
Joined: Sat Sep 14, 2013 9:27 am
Location: Miramar Beach, Florida

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 8:49 pm

Then I would recommend UDP as the protocol. Since I am also on the Arduino forum in networking, I am aware of the example ethernet code that comes standard with the IDE. The UdpNtpClient code is a good example of a "client". I think I still have C code for the RPi "server" around somewhere if you are interested.

Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 9:30 pm

SurferTim wrote:
Sat Oct 14, 2017 8:49 pm
Then I would recommend UDP as the protocol. Since I am also on the Arduino forum in networking, I am aware of the example ethernet code that comes standard with the IDE. The UdpNtpClient code is a good example of a "client". I think I still have C code for the RPi "server" around somewhere if you are interested.
An example code would be awesome! I'm familiar with C as well so that's even better.

Thanks!

mlepage
Posts: 95
Joined: Tue Jun 12, 2012 1:58 am

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 10:26 pm

Just a note that if they were all close together, the answer might have been I2C.

SurferTim
Posts: 1769
Joined: Sat Sep 14, 2013 9:27 am
Location: Miramar Beach, Florida

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 10:36 pm

Here is the code for the RPi "server". Compile and run with

Code: Select all

cc udpbasic.c -o udpbasic
./udpbasic

Code: Select all

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>

int main(int argc, char *argv[]) {

	if(argc < 2) { 
//		if(daemon(0,0) == -1) err(1,NULL);
	}

	int sock, n, nr;
	socklen_t fromlen;
	struct sockaddr_in server;
	struct sockaddr_in from;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0)
	printf("Can not create socket in server\n");

	memset(&server, 0, sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(5005);
	server.sin_addr.s_addr = INADDR_ANY;

	if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
	printf("Can not bind in server!\n");
	memset(&from, 0, sizeof(struct sockaddr_in));
	fromlen = sizeof(struct sockaddr_in);


	while(1) {
		int n, l1;
		unsigned char tBuf[300];
		unsigned char outBuf[300];
//		fflush(stdout);

		n = recvfrom(sock, tBuf, 300, 0, (struct sockaddr*) &from, &fromlen);
		if (n < 0) {
			printf("Can not receive in server!\n");
		}

		printf("%s from IP:%s, Port:%hu\r\n",&tBuf[0],inet_ntoa(from.sin_addr), ntohs(from.sin_port));

		strcpy(outBuf,"127 127 0 0\n\0");
		socklen_t length = sizeof(struct sockaddr_in);	
		n = sendto(sock, tBuf, 64, 0, (const struct sockaddr *)&from, fromlen);
		if(n < 0) {
			printf("Can not send from client");
		}

	}
}
Here is the code for the Arduino "clients". Change the mac address and IP for each client. No duplicates of either. Change the remoteIP to the IP address of the RPi "server".

Code: Select all

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 4);
IPAddress remoteIP(192,168,1,3);

unsigned int localPort = 8888;      // local port to listen on
unsigned int remotePort = 5005;
unsigned int loopCount = 0;
unsigned long currentTime;
unsigned long lastTime;

// buffers for receiving and sending data
byte packetBuffer[48]; //buffer to hold incoming packet,
byte  ReplyBuffer[48];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  Serial.begin(115200);

  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  currentTime = millis();
  lastTime = currentTime;
}

void loop() {
  currentTime = millis();
  
  if(currentTime - lastTime > 5000) {
    lastTime = currentTime;
    // send a reply, to the IP address and port that sent us the packet we received
    ReplyBuffer[0] = 0x12;
    ReplyBuffer[1] = 0x34;
    ReplyBuffer[2] = 0x56;
    ReplyBuffer[3] = 0x78;
    sprintf((char*)&ReplyBuffer[4],"Arduino count: %u",loopCount);
    
    Udp.beginPacket(remoteIP, remotePort);
    Udp.write(ReplyBuffer,48);
//    Udp.print(loopCount,DEC);
    if(Udp.endPacket()) Serial.println("OK") ;
    loopCount++;
  }
  
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,48);
    Serial.println("Contents:");

    Serial.print(packetBuffer[0],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[1],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[2],DEC);
    Serial.print(" ");
    Serial.println(packetBuffer[3],DEC);

    unsigned long myEpoch = 0UL;
    myEpoch = packetBuffer[0];
    myEpoch = myEpoch << 8;
    myEpoch = (myEpoch | packetBuffer[1]) << 8;
    myEpoch = (myEpoch | packetBuffer[2]) << 8;
    myEpoch = myEpoch | packetBuffer[3];
    Serial.println(myEpoch);
    
    Serial.println((char*)&packetBuffer[4]);
  }
}

Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 11:05 pm

mlepage wrote:
Sat Oct 14, 2017 10:26 pm
Just a note that if they were all close together, the answer might have been I2C.
Was a possibility but no, they will be at a distance. The project is a bunch of Arduino hooked up to electrical strikes for each class in our electrical engineering department. Therefore every Arduino is one student's project and we combine them all with a raspberry pi through either a router or an Ethernet switch. But thanks for the suggestion!

Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 11:12 pm

SurferTim wrote:
Sat Oct 14, 2017 10:36 pm
Here is the code for the RPi "server". Compile and run with

Code: Select all

cc udpbasic.c -o udpbasic
./udpbasic

Code: Select all

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>

int main(int argc, char *argv[]) {

	if(argc < 2) { 
//		if(daemon(0,0) == -1) err(1,NULL);
	}

	int sock, n, nr;
	socklen_t fromlen;
	struct sockaddr_in server;
	struct sockaddr_in from;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0)
	printf("Can not create socket in server\n");

	memset(&server, 0, sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(5005);
	server.sin_addr.s_addr = INADDR_ANY;

	if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
	printf("Can not bind in server!\n");
	memset(&from, 0, sizeof(struct sockaddr_in));
	fromlen = sizeof(struct sockaddr_in);


	while(1) {
		int n, l1;
		unsigned char tBuf[300];
		unsigned char outBuf[300];
//		fflush(stdout);

		n = recvfrom(sock, tBuf, 300, 0, (struct sockaddr*) &from, &fromlen);
		if (n < 0) {
			printf("Can not receive in server!\n");
		}

		printf("%s from IP:%s, Port:%hu\r\n",&tBuf[0],inet_ntoa(from.sin_addr), ntohs(from.sin_port));

		strcpy(outBuf,"127 127 0 0\n\0");
		socklen_t length = sizeof(struct sockaddr_in);	
		n = sendto(sock, tBuf, 64, 0, (const struct sockaddr *)&from, fromlen);
		if(n < 0) {
			printf("Can not send from client");
		}

	}
}
Here is the code for the Arduino "clients". Change the mac address and IP for each client. No duplicates of either. Change the remoteIP to the IP address of the RPi "server".

Code: Select all

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 4);
IPAddress remoteIP(192,168,1,3);

unsigned int localPort = 8888;      // local port to listen on
unsigned int remotePort = 5005;
unsigned int loopCount = 0;
unsigned long currentTime;
unsigned long lastTime;

// buffers for receiving and sending data
byte packetBuffer[48]; //buffer to hold incoming packet,
byte  ReplyBuffer[48];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  Serial.begin(115200);

  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  currentTime = millis();
  lastTime = currentTime;
}

void loop() {
  currentTime = millis();
  
  if(currentTime - lastTime > 5000) {
    lastTime = currentTime;
    // send a reply, to the IP address and port that sent us the packet we received
    ReplyBuffer[0] = 0x12;
    ReplyBuffer[1] = 0x34;
    ReplyBuffer[2] = 0x56;
    ReplyBuffer[3] = 0x78;
    sprintf((char*)&ReplyBuffer[4],"Arduino count: %u",loopCount);
    
    Udp.beginPacket(remoteIP, remotePort);
    Udp.write(ReplyBuffer,48);
//    Udp.print(loopCount,DEC);
    if(Udp.endPacket()) Serial.println("OK") ;
    loopCount++;
  }
  
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,48);
    Serial.println("Contents:");

    Serial.print(packetBuffer[0],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[1],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[2],DEC);
    Serial.print(" ");
    Serial.println(packetBuffer[3],DEC);

    unsigned long myEpoch = 0UL;
    myEpoch = packetBuffer[0];
    myEpoch = myEpoch << 8;
    myEpoch = (myEpoch | packetBuffer[1]) << 8;
    myEpoch = (myEpoch | packetBuffer[2]) << 8;
    myEpoch = myEpoch | packetBuffer[3];
    Serial.println(myEpoch);
    
    Serial.println((char*)&packetBuffer[4]);
  }
}
This is gonna help a lot!

One more question, what IDE do you use on raspberry pi for C?

Thank you for taking your time!

Majorzakyo
Posts: 6
Joined: Sat Oct 14, 2017 7:45 pm

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 11:20 pm

Majorzakyo wrote:
Sat Oct 14, 2017 11:12 pm
SurferTim wrote:
Sat Oct 14, 2017 10:36 pm
Here is the code for the RPi "server". Compile and run with

Code: Select all

cc udpbasic.c -o udpbasic
./udpbasic

Code: Select all

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>

int main(int argc, char *argv[]) {

	if(argc < 2) { 
//		if(daemon(0,0) == -1) err(1,NULL);
	}

	int sock, n, nr;
	socklen_t fromlen;
	struct sockaddr_in server;
	struct sockaddr_in from;

	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0)
	printf("Can not create socket in server\n");

	memset(&server, 0, sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(5005);
	server.sin_addr.s_addr = INADDR_ANY;

	if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
	printf("Can not bind in server!\n");
	memset(&from, 0, sizeof(struct sockaddr_in));
	fromlen = sizeof(struct sockaddr_in);


	while(1) {
		int n, l1;
		unsigned char tBuf[300];
		unsigned char outBuf[300];
//		fflush(stdout);

		n = recvfrom(sock, tBuf, 300, 0, (struct sockaddr*) &from, &fromlen);
		if (n < 0) {
			printf("Can not receive in server!\n");
		}

		printf("%s from IP:%s, Port:%hu\r\n",&tBuf[0],inet_ntoa(from.sin_addr), ntohs(from.sin_port));

		strcpy(outBuf,"127 127 0 0\n\0");
		socklen_t length = sizeof(struct sockaddr_in);	
		n = sendto(sock, tBuf, 64, 0, (const struct sockaddr *)&from, fromlen);
		if(n < 0) {
			printf("Can not send from client");
		}

	}
}
Here is the code for the Arduino "clients". Change the mac address and IP for each client. No duplicates of either. Change the remoteIP to the IP address of the RPi "server".

Code: Select all

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 4);
IPAddress remoteIP(192,168,1,3);

unsigned int localPort = 8888;      // local port to listen on
unsigned int remotePort = 5005;
unsigned int loopCount = 0;
unsigned long currentTime;
unsigned long lastTime;

// buffers for receiving and sending data
byte packetBuffer[48]; //buffer to hold incoming packet,
byte  ReplyBuffer[48];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  Serial.begin(115200);

  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);

  currentTime = millis();
  lastTime = currentTime;
}

void loop() {
  currentTime = millis();
  
  if(currentTime - lastTime > 5000) {
    lastTime = currentTime;
    // send a reply, to the IP address and port that sent us the packet we received
    ReplyBuffer[0] = 0x12;
    ReplyBuffer[1] = 0x34;
    ReplyBuffer[2] = 0x56;
    ReplyBuffer[3] = 0x78;
    sprintf((char*)&ReplyBuffer[4],"Arduino count: %u",loopCount);
    
    Udp.beginPacket(remoteIP, remotePort);
    Udp.write(ReplyBuffer,48);
//    Udp.print(loopCount,DEC);
    if(Udp.endPacket()) Serial.println("OK") ;
    loopCount++;
  }
  
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,48);
    Serial.println("Contents:");

    Serial.print(packetBuffer[0],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[1],DEC);
    Serial.print(" ");
    Serial.print(packetBuffer[2],DEC);
    Serial.print(" ");
    Serial.println(packetBuffer[3],DEC);

    unsigned long myEpoch = 0UL;
    myEpoch = packetBuffer[0];
    myEpoch = myEpoch << 8;
    myEpoch = (myEpoch | packetBuffer[1]) << 8;
    myEpoch = (myEpoch | packetBuffer[2]) << 8;
    myEpoch = myEpoch | packetBuffer[3];
    Serial.println(myEpoch);
    
    Serial.println((char*)&packetBuffer[4]);
  }
}
This is gonna help a lot!

One more question, what IDE do you use on raspberry pi for C?

Thank you for taking your time!
Just saw your message about what to use to Compile it, srr bout that :P

SurferTim
Posts: 1769
Joined: Sat Sep 14, 2013 9:27 am
Location: Miramar Beach, Florida

Re: Communication between multiple Arduino and single Raspberry Pi

Sat Oct 14, 2017 11:23 pm

FYI: If you have a SD card in the Arduino's SD slot, insure you set D4 HIGH before initializing the w5100. Otherwise, it will cause you much grief with UDP.

mlepage
Posts: 95
Joined: Tue Jun 12, 2012 1:58 am

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 12:04 am

For IDE, recently, I'm liking Visual Studio Code. It's a lighter, electron-based editor, like atom.io or Sublime Text, but with better debugging functionality.

You can install it on Raspberry Pi. Then install a C++ extension for it.

Instructions etc. here: https://code.headmelted.com/

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 12:05 am

If all the Arduinos have ethernet, then perhaps MQTT is an option. They can publish/subscribe to send/receive data.

SurferTim
Posts: 1769
Joined: Sat Sep 14, 2013 9:27 am
Location: Miramar Beach, Florida

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 12:28 am

asandford wrote:
Sun Oct 15, 2017 12:05 am
If all the Arduinos have ethernet, then perhaps MQTT is an option. They can publish/subscribe to send/receive data.
If you don't plan on doing anything else, or have a Mega2560 or bigger, then MQTT would be an option. The Uno has 32K Flash (program) memory and 2K SRAM (data).

Edit: unless there is something an Arduino can do that a RPi can't, like ADC, then a RPi is much more powerful and less expensive than an Arduino/ethernet shield.

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 1:01 am

SurferTim wrote:
Sun Oct 15, 2017 12:28 am

If you don't plan on doing anything else, or have a Mega2560 or bigger, then MQTT would be an option. The Uno has 32K Flash (program) memory and 2K SRAM (data).

Edit: unless there is something an Arduino can do that a RPi can't, like ADC, then a RPi is much more powerful and less expensive than an Arduino/ethernet shield.
The MQTT client for Arduino is quite small and easily incorporated into existing sketches (assuming they're not huge).

The official UNO and ethernet sheild are very expensive compared to other devices (clones are much cheaper).

If specific features of an Arduino are not required (such as strict timing, bank programming), then use something else (ADCs are cheap addons for a Pi). The OP's phrasing of "The project is a bunch of Arduino hooked up to electrical strikes for each class in our electrical engineering department" isn't clear (to me).

User avatar
DougieLawson
Posts: 38883
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 7:46 am

asandford wrote:
Sun Oct 15, 2017 12:05 am
If all the Arduinos have ethernet, then perhaps MQTT is an option. They can publish/subscribe to send/receive data.
You can do networking from an Arduino with an ESP8266 (cheap) or Arduino Yun (£60) or ENC28J60 (10Mb/s) or Wiznet Ethernet W5100 Shield (also 10Mbp/s)
Note: Any requirement to use a crystal ball or mind reading will result in me ignoring your question.

Criticising any questions is banned on this forum.

Any DMs sent on Twitter will be answered next month.
All non-medical doctors are on my foes list.

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Communication between multiple Arduino and single Raspberry Pi

Sun Oct 15, 2017 11:00 pm

DougieLawson wrote:
Sun Oct 15, 2017 7:46 am
You can do networking from an Arduino with an ESP8266 (cheap) or Arduino Yun (£60) or ENC28J60 (10Mb/s) or Wiznet Ethernet W5100 Shield (also 10Mbp/s)
Yes, I know, not sure why you're teling me, the OP already has the gear. Anyway, I use this combination; one of these for the processing coupled with this for the I/O. If ethernet is essential, then is has that as well. I think further discussion of non-pi hardware is rather rude on this forum especially as it can replace the Pi (in certain situations - it has no video or sound).

Return to “Advanced users”