Open shrepat opened 3 years ago
Can you please share the code of how you read the data? Both the class and the function reading into it.
And do you have turned of data block optimization? See https://github.com/S7NetPlus/s7netplus/wiki/S7-1200-1500-Notes#s7-12001500-notes
@scamille Hi,
Thanks for responding. Sure. The code is Apologies. Hopefully it is not too long to read. Do let me know if you would want to fix the code. TIA
public class HMIDb1Read : ObservableModel
{
private double _Sample_1;
private double _Sample_2;
private double _Sample_3;
private double _Sample_4;
private double _Sample_5;
public double Sample_1
{
get
{
return _Sample_1;
}
set
{
if (_Sample_1!= value)
{
_Sample_1= value;
OnPropertyChanged("Sample_1");
}
}
}
public double Sample_2
{
get
{
return _Sample_2;
}
set
{
if (_Sample_2!= value)
{
_Sample_2= value;
OnPropertyChanged("Sample_2");
}
}
}
public double Sample_3
{
get
{
return _Sample_3;
}
set
{
if (_Sample_3!= value)
{
_Sample_3= value;
OnPropertyChanged("Sample_3");
}
}
}
public double Sample_4
{
get
{
return _Sample_4;
}
set
{
if (_Sample_4!= value)
{
_Sample_4= value;
OnPropertyChanged("Sample_4");
}
}
}
public double Sample_5
{
get
{
return _Sample_5;
}
set
{
if (_Sample_5!= value)
{
_Sample_5= value;
OnPropertyChanged("Sample_5");
}
}
}
The above code is my HMIDB Class. I read this on my ViewModel as follows:
public HMIDb1Read db1Read { get; set; }
public HMIDb1Write db1Write { get; set; }
public DataViewModel()
{
db1Read = new HMIDb1Read();
db1Write = new HMIDb1Write();
}
In my WPF xaml- I bind it using dataContext as
<TextBlock
Grid.Row="25"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_1
</TextBlock>
<TextBlock
Grid.Row="26"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_2
</TextBlock>
<TextBlock
Grid.Row="27"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_3
</TextBlock>
<TextBlock
Grid.Row="28"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_4
</TextBlock>
<TextBlock
Grid.Row="29"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_5
</TextBlock>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_1}"
VerticalAlignment="Center">
</TextBlock>
<TextBlock
Grid.Row="1"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_2}"
VerticalAlignment="Center">
</TextBlock>
<TextBlock
Grid.Row="2"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_3}"
VerticalAlignment="Center">
</TextBlock>
<TextBlock
Grid.Row="3"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_4}"
VerticalAlignment="Center">
</TextBlock>
<TextBlock
Grid.Row="4"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_5}"
VerticalAlignment="Center">
</TextBlock>
The PLC Class code is:
plcDriver.ReadClass(DataViewModel.Instance.db1Read, 61, 0);
Also,
yes optimised data access is unchecked.
@shrepat ,
I am not sure if this can be the reason but as I can see you want to read multiple S7-Real values from the plc. According to the wiki the datatype in C# within the class needs to be float when using the "read-class"-method.
I use the "read-class"-method a lot but this behaviour you showed never ever occured....interresting
Maybe you can give it a try?
Alternatively you can try to use "read-multiple-items".
Yes,
I tried float instead of double earlier. The problem remained even then. I am not sure how to use read multiple items. I will look into it and see if that fixes the issue.
Thanks.
I am pretty sure you need float / System.Single to match 32bit S7 Real data type. Please try again with this, and if it is still not working we can continue looking at other possibilities.
I am not sure if it is caused by only showing a snippet of your code, but I can't really match the grid.Rows between your labels and content. E.g
<TextBlock
Grid.Row="25"
Grid.Column="0"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center">Sample_1
</TextBlock>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Foreground="Black"
FontSize="24"
HorizontalAlignment="Center"
Text="{Binding db1Read.Sample_1}"
VerticalAlignment="Center">
</TextBlock>
With Grid.Row=25 and Grid.Row=0
Yeah sorry, I had to swap different grid values just for code. It is only a snippet of the entire code. Mine had around 30 samples I had to take only 5 due to space concerns.
I just tried replacing the double with float type for the real values. Still the same error.
Hmm it might be related to #300 . In effect, the ordering of properties we get through reflection is not guaranteed to be the same order in which you declared those properties in your class. But that hasn't been a problem in practice so far.
Can you try creating a more simple struct. struct HMIDb1ReadData { public float Sample1; public float Sample2; ... } and read into that using Plc.ReadStruct ?
You can wrap that struct inside your HMIDb1Read class and use it as a backing field for your properties. If you update all variables in 1 go you can also just call NotifyPropertyChanged for all of them to get WPF to update it, no need to build those wrapper setters for every individual one.
I just would like to share my code how I am reading class from plc:
The class:
public class Heizung
{
public Heizung();
public float Aussentemperatur { get; set; }
public float TempPufferOben { get; set; }
public float TempPufferMitte { get; set; }
public float TempPufferUnten { get; set; }
public float VLTempLufterhitzer { get; set; }
public float VLTempWT23 { get; set; }
public float BetriebsstundenGlattAufheizbetrieb { get; set; }
public float BetriebsstundenGlattNachheizbetrieb { get; set; }
public float BetiebsstundenFrostschutz { get; set; }
public bool Sammelstörung { get; set; }
public bool HeizungAUS { get; set; }
public bool HeizungEIN { get; set; }
}
the declaration:
readonly Heizung DatenHeizung = new Heizung();
read class from plc:
if (plcHeizungRNV1.IsConnected)
{
plcHeizungRNV1.ReadClass(DatenHeizung, PLC_DB_HEIZUNG, 0);
}
I then write the values of the class into a database and show them on a ASP.Net website:
DatenHeizungRNV1.Aussentemperatur = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "Aussentemperatur")]);
DatenHeizungRNV1.TempPufferOben = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "TempPufferOben")]);
DatenHeizungRNV1.TempPufferMitte = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "TempPufferMitte")]);
Hello all,
Thank you for all the assistance. The issue has been identified to be coming from INotifyPropertyChanged and not from the ReadClass. When I bind with INotifyPropertyChanged, the values get jumbled and mismatched. I tried displaying the class as is with the notifyproperty and without it and noticed it. We would like to bind it to our xaml UI WPF program which is where this problem occurs. Do let me know if someone can assist with this.
I just would like to share my code how I am reading class from plc:
The class:
public class Heizung { public Heizung(); public float Aussentemperatur { get; set; } public float TempPufferOben { get; set; } public float TempPufferMitte { get; set; } public float TempPufferUnten { get; set; } public float VLTempLufterhitzer { get; set; } public float VLTempWT23 { get; set; } public float BetriebsstundenGlattAufheizbetrieb { get; set; } public float BetriebsstundenGlattNachheizbetrieb { get; set; } public float BetiebsstundenFrostschutz { get; set; } public bool Sammelstörung { get; set; } public bool HeizungAUS { get; set; } public bool HeizungEIN { get; set; } }
the declaration:
readonly Heizung DatenHeizung = new Heizung();
read class from plc:
if (plcHeizungRNV1.IsConnected) { plcHeizungRNV1.ReadClass(DatenHeizung, PLC_DB_HEIZUNG, 0); }
I then write the values of the class into a database and show them on a ASP.Net website:
DatenHeizungRNV1.Aussentemperatur = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "Aussentemperatur")]); DatenHeizungRNV1.TempPufferOben = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "TempPufferOben")]); DatenHeizungRNV1.TempPufferMitte = Convert.ToSingle(dsHeizungRNV1.Tables[0].Rows[0].ItemArray[spaltenNameHeizungRNV1.FindIndex(x => x == "TempPufferMitte")]);
Hello,
Yes this is very similar to how we read the class now and is working seamlessly.
Thank you and appreciate you for sharing the code.
Regards, Shreyas
Maybe set it up like this:
class Data
{
public float Value {get;set;}
}
class Wrapper : INotifyPropertyChanged
{
public Data Data {get;set;} // Add INotifyProperyChanged stuff to getter and setter here
}
auto wrapper = new Wrapper();
auto data = new Data();
plc.ReadClass(data);
wrapper.Data = data;
And in your UI bind like this: Text="{Binding Data.Value}"
Hello,
I am trying to access my DB from TIA to my WPF GUI c# Project. While binding the class I happen to notice mismatch of values while binding the class and accessing the structure. The TIA DB looks like this with their current values.
When binding it on my WPF app. The binding mismatch happens. I have tried multiple iterations but I noticed the change in value when I try to reshuffle the DB value location and come back to notice the values have been mismatched in a random pattern. Here is the output from the GUI.
Please let me know if I am missing something or if there is a solution for the same.
Thank you, Shreyas