【问题标题】:Sending JSON over serial in Python to Arduino在 Python 中通过串行方式向 Arduino 发送 JSON
【发布时间】:2019-04-15 22:29:55
【问题描述】:

我一直在尝试设置此示例 sn-p 以通过串行与 Python 进行通信。我打算发送一个简单的 JSON 数据包并在另一端使用 Arduino 对其进行反序列化。

但是从here 获取的 JSON 库会抛出 Invalid Input 的错误。

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200); 
  while(!Serial) {
  }
}

void loop() {
  int     size_ = 0;
  char    payload[256];
  String  string = "";
  if (size_ = Serial.available()) {
  for(int i =0; i < size_; i++) {
     payload[i] = Serial.read();
     string += payload[i];   
  }

  const size_t capacity = 1024;
  DynamicJsonDocument doc(capacity);
  DeserializationError error = deserializeJson(doc, payload);
  if (error) {
    Serial.println(error.c_str());
    return;
  }
    if(doc["operation"] == "ACK") {
      Serial.println("ACK has been received");
    }
    else {
      Serial.println("Error!");
    }
  }
  while (!Serial.available()) {
  }
  delay(20);
}

这是python sn-p。

import time
import json
import serial
import pprint


if __name__ == "__main__":
    print ("Ready...")
    data = {}
    data["operation"] = "ACK"
    ser = serial.Serial("COM3", baudrate= 115200, timeout=0.5)
    data = json.dumps(data)
    if ser.isOpen(): 
        (ser.write(bytes(data, "utf-8"), ))
        try:
            incoming = ser.readline().decode("utf-8")
            print ((incoming))
        except Exception as e:
            print (e)
        ser.close()
    else:
        print ("opening error")

由于某种原因,我不知道为什么,当 python 发送块时,它似乎无法识别输入。

是因为前面加了'b'吗? 是不是因为使用了编码方式?

当我尝试通过终端输入{"operation":"ACK"} 时,它可以完美识别,并返回成功消息。

为什么它不能在 python 上运行? [我正在使用 Python 3]

[更新] 我尝试更改一些 python 代码来进行一些调试。

if __name__ == "__main__":
    print ("Ready...")
    data = {}
    data["operation"] = "ACK"
    ser = serial.Serial("COM3", baudrate= 115200, timeout=1)
    data = json.dumps(data)
    buf = []

    if ser.isOpen():
        for x in (data):
            buf.append(ord(x))

        ser.write(bytearray(buf))
        try:
            incoming = ser.readline()
            for x in incoming:
                print ((x))
        except Exception as e:
            print (e)
        ser.close()
    else:
        print ("opening error")

并更改 Arduino 脚本以发回它收到的字符串。

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200); 
  while(!Serial) {
  }
}

void loop() {
  int     size_ = 0;
  char    payload[256];
  String  string = "";
  while (size_ = Serial.available()) {
  for(int i =0; i < size_; i++) {
     payload[i] = Serial.read();
     string += payload[i];   
  }

  const size_t capacity = 1024;
  DynamicJsonDocument doc(capacity);
  DeserializationError error = deserializeJson(doc, payload);
  if (error) {
    //Serial.println(error.c_str());
    Serial.print(string.length());
    for (int i = 0; i < string.length() ; i++) {
      Serial.write(string[i]);
    }
    return;
  }
    if(doc["operation"] == "ACK") {
      Serial.println("ACK has been received");
    }
    else {
      Serial.println("Error!");
    }
  }
  while (!Serial.available()) {
  }
  delay(20);
}

这是 python 输出。

Ready...

50
50
240
240
123
34
111
112
101
114
97
116
105
111
110
34
58
32
34
65
67
75
34
125

正如您所见,大小在“准备好...”之后打印了两次,并且从 Arduino 发送了两个值 240 的字符。我不明白为什么前面有这两个字符。

【问题讨论】:

  • 似乎这取决于 arduino 接收到的试图解码的实际数据——你能把它编辑成你的问题吗?如果您使用的是 Python 3,那么字符串上的 a b' 将无法识别,因为它不是有效的 JSON - 您几乎肯定需要在传输之前将字符串编码为 ascii。
  • 你用的是哪个版本的python? 2.7 还是 3?检查此链接以查找版本ehmatthes.github.io/pcc/chapter_01/osx_setup.html
  • @barny 是的,它的 python 3。你能放一个你想说的样本吗?
  • 我想说的是,您应该在问题中编辑一个示例,说明您的代码输出/尝试发送到 arduino 进行解码的确切内容。查看它(或者尝试使用 python 自己解码)几乎肯定会回答您的问题。
  • 您所要做的就是将bytes(data, "utf-8") 写入文件,然后检查文件。

标签: python c++ json arduino pyserial


【解决方案1】:

在找出问题所在一段时间后,有几个问题。

  • 波特率太快,我不得不将其降低到 9600。

  • python 的编码应该以 ASCII 格式发送。

  • 在 Arduino 上读取字符串直到需要 '\n'。
  • 将 JsonDocument 静态分配到 512 个字节有效。

    arduino JSON-Assistant 有一种方法可以找出所用架构的需求分配。

下面的python代码。

import time
import json
import serial
from pprint import pprint
import random

if __name__ == "__main__":
    print ("Ready...")
    ser  = serial.Serial("COM3", baudrate= 9600, 
           timeout=2.5, 
           parity=serial.PARITY_NONE, 
           bytesize=serial.EIGHTBITS, 
           stopbits=serial.STOPBITS_ONE
        )
    data = {}
    data["operation"] = "sequence"

    data=json.dumps(data)
    print (data)
    if ser.isOpen():
        ser.write(data.encode('ascii'))
        ser.flush()
        try:
            incoming = ser.readline().decode("utf-8")
            print (incoming)
        except Exception as e:
            print (e)
            pass
        ser.close()
    else:
        print ("opening error")

arduino 代码。

#include <ArduinoJson.h>
void setup() {
  Serial.begin(9600); 
  while(!Serial) {
  }
}

void loop() {
  int     size_ = 0;
  String  payload;
  while ( !Serial.available()  ){}
  if ( Serial.available() )
    payload = Serial.readStringUntil( '\n' );
  StaticJsonDocument<512> doc;

  DeserializationError   error = deserializeJson(doc, payload);
  if (error) {
    Serial.println(error.c_str()); 
    return;
  }
  if (doc["operation"] == "sequence") {
     Serial.println("{\"Success\":\"True\"}");
  }
  else {
      Serial.println("{\"Success\":\"False\"}");
   }
  delay(20);
}

希望有人觉得这很有用。

【讨论】:

  • 在python端,使用myJson = json.loads(incoming)读取json
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多