S7NetPlus / s7netplus

S7.NET+ -- A .NET library to connect to Siemens Step7 devices
MIT License
1.35k stars 595 forks source link

Problem Reading Real Value from PLC #460

Closed CFish66 closed 1 year ago

CFish66 commented 1 year ago

Hi everybody,

I'm a new in VS and S7.Net, In my case, i got an error when reading Real value. Below is my code, it cannot use ".ConvertToUInt()". C# display and error. I try to translate from Chinese to English. It mean 'Double' not included definatiion of ".ConvertTDouble()'.

For write a real value to PLC. My case can write a float value directly to plc and plc value is correct.

private void button2_Click_1(object sender, EventArgs e) { double val = 35.687; uint val_1; float aa;

    //val_1 = (double)val.ConverToShort();
    //Globals.PLC_Struct[5].plc.Write("DB1.DBD0", val.ConvertToUInt());

    var dword = (uint)(Globals.PLC_Struct[5].plc.Read("DB1.DBD0"));
    double result = dword.ConvertToDouble();
}

}

Himmelt commented 1 year ago

@CFish66 错误 CS1061 “uint”未包含“ConvertToDouble”的定义,并且找不到可接受第一个“uint”类型参数的可访问扩展方法“ConvertToDouble”(是否缺少 using 指令或程序集引用?)

这个提示已经很清楚了。首先,就没有 uint.ConvertToDouble 这个方法,只有 uint.ConvertToFloat,其次,double 占 8 个字节,你 dword 长度都不够,PLC里也没有可以直接表示8个字节的地址类型,所以没有办法用地址的形式直接读出一个所谓的DoubleDoubleWorld,或者 Int64/UInt64。

如果你想读写 Real/LReal 类型的,应该使用 Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0),可以指定 VarType.RealVarType.LReal , 分别返回 floatdouble ,强制转换一下就行。


There is no method uint.ConvertToDouble, just uint.ConvertToFloat. Also, double takes 8 bytes, but DWord just takes 4 bytes. As well, PLC has no address expression (like MW2,MD4,DB1.DBD0) to represent 8 bytes (so called DDWord or Int64, Uint64).

If you want to read/write Real/LReal type data, you should use Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0) , you can assign VarType.Real or VarType.LReal to varType, that will returns float or double , just force convert the result.

mycroes commented 1 year ago

Hi @CFish66, did @Himmelt's advice work for you? I think you might need to use ConvertToSingle(), if I'm correct Real from PLC is a 32 bit floating point number, which is covered by Single / float in C#. I think that might also be what @Himmelt is saying, but I don't speak (nor read) Chinese (and if it's not even Chinese, I even mistakenly take it as Chinese!).

@Himmelt would you mind accompanying your reply with a short English summary as well in the future? That makes it understandable for English users as well.

Himmelt commented 1 year ago

@mycroes Oh, thanks for your suggestions. I considered the author is a Chinese, so I just reply with Chinese. And, my English is not good as well, if you find some grammar errors, just ignore it please 😂

这个提示已经很清楚了。首先,就没有 uint.ConvertToDouble 这个方法,只有 uint.ConvertToFloat,其次,double 占 8 个字节,你 dword 长度都不够,PLC里也没有可以直接表示8个字节的地址类型,所以没有办法用地址的形式直接读出一个所谓的DoubleDoubleWorld,或者 Int64/UInt64。

如果你想读写 Real/LReal 类型的,应该使用 Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0),可以指定 VarType.RealVarType.LReal , 分别返回 floatdouble ,强制转换一下就行。

Translation: There is no method uint.ConvertToDouble, just uint.ConvertToFloat. Also, double takes 8 bytes, but DWord just takes 4 bytes. As well, PLC has no address expression (like MW2,MD4,DB1.DBD0) to represent 8 bytes (so called DDWord or Int64, Uint64).

If you want to read/write Real/LReal type data, you should use Read(DataType dataType, int db, int startByteAdr, VarType varType, int varCount, byte bitAdr = 0) , you can assign VarType.Real or VarType.LReal to varType, that will returns float or double , just force convert the result.

mycroes commented 1 year ago

@Himmelt that's actually a pretty thorough explanation for someone worrying about his English 😉 Thanks for adding the translation. @CFish66 let us know if this works for you?

CFish66 commented 1 year ago

Hi everybody, sorry for lated reply. The function of "ConvertToDouble():" is show in the manual as below :

"Read S7 Real, you need to use ConvertToDouble(): double result = ((uint)plc.Read("DB1.DBD40")).ConvertToDouble();"

Since I posted and wait for very long time but didn't get reply. So, i looked in the source code of S7NetPlus. I found "uint.ConvertToFloat" that can fix my problem.

Thank you very much for all.