FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: privat58 am 10 Februar 2016, 20:03:22

Titel: serielle Schnittstelle Daten lesen
Beitrag von: privat58 am 10 Februar 2016, 20:03:22
Hallo,
vorab muss ich sagen, das ich von programmieren eigentlich keine Ahnung habe und vieles nur durch Probieren hinbekomme. Manches lerne ich mit der Zeit und bei Vielem fange ich jedes mal von vorn an.
Nun aber zu meinem Problem. Ich habe das Arduino-Programm uvr2web für meine Solarsteuerung ESR31 angepasst. Da gibt es eventuell noch Probleme mit den Minusgraden, ist aber nicht das Problem.
Auf der seriellen Schnittestelle kommen die Werte zeilenweise endlos raus:
Received .
DataFrameDamaged .
Receiving .
Received .
Sensor1 5.90
Sensor2 36.90
Sensor3 0.00
Leistung 0.00
kWh 361.20
MWh 8
Pumpe1 off
Drehzahlstufe1 0

Receiving .
Received .
Sensor1 5.90
Sensor2 36.90
Sensor3 0.00
Leistung 0.00
kWh 361.20
MWh 8
Pumpe1 off
Drehzahlstufe1 0

Receiving .
Received .
Sensor1 5.90
Sensor2 36.90
Sensor3 0.00
Leistung 0.00
kWh 361.20
MWh 8
Pumpe1 off
Drehzahlstufe1 0

Receiving .
Received .

usw..

Auf dem seriellen Monitor der arduino-Software werden die Daten ohne Probleme ausgegeben. Es gibt keine Fehler etc.

Ich habe auch einen Batteriemonitor BMV600 der die Daten auch ähnlich ausgibt. (Auch dort gibt es das selbe Problem)
Das Modul des Batteriemonitors habe ich mit dem readingsBulkUpdate angepasst. Das Modul sieht so aus:
#########################################################################
# fhem Modul für Solarregelung ESR 31 von Technische Alternative
# Die Beschreibung und Kommentierung dieses Moduls ist in deutsch gehalten,
# um anderen das erstellen eigener Module zu erleichtern.
#########################################################################
#
# # Kommentarbereich
package main;

use strict;                         #
use warnings;                       #
use Time::HiRes qw(gettimeofday);   #

sub ESR31_Read($);                  #
sub ESR31_Ready($);                 #
sub ESR31_setbits($$);              #
sub ESR31_SetReading($$$$);         #

my $buf1 = "";                      # Hilfsvariable für auslesen des Buffers
my $Zeit = 0;                       # Hilfsvariable Zeit
my $Tmin = -30; # Temperaturgrenze minimum
my $Tmax = 150; # Temperaturgrenze maximum
my $Dmin = 0; # Drehzahlstufe minimum
my $Dmax = 31; # Drehzahlstufe maximum
my $Pmin = 0; # Momentanleistung minimum
my $Pmax = 4500; # Momentanleistung maximum


my %ESR31_sets = (    #

);


#########################################################################
sub ESR31_Initialize($)
{
my ($hash) = @_;

require "$attr{global}{modpath}/FHEM/DevIo.pm";

$hash->{ReadFn}  = "ESR31_Read";
$hash->{ReadyFn} = "ESR31_Ready";
$hash->{DefFn}   = "ESR31_Define";
$hash->{UndefFn} = "ESR31_Undef";
$hash->{SetFn}   = "ESR31_Set";
$hash->{AttrList} =
  "do_not_notify:1,0 loglevel:0,1,2,3,4,5,6 " . $readingFnAttributes;
}

######################################################################### #
sub ESR31_Define($$)
{
my ( $hash, $def ) = @_;
my @a = split( "[ \t][ \t]*", $def );

return "wrong syntax: define <name> ESR31 [devicename|none]"
  if ( @a != 3 );

DevIo_CloseDev($hash);
my $name = $a[0];
my $dev  = $a[2];

if ( $dev eq "none" )
{
Log3 undef, 1, "ESR31 device is none, commands will be echoed only";
return undef;
}

$hash->{DeviceName} = $dev;
my $ret = DevIo_OpenDev( $hash, 0, "ESR31_Poll" );
return $ret;
}

#########################################################################
sub                   #
  ESR31_Undef($$)    #
{                     #
my ( $hash, $arg ) = @_;       #
DevIo_CloseDev($hash);         #
RemoveInternalTimer($hash);    #
return undef;                  #
}    #

#########################################################################
sub ESR31_Set($@)
{
my ( $hash, @a ) = @_;
my $name = $hash->{NAME};
return "\"set ESR31\" needs at least an argument" if ( @a < 2 );

my $cmd = $ESR31_sets{ $a[1] };
return "Unknown argument $a[1], choose one of "
  . join( " ", sort keys %ESR31_sets )
  if ( !defined($cmd) );

Log3 $name, 3, "DevIo_SimpleWrite: $hash $cmd";
DevIo_SimpleWrite( $hash, $cmd, 1 );
return undef;
}

