DllCall() DLL von einem Messgerät auslesen Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

DllCall() DLL von einem Messgerät auslesen

28 Jul 2023, 15:36

Hallo zusammen,

ich nutze auf der Arbeit ein Messgerät der Firma AST.
Diese bieten zusätzlich zu ihrer Software eine DLL für das Auslesen des Messgerätes an.

Jetzt wollte ich zum testen die Version auslesen, bekomme aber keinen richtigen Rückgabewert wie in der Doku beschrieben wird.

Hier gibts die DLL und Doku
https://www.ast.de/de/produkt/category/easyforcepro?file=files/dresden/downloads/Mess-und-Regeltechnik/ASTAS_DLL.zip

Code: Select all

MsgBox, % DllCall("ASTAS_DLL\AstasDllInit")    ; Kommt 0 zurück und ist laut Doku Initialisiert
MsgBox, % DllCall("ASTAS_DLL\AstasDllDLLVersion")   ; 852327 sollte aber irgendwie Version 0131 ergeben
Was mache ich falsch?
Wie muss ich die Werte mit
AstasDllReadData(int list_idx, t_DeviceData *p_dev_data)
abholen?


Danke
Grüße Daniel
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

29 Jul 2023, 05:52

Moin,

wie Du schon richtig erkannt hast, hat die DLL eine Init Funktion, die laut Beschreibung zwingend als erste aufgerufen werden muss. Weil ein Aufruf von DllCall eine nicht bereits geladenen DLL lädt und sofort wieder entlädt, mag der Aufruf der Init-Funktion 'verpuffen'. Zuerst einmal empfehle ich deshalb, die DLL vor der Nutzung dauerhaft zu laden:

Code: Select all

DllCall("LoadLibrary", "Str", "ASTAS_DLL.dll")
(Das Entladen erledigt das System bei Programmende automatisch!)

Dann musst Du Dir in der Doku die Beschreibung der Funktionsaufrufe, der Parameter und der Rückgabewerte ansehen.
Wegen

Code: Select all

extern "C"
vermute ich, dass die Funktionen nach C-Standard aufgerufen werden. Für diese Aufrufe verwendet AHK im Parameter Return Type der DllCall() Funktion den Wert CDecl.

Code: Select all

int AstasDllInit(void)
Diese Funktion hat keinen Parameter, der Typ des Rückgabewerts ist int. Der Aufruf ist deshalb:

Code: Select all

RC := DllCall("ASTAS_DLL.dll\AstasDllInit", "CDecl Int")

Code: Select all

int AstasDllDLLVersion(void)
Diese Funktion ist wie AstasDllInit, der Aufruf ist deshalb:

Code: Select all

Version:= DllCall("ASTAS_DLL.dll\AstasDllDLLVersion", "CDecl Int")

Code: Select all

int AstasDllReadData(int list_idx, t_DeviceData *p_dev_data)
Diese Funktion erwartet zwei Parameter. Der Erste vom Typ int ist der Index des Geräts. Das muss ein Wert von 0 bis 15 sein.
Der Zweite ist ein Zeiger auf eine Datenstruktur, in die die Gerätewerte geschrieben werden sollen:

Code: Select all

typedef struct
{
float brutto; // Brutto / Messwert
float netto; // Netto
float tara; // Tara
float min; // Min (bezogen auf aktuelle An-Zeit)
float max; // Max (bezogen auf aktuelle An-Zeit)
int me; // Maßeinheit
int dec; // Anzahl Nachkommastellen
int status; // Status-Byte
} t_DeviceData;
Diese Struktur enthält 8 32-Bit Werte, 5 mal float und 3 mal int. In AHK wird der notwendige Speicherlatz mir VarSetCapacity() reserviert:

Code: Select all

VarSetCapacity(DeviceDate, 8 * 4, 0)
Die Adresse des Bereichs wird der Funktion übergeben:

Code: Select all

Idx := 0
VarSetCapacity(DeviceData, 8 * 4, 0)
RC := DllCall("ASTAS_DLL.dll\AstasDllReadData", "Int", Idx, "Ptr", &DeviceData, "CDecl Int")
Wenn der Aufruf klappt, stehen die Gerätedaten in der Variablen DeviceData. Du kannst sie dann mit NumGet() auslesen.

Viel Spaß noch!
Guest

Re: DllCall() DLL von einem Messgerät auslesen

