08-27-2015 02:02 AM - edited 08-27-2015 02:03 AM
Hallo liebe Diadem-Gemeinde,
da ich im Moment vor einem großen Problem stehe und euer Forum hier gefunden habe, hoffe ich das ihr mir helfen könnt.
Ich möchte einen Gyro-Sensor über die serielle Schnittstelle in Diadem-Script einbinden.
Über ein Terminalprogramm habe ich bereits problemlos die Kommunikation zum Sensor überprüft, ein Schreibbefehl mit "C2" reicht, um eine 31Byte lange Antwort zu erhalten, siehe Anhang.
Um die Kommunikation über Diadem zu testen habe ich den Schnittstellenmonitor verwendet, und bin schon über die erste Probleme gestolpert. Der Schnittstellenmonitor zeigt mir nie die komplette Antwort fehlerfrei an. Wieso ist das so? Ich habe auch mehrere Einstellungen durchprobiert, s. Anhang.
Nun zum eigentlichen Code, der im Endeffekt funktionieren soll.
Bei der Init des Programms sowie der COM-Init habe ich mich an die Beispiele aus der Diadem-Hilfe orierntiert, sodass dort kein Fehler vorhanden sein sollte.
Bei Read_Channel habe ich nun das Problem, dass ich offensichtlich keine oder falsche Daten zurück bekomme. Möglicherweise schicke ich auch nicht korrekt den Write-Befehl ab.....Jedenfalls erhalte ich den Fehler "Index außerhalb des gültigen Bereichs" in der Zeile
if (Datenarray(00) = "C2") Then
Ich nehme an, dass im Datenarray möglicherweise garnichts drinsteht.
Hier der Code:
Option Explicit 'Erzwingt die explizite Deklaration aller Variablen in einem Script'
Dim oUDIM
'******************************************************************************
' Funktion zur Initialisierung des Gerätes
'******************************************************************************
Sub SFD_Init( DeviceParam1V, DeviceParam2V, ErrorP )
'Initialisiert den Ablauf // DeviceParam1V gibt den Seriellen Port an'
Set oUDIM=CreateObject("DIAdem.SFD.UDI" ) 'Generiert das Objekt DIAdem.SFD'
Dim Port
Port = DeviceParam1V 'COM-Port des Sensors'
'ruft die COMInit-Funktion auf'
Call SFDU_COMInit(oUDIM, Port & ",115200,N,8,1") 'baud 115200, bytesize 8, parity none, onestopbit'
End sub
'******************************************************************************
' Prozedur zur Deinitialisierung der Geräte
'******************************************************************************
Sub SFD_DeInit(ErrorP )
oUDIM.Close()
' Löschen des UDI-Objekts
Set oUDIM = Nothing
End Sub
'******************************************************************************
' Com-Init
'******************************************************************************
Sub SFDU_COMInit(oUDI,sgCOMParams)
Dim aCOMParams,sgParamsT,sgTimeoutCurrentT
' Umsetzen der Parameterbeschreibung, um die Schlüsselworter schnell
' und einfach erkennen zu können
sgParamsT = UCase(sgCOMParams)
' Zerlegen der gesamten Beschreibung in einzelne Abschnitte
aCOMParams = Split(sgParamsT,",")
' Wurden Parameter gefunden?
if ( Not IsArray(aCOMParams) ) Then Exit Sub
'-------------------------------------------------
' Prüfen, ob der "Name" des seriellen I/O port
' richtig angegeben wurde...
'-------------------------------------------------
if ( 0 <= UBound(aCOMParams) ) Then
If ( 1 > InStr(aCOMParams(0),"COM")) Then Exit Sub
'-------------------------------------------------
' Prüfen, ob die Schnittstelle bereits
' geöffnet ist
'-------------------------------------------------
if ( not oUDI.IsOpen ) then Call oUDI.Open("COM",aCOMParams(0))
Else
Exit Sub
End If
'-------------------------------------------------
' Prüfen, ob Parameter für die serielle Schnitt-
' stelle angegeben wurden
'-------------------------------------------------
if ( 1 <= UBound(aCOMParams) ) Then
Call oUDI.ParamSet( "BAUDRATE",aCOMParams(1))
End If
'-------------------------------------------------
' .. Prüfen der Baudrate
'-------------------------------------------------
if ( 2 <= UBound(aCOMParams) ) Then
Select Case aCOMParams(2)
Case "N"
Call oUDI.ParamSet( "PARITY", "NONE" )
End Select
End If
'-------------------------------------------------
' .. Prüfen der Anzahl der Datenbits
'-------------------------------------------------
if ( 3 <= UBound(aCOMParams) ) Then
Call oUDI.ParamSet( "DATABITS",aCOMParams(3))
End If
'-------------------------------------------------
' .. Prüfen der Anzahl der Stopbits
'-------------------------------------------------
if ( 4 <= UBound(aCOMParams) ) Then
Call oUDI.ParamSet( "STOPBITS",aCOMParams(4))
End If
'-------------------------------------------------
' Lesen "alter" Werte ...
'-------------------------------------------------
sgTimeoutCurrentT = oUDI.ParamGet("Timeout")
if ( 1 <= Len(sgTimeoutCurrentT) ) Then
Call oUDI.ParamSet("Timeout",10)
Call oUDI.Read(1000,0)
' Zurücksetzen der Einstellungen für "Timeout"
Call oUDI.ParamSet("Timeout",sgTimeoutCurrentT)
End If
End Sub
'******************************************************************************
' Funktionen zum Einlesen von Daten
'******************************************************************************
'
Sub SFD_ReadChannel(ChannelNumberP,ParamP,DataP,ErrorP )
Dim result
Dim Datenarray
' Diese Funktion muss für ein Skript zur Datenerfassung implementiert werden'
DataP = 0
oUDIM.Write "$C2"
result = oUDIM.Read()
'Antwort des Sensors splitten, um einzelne Ergebnisse zu erhalten'
Datenarray = Split(result, ";", -1, 1)
'Datenauswertung'
if (Datenarray(00) = "C2") Then
If ParamP = "AccelX" Then
Dim accelx_hexarray(3)
accelx_hexarray(00) = Datenarray(01)
accelx_hexarray(01) = Datenarray(02)
accelx_hexarray(02) = Datenarray(03)
accelx_hexarray(03) = Datenarray(04)
DataP = Umrechung (accelx_hexarray)
End if
End Sub
Sub Umrechnung (IEEE)
'wird noch erstellt'
End Sub
Könnt ihr mir weiterhelfen??
08-28-2015 03:49 AM - edited 08-28-2015 03:50 AM
Hallo Keve,
nach dem Screenshot zu urteilen wird das angeschlossene Gerät mit einem reinen binären Format angesteuert.
Der Befehl oUDIM.Write "$C2" schickt aber Text. VBScript verwendet bei hexdezimale Konstanten &h als Prefix.
Der Befehl müßte dann so lauten: oUDIM.Write &hC2
Eventuell ist aber auch besser alle Parameter zu spezifizieren: call oUDIM.Write( &hC2,1,0)
Auch beim Lesen muss man beim Auswerten der Daten binär arbeiten: If (Datenarray(00) = &hC2 ) Then...
Vielleicht hilft aber auch die Parse-Funktion weiter. Damit kann man aus den binären Daten direkt Werte ermitteln.
Ich hoffe die Tipps helfen schon mal weiter.
DIAdemo
08-31-2015 01:04 AM
Vielen Dank für deine Hilfe. Ich werde deine Tipps mal ausprobieren und mich nochmal melden!
Schönen Montag noch!
09-02-2015 09:02 AM
Also ich habe heute mal fleißig weiter rumprobiert.....
- oUDIM.write funktioniert nun.....und zwar als ich oUDIM.write("Â",1,0) daraus gemacht habe...das Ascii-Zeichen  entspricht Hex C2, sodass mein Sensor die Daten losschickt.
Mit den Erweiterungen &hC2 hat er leider nicht die gewünschte HEX-Zahl rausgeschickt.
- bei dem Auslesen der Werte bin ich noch keinen Schritt weiter.......in result = oUDIM.Read() scheint einfach kein Ergebnis anzukommen....als wenn nichts auf dem Bus wäre (ich habe aber Daten zugesendet)
Hat noch jemand einen Tipp für mich??
09-03-2015 03:27 AM
Hallo Keve,
grundsätzlich ist die Verarbeitung von Binärdaten, die über UDI geschrieben und gelesen werden sollen, nicht ganz unproblematisch. Der Grund dafür liegt in der Tatsache, dass UDI beim Lesen und Schreiben mit Strings arbeitet und nicht mit Byte Arrays. Bei den Strings in Visual Basic handelt es sich aber um UNICODE Strings, die bei der Übertragung an UDI in ASCII Strings umgewandelt werden (und umgekehrt). Bei Zeichen, deren ASCII-Wert kleiner als 128 ist (7 Bit ASCII Code) ist diese Umwandlung unproblematisch. Die Zeichen lassen sich 1:1 von UNICODE in ASCII und zurück umwandeln. Bei Zeichen mit einem ASCII-Wert >= 128 werden die Zeichen jedoch bei der Umwandlung entsprechend der eingestellten Code Pages interpretiert und ggf. auf andere Werte abgebildet. Das folgende Beispiel zeigt wie die Daten "verfälscht" werden, wenn man die Funktionen chr() und asc() für die Bearbeitung der Binärdaten verwendet:
Dim InString
Dim OutString
Dim TempString
Dim i
OutString = ""
for i = 0 to 255
OutString = OutString & chr(i)
next
call oUDIM.Write(OutString, 256, 0)
InString = oUDIM.Read(256, 0)
TempString = ""
for i = 126 to 145
TempString = TempString & asc(mid(InString,i,1)) & ", "
next
call MsgBox(TempString)
Das Ergebnis sieht dann so aus:
"125, 126, 127, 0, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 143, 144,"
Die eingelesenen Binärdaten sind also unbrauchbar. Verwendet man statt der Funktionen chr() und asc() die Funktionen chrw() und ascw(), so werden die Daten korrekt ausgegeben.
Dim InString
Dim OutString
Dim TempString
Dim i
OutString = ""
for i = 0 to 255
OutString = OutString & Chrw(i)
next
call oUDIM.Write(OutString, 256, 0)
InString = oUDIM.Read(256, 0)
TempString = ""
for i = 126 to 145
TempString = TempString & ascw(mid(InString,i,1)) & ", "
next
call MsgBox(TempString)
Das Ergebnis sieht dann wie folgt aus:
"125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,"
Die eingelesenen Daten sind also korrekt.
Für das konkrete Beispiel bedeutet dies:
Senden des Hex Werts "C2":
call oUDIM.Write(chrw(&hC2), 1, 0)
Die Daten werden anschließend mit
result = oUDIM.Read(31, 0)
eingelesen. Hier ist es wichtig, dass
Nachdem nun die Daten des Sensors eingelesen sind, können diese wie folgt in ein Byte-Array umgewandelt werden:
for i = 1 to 31
Datenarray(i - 1) = ascw(mid(result, i, 1))
next
Jetzt können die einzelnen Bytes in dem Datenarray weiter analysiert werden.
Ich hoffe, das hilft weiter.
Gruß
Rainer
09-07-2015 06:17 AM - edited 09-07-2015 06:20 AM
Hallo Rainer,
kurz bevor ich deinen Beitrag gelesen habe bin ich nun auch drauf gekommen.....
Allerdings habe ich statt ASCW nur ASC verwendet....
Als Wert bekomme ich jetzt mein erwartetes Ergebnis (z.B. C2) aber in dezimaler Form, sprich 194 zurück. Das ist für mich soweit ok.
Wo ist dann der Unterschied zu deinem ASCW? Wenn ich ASCW verwende, bekomme ich das gleiche Ergebnis.
Vorab vielen Dank für die Hilfe!