M.M.A.R.S.C. (HTC HD2)

 

Der Mobile M.A.R.S. Commander ist die Software zur mobile Fernsteuerung von M.A.R.S. auf einem Smartphone. Das Programm ist grundsätzlich auf jedem Smartphone mit einem Windows Mobile 6.5 Betriebssystem lauffähig. Das Programm ist natürlich auf meine Bedürfnisse angepasst, das heißt speziell für das HTC HD2 programmiert wurden. Außerdem für läuft auf meinem HTC HD2 das ENERGY Rom.

Für alle die das ebenfalls versuchen möchten: Da im Visual Studio die DTKs und TSKs nicht richtig integriert werden nach der Installation gibt es hier eine kleine Anleitung wie man die Module auch richtig einbettet und aktiviert:

http://www.davidmillington.net/news/index.php/2010/06/18/windows-mobile-6-5-3-dtk-in-visual-studio-2008

Außerdem verwende ich die .netCF 3.5 Sense Interface SDK v1.3 von

http://forum.xda-developers.com/showthread.php?t=648906

Damit das ganze etwas besser aussieht. Auf dem Video von M.A.R.S. + HTC HD2, ist dies noch nicht der Fall, bei dieser kleinen Dokumentation aber schon.

Nachdem das alles installiert ist, kann man fortfahren. Die Sense Interface SDK ist dabei keineswegs Pflicht, wird also NICHT UNBEDINGT BENÖTIGT.

Zu beachten ist, dass ich die Steuerelemente nicht mit WYSIWYG Editor des Visual Studios auf die Formfläche platziere. Dies mache ich aus zwei Gründen zur Laufzeit mittels Code: Zum einen gibt es die Sense Interface Controls nicht in der Toolbox, zum anderen erlaubt das eine größere Dynamik.

Also, los geht’s…

Nach dem Starten von Visual Studio klicken wir gleich auf :

File>New>Project

Dort auf:

Smart Device>Smart Device Project

Wichtig: wir benötigen .NET Famework 3.5

Nach dem OK wählen wir „Device Application“ und Windows Mobile 6 Professional SDK mit .NET Compact Framework Version 3.5

Nun befolgen wir David Millingtons Anleitung und gehen zu:

Project>Change Target Platform

Dort wählen wir Change to: Windows Mobile 6.5.3 Professional DTK

Nach dem neu-öffnen des Projekts können wir in der Form Faktor Drop-Down liste die von uns erstellte

„Windows Mobile 6.5.3 Professional WVGA“

auswählen.

Nun können wir ans programmieren gehen….

Zunächst fügen wir X Forms hinzu:

· frmConnection (Verbindungen)

· frmGDrive (fahren mit dem G-Sensor)

· frmTDrive (fahren mit dem Touch-Sensor)

· frmSensor (Sensoren Anzeige)

· frmCam (Steuerung eines Kamerakopfes)

dabei ist die frmConnection die Start-Up Form.

Nun zum Code:

frmConnection:

Wir benötigen zunächst die Imports:

Imports System.IO
Imports System.Drawing
Imports System.Globalization
Imports System.Reflection
Imports System.Windows.Forms
Imports Microsoft.Drawing
Imports StedySoft.SenseSDK
Imports StedySoft.SenseSDK.DrawingCE
Imports StedySoft.SenseSDK.Localization

Diese sollten klar sein.

Nun füge ich die Steuerelemente hinzu. Wenn ihr die Stedysoft Lib nicht benutzt wird das natürlich bei euch nicht so aussehen. Das ist wirklich nur die Oberfläche ohne jegliche Funktion:

Imports System.IO
Imports System.Drawing
Imports System.Globalization
Imports System.Reflection
Imports System.Windows.Forms
Imports Microsoft.Drawing
Imports StedySoft.SenseSDK
Imports StedySoft.SenseSDK.DrawingCE
Imports StedySoft.SenseSDK.Localization

