Code Snippets

Software zur Datenerfassung: GSVcontrol, GSVmulti, GSVterm, ...;
Treiber: Labview, Windows-DLL, ...
Programmierung: Code-Snippets, ..
Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Code Snippets

Beitragvon Kabelitz » Fr 5. Aug 2011, 23:41

Die Erstellung von Software unter Windows für GSV-2, GSV-3 und GSV-4 Messverstärker geht am besten mit der entsprechenden Windows-DLL.
megsv.dll für GSV-2 und GSV-3
megsv4.dll für GSV-4

Was ist mit Android?
Hier helfen vermutlich die Code-Snippets.

Anbei der Quelltext, der für ein Experiment mit GSV-3BT und Windows-Mobile 5 unter "Pocket-Zeus Basic" geschrieben wurde.
Von Zeile 366 bis 797 sind die wesentlichen Funktionen untergebracht...
Vielleicht hilft der Code, die Bedienungsanleitung ba-gsv3.pdf zu verstehen.

Code: Alles auswählen

' ***************************************************************************
func gsvstop()
  ComOutput(Channel1,chr(35))
endfunc
' ***************************************************************************
func gsvstart()
  ComOutput(Channel1,chr(36))
endfunc
' ***************************************************************************
func gsvsetzero()
  ComOutput(Channel1,chr(14))
  pause(1000)
  ComOutput(Channel1,chr(12))
  playsound("xx")
endfunc
' ***************************************************************************
func gsvsetfrequency(freq as integer)
dim line as string

protocol = 2

  ' gsvstop()
  ' pause(1000)
  ' ComPurge(Channel1)
  line = Chr($8A)+Chr($08)+Chr($B3)+Chr($B4)

  select integer freq
  case 1
    line = Chr($8A)+Chr($08)+Chr($B3)+Chr($B4)
  case 10
    line = Chr($8A)+Chr($08)+Chr($F8)+Chr($5F)
  case 20
    line = Chr($8A)+Chr($07)+Chr($F8)+Chr($5F)
  case 50
    line = Chr($8A)+Chr($07)+Chr($FC)+Chr($F3)
  case 100
    line = Chr($8A)+Chr($06)+Chr($FC)+Chr($F3)
  endselect
  ComOutput(Channel1,line)
  pause(1000)


      gsvfrequency    = gsvGetFrequency()
      gsvintervall    = 1/gsvfrequency     
      cgsvfrequency   = formatvalue(1000.0,gsvfrequency)+" Hz"     
      cgsvintervallformat = getformatstring(100.0,gsvintervall)     
      FormLabel(Main_Frequency,-1,-1,-1,-1,cgsvfrequency)

 
  protocol = 2
  gsvstart()
endfunc


' ***************************************************************************
func gsvGetSerialNumber() as string
dim line as string
  ComPurge(Channel1)
  ComOutput(Channel1,chr(31))
  pause(2000)
  line = gsvreadline(2000)
  ' print line
  exit(line) 
endfunc

' ***************************************************************************
func gsvGetFrequency() as single
dim highbyte, midbyte, lowbyte as integer
dim i, inbyte as integer
dim inchar as string
dim line as string

  ComPurge(Channel1)
  ComOutput(Channel1,chr(22))
  pause(1000)
  line = gsvreadline(2000)
  ' print line
  for i = 1 to 4
    inchar = Mid(line,i,1)
    inbyte = Asc(inchar)
    ' print inbyte
    ongosub i-1, label0, label1, label2, label3
  next
   
 
  gsvfrequency=5000000.0/(16777216.0-((highbyte*65536.0)+(midbyte*256.0)+lowbyte))
  ' gsvfrequency = (highbyte*65536.0)+(midbyte*256.0)+lowbyte
  ' gsvfrequency = 16777216.0 - gsvfrequency
  ' gsvfrequency = 5000000.0 / gsvfrequency
 
  ' print "gsvfrequency=";gsvfrequency
  exit(gsvfrequency) 
 