29 Jul 2023, 06:21

Danke just me,
die ausführliche Beschreibung ist super :bravo:
Die Funktion AstasDllReadData kann ich erst Montag mit dem Messgerät testen.

Was mich dennoch immer noch verwundert ist dass bei der Version der Wert 852327 ausgelesen wird. Es sollte ja irgendein Bezug zu der Version 0131 geben ?!?
Oder wie ist der Int Wert zu deuten?

Grüße
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

29 Jul 2023, 07:32

Hallo,

die Version ergibt sich laut Doku wie folgt:
Byte3: Hauptversion
Byte2: Unterversion
Byte1: Revisionsversion
Byte0: Reserve (int. Zähler)
Beispiel:
Hex: 0x000D00yy – Vers. 0.13.0.yy
Die Zahl 852327 ergibt folgende Bytefolge:

Code: Select all

MsgBox, % Format("{:08X}", 852327) ; >>>> 000D0167
Das ergibt dann:
Byte3: 0x00 -> 0
Byte2: 0x0D -> 13
Byte3: 0x01 -> 1
Byte4: 0x67 -> 103
--> 0.13.1.103

Das geht auch mit:

Code: Select all

Version := 852327
Hauptversion := (Version >> 24) & 0xFF ; Byte 3
Unterversion := (Version >> 16) & 0xFF ; Byte 2
Revisionsversion := (Version >> 8) & 0xFF ; Byte 1
Reserve := Version & 0xFF ; Byte 0
MsgBox, 0, Version, %Hauptversion%.%Unterversion%.%Revisionsversion%.%Reserve%
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

29 Jul 2023, 09:15

:thumbup: Du bist der beste.
Vielen Dank.
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

30 Jul 2023, 12:16

Hi, ich versteh es nicht. :headwall:

Hab die Speichergröße auf 27Byte gemacht.
6 x 32 und 3 x 8

Code: Select all

typedef struct
{
DWORD usb_hid_idx; // USB-Geraete-Index -> interne Verwendung!
int open; // Zustand -> 1=Open / 0=Close
char vid_pid[256]; // VID/PID-String
char dev_info[256]; // GeräteInfo-String
char sn_info[256]; // S/N-String
int hw_info; // HW-Info (5xxx)
int fw_var; // HW-Variante
int fw_vers; // FW-Version
int chn; // Kanal
} t_DeviceInfo;

Code: Select all

VarSetCapacity(DeviceInfo, 27)
MsgBox,,AstasDllSearch, % "Gefundene Geräte: " . DllCall("ASTAS_DLL\AstasDllSearch", "Ptr", &DeviceInfo, "CDecl Int")
MsgBox,,NumGet, % NumGet(DeviceInfo, 10, "Char")
Wie lese ich nun richtig den GeräteInfo-String aus?

Grüße
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 03:39

Moin,

(6 * 32) + (3 * 8) = 27 ist schon eine interessante Berechnung. ;) Aber Spaß beiseite:

Code: Select all

typedef struct
{
   DWORD usb_hid_idx;   int  -> 32 Bit ->                     4 Bytes   // USB-Geraete-Index -> interne Verwendung!
   int open;            int  -> 32 Bit ->                     4 Bytes   // Zustand -> 1=Open / 0=Close
   char vid_pid[256];   char ->  8 Bit -> 1 Byte * [256] -> 256 Bytes   // VID/PID-String
   char dev_info[256];  char ->  8 Bit -> 1 Byte * [256] -> 256 Bytes   // GeräteInfo-String
   char sn_info[256];   char ->  8 Bit -> 1 Byte * [256] -> 256 Bytes   // S/N-String
   int hw_info;         int  -> 32 Bit ->                     4 Bytes   // HW-Info (5xxx)
   int fw_var;          int  -> 32 Bit ->                     4 Bytes   // HW-Variante
   int fw_vers;         int  -> 32 Bit ->                     4 Bytes   // FW-Version
   int chn;             int  -> 32 Bit ->                     4 Bytes   // Kanal
} t_DeviceInfo;                                           = 792 Bytes
Die Werte in vid_pid, dev_info und sn_info sind max. 256 Zeichen lange ASCII/ANSI-Strings. Ihre Werte kannst Du mit der Funktion StrGet() auslesen. Versuche es mal mit:

Code: Select all