Public Class frmConnection
    Dim WithEvents Connection As New SensePanelOnOffItem
    Dim WithEvents ONOFF1 As New SensePanelOnOffItem
    Dim WithEvents ONOFF2 As New SensePanelOnOffItem
    Dim WithEvents ONOFF3 As New SensePanelOnOffItem
    Dim WithEvents ONOFF4 As New SensePanelOnOffItem
    Dim WithEvents txtWait As New SensePanelTextboxItem
    Dim WithEvents txtIn As New SensePanelTextboxItem
    Dim WithEvents txtOut As New SensePanelTextboxItem
    Dim WithEvents drCOM As New SensePanelComboItem
    Dim WithEvents Panel As New SenseListControl
    Dim WithEvents COMPORT As New System.IO.Ports.SerialPort

    Dim Div As New SensePanelDividerItem
    Dim Cap As New SensePanelDividerItem
    Dim Div2 As New SensePanelDividerItem
    Dim COM2 As New SensePanelComboItem.Item("COM2", 0)
    Dim COM1 As New SensePanelComboItem.Item("COM4", 0)

    Dim inCMD As String

    Private Sub frmConnection_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '--------------- PANEL ANFANG -----------------
        Panel.AddItem(New SensePanelDividerItem(("DividerItem"), "www.techgeek.at"))
        Panel.Location = New Point(0, 0)
        Panel.Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, 320)
        Cap.Text = "Verbindung"
        Panel.AddItem(Cap)
        'VERBINDUNG
        Connection.PrimaryText = "Verbinden"
        Connection.Enabled = True
        Connection.Status = ItemStatus.Off
        Connection.SecondaryText = "Nicht Verbunden"
        Panel.AddItem(Connection)
        'IP LISTE
        drCOM.Items.Add(COM2)
        drCOM.Items.Add(COM1)
        drCOM.SelectedItem = COM2
        Panel.AddItem(drCOM)
        'WAIT TEXTBOX
        txtWait.Text = "60"
        txtWait.Multiline = False
        Panel.AddItem(txtWait)
        'Programme
        Div.Text = "Programme"
        Panel.AddItem(Div)
        'Schalter1
        ONOFF1.PrimaryText = "Autonomes Fahren"
        ONOFF1.Enabled = True
        ONOFF1.Status = ItemStatus.Off
        ONOFF1.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF1)
        'Schalter2
        ONOFF2.PrimaryText = "Linienfolgen"
        ONOFF2.Enabled = True
        ONOFF2.Status = ItemStatus.Off
        ONOFF2.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF2)
        'Schalter3
        ONOFF3.PrimaryText = "Fernsteuerung"
        ONOFF3.Enabled = True
        ONOFF3.Status = ItemStatus.Off
        ONOFF3.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF3)
        'Schalter4
        ONOFF4.PrimaryText = "Erkunden"
        ONOFF4.Enabled = True
        ONOFF4.Status = ItemStatus.Off
        ONOFF4.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF4)
        'Terminal
        Div2.Text = "Terminal"
        Panel.AddItem(Div2)
        'inBox
        txtIn.Text = "----TERTMINAL IN-----" & vbCrLf
        txtIn.Multiline = True
        txtIn.Enabled = True
        txtIn.Height = 200
        txtIn.ScrollBars = ScrollBars.Vertical
        Panel.AddItem(txtIn)
        'outBox
        txtOut.Text = ""
        txtOut.Multiline = False
        txtOut.Enabled = True
        Panel.AddItem(txtOut)

        Me.Controls.Add(Panel)
    End Sub
    Private Sub frmConnection_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
        Panel.Location = New Point(0, 0)
        Panel.Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, 800)
    End Sub

 

Screen01 Screen011

 

Das sieht doch schon ganz gut aus. Vielleicht was nicht ganz klar ist: Die texbox mit „60“ ist die Verzögerung zwischen den einzelnen Befehlen in Millisekunden. Das ist auf jedenfalls ratsam.

Eine Zeile ist wichtig:

Dim WithEvents COMPORT As New System.IO.Ports.SerialPort

Damt erstellen wir unsere neue COM-Komponente und nennen sie COMPORT. Mit COMPORT.ReadLine können wir nun die Zeilen auslesen bzw COMPORT.Write Bytes oder Strings senden.

Wenn wir nun auf eine Komponente klicken (sei es ein Button oder wie bei mir ein Change Button) soll zunächst der COM-PORT geöffnet werden mit den Parametern BAUD: 19200 COM-PORT aus der Listbox:

    Private Sub Connection_OnStatusChanged(ByVal Sender As Object, ByVal Status As StedySoft.SenseSDK.ItemStatus) Handles Connection.OnStatusChanged
        Try
            Select Case Status
                Case ItemStatus.On
                    Try
                        COMPORT.BaudRate = 19200
                        COMPORT.PortName = drCOM.SelectedText
                        COMPORT.Open()
                        Connection.SecondaryText = "Verbinden..."
                        System.Threading.Thread.Sleep(1000)
                        If (InStr(getCMD(), "Bluetooth connected")) > 0 Then
                            Connection.SecondaryText = "Verbunden"
                        Else
                            Connection.SecondaryText = "Nicht Verbunden"
                        End If
                    Catch
                        Connection.SecondaryText = "COM Fehler"
                    End Try
                Case Else
                    COMPORT.Close()
                    Connection.SecondaryText = "Nicht Verbunden"
            End Select
        Catch
            Connection.SecondaryText = "Fehler"
        End Try

    End Sub

Zu beachten ist, dass ich eine Sekunde auf den Text „Bluetooth Connected“ warte. Mein Roboter sendet zweimal den String „Bluetooth Connected“. Wenn das von unserem Programm gefunden wird, gilt das als Verbunden.

Wie man sehen kann verwende ich hier eine neue Funktion, getCMD().

Über diese Funktion lese ich die Daten über die serielle Schnittstelle.

    Function getCMD() As String
        Dim cmdIn As String = ""
        cmdIn = COMPORT.ReadLine
        txtIn.Text = txtIn.Text & "In: " & cmdIn
        txtIn.ScrollToCaret()
        getCMD = cmdIn
        COMPORT.DiscardInBuffer()
    End Function

Dabei wir alles Empfangene in der Textbox geloggt. Da alle Befehle mit dem „\r\n“ (Carrige Return, New Line) vom Roboter beendet werden, lese ich immer nur eine Zeile aus.

Das Senden geschieht über die Sub :

  Private Sub sendCMD(ByVal cmd As String)
        Dim outByte(0) As Byte

        Select Case cmd
            'Ultraschall LINKS
            Case "US_L"
                outByte(0) = 111
                Exit Select

                'ULTRASCHALL RECHTS
            Case "US_R"
                outByte(0) = 112
                Exit Select

                'AUTONOMES FAHREN = AN
            Case "Prog1=AN"
                outByte(0) = 200
                Exit Select

                'AUTONOMES FAHREN = AUS
            Case "Prog1=AUS"
                outByte(0) = 201
                Exit Select
        End Select
        Try
            COMPORT.Write(outByte, 0, 1)
            txtIn.Text = txtIn.Text & "Out: " & outByte(0) & vbCrLf
        Catch
            MsgBox("Fehler beim senden")
        End Try
    End Sub

Damit das hier nicht zu lang wird, sind nur 4 Befehle vertreten

 

Da man nur Arrays über die serielle Schnittstelle senden kann muss man das Byte, welches man senden möchte in einem Array speichern.

Fügen wir noch ein Menü hinzu, um an die anderen Forms zu kommen, und noch um die Applikation beenden zu können.

So sieht nun der Code für unsere erste Form aus:

Imports System.IO
Imports System.Drawing
Imports System.Globalization
Imports System.Reflection
Imports System.Windows.Forms
Imports Microsoft.Drawing
Imports StedySoft.SenseSDK
Imports StedySoft.SenseSDK.DrawingCE
Imports StedySoft.SenseSDK.Localization

Public Class frmConnection
    Dim WithEvents Connection As New SensePanelOnOffItem
    Dim WithEvents ONOFF1 As New SensePanelOnOffItem
    Dim WithEvents ONOFF2 As New SensePanelOnOffItem
    Dim WithEvents ONOFF3 As New SensePanelOnOffItem
    Dim WithEvents ONOFF4 As New SensePanelOnOffItem
    Dim WithEvents txtWait As New SensePanelTextboxItem
    Dim WithEvents txtIn As New SensePanelTextboxItem
    Dim WithEvents txtOut As New SensePanelTextboxItem
    Dim WithEvents drCOM As New SensePanelComboItem
    Dim WithEvents Panel As New SenseListControl
    Dim WithEvents COMPORT As New System.IO.Ports.SerialPort

    Dim Div As New SensePanelDividerItem
    Dim Cap As New SensePanelDividerItem
    Dim Div2 As New SensePanelDividerItem
    Dim COM2 As New SensePanelComboItem.Item("COM2", 0)
    Dim COM1 As New SensePanelComboItem.Item("COM4", 0)

    Dim inCMD As String

    Private Sub frmConnection_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '--------------- PANEL ANFANG -----------------
        Panel.AddItem(New SensePanelDividerItem(("DividerItem"), "www.techgeek.at"))
        Panel.Location = New Point(0, 0)
        Panel.Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, 320)
        Cap.Text = "Verbindung"
        Panel.AddItem(Cap)
        'VERBINDUNG
        Connection.PrimaryText = "Verbinden"
        Connection.Enabled = True
        Connection.Status = ItemStatus.Off
        Connection.SecondaryText = "Nicht Verbunden"
        Panel.AddItem(Connection)
        'IP LISTE
        drCOM.Items.Add(COM2)
        drCOM.Items.Add(COM1)
        drCOM.SelectedItem = COM2
        Panel.AddItem(drCOM)
        'WAIT TEXTBOX
        txtWait.Text = "60"
        txtWait.Multiline = False
        Panel.AddItem(txtWait)
        'Programme
        Div.Text = "Programme"
        Panel.AddItem(Div)
        'Schalter1
        ONOFF1.PrimaryText = "Autonomes Fahren"
        ONOFF1.Enabled = True
        ONOFF1.Status = ItemStatus.Off
        ONOFF1.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF1)
        'Schalter2
        ONOFF2.PrimaryText = "Linienfolgen"
        ONOFF2.Enabled = True
        ONOFF2.Status = ItemStatus.Off
        ONOFF2.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF2)
        'Schalter3
        ONOFF3.PrimaryText = "Fernsteuerung"
        ONOFF3.Enabled = True
        ONOFF3.Status = ItemStatus.Off
        ONOFF3.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF3)
        'Schalter4
        ONOFF4.PrimaryText = "Erkunden"
        ONOFF4.Enabled = True
        ONOFF4.Status = ItemStatus.Off
        ONOFF4.SecondaryText = "Nicht Aktiv"
        Panel.AddItem(ONOFF4)
        'Terminal
        Div2.Text = "Terminal"
        Panel.AddItem(Div2)
        'inBox
        txtIn.Text = "----TERTMINAL IN-----" & vbCrLf
        txtIn.Multiline = True
        txtIn.Enabled = True
        txtIn.Height = 200
        txtIn.ScrollBars = ScrollBars.Vertical
        Panel.AddItem(txtIn)
        'outBox
        txtOut.Text = ""
        txtOut.Multiline = False
        txtOut.Enabled = True
        Panel.AddItem(txtOut)

        Me.Controls.Add(Panel)
    End Sub
    Private Sub frmConnection_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
        Panel.Location = New Point(0, 0)
        Panel.Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, 800)
    End Sub

    Private Sub Connection_OnStatusChanged(ByVal Sender As Object, ByVal Status As StedySoft.SenseSDK.ItemStatus) Handles Connection.OnStatusChanged
        Try
            Select Case Status
                Case ItemStatus.On
                    Try
                        COMPORT.BaudRate = 19200
                        COMPORT.PortName = drCOM.SelectedText
                        COMPORT.Open()
                        Connection.SecondaryText = "Verbinden..."
                        System.Threading.Thread.Sleep(1000)
                        If (InStr(getCMD(), "Bluetooth connected")) > 0 Then
                            Connection.SecondaryText = "Verbunden"
                        Else
                            Connection.SecondaryText = "Nicht Verbunden"
                        End If
                    Catch
                        Connection.SecondaryText = "COM Fehler"
                    End Try
                Case Else
                    COMPORT.Close()
                    Connection.SecondaryText = "Nicht Verbunden"
            End Select
        Catch
            Connection.SecondaryText = "Fehler"
        End Try

    End Sub

    Private Sub sendCMD(ByVal cmd As String)
        Dim outByte(0) As Byte

        Select Case cmd
            'Ultraschall LINKS
            Case "US_L"
                outByte(0) = 111
                Exit Select

                'ULTRASCHALL RECHTS
            Case "US_R"
                outByte(0) = 112
                Exit Select

                'AUTONOMES FAHREN = AN
            Case "Prog1=AN"
                outByte(0) = 200
                Exit Select

                'AUTONOMES FAHREN = AUS
            Case "Prog1=AUS"
                outByte(0) = 201
                Exit Select
        End Select
        Try
            COMPORT.Write(outByte, 0, 1)
            txtIn.Text = txtIn.Text & "Out: " & outByte(0) & vbCrLf
        Catch
            MsgBox("Fehler beim senden")
        End Try
    End Sub

    Function getCMD() As String
        Dim cmdIn As String = ""
        cmdIn = COMPORT.ReadLine
        txtIn.Text = txtIn.Text & "In: " & cmdIn
        txtIn.ScrollToCaret()
        getCMD = cmdIn
        COMPORT.DiscardInBuffer()
    End Function

    Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
        COMPORT.Close()
        Application.Exit()
    End Sub

    Private Sub ONOFF1_OnStatusChanged(ByVal Sender As Object, ByVal Status As StedySoft.SenseSDK.ItemStatus) Handles ONOFF1.OnStatusChanged
        Select Case Status
            Case ItemStatus.On
                sendCMD("Prog1=AN")
                System.Threading.Thread.Sleep(1000)
                If (InStr(getCMD(), "#,200,AUT=AN,*")) > 0 Then
                    ONOFF1.SecondaryText = "Programm Aktiv"""
                Else
                    ONOFF1.SecondaryText = "Nicht Aktiv"
                End If
            Case Else
                sendCMD("Prog1=AUS")
                If (InStr(getCMD(), "#,201,AUT=AUS,*")) > 0 Then
                    ONOFF1.SecondaryText = "Nicht Aktiv"
                Else
                    ONOFF1.SecondaryText = "Programm Aktiv"
                End If
        End Select
    End Sub

    Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem3.Click
        Me.Hide()
    End Sub

    Private Sub MenuItem4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem4.Click
        frmGDrive.Show()
    End Sub

    Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem5.Click
        frmTDrive.Show()
    End Sub

    Private Sub MenuItem6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem6.Click
        frmSensor.Show()
    End Sub

    Private Sub MenuItem7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem7.Click
        frmCam.Show()
    End Sub
End Class

Screen02 Screen03

  1. Noch keine Kommentare vorhanden.

  1. Noch keine TrackBacks.

*