【问题标题】:Issues with TCP on Arduino. Reading Strings from a Python TCP Socket ServerArduino 上的 TCP 问题。从 Python TCP 套接字服务器读取字符串
【发布时间】:2014-10-08 00:22:37
【问题描述】:

我正在试验我的新 arduino UNO Rev 3 和一个简单的 python 套接字服务器。服务器代码是:

##server.py
from socket import *      #import the socket library

#MY FUNCTIONS
def send(data = str):
    conn.send(data.encode())
def recieve():
    recieve.data = conn.recv(BUFSIZE)
    recieve.data = recieve.data.decode()
    return recieve.data

##let's set up some constants
HOST = ''    #we are the host
PORT = 29876    #arbitrary port not currently in use
ADDR = (HOST,PORT)    #we need a tuple for the address
BUFSIZE = 4096    #reasonably sized buffer for data

## now we create a new socket object (serv)
## see the python docs for more information on the socket types/flags
serv = socket( AF_INET,SOCK_STREAM)

##bind our socket to the address
serv.bind((ADDR))    #the double parens are to create a tuple with one element
serv.listen(5)    #5 is the maximum number of queued connections we'll allow
print(" ")
print("Listening")
print(" ")
conn,addr = serv.accept() #accept the connection
print("Connection Established")
send('HELLOCLIENT')
send('%')
leave()

我要做的就是确认我可以与 Arduino 通信并从那里构建。以下是相关的 Arduino 代码:

void loop()
{
    int n =-1;
    while (client.connected())
    {
        n++;
        char recieved = client.read();
        inData[n] = recieved; 

        // Process message when new line character is recieved
        if (recieved == '%')
        {
            Serial.print("Arduino Received: ");
            Serial.print(inData);
            n = -1;
        }
    }
    Serial.println();
    Serial.println("Disconnecting.");
    client.stop();

}

我不断得到这个输出:

连接
Arduino 收到:ÿÿÿÿÿÿÿÿÿÿHELLOCLIENT%
断开连接。

为什么我会收到所有这些填充字符?我研究了不同的编码方法并尝试了 ASCII 和 UTF-32,但它一直在做,我错过了什么?

【问题讨论】:

  • 第一条评论:“#the double parens are to create a tuple with one element”那行不通。元组由 逗号 创建。有时您碰巧需要括号来消除歧义,但它们不是元组的一部分。 ((ADDR,)) 将一个元素的元组作为参数传递; ((ADDR)) 刚刚通过 ADDR
  • 下一步:data = str 没有将data 声明为字符串,而是将字符串类型(不是字符串值,表示类型本身的对象)设置为data 的默认值.使用recieve.data 并不完全是非法的,但它很奇怪;当您真正想要的只是一个局部变量data 时,您将属性附加到函数recieve.data。 (另外,你拼错了“receive”。)另外,leave() 应该做什么?
  • 另外,为什么这个标签是C?您有 Python 代码和 Arduino/接线代码,但我在任何地方都看不到任何 C 代码。
  • 最重要的是:您的 Arduino 代码中的 client 是什么类型?它是如何连接的?我敢打赌你正在使用某种非阻塞流,其 read 方法返回 -1(在一个字节中,它与 255 相同,这是 ÿ 的拉丁语 1)还没有什么可读的。但是在不知道你在使用什么的情况下,我无法告诉你如何修复它。

标签: python c sockets arduino


【解决方案1】:

我敢打赌这是你的问题:

无论您的 client 对象是什么,它都可能是 Arduino Ethernet Client,或具有相同接口的许多其他类型之一。

如果您查看 read 方法的文档,它会返回:

下一个字节(或字符),如果没有可用,则为 -1。

所以,当你第一次连接时,你会立即开始读取,但还没有发送任何内容,所以前几次读取都返回 -1。

由于这是一个char,-1 和 255 是相同的值。而字符 255,在 Latin-1(和 Latin-1 派生的字符集)中是 ÿ,这就是为什么你在开始时会看到一堆 ÿ。更改编码要么给你编码错误,要么将 255 解释为一些不同的字符,它不会摆脱它。

那么,你如何解决这个问题?


一些客户端类(虽然不是全部,基本的以太网客户端不是其中之一)可以进入阻塞模式,这意味着read 将等到有东西要读取。


客户端协议实际上并没有指定read 返回的类型。某些客户端类型返回 int。在int 中,与char 不同,您可以区分-1255。但是一旦你将它转换为char,你就会丢弃其他 3 个字节,并且不能再这样做了。因此,根据您使用的类型,您可以这样做:

int recieved = client.read();
if (recieved == -1) continue;
inData[n] = (char)recieved;

如果您只想发送 ASCII 文本(因此只有高达 127 的值有效),您知道 -1 永远不会是实际字符。在这种情况下,您可以这样做:

char recieved = client.read();
if (recieved == -1) continue;

大多数客户端类型都有一个方法available,它告诉您有多少字节可供读取。如果返回 0,请稍等,然后重试,而不是读取:

if (!client.available()) {
    delay(200);
    continue;
}

许多 Arduino 示例在程序开始时将其与 delay(500) 或更长的时间放在一起,因为当机会非常高以至于什么都没有时,没有必要浪费时间检查数据。


您可以在协议中添加“开始”字符,就像“结束”字符一样。与您继续阅读直到获得% 然后断开连接的方式相同,您可以先继续阅读直到获得例如$ 字符,然后丢弃所有内容:

while (client.connected()) {
    char received = client.read();
    if (received == '$') break;
}
while (client.connected()) {
    /* your original code here */
}

【讨论】:

    猜你喜欢
    • 2012-10-04
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多