vid_pid_offset := 8  ; <- 2 * 4
vid_pid := StrGet(&DeviceInfo + vid_pid_offset, 256, "CP0")
dev_info_offset := vid_pid_offset + 256
dev_info := StrGet(&DeviceInfo + dev_info_offset, 256, "CP0")
sn_info_offset := dev_info_offset + 256
sn_info := StrGet(&DeviceInfo + sn_info_offset, 256, "CP0")
MsgBox, vid_pid: %vid_pid%`ndev_info: %dev_info%`nsn_info: %sn_info%
Viel Erfolg!
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 04:30

Du hast recht. 1 Char = Byte. Denkfehler.
Hab die VarSetCapacity auf 792 geändert.

Beim Aufruf der StrGet Funktion stürzt das Programm ab ohne Fehlermeldung. Irgendwas wird mit dem Speicher nicht passen.
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 05:45

Zeigst Du mal Deinen aktuellen Testcode?
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 06:08

Was mir auch aufgefallen ist wenn ich das Gerät per USB verbinde, Zeile 10 auskommentiere (eigentlich nur die Versionsinfo) bringt er als return code bei AstasDllSearch keinen Wert. Sollte Anzahl der gefunden Geräte zurück geben.
Wenn die Zeile 10 ausgeführt wird kommt 1 bei return code in AstasDllSearch. Auch komisch oder?

Code: Select all

#SingleInstance Force
#NoEnv
SetWorkingDir %A_ScriptDir%

DllCall("LoadLibrary", "Str", "ASTAS_DLL.dll", "Ptr")
Init := DllCall("ASTAS_DLL\AstasDllInit", "CDecl Int")
if Init
	MsgBox,,AstasDllInit, % ASTAS_ReturnCodeMsg(Init)

; MsgBox,,AstasDllDLLVersion, % ASTAS_CreateVersion(DllCall("ASTAS_DLL\AstasDllDLLVersion", "CDecl Int"))

VarSetCapacity(DeviceInfo, 792)
RC := DllCall("ASTAS_DLL\AstasDllSearch", "Ptr", &DeviceInfo, "CDecl Int")
MsgBox,,AstasDllSearch, Gefundene Geräte: %rc%

vid_pid_offset := 8  ; <- 2 * 4
vid_pid := StrGet(&DeviceInfo + vid_pid_offset, 256, "CP0")
dev_info_offset := vid_pid_offset + 256
dev_info := StrGet(&DeviceInfo + dev_info_offset, 256, "CP0")
sn_info_offset := dev_info_offset + 256
sn_info := StrGet(&DeviceInfo + sn_info_offset, 256, "CP0")
MsgBox, vid_pid: %vid_pid%`ndev_info: %dev_info%`nsn_info: %sn_info%

; MsgBox,,AstasDllOpen, % ASTAS_ReturnCodeMsg(DllCall("ASTAS_DLL\AstasDllOpen", "Int", 0, "CDecl Int"))
; Idx := 0
; VarSetCapacity(DeviceData, 8 * 4, 0)
; MsgBox,,AstasDllReadData, % ASTAS_ReturnCodeMsg(DllCall("ASTAS_DLL\AstasDllReadData", "Int", Idx, "Ptr", &DeviceData, "CDecl Int"))
; MsgBox,,NumGet, % NumGet(&DeviceData, 4, "Float")

ExitApp


ASTAS_CreateVersion(input) {
	; MsgBox, % Format("{:08X}", Version)
	Hauptversion := (input >> 24)  & 0xFF ; Byte 3
	Unterversion := (input >> 16) & 0xFF ; Byte 2
	Revisionsversion := (input >> 8) & 0xFF ; Byte 1
	Reserve := input & 0xFF ; Byte 0
	return Hauptversion "." Unterversion "." Revisionsversion "." Reserve
}