label0:
return
label1:
highbyte = inbyte
return
label2:
midbyte = inbyte
return
label3:
lowbyte = inbyte
return

endfunc


Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Einzelwertabfrage

Beitragvon Kabelitz » Di 16. Aug 2011, 21:11

Die Einzelwertabfrage ist bei GSV-2, GSV-3 und GSV-4 mit getvalue möglich.
Der Befehl getvalue wird ausgeführt, indem man ein ; (Semikolon, Zeichen 0x3B, ASCII 59) sendet.

Vorher sollte man den Messverstärker aber so konfigurieren, dass er nur noch auf getvalue einen Messwert sendet.

Das kann man auf verschiedene Arten tun.
a)
bei GSV-2 und GSV-3: man sendet StopTransmit. (Zeichen 0x23, ASCII 35)
Allerdings merkt sich der GSV-2/3 diesen Zustand nicht. Nach dem Aus/Einschalten sendet er wieder fleißig mit der eingestellten Frequenz.
Damit sich der GSV-2/GSV-3 diesen Zustand merkt, muss man ihn in den "Logger" Modus versetzen, (Einzelwertabfrage).
Dann wird gleichzeitig der digitale Eingang zum Nullsetzen umfunktioniert zu einem digitalen Eingang für die Einzelwertabfrage (Triggereingang).

b)
Für den Logger-Modus muss man bei GSV-2 und GSV-3 das Status Register verändern.
Am einfachsten erreicht man das, indem man die Software GSVControl aufruft. In der Karteilkarte "Experte" gibt es eine Checkbox "Logger-Modus". Diese muss man aktivieren.

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Einzelwertabfrage ein- ausschalten

Beitragvon Kabelitz » Fr 19. Aug 2011, 22:20

Um die Datenübertragung bei GSV-2 und GSV-3 dauerhaft auszuschalten, muss der "Logger-Mode" gesetzt werden.
Für den Logger-Mode muss Bit 3 im Mode Register auf 1 gesetzt werden.

Die macht man am besten, indem man erst den aktuellen Zustand des Modus-Registers ausliest und eine Oder Verknüpfung mit 0x08 durchführt.

Anbei ist der Perl Code für das Ein- und Ausschalten des Einzelwert-Modus.

Code: Alles auswählen

sub set_modelog
{
  my ($portobj, $loggermode) = @_;
  my ($kommando);
  my (@params, @bytes_from_gsv);
  my ($modus, $muster, $check_protokoll);

  # aktuelles Modus Register auslesen:
  $kommando  = "gsvgetmode";
  @params    = ();
 
  # Kommando gsvgetmode ausführen:
  (@bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);
  $modus = $bytes_from_gsv[0];
 
  if ($loggermode == 1)
  {
    # Logger-Modus (Einzelwertabfrage) soll eingeschaltet werden:
    $muster = "\x08";
    # aktuellen Modus und Logger Modus mit ODER verknüpfen:
    $check_protokoll = $modus | $muster;
    # Modus setzen:
    $kommando  = "gsvsetmode";
    @params    = ($check_protokoll);
    (@bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);

  }
  elsif ($loggermode == 0)
  {
    # Logger-Modus (Einzelwertabfrage) soll ausgeschaltet werden:
    $muster = "\xF7";
    # aktuellen Modus und Logger Modus mit UND verknüpfen:
    $check_protokoll = $modus & $muster;   
    # Modus setzen:
    $kommando  = "gsvsetmode";
    @params    = ($check_protokoll);
    (@bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);   
  }
}

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Messfrequenz auslesen

Beitragvon Kabelitz » Fr 19. Aug 2011, 22:37

Bei den Messverstärkern GSV-2 und GSV-3 lässt sich die Frequenz auslesen, mit der ein neuer Messwert zur Verfügung steht.
Wenn der Einzelwertmodus NICHT eingeschaltet ist, dann werden die Messwerte mit dieser Frequenz über die Schnittstelle gesendet.

