AdvancedHMI Software
General Category => Support Questions => Topic started by: yovanino on November 04, 2019, 06:05:35 PM
-
Im getting an error when try to write a UDT
C# side
public struct Order_Info
{
public Int32 Id;
public string Name;
public Int32 Plan_Qty;
public Int32 Time_Est;
}
Order_Info[] Orders = new Order_Info[5];
DriverAB.WriteUDT("Orders_Pool", Orders);
I Get "Not Enough Data"
PLC side
Order_Pool
Order_Pool[0].ID DINT
Order_Pool[0].Name STRING
Order_Pool[0].Plan_QTY DINT
Order_Pool[0].Time_Est DINT
Thanks
-
Archie would probably know better about this but where do you assign values to structure members?
If I try your code as it is, Name is null for each one of them (while the other 3 have value of "0").
-
I asign the values from a DB, no nulls.
But allways get the same error.
Ive read that maybe is the length of the string but idont know.
-
What version are you using? 3.99y Beta 28 introduced some fixes related to UDT arrays
-
Im using 3.99y beta 34
-
It looks like ReadUDT and WriteUDT don't work properly while ReadRaw and WriteRaw do work.
For my example I used this code:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public struct Order_Info
{
public Int32 ID;
public string Name;
public Int32 Plan_QTY;
public Int32 Time_Est;
}
private void MainForm_Load(object sender, EventArgs e)
{
var tags = ethernetIPforCLXCom1.GetTagList(); //Used to confirm that PLC is responding properly
var udtReadBytes = ethernetIPforCLXCom1.ReadRaw("Orders_Pool", 5); //Read UDT with ReadRaw method (works - this example has 100 bytes returned per UDT member)
Order_Info[] Orders = new Order_Info[5];
for (int i = 0; i < Orders.Length; i++)
{
Orders[i] = new Order_Info
{
ID = BitConverter.ToInt32(udtReadBytes, 0 + i * 100),
Name = System.Text.Encoding.Default.GetString(udtReadBytes, 8 + i * 100, BitConverter.ToInt32(udtReadBytes, 4 + i * 100)),
Plan_QTY = BitConverter.ToInt32(udtReadBytes, 92 + i * 100),
Time_Est = BitConverter.ToInt32(udtReadBytes, 96 + i * 100),
};
}
var udt1 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool"); //Read UDT with ReadUDT method (doesn't work properly, all values are 0 or null)
var udt2 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool", 5); //Read UDT with ReadUDT method (doesn't work properly, all values are 0 or null)
Byte[] udtWriteBytes = new Byte[500];
Order_Info[] Orders_Pool = new Order_Info[5];
for (int i = 0; i < Orders_Pool.Length; i++)
{
Orders_Pool[i].ID = i;
BitConverter.GetBytes(Orders_Pool[i].ID).CopyTo(udtWriteBytes, 0 + i * 100);
Orders_Pool[i].Name = "Name" + i.ToString();
BitConverter.GetBytes(Orders_Pool[i].Name.Length).CopyTo(udtWriteBytes, 4 + i * 100);
System.Text.Encoding.Default.GetBytes(Orders_Pool[i].Name).CopyTo(udtWriteBytes, 8 + i * 100);
Orders_Pool[i].Plan_QTY = i + 1;
BitConverter.GetBytes(Orders_Pool[i].Plan_QTY).CopyTo(udtWriteBytes, 92 + i * 100);
Orders_Pool[i].Time_Est = i + 2;
BitConverter.GetBytes(Orders_Pool[i].Time_Est).CopyTo(udtWriteBytes, 96 + i * 100);
}
ethernetIPforCLXCom1.WriteRaw("Orders_Pool", 5, udtWriteBytes); //Write UDT with WriteRaw method (works)
ethernetIPforCLXCom1.WriteUDT("Orders_Pool", Orders_Pool); //Write UDT with WriteUDT method (doesn't work properly - "Not Enough Data")
}
}
It is possible that I wasn't doing it right.
-
Im getting an error when try to write a UDT
C# side
public struct Order_Info
{
public Int32 Id;
public string Name;
public Int32 Plan_Qty;
public Int32 Time_Est;
}
Order_Info[] Orders = new Order_Info[5];
DriverAB.WriteUDT("Orders_Pool", Orders);
I Get "Not Enough Data"
PLC side
Order_Pool
Order_Pool[0].ID DINT
Order_Pool[0].Name STRING
Order_Pool[0].Plan_QTY DINT
Order_Pool[0].Time_Est DINT
Is your tag in the PLC declared as type Order_Pool[5] ?
-
If it's of any help, the attached pictures show how I have it.
-
This definitely does not work, for now the work-around is this:
DriverAB.WriteUDT("Orders_Pool[0]", Orders[0]);
DriverAB.WriteUDT("Orders_Pool[1]", Orders[1]);
DriverAB.WriteUDT("Orders_Pool[2]", Orders[2]);
DriverAB.WriteUDT("Orders_Pool[3]", Orders[3]);
DriverAB.WriteUDT("Orders_Pool[4]", Orders[4]);
-
How about ReadUDT?
All the following show 0 or null:
var udt1 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool");
var udt2 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool", 5);
var udt3 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool[0]", 5);
var udt4 = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool[1]");
Is this correct code or should I be doing it differently?
-
This seems to work, the structure was converted to class::
public class Order_Info
{
public Int32 ID;
public string Name;
public Int32 Plan_QTY;
public Int32 Time_Est;
public Order_Info()
{
ID = 0;
Name = string.Empty;
Plan_QTY = 0;
Time_Est = 0;
}
}
var udt = ethernetIPforCLXCom1.ReadUDT<Order_Info>("Orders_Pool", 5);
-
This seems to work, the structure was converted to class::
I was just about to post code using a class instead of structure that works.
-
GetTagList() does get tag info, as in the attached picture, and shows it as a structure but doesn't know how many members it has.
100 bytes shown are for a single member.
-
Maybe you should keep the current WriteUDT code since it allows writing any member of the structure individually.
Some people might find it useful.
-
I try this and works fine
for (i = 0; i < 5; i++)
{
Fill Orders(i) ==>>>>> Call Procedure to fill Order
DriverAB.WriteUDT("Orders_Pool[" + i + "]", Orders);
}