ASTAS_ReturnCodeMsg(input) {
	Switch input
	{
	Case 0:
	    Return "kein Fehler"
	Case 1:
	    Return "allg. Fehler (z.B. Gerät nicht ansprechbar)"
	Case 10:
	    Return "Gerät nicht geöffnet"
	Case 20:
	    Return "Funktion nicht implementiert"
	Case 30:
	    Return "Lesefehler von Gerät"
	Case 40:
	    Return "Funk-Fehler"
	Case 50:
	    Return "Fehler bei Öffnen Gerät"
	Case 60:
	    Return "Lesefehler"
	Case 100:
	    Return "bei Maßeinheit mV/V (UNIT_mV_V) keine Kalibrierung möglich"
	Case 101:
	    Return "erst Messwert lesen, dann werden Kalibrier-Funktionen ausgeführt"
	Case 250:
	    Return "Fehler bei ReInit der ASTAS-DLL"
	Case 251:
	    Return "Speicherfehler beim init. der ASTAS-DLL"
	Case 252:
	    Return "DLL ist schon initialisiert"
	Case 253:
	    Return "falscher Wert für list_idx"
	Case 254:
	    Return "gewähltes Gerät nicht vorhanden"
	Case 255:
	    Return "ASTAS-DLL wurde nicht initialisiert"
	Default:
	    return "Fehler, kein Rückgabewert"
	}
}

just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 06:39

Ich kann erstmal keinen 'groben' Fehler finden. Ich habe ein paar kleine Anpassungen gemacht. Kannst Du das mal testen?

Code: Select all

#SingleInstance Force
#NoEnv
SetWorkingDir %A_ScriptDir%

If !DllCall("LoadLibrary", "Str", "ASTAS_DLL.dll", "UPtr") {
   MsgBox,,LoadLibrary, ASTAS_DLL konnte nicht geladen werden!
   ExitApp
}
Init := DllCall("ASTAS_DLL\AstasDllInit", "CDecl Int")
if Init
	MsgBox,,AstasDllInit, % ASTAS_ReturnCodeMsg(Init)

MsgBox,,AstasDllDLLVersion, % ASTAS_CreateVersion(DllCall("ASTAS_DLL\AstasDllDLLVersion", "CDecl Int"))

; Die Informationen für maximal 16 Geräte werden gesucht, DeviceInfo sollte mit NULL-Bytes initialisiert werden
VarSetCapacity(DeviceInfo, 792 * 16, 0)
RC := DllCall("ASTAS_DLL\AstasDllSearch", "Ptr", &DeviceInfo, "CDecl Int")
MsgBox,,AstasDllSearch, Gefundene Geräte: %rc%

vid_pid_offset := 8  ; <- 2 * 4
vid_pid := StrGet(&DeviceInfo + vid_pid_offset, 256, "CP0")
dev_info_offset := vid_pid_offset + 256
dev_info := StrGet(&DeviceInfo + dev_info_offset, 256, "CP0")
sn_info_offset := dev_info_offset + 256
sn_info := StrGet(&DeviceInfo + sn_info_offset, 256, "CP0")
MsgBox, vid_pid: %vid_pid%`ndev_info: %dev_info%`nsn_info: %sn_info%

; MsgBox,,AstasDllOpen, % ASTAS_ReturnCodeMsg(DllCall("ASTAS_DLL\AstasDllOpen", "Int", 0, "CDecl Int"))
; Idx := 0
; VarSetCapacity(DeviceData, 8 * 4, 0)
; MsgBox,,AstasDllReadData, % ASTAS_ReturnCodeMsg(DllCall("ASTAS_DLL\AstasDllReadData", "Int", Idx, "Ptr", &DeviceData, "CDecl Int"))
; MsgBox,,NumGet, % NumGet(&DeviceData, 4, "Float")

ExitApp


ASTAS_CreateVersion(input) {
	; MsgBox, % Format("{:08X}", Version)
	Hauptversion := (input >> 24)  & 0xFF ; Byte 3
	Unterversion := (input >> 16) & 0xFF ; Byte 2
	Revisionsversion := (input >> 8) & 0xFF ; Byte 1
	Reserve := input & 0xFF ; Byte 0
	return Hauptversion "." Unterversion "." Revisionsversion "." Reserve
}

ASTAS_ReturnCodeMsg(input) {
	Switch input
	{
	Case 0:
	    Return "kein Fehler"
	Case 1:
	    Return "allg. Fehler (z.B. Gerät nicht ansprechbar)"
	Case 10:
	    Return "Gerät nicht geöffnet"
	Case 20:
	    Return "Funktion nicht implementiert"
	Case 30:
	    Return "Lesefehler von Gerät"
	Case 40:
	    Return "Funk-Fehler"
	Case 50:
	    Return "Fehler bei Öffnen Gerät"
	Case 60:
	    Return "Lesefehler"
	Case 100:
	    Return "bei Maßeinheit mV/V (UNIT_mV_V) keine Kalibrierung möglich"
	Case 101:
	    Return "erst Messwert lesen, dann werden Kalibrier-Funktionen ausgeführt"
	Case 250:
	    Return "Fehler bei ReInit der ASTAS-DLL"
	Case 251:
	    Return "Speicherfehler beim init. der ASTAS-DLL"
	Case 252:
	    Return "DLL ist schon initialisiert"
	Case 253:
	    Return "falscher Wert für list_idx"
	Case 254:
	    Return "gewähltes Gerät nicht vorhanden"
	Case 255:
	    Return "ASTAS-DLL wurde nicht initialisiert"
	Default:
	    return "Fehler, kein Rückgabewert"
	}
}