Achtung: Auch im Einzelwertmodus sollte die Frequenz sinnvoll eingestellt sein.
Es macht keinen Sinn, die Messfrequenz auf 1Hz zu stellen und mit 50Hz die Werte abzuholen. Man bekommt dann eben 50x den gleichen Messwert!

Ein Basic Code Snippet zu gsvgetfrequency hatten wir schon, hier ist der Code in Perl:

Code: Alles auswählen

sub get_frequency{
my ($portobj) = @_;
my (@out, @params, @bytes_from_gsv);
my ($frequency);

(@bytes_from_gsv) = &gsv_command ($portobj, "gsvgetfrequency", @params);
@out = (ord($bytes_from_gsv[0]), (ord($bytes_from_gsv[1])), (ord($bytes_from_gsv[2])));

$frequency=5000000/(16777216-($out[0]*65536+$out[1]*256+$out[2]));

return ($frequency);
};

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Einheit lesen und schreiben

Beitragvon Kabelitz » Fr 19. Aug 2011, 22:57

Nur der Vollständigkeit halber: Lesen und Schreiben der Einheit.
Wichtig: das Setzen der Einheit hat keinerlei Einfluss auf die Skalierung der Messwerte.
Es handelt sich nur um eine Information, die Im EEProm des Messverstärkers abgelegt wird.
Weiter oben hatten wir schon ein Basic-Beispiel...

Code: Alles auswählen

sub get_unit{
my ($portobj) = @_;
my (@units, @params);
my @bytes_from_gsv;
my $unit;

@units=("mV/V","kg","g","N","cN","V","µm/m","","t","kN","lb","oz","kp","lbf","pdl","mm","m","cNm","Nm");

(@bytes_from_gsv) = &gsv_command ($portobj, "gsvgetunit", @params);
$unit = ord($bytes_from_gsv[0]);

# gibt den Index der Einheit zurück, nicht die Einheit als string:
return ($unit);
};

sub set_unit{
my ($portobj, $unit) =@_;
my (@params);
my @bytes_from_gsv;
my (@units);
my ($i, $item);
@units=("mV/V","kg","g","N","cN","V","µm/m","","t","kN","lb","oz","kp","lbf","pdl","mm","m","cNm","Nm");

$i = 0;
foreach $item (@units)
{
    if($item eq $unit)
    {
        $unit = $i;
    }
    $i++;
}

@params    = chr($unit);
(@bytes_from_gsv) = &gsv_command ($portobj, "gsvsetunit", @params);
};

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Bits im Modus Register prüfen

Beitragvon Kabelitz » Fr 19. Aug 2011, 23:04

Code: Alles auswählen

sub get_modetext
{
  my ($portobj) = @_;
  my ($kommando);
  my (@params, @bytes_from_gsv);
  my ($modus, $muster, $check_protokoll);

  # Modus überprüfen:
  $kommando  = "gsvgetmode";
  @params    = ();
  ($l1, $line, @bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);

  $modus = $bytes_from_gsv[0];
  $muster = "\x02";
  $check_protokoll = $modus & $muster;

  if ( $check_protokoll ne "\x02")
  {
    # Binärprotokoll
    return (1);
  }
  else
  {
    # Textprotokoll
    return (0);
  }
}
sub get_modewindow
{
  my ($portobj) = @_;
  my ($kommando);
  my (@params, @bytes_from_gsv);
  my ($modus, $muster, $check_protokoll);

  # Modus überprüfen:
  $kommando  = "gsvgetmode";
  @params    = ();
  ($l1, $line, @bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);

  $modus = $bytes_from_gsv[0];
  $muster = "\x10";
  $check_protokoll = $modus & $muster;

  if ($check_protokoll ne "\x10")
  {
    # Windowmode ist aus:
    return (0);
  }
  else
  {
    # Windowmode ist an
    return (1);
  }
}

