DIAdem

cancel
Showing results for 
Search instead for 
Did you mean: 

Verarbeitungsprobleme Daten von serieller Schnittstelle // SC und Code vorhanden

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??

0 Kudos
Message 1 of 6
(5,191 Views)

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

 

0 Kudos
Message 2 of 6
(5,144 Views)

Vielen Dank für deine Hilfe. Ich werde deine Tipps mal ausprobieren und mich nochmal melden!

 

Schönen Montag noch!

0 Kudos
Message 3 of 6
(5,112 Views)

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??

0 Kudos
Message 4 of 6
(5,076 Views)

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

  1. die genaue Anzahl der einzulesenden Bytes angegeben wird.
  2. ohne Delimiter gearbeitet wird, da dieser ja zufällig im Datenstrom enthalten sein könnte.

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

 

 

 

 

 

 

0 Kudos
Message 5 of 6
(5,046 Views)

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!

0 Kudos
Message 6 of 6
(4,992 Views)