d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

31 Jul 2023, 08:41

Jetzt schaut es gut aus.
Musste bei den Strings noch `n`r entfernen. Ansonsten hat es in der MessageBox direkt nach der ersten Variable nichts mehr angezeigt.

Das Nullen des Geräts mit AstasDllNull(int list_idx) funktioniert soweit. Leider kommen keine Werte aus dem AstasDllReadData.
Last edited by d1niel84 on 01 Aug 2023, 03:57, edited 1 time in total.
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

01 Aug 2023, 03:45

Moin,

wenn ich die Doku richtig verstehe, gibt AstasDllSearch die Anzahl der gefundenen Geräte zurück. Wenn nur ein Gerät gefunden wurde, ist das 1 und der zugehörige list_idx ist 0. Bei zwei gefundenen Geräten sind die Indizes entsprechend 0 und 1, u.s.w.

Warum ein gefundenes Gerät nicht ansprechbar ist, kann ich leider nicht klären.

Viel Glück!
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

01 Aug 2023, 03:58

Danke Jetzt schaut es gut aus.
Musste bei den Strings noch `n`r entfernen. Ansonsten hat es in der MessageBox direkt nach der ersten Variable nichts mehr angezeigt.

Das Nullen des Geräts mit AstasDllNull(int list_idx) funktioniert soweit.

Und noch was , die Schreibweise ist doch richtig für den Befehl?
DllCall("ASTAS_DLL\AstasDllSetMinMax", "Int", 0, "Int", 2,"CDecl Int") -> MODE_SETMAX

Grüße
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

01 Aug 2023, 10:49

Code: Select all

DllCall("ASTAS_DLL\AstasDllSetMinMax", "Int", 0, "Int", 2, "CDecl Int") ; -> MODE_SETMAX
sieht gut aus. Es gibt die Funktion laut Doku aber nur für:
Geräte: AE703 / BD341/2
d1niel84
Posts: 51
Joined: 20 Oct 2019, 12:28
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen  Topic is solved

01 Aug 2023, 11:43

Ja genau hab ein AE703. Beim Ausführen sagt der Rückgabewert alles OK aber auf dem Gerät tut sich nichts. :think:
Alles andere Funktioniert jetzt richtig gut :dance:
Auch das Auslesen der aktuellen Werte.

Vielen Dank

Code: Select all


     ██╗██╗   ██╗███████╗████████╗    ███╗   ███╗███████╗
     ██║██║   ██║██╔════╝╚══██╔══╝    ████╗ ████║██╔════╝
     ██║██║   ██║███████╗   ██║       ██╔████╔██║█████╗  
██   ██║██║   ██║╚════██║   ██║       ██║╚██╔╝██║██╔══╝  
╚█████╔╝╚██████╔╝███████║   ██║       ██║ ╚═╝ ██║███████╗
 ╚════╝  ╚═════╝ ╚══════╝   ╚═╝       ╚═╝     ╚═╝╚══════╝
                                                         

Hab viel gelernt was DLLCall und StrGet/NumGet angeht.

Grüße
just me
Posts: 9532
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: DllCall() DLL von einem Messgerät auslesen

02 Aug 2023, 02:20

Moin, ich habe noch mal gelesen:
int AstasDllSetMinMax(int list_idx, int mode)
Setzen der min/Max-Werte auf aktuelle Meßwerte.
Ich als Laie könnte das so verstehen, dass der aktuelle Messwert zum minimalen/maximalen Wert (einer Messreihe) bestimmt wird. Wenn das so ist, sollte man die Werte in den Feldern min bzw. max der Struktur t_DeviceData wiederfinden. Vielleicht dient es aber auch dazu, den Messbereich zu begrenzen?

Mach's gut,
just me

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 26 guests