sub get_modelog
{
  my ($portobj) = @_;
  my ($kommando);
  my (@params, @bytes_from_gsv);
  my ($modus, $muster, $check_protokoll, $cond);

  # Modus überprüfen:
  $kommando  = "gsvgetmode";
  @params    = ();
  ($l1, $line, @bytes_from_gsv) = &gsv_command($portobj, $kommando, @params);

  $modus = $bytes_from_gsv[0];
  $muster = "\x08";
  $check_protokoll = $modus & $muster;

  if ( $check_protokoll ne "\x08")
  {
    return (0);
  }
  else
  {
    return (1);
  }
}

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Schwellwert lesen / setzen

Beitragvon Kabelitz » Fr 19. Aug 2011, 23:09

Code: Alles auswählen

sub get_threshold1
{
my ($portobj, $mbendwert) = @_;
my ($hb_on, $lb_on, $hb_off, $lb_off);
my ($sw_on, $sw_off);
my (@bytes_from_gsv, @params);

(@bytes_from_gsv) = &gsv_command ($portobj, "gsvgetthreshold1", @params);
$hb_on = ord($bytes_from_gsv[0]);
$lb_on = ord($bytes_from_gsv[1]);
$hb_off = ord($bytes_from_gsv[2]);
$lb_off = ord($bytes_from_gsv[3]);

  $sw_on = (($lb_on + $hb_on * 256) - 32767)/32768 * 1.05 * $mbendwert ;
  $sw_off = (($lb_off + $hb_off * 256) - 32767)/32768 * 1.05 * $mbendwert ;

return ($sw_on, $sw_off);
};


Code: Alles auswählen

sub set_threshold1
{
    my ($portobj, $schwellwert, $schwellwert_aus, $mbendwert) = @_;
    my ($lowbyte_einschwelle, $highbyte_einschwelle, $lowbyte_ausschwelle, $highbyte_ausschwelle);
    my (@params);
    my (@bytes_from_gsv);
   
    $schwellwert     = sprintf ("byte 0x%04X", ($schwellwert/$mbendwert)/1.05*32768+32768);
    $schwellwert_aus = sprintf ("byte 0x%04X", ($schwellwert_aus/$mbendwert)/1.05*32768+32768);
   
    $highbyte_einschwelle = chr(hex(substr($schwellwert,-4,2))); #umwandeln in ein zeichen
    $lowbyte_einschwelle = chr(hex(substr($schwellwert,-2,2)));
   
    $highbyte_ausschwelle = chr(hex(substr($schwellwert_aus,-4,2)));;
    $lowbyte_ausschwelle = chr(hex(substr($schwellwert_aus,-2,2)));
   
    @params = ($highbyte_einschwelle, $lowbyte_einschwelle, $highbyte_ausschwelle, $lowbyte_ausschwelle);
   
    &gsv_command ($portobj, "gsvsetthreshold1", @params);

    return 0;
};

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

getall-Parametersatz laden

Beitragvon Kabelitz » Mi 24. Aug 2011, 16:37

Mit der Funktion getall lassen sich bei GSV-2 und GSV-3 komplette Parametersätze laden,
sprich komplette Konfigurationen herstellen.
Also eine gewünschte Samplingrate, gewünschet Einheit, gewünschtes Datenformat, Schwellwert-Konfiguration.
Bis zu 6 Konfigurationen kann man im EEProm ablegen.

Achtung: die Parameter von getall haben den Wertebereich von $00 bis $07, und nicht die ASCII Zeichen "0" bis "7".

Dazu muss die Funktion "getall" aufgerufen werden.
"getall" hat nur einen Parameter.
$01: Hersteller-Konfiguration
$02 ...$07: eigene Konfigurationen

Hier ist ein Basic Beispiel

Code: Alles auswählen

func gsvgetall(user as integer)
dim line as string

  line = Chr($09)+Chr(user - 48)

  ComOutput(Channel1,line)
  pause(1000)
endfunc

Kabelitz
Beiträge: 431
Registriert: Fr 5. Aug 2011, 12:09

Re: Code Snippets

Beitragvon Kabelitz » So 15. Jan 2012, 19:33

