通过局域网实现树莓派和Arduino之间的通信

4
我正在使用树莓派进行图像处理,并希望它能够通过局域网与我的Arduino通信,根据树莓派的指令控制光束方向。我看到的唯一大量相关资料是在树莓派和Arduino之间建立直接连接。也许这显得有些天真,但我试图通过以太网库程序化的Arduino作为服务器,通过套接字库程序化的树莓派作为客户端来实现通信。我在路由器上给它们都设置了静态IP,并使用以下代码来尝试连接,但当我的Python代码执行连接到Arduino的IP特定端口的命令时,遇到了 "socket.error: [Errno 113] No route to host" 错误。

你有任何更好的方法来建立这种连接吗?对我来说,主要目标是能够通过局域网完成此操作,所以USB连接和直接I2C连接并不管用,虽然它们肯定能胜任该工作。

树莓派:

from socket import *
import select

data = None

timeout = 3 # timeout in seconds
msg = "test"

host = "192.168.1.113"
print ("Connecting to " + host)

port = 23

s = socket(AF_INET, SOCK_STREAM)
print "Socket made"

ready = select.select([s],[],[],timeout)


s.connect((host,port))
print("Connection made")

while True:

    if data != None:
        print("[INFO] Sending message...")
        s.sendall(msg)
        data = None
        print("[INFO] Message sent.")
        continue

    if ready[0]:        #if data is actually available for you
        data = s.recv(4096)
        print("[INFO] Data received")
        print data
        continue

Arduino:

//90-a2-da-0f-25-E7
byte mac[] = {0x90, 0xA2, 0xDA, 0x0f, 0x25, 0xE7};

//ip Address for shield
byte ip[] = {192,168,1,113};

//Use port 23
EthernetServer server = EthernetServer(23);

void setup() {
  //init device
  Ethernet.begin(mac,ip);
  //start listening for clients
  server.begin();

  Serial.begin(9600);     //For visual feedback on what's going on
  while(!Serial){
    ;   //cause Leonardo
  }
  delay(1000);
  if(server.available()){
  Serial.write("Client available");
}
}

void loop() {
  // put your main code here, to run repeatedly:
  EthernetClient client = server.available();
    if (client == true){
      Serial.write("Client Connected.");

      if(client.read() > 0){
        Serial.write(client.read());        
      }
      else{
        server.write("ping");
      }
    }
    else{
      Serial.println("No one's here yet...");
    }
    delay(1500);
}

你尝试过使用电脑发送和接收数据,以确定问题出在哪里吗? - Mido
我没有这样做,但我最初认为可能是他们的协议不兼容之类的问题。你认为我应该能够进行直接连接吗?无论如何,我会尝试一下并回来告诉你。 - David Tran
1个回答

7
挖掘一番之后,我找到了解决方案以及更多细节。因此,树莓派和Arduino都可以进行TCP通信,而且我找到了导致错误的原因。
1)我认为在Arduino代码中的server.begin()后设置的延迟是给我带来错误的原因,因为它会暂停程序,所以可能也会暂停监听进程。
2)R-Pi客户端代码中的while循环导致了一个broken pipe错误。
3)Arduino的loop()中的if (client == True)测试无法正常工作。R-Pi可以连接并发送消息而不会出现错误,但Arduino似乎没有正确响应。一旦我将所有内容都从if语句中删除,R-Pi就开始接收我的消息,并且我可以看到所有反应。这是我的最终代码:
R-Pi:
from socket import *
import select

data = None

timeout = 3 # timeout in seconds
msg = "test"

host = "192.168.1.113"
print ("Connecting to " + host)

port = 23

s = socket(AF_INET, SOCK_STREAM)
print "Socket made"

ready = select.select([s],[],[],timeout)


s.connect((host,port))
print("Connection made")


if ready[0]:        #if data is actually available for you
    print("[INFO] Sending message...")
    s.sendall(msg)
    print("[INFO] Message sent.")

    data = s.recv(4096)
    print("[INFO] Data received")
    print data

Arduino:

#include <SPI.h>
#include <Ethernet.h>

//90-a2-da-0f-25-E7
byte mac[] = {0x90, 0xA2, 0xDA, 0x0f, 0x25, 0xE7};

//ip Address for shield
byte ip[] = {192,168,1,113};

//Use port 23 for telnet
EthernetServer server = EthernetServer(23);

void setup() {
  Serial.begin(9600);     //For visual feedback on what's going on
  while(!Serial){
    ;   //wait for serial to connect -- needed by Leonardo
  }

  Ethernet.begin(mac,ip); // init EthernetShield
  delay(1000);

  server.begin();
  if(server.available()){
    Serial.println("Client available");
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  EthernetClient client = server.available();
  message = client.read();

  server.write(message);
  server.write("Testu ");
  Serial.println(message);

//  if (client == true){                    <----- This check screwed it up. Not needed.
//    Serial.println("Client Connected.");
//    server.write(client.read());        //send back to the client whatever     the client sent to us.
//  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接