2016-09-04 1 views
1

Ich habe einen Raspberry Pi 3B und einen CRIUS All in One Pro (v2.0) MultiWii Flugcontroller. Ich benutze die MultiWii 2.4 Version und die neuesten NOOBS. Ich war in der Lage, beides in Ordnung zu bringen, und nun versuche ich, den Raspberry Pi über ein USB/Micro-USB-Kabel, das die beiden Boards verbindet, mit dem MultiWii zu kommunizieren.Raspberry Pi erhält Daten von MultiWii

Momentan gibt das MultiWii keine Daten zurück, und ich bin nicht sicher warum. Von dem, was ich sehen kann, habe ich das Protokoll korrekt. Ich habe mehrere Arbeitscode-Repos (geschrieben in Python von Java für Arduino) angeschaut und bin dem MultiWii documentation gefolgt und habe den zugehörigen forum post gelesen.

Hier ist der Client-Code, den ich geschrieben habe.

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 ""; 
    } 

} 

I „/ dev/ttyUSB0“ bin mit zu verbinden, was ich bestätigt ist die korrekte Lage und es scheint (keine Fehler zu arbeiten, wenn ich es laufen, und wenn ich anfangen zu laufen und dann den USB trennen , es löst eine Ausnahme aus, weil es die Verbindung verloren hat).

Beim Laufen, erhalte ich die folgende Ausgabe (Sendebefehl 100, MSP_IDENT):

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

Siehe my Git repo für mehr Code Kontext.

EDIT: Der Fehler, der Prüfsummencodes in meinem Beitrag

Antwort

1

I stellt sich heraus, dass das Problem in meine Richtung etwas war. Ich dachte, dass dort '<' zum Senden von Befehlen verwendet wurde und '>' zum Anfordern von Daten verwendet wurde. Es stellt sich heraus, dass in beiden Fällen '<' verwendet werden sollte. Das Zeichen '>' wird nur verwendet, wenn der MultiWii antwortet.

1

Es sieht so aus, als ob es alles ist, wie es sein sollte, obwohl ich nicht sehen kann, wo Sie das Versions-Byte zurück von der seriellen Schnittstelle erhalten. In sendMessage haben Sie return "".

Mit Blick auf Ihre Github Repo, sehe ich, dass sendMessage ein bisschen anders ist.

while (!serial.getCTS()) { 
     try{ 
      Thread.sleep(100); 
     } catch (Exception e) {} 
    } 

    StringBuilder response = new StringBuilder(); 
    while (serial.available() != 0) { 
     response.append(serial.read()); 
    } 

serial.getCTS() sollte nicht als Sie deaktiviert Flusssteuerung verwendet werden, wenn Sie den Port im Konstruktor initialisiert.

Ich vermute, dass CTS hier als eine Möglichkeit verwendet wird zu erkennen, wenn das andere Gerät die Verarbeitung der Nachricht abgeschlossen hat und geantwortet hat.

Es scheint, es gibt keine Garantie, dass, nachdem die CTS-Leitung hoch gegangen ist, diese Bytes tatsächlich verfügbar sind, um empfangen zu werden; Das CTS-Signal würde nur bedeuten, dass das Gerät die Übertragung an Sie beendet hat. Sie können eine weitere Verzögerung einlegen, nachdem CTS auf "high" gesetzt wurde, um sicherzustellen, dass alle Bytes tatsächlich übertragen wurden.

+0

Sie haben Recht. Ich endete mit einer Weile (serial.available() == 0), um stattdessen auf die Daten zu warten. Ich habe eine Zählung hinzugefügt, um sicherzustellen, dass ich nicht zu lange auf die Daten warte, um zurück zu kommen, sonst könnte ich Threads binden. – Jason