#########################################################################
sub ESR31_Read($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my ( $data, $crc );
my $buf = DevIo_SimpleRead($hash);
my $tn  = TimeNow();
my ( $key, $val ) = ( "key", "val" );
#my $Gesamtertrag = 0; 
 
###### Daten der seriellen Schnittstelle holen und an $buf1 anhaengen

return "" if ( !defined($buf) );
$buf1 .= $buf;

#Log3 $name, 5, "Current buffer content: "  $buf1;

        my $pos_cs0 = index($buf1,"\nReceiving"); #sucht nach neuer Zeile mit Receiving
        my $pos_cs1 = -1;
#if($pos_cs0 >= 0)
#{
#       $pos_cs1 = index($buf1,"\nReceiving",$pos_cs0+1);
#}
#if(($pos_cs0 >= 0) && ($pos_cs1 >= 0)) #wenn 2mal Receiving dann beginnt er das lesen
{
readingsBeginUpdate($hash);
              my @e = split("\n",$buf1); #Splittet die Daten bei einer neuen Zeile auf
my $V_first = index($e[1],"Receiving") >= 0; #schaut in die Schlaufe und fängt bei Receiving an
for my $i (0 .. $#e)
{

      my @e_ = split(" ",$e[$i]);
if($e_[0] eq "Received")
{
next;
}
      if($e_[0] eq "Receiving")
{
readingsBulkUpdate($hash,"Daten lesen",$e_[1]); # Daten lesen
}

      if($e_[0] eq "Received")
{
        readingsBulkUpdate($hash,"Daten empfangen",$e_[1]); # Daten empfangen
}
     
      if($e_[0] eq "Sensor1")
{
readingsBulkUpdate($hash,"Sensor1",sprintf("%.1f",$e_[1])); # Sensor1 Temperatur in *C
}
      if($e_[0] eq "Sensor2")

        readingsBulkUpdate($hash,"Sensor2",sprintf("%.1f",$e_[1])); # Sensor2 Temperatur in *C
}
      if($e_[0] eq "Sensor3")
{
        readingsBulkUpdate($hash,"Sensor3",sprintf("%.1f",$e_[1])); # Sensor3 Durchflussmenge in l/h
}
  if($e_[0] eq "Sensor4")
{
        readingsBulkUpdate($hash,"Sensor4",sprintf("%.1f",$e_[1])); # Sensor4
}
      if($e_[0] eq "Sensor5")
{
        readingsBulkUpdate($hash,"Sensor5",sprintf("%.1f",$e_[1])); # Sensor5
}
      if($e_[0] eq "Sensor6")
{
        readingsBulkUpdate($hash,"Sensor6",sprintf("%.1f",$e_[1])); # Sensor6
}
      if($e_[0] eq "Sensor7")
{
        readingsBulkUpdate($hash,"Sensor7",sprintf("%.1f",$e_[1])); # Sensor7
}
      if($e_[0] eq "Sensor8")
{
        readingsBulkUpdate($hash,"Sensor8",sprintf("%.1f",$e_[1])); # Sensor8
}
      if($e_[0] eq "Sensor9")
{
        readingsBulkUpdate($hash,"Sensor9",sprintf("%.1f",$e_[1])); # Sensor9
}
      if($e_[0] eq "DataFrameDamaged")
{
        readingsBulkUpdate($hash,"Datenrahmen defekt",$e_[1]); # Datenrahmen defekt und verworfen
}
      if($e_[0] eq "Pumpe1")
{
        readingsBulkUpdate($hash,"Pumpe",$e_[1]); # Pumpe ein / aus
}
      if($e_[0] eq "Drehzahlstufe1")
#{
#if(($e_[1]) > $Dmin && ($e_[1]) < $Dmax ) #nur Werte übernehmen die im gültigen bereich liegen
{
readingsBulkUpdate($hash,"Drehzahlstufe",$e_[1]); # Drehzahlstufe Pumpe
}
#}
      if($e_[0] eq "kWh")
{
        readingsBulkUpdate($hash,"kWh",$e_[1]); # Gesamt kWh
#$Gesamtertrag = $e_[1] /1000 ;  #für Gesamtertrag als Reading
}
      if($e_[0] eq "MWh")
{
        readingsBulkUpdate($hash,"MWh",$e_[1]); # Gesamt MWh
#$Gesamtertrag = $Gesamtertrag + ($e_[1]);           #für Gesamtertrag als Reading
}
      if($e_[0] eq "Leistung")
{
        readingsBulkUpdate($hash,"Leistung",sprintf("%.0f",$e_[1]*1000)); # Momentanleistung
}
     
    }
#readingsBulkUpdate($hash,"Gesamtertrag",$Gesamtertrag);
#readingsBulkUpdate($hash,"Gesamtertrag",sprintf("%.1f",$Gesamtertrag)); # errechneter Gesamtertrag aus kWh und MWh als Reading
#readingsBulkUpdate($hash,"Power",sprintf("%.2f",$Power));

readingsEndUpdate( $hash, 1 );
$buf1 = "";
}
}