Gibt es ein Beispiel für die Synchronisation beim GSV-3BT im Binär-Protokoll?
Das Startbyte ist 0xA5, dann folgen HighByte und LowByte. Prinzipiell kann aber 0xA5 auch im High-Byte oder Low Byte vorkommen.
Wie macht man das sicher?

Außerdem: wie erkennt man am einfachsten, ob es sich um einen GSV-4BT oder GSV-3BT handelt?

Wetz

Re: Code Snippets

Beitragvon Wetz » Fr 29. Jun 2012, 16:18

Synchronisation der Messwertbytes GSV-3
1. Nach Öffnen der Schnittstelle: einmal stopTX (Cmd. 0x23), dann ggf Software-Buffer löschen, dann startTX (Cmd 0x24) geben.
Dadurch beginnt der GSV-3 auf jeden Fall mit einem kompletten Frame.

2. Nun werden 2 Zustände unterschieden: a) Hohe Datenrate und b) niedrige Datenrate. Wo der Umbruch der Datenraten ist,
hängt davon ab, unterhalb welcher Datenrate das Kommunikationssystem (Bluetooth, USB) nur noch einen Messwert in einen
Kommunikationsframe packt. Es wird dabei davon ausgegangen, daß bei hoher Datenrate (a) das Lowbyte des Messwertes rauscht,
d.h. daß es nie mehr als zweimal nacheinander denseben Wert hat. Dabei ist der kritische Wert der des Präfixes, d.h. 0xA5,
da hierbei Fehlsynchronisation droht.

Prinzipiell wird immer erst ein Byte gelesen; ist dieses =0xA5, werden 2 weitere Bytes gelesen, von denen angenommen wird, es seien Messwertbytes.
Ist das erste gelesene Byte nicht A5, wird es verworfen

2 a) Lese drei Messwertframes und speichere diese. Wenn das vermeindliche Lowbyte des Messwertes bei allen 3 =0xA5 ist, ist folgende Fehlsynchronisation der Fall:

Wahre Frames: A5A5xx A5A5xx A5A5xx A5A5xx

Gelesene Frames: A5xxA5 A5xxA5 A5xxA5

Dann die nächsten 2 Bytes ungeachtet ihres Wertes verwerfen, d.h. das nächste A5 und das Byte dannach zwar lesen, aber nicht beachten.
Dann wieder ein Byte lesen und auf Präfix auswerten, u.s.w.

2 b) Bei niedriger Datenrate wird davon ausgegangen, daß zwischen 2 Messwertframes ein zeitlicher Abstand ist, den das
Kommunikationssystem nicht auffüllt. Hiebei:
Immer erst Einzelbytes versuchen zu lesen (d.h. vom Empfangspuffer holen). Wenn KEIN Byte gelesen wurde, einen zeitlichen Zwischenraum annehmen
und ein "Präfix-Erwartungsflag" setzen. Wenn nun ein Präfix gelesen wurde und diese Flag gesetzt ist, werden die beiden Messwertbytes gelesen.
Ist es nicht gesetzt, Einzelbytes lesen, bis kein Byte gelesen wurde (d.h. bis zum Zeitabstand), u.s.w.

Der Knackpunkt dieser Methoden sind Datenraten, bei denen das Lowbyte noch nicht rauscht, dennoch bereits mehrere Messwerte in einen
Kommunikationsframe gepackt werden, so daß am Empfangsgerät kein zeitlicher Abstand zwischen den Messwerten zu detektieren ist.
Dann wird das leider kaum funktionieren, da das Lowbyte auch oft nacheinander =0xA5 sein könnte.
Vielleicht können wir die Kommunikationssysteme (USB-chip bzw Bluetooth-Modul) so konfigurieren, daß wir die Wartezeit
verändern, die es auf Bytes wartet, bis diese in einem Kommunikationsframe gesendet werden, und diese Zeit anhand der
Grenzdatenrate des o.g. Algorithmus einstellen.


Zurück zu „Software“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste