Raspberry Pi 从 MultiWii 获取数据
Raspberry Pi getting data from MultiWii
我有一个 Raspberry Pi 3B 和一个 CRIUS All in One Pro (v2.0) MultiWii 飞行控制器。我使用的是 MultiWii 2.4 版本和最新的 NOOBS。我能够很好地设置两者,现在我正在尝试让 Raspberry Pi 通过连接两块板的 USB/Micro USB 电缆与 MultiWii 通信。
目前,MultiWii 没有返回任何数据,我不确定为什么。据我所知,我的协议是正确的。我查看了几个工作代码回购协议(在 Arduino Java 的 Python 中编写),并遵循了 MultiWii documentation and read through the associated forum post.
这是我写的客户端代码。
package com.jmace.MaceDrone.msp;
import com.pi4j.io.serial.Baud;
import com.pi4j.io.serial.DataBits;
import com.pi4j.io.serial.FlowControl;
import com.pi4j.io.serial.Parity;
import com.pi4j.io.serial.Serial;
import com.pi4j.io.serial.SerialConfig;
import com.pi4j.io.serial.SerialDataEvent;
import com.pi4j.io.serial.SerialDataEventListener;
import com.pi4j.io.serial.SerialFactory;
import com.pi4j.io.serial.StopBits;
import java.io.IOException;
import java.math.BigInteger;
public class MultiWiiClient {
private final Serial serial;
//The preamble is defined by the protocol.
//Every message must begin with the characters $M
private static final String PREAMBLE = "$M";
//Character that denotes information being passed to the MultiWii
private static final char TO_MUTLIWII = '<';
//Character that denotes information being requested from by the MultiWii
private static final char FROM_MUTLIWII = '>';
public MultiWiiClient(String usbPort) {
SerialConfig config = new SerialConfig();
config.device(usbPort)
.baud(Baud._115200)
.dataBits(DataBits._8)
.parity(Parity.NONE)
.stopBits(StopBits._1)
.flowControl(FlowControl.NONE);
this.serial = SerialFactory.createInstance();
serial.addListener(new SerialDataEventListener() {
@Override
public void dataReceived(SerialDataEvent event) {
try {
System.out.println("[HEX DATA] " + event.getHexByteString());
System.out.println("[ASCII DATA] " + event.getAsciiString());
} catch (IOException e) {
e.printStackTrace();
}
}
});
try {
this.serial.open(config);
} catch (Exception e) {
e.printStackTrace();
}
}
public String sendRequest(MultiWiiRequest request) throws IllegalStateException, IOException {
String message = createMessage(request.getId(), false, null);
//////////////////////////////////////////////////////////////////////////////////
System.out.println(message);
System.out.println(String.format("%040x", new BigInteger(1, message.getBytes())));
//////////////////////////////////////////////////////////////////////////////////
return sendMessage(message);
}
public String sendCommand(MultiWiiCommand command, String payload) throws IllegalStateException, IOException {
String message = createMessage(command.getId(), true, payload);
return sendMessage(message);
}
/**
* This method creates the message that will be sent to the MultiWii
*
* Message format is as follows:
* +--------+---------+----+-------+----+---+
* |preamble|direction|size|command|data|crc|
* +--------+---------+----+-------+----+---+
*
* Preamble (2 bytes):
* Marks the start of a new message; always "$M"
*
* Direction (1 byte):
* Either '<' for a command going to the MultiWii or '>' for
* information being requested from the MultiWii
*
* Size (1 byte):
* The number of bytes in the payload
*
* Command (1 byte):
* The message ID of the command, as defined in the protocol
* 100's for requesting data, and 200's for requesting an action
*
* Data (variable bytes):
* The data to pass along with the command
*
* CRC (1 byte):
* Calculated with an XOR of the size, command, and each byte of data
*/
private String createMessage(int mutliWiiCommandnumber, boolean isCommand, String payload) {
StringBuilder message = new StringBuilder(PREAMBLE);
byte checksum=0;
//Get the direction of the message
if (isCommand) {
message.append(TO_MUTLIWII);
} else {
message.append(FROM_MUTLIWII);
}
int datalength = (payload != null) ? payload.length() : 0;
message.append((char) datalength);
checksum ^= datalength;
message.append((char) mutliWiiCommandnumber);
checksum ^= ((int) mutliWiiCommandnumber);
if (payload != null) {
for (char c : payload.toCharArray()){
message.append(c);
checksum ^= (int) c;
}
}
message.append((char) checksum);
return message.toString();
}
private String sendMessage(String message) throws IllegalStateException, IOException {
serial.write(message.getBytes());
serial.flush();
System.out.println("TESTING ------------------");
return "";
}
}
我正在使用“/dev/ttyUSB0”进行连接,我确认这是正确的位置并且它似乎在工作(当我 运行 它时没有错误;如果我开始 运行ning然后断开USB,它会抛出异常,因为它失去了连接)。
当运行ning时,我得到以下输出(发送命令100,MSP_IDENT):
$M>dd
00000000000000000000000000244d3e006464
TESTING ------------------
有关更多代码上下文,请参阅 my Git repo。
编辑:修复了我的 post
中的校验和代码
我发现问题出在我的方向上。我虽然那里'<'用于发送命令而'>'用于请求数据。事实证明,在这两种情况下,都应该使用“<”。 '>' 字符仅在 MultiWii 响应时使用。
看起来一切正常,但我看不到您从串行端口接收返回的版本字节的位置。在 sendMessage 中,你有 return ""
.
查看您的 github 存储库,我发现 sendMessage 有点不同。
while (!serial.getCTS()) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
StringBuilder response = new StringBuilder();
while (serial.available() != 0) {
response.append(serial.read());
}
serial.getCTS() 不应使用,因为您在构造函数中初始化端口时禁用了流量控制。
我猜这里使用 CTS 来检测其他设备何时完成消息处理并响应。
似乎不能保证在看到 CTS 线变高后,这些字节实际上可以被接收; CTS 信号仅表示设备已将它们发送给您。
您可能希望在 CTS 变高后再次延迟,以确保确实已传输所有字节。
我有一个 Raspberry Pi 3B 和一个 CRIUS All in One Pro (v2.0) MultiWii 飞行控制器。我使用的是 MultiWii 2.4 版本和最新的 NOOBS。我能够很好地设置两者,现在我正在尝试让 Raspberry Pi 通过连接两块板的 USB/Micro USB 电缆与 MultiWii 通信。
目前,MultiWii 没有返回任何数据,我不确定为什么。据我所知,我的协议是正确的。我查看了几个工作代码回购协议(在 Arduino Java 的 Python 中编写),并遵循了 MultiWii documentation and read through the associated forum post.
这是我写的客户端代码。
package com.jmace.MaceDrone.msp;
import com.pi4j.io.serial.Baud;
import com.pi4j.io.serial.DataBits;
import com.pi4j.io.serial.FlowControl;
import com.pi4j.io.serial.Parity;
import com.pi4j.io.serial.Serial;
import com.pi4j.io.serial.SerialConfig;
import com.pi4j.io.serial.SerialDataEvent;
import com.pi4j.io.serial.SerialDataEventListener;
import com.pi4j.io.serial.SerialFactory;
import com.pi4j.io.serial.StopBits;
import java.io.IOException;
import java.math.BigInteger;
public class MultiWiiClient {
private final Serial serial;
//The preamble is defined by the protocol.
//Every message must begin with the characters $M
private static final String PREAMBLE = "$M";
//Character that denotes information being passed to the MultiWii
private static final char TO_MUTLIWII = '<';
//Character that denotes information being requested from by the MultiWii
private static final char FROM_MUTLIWII = '>';
public MultiWiiClient(String usbPort) {
SerialConfig config = new SerialConfig();
config.device(usbPort)
.baud(Baud._115200)
.dataBits(DataBits._8)
.parity(Parity.NONE)
.stopBits(StopBits._1)
.flowControl(FlowControl.NONE);
this.serial = SerialFactory.createInstance();
serial.addListener(new SerialDataEventListener() {
@Override
public void dataReceived(SerialDataEvent event) {
try {
System.out.println("[HEX DATA] " + event.getHexByteString());
System.out.println("[ASCII DATA] " + event.getAsciiString());
} catch (IOException e) {
e.printStackTrace();
}
}
});
try {
this.serial.open(config);
} catch (Exception e) {
e.printStackTrace();
}
}
public String sendRequest(MultiWiiRequest request) throws IllegalStateException, IOException {
String message = createMessage(request.getId(), false, null);
//////////////////////////////////////////////////////////////////////////////////
System.out.println(message);
System.out.println(String.format("%040x", new BigInteger(1, message.getBytes())));
//////////////////////////////////////////////////////////////////////////////////
return sendMessage(message);
}
public String sendCommand(MultiWiiCommand command, String payload) throws IllegalStateException, IOException {
String message = createMessage(command.getId(), true, payload);
return sendMessage(message);
}
/**
* This method creates the message that will be sent to the MultiWii
*
* Message format is as follows:
* +--------+---------+----+-------+----+---+
* |preamble|direction|size|command|data|crc|
* +--------+---------+----+-------+----+---+
*
* Preamble (2 bytes):
* Marks the start of a new message; always "$M"
*
* Direction (1 byte):
* Either '<' for a command going to the MultiWii or '>' for
* information being requested from the MultiWii
*
* Size (1 byte):
* The number of bytes in the payload
*
* Command (1 byte):
* The message ID of the command, as defined in the protocol
* 100's for requesting data, and 200's for requesting an action
*
* Data (variable bytes):
* The data to pass along with the command
*
* CRC (1 byte):
* Calculated with an XOR of the size, command, and each byte of data
*/
private String createMessage(int mutliWiiCommandnumber, boolean isCommand, String payload) {
StringBuilder message = new StringBuilder(PREAMBLE);
byte checksum=0;
//Get the direction of the message
if (isCommand) {
message.append(TO_MUTLIWII);
} else {
message.append(FROM_MUTLIWII);
}
int datalength = (payload != null) ? payload.length() : 0;
message.append((char) datalength);
checksum ^= datalength;
message.append((char) mutliWiiCommandnumber);
checksum ^= ((int) mutliWiiCommandnumber);
if (payload != null) {
for (char c : payload.toCharArray()){
message.append(c);
checksum ^= (int) c;
}
}
message.append((char) checksum);
return message.toString();
}
private String sendMessage(String message) throws IllegalStateException, IOException {
serial.write(message.getBytes());
serial.flush();
System.out.println("TESTING ------------------");
return "";
}
}
我正在使用“/dev/ttyUSB0”进行连接,我确认这是正确的位置并且它似乎在工作(当我 运行 它时没有错误;如果我开始 运行ning然后断开USB,它会抛出异常,因为它失去了连接)。
当运行ning时,我得到以下输出(发送命令100,MSP_IDENT):
$M>dd
00000000000000000000000000244d3e006464
TESTING ------------------
有关更多代码上下文,请参阅 my Git repo。
编辑:修复了我的 post
中的校验和代码我发现问题出在我的方向上。我虽然那里'<'用于发送命令而'>'用于请求数据。事实证明,在这两种情况下,都应该使用“<”。 '>' 字符仅在 MultiWii 响应时使用。
看起来一切正常,但我看不到您从串行端口接收返回的版本字节的位置。在 sendMessage 中,你有 return ""
.
查看您的 github 存储库,我发现 sendMessage 有点不同。
while (!serial.getCTS()) {
try{
Thread.sleep(100);
} catch (Exception e) {}
}
StringBuilder response = new StringBuilder();
while (serial.available() != 0) {
response.append(serial.read());
}
serial.getCTS() 不应使用,因为您在构造函数中初始化端口时禁用了流量控制。
我猜这里使用 CTS 来检测其他设备何时完成消息处理并响应。
似乎不能保证在看到 CTS 线变高后,这些字节实际上可以被接收; CTS 信号仅表示设备已将它们发送给您。 您可能希望在 CTS 变高后再次延迟,以确保确实已传输所有字节。