2016-09-04 40 views
1

我有一個Raspberry Pi 3B和一個Pro(v2.0)MultiWii飛行控制器中的CRIUS All。我正在使用MultiWii 2.4版本和最新的NOOBS。我能夠設置好,現在我正試圖讓Raspberry Pi通過連接兩個主板的USB/Micro USB電纜與MultiWii進行通信。Raspberry Pi從MultiWii獲取數據

目前,MultiWii沒有返回任何數據,我不知道爲什麼。從我所看到的,我有正確的協議。我已經看了幾個工作代碼回購(用Arduino的Java編寫的Python代碼),並且遵循了MultiWii documentation並閱讀了關聯的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」來連接,這是我證明是正確的位置,似乎當我運行其上工作(沒有錯誤,如果我開始運行,然後斷開USB它會拋出一個異常,因爲它失去了連接)。

在運行時,得到以下輸出(發送命令100,MSP_IDENT):

$M>dd 
00000000000000000000000000244d3e006464 
TESTING ------------------ 

更多代碼上下文參見my Git repo

編輯:固定的校驗碼在我的崗位

回答

1

我原來的問題是在我的方向位。我雖然認爲'<'用於發送命令,'>'用於請求數據。事實證明,在兩種情況下,都應該使用'<'。 '>'字符僅在MultiWii響應時使用。

1

它看起來應該是這樣,儘管我看不到從串行端口接收版本字節的位置。在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變高後再延遲一段時間以確保所有字節確實已傳輸。

+0

你是對的。我結束了一段時間(serial.available()== 0)來等待數據回來,而不是。我添加了一個計數來確保我沒有等待太久的數據返回,否則我可以綁定線程。 – Jason