#########################################################################
sub ESR31_Ready($)
{
my ($hash) = @_;

return DevIo_OpenDev( $hash, 1, undef )
  if ( $hash->{STATE} eq "disconnected" );

# This is relevant for windows/USB only
my $po = $hash->{USBDev};
my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;
return ( $InBytes > 0 );
}

#########################################################################
sub ESR31_Poll($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
push @{ $hash->{SENDBUFFER} }, $ESR31_sets{"logmode"};
DevIo_SimpleWrite( $hash, "07F0009B01014A070F", 1 );
Log3 $name, 5, "RS232 Modus PC-Master";
return undef;
}

#########################################################################
sub ESR31_SetReading($$$$)
{
my ( $hash, $tn, $key, $val ) = @_;
my $name = $hash->{NAME};
Log3 $name, 4, "$name: $key $val";
$hash->{READINGS}{$key}{TIME} = $tn;
$hash->{READINGS}{$key}{VAL}  = $val;
DoTrigger( $name, "$key: $val" );
}


1;


Im großen und ganzen stimmen die Werte, die ankommen. Aber ab und zu wird etwas nicht richtig "gelesen" und es kommen total falsche Werte, die ncht stimmen. Damit stimmt natürlich kein Plot und auch ein "event on change reading" wird irreführend ausgelöst.

Eventuell hat jemand einen Tip für mich.
Steffen
Titel: Antw:serielle Schnittstelle Daten lesen
Beitrag von: privat58 am 15 Februar 2016, 12:11:49
Hochschieb ;)
Ich habe heute Vormittag den Arduino am Rechner gehabt und die Daten angeschaut. Aus der Schnittstelle kommen die Daten ohne Fehler raus.
Somit liegt das Problem an meinem Modul, wo sie dann fehlerhaft nachbereitet werden.
Titel: Antw:serielle Schnittstelle Daten lesen
Beitrag von: privat58 am 14 März 2016, 14:48:05
Leider komme ich nicht weiter und werde wohl mit den Aussetzern leben müssen, falls jemand eine Idee hat bin ich jederzeit offen.
Hatte angenommen, das noch andere einen Arduino seriell auslesen. Dem ist wahrscheinlich nicht so.
mfg
Titel: Antw:serielle Schnittstelle Daten lesen
Beitrag von: CoolTux am 14 März 2016, 15:11:59
Die Frage die sich mir stellt ist, sind Deine Reading Values fehlerhaft oder schon die Raw Daten. Immer hin formatierst Du ja Deine Values, eventuell kommen daher die Fehler zu stande. Am besten Du schneidest die erste Zeit Irgendwie Deine Rawdaten mit und legst sie zum Vergleichen in ein log ab. Wegen meiner auch zuschaltbar über das Attribut verbose.



Grüße
Titel: Antw:serielle Schnittstelle Daten lesen
Beitrag von: Icinger am 14 März 2016, 15:14:54
Fürs auslesen der Seriellen gibts extra das ECMD-Device, mit dem geht das ganz easy.
Titel: Antw:serielle Schnittstelle Daten lesen
Beitrag von: privat58 am 28 März 2016, 09:28:22
Ups, gar nicht bitbekommen, das da Antworten waren. Sorry
@CoolTux
Die Rohdaten stimmen. Diese hatte ich schon mal stundenlag mitschreiben lassen (auch auf einem Win-PC). Was immer mal nicht stimmt sind die Reading Values (egal ob formatiert oder nicht). Dadurch nehme ich an, das ich einen Fehler im Modul habe, kann diesen aber nicht finden.
Das selbe Problem hatten wir auch bei dem Batteriemonitor https://forum.fhem.de/index.php/topic,48130.msg397993.html#msg397993 (https://forum.fhem.de/index.php/topic,48130.msg397993.html#msg397993)
Hier hatte dann Askie eine Grenze der Werte nach unten und oben festgelegt und alles, was nicht dazwischen passt wird ignoriert.
@Icinger
ECMD nutze ich schon für die Holzvergaser-Steuerung. Da ich aber nun mittlerweile 4 Geräte habe, die seriell ausgelesen werden, wäre es mir lieber dies in einzelne Module auszulagern, da eventuell auch andere User die Geräte haben und es dann einzeln genutzt werden könnte.

Was mich halt absolut irritiert ist, das die Reading Values im großen und ganzen stimmen aber es ab und zu totale Ausreißer in alle Himmelsrichtungen gibt.