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:
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
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
Noch keine Kommentare vorhanden.