Marco G Posted January 6, 2015 Report Share Posted January 6, 2015 Hey there, I've been tweaking around a bit and i got the software i'm writing at the point that it does connect to the plc and reads things like the PLC name, However: When i want to send data to the plc it gets a error: System.Collections.Generic.KeyNotFoundException was unhandled Message=De gegeven sleutel is niet aanwezig in het woordenboek. Source=mscorlib StackTrace: bij System.Collections.Generic.Dictionary`2.get_Item(TKey key) bij Unitronics.DataTables.Collections.DataTablesCollections`2.get_Item(TKey key) bij Voersysteem.Hoofdscherm.btnWrite_Click(Object sender, EventArgs e) in C:\Users\Marco\Documents\Visual Studio 2010\Projects\Voerkar v0.1\Voerkar v0.1\homescreen.vb:regel 445 bij System.Windows.Forms.Control.OnClick(EventArgs e) bij System.Windows.Forms.Button.OnClick(EventArgs e) bij System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) bij System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) bij System.Windows.Forms.Control.WndProc(Message& m) bij System.Windows.Forms.ButtonBase.WndProc(Message& m) bij System.Windows.Forms.Button.WndProc(Message& m) bij System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) bij System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) bij System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) bij System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) bij System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) bij System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) bij System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) bij Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() bij Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() bij Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine) bij Voersysteem.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:regel 81 bij System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) bij System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) bij Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() bij System.Threading.ThreadHelper.ThreadStart_Context(Object state) bij System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) bij System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) bij System.Threading.ThreadHelper.ThreadStart() InnerException: The code where the error occur's: If Not plc Is Nothing Then Dim dt As Unitronics.DataTables.DataTables dt = New DataTables(plc, DataTablesReadOptions.StructureAndValues) ' You can also read just the structure. depending on your needs ' we are working with unitronics data tables, not the .net data tables. those are 2 different objects Dim table As Unitronics.DataTables.Table table = dt.Tables("verzenden") ' alter the data on the tables, for example: table.Rows(0).Cells(0).Fields(0).Value = lblvoerzend1.Text table.Rows(0).Cells(1).Fields(0).Value = lblzendgewicht1.Text table.Rows(0).Cells(2).Fields(0).Value = lblvoerbaknr.Text dt.SaveToUDT("C:\Voerkar\" & sDateTimePicker & ".udt") ' We can now read the file to a bytes array voor het schrijven naar d eplc Dim fileContent As Byte() fileContent = System.IO.File.ReadAllBytes("c:\Voerkar\" & sDateTimePicker & ".udt") plc.SD.WriteFile(SD.SdFolder.EXCEL_EXCEL1, sDateTimePicker & ".udt", fileContent, Nothing) End If To be precise: Where the code wants to transfer the data(3 numeric items, for example 10, 20 and 2) to the datatable at table = dt.Tables("verzenden") Link to comment Share on other sites More sharing options...
Saragani Posted January 6, 2015 Report Share Posted January 6, 2015 Your PLC doesn't seem to have a table called verzenden You need to download a matching project to the PLC which have the required Data Tables structure. Link to comment Share on other sites More sharing options...
Marco G Posted January 7, 2015 Author Report Share Posted January 7, 2015 Thanks, that was indeed the problem, i named the table in the plc something else then i did in the code. Now that part works. I thought i did something wrong in the code but couldn't find it. Now it's up to the last part of the inserting to the datatable(i also have a other issue but i think that's related to this one so let's finish this first). I don't get a error, yet when i use visiLogic to read the datatable in the PLC, the inserted data(some numbers) are not there, it's all "0" Link to comment Share on other sites More sharing options...
Saragani Posted January 7, 2015 Report Share Posted January 7, 2015 Hi, I see that you write a file to the SD. Are you loading that file afterwards by ladder from the SD Card into the Data Table? Link to comment Share on other sites More sharing options...
Marco G Posted January 7, 2015 Author Report Share Posted January 7, 2015 Hi, I see that you write a file to the SD. Are you loading that file afterwards by ladder from the SD Card into the Data Table? Hmm, i do indeed got a part where i write to SD, but i thought this code would write directly to the PLC. This is how i have it right now. When i use the part where it save's to the pc first i get a error at the first(bold) savetoUDT statement: dt.SaveToUDT("C:\Voerkar\" & sDateTimePicker & ".udt") ' We can now read the file to a bytes array voor het schrijven naar d eplc Dim fileContent As Byte() fileContent = System.IO.File.ReadAllBytes("c:\Voerkar\" & sDateTimePicker & ".udt") plc.SD.WriteFile(SD.SdFolder.EXCEL_EXCEL1, sDateTimePicker & ".udt", fileContent, Nothing) End If Cannot save into UDT file format from XML or FDT file formats, or from Data Tables Structure that was read from PLC. Communicating with a PLC is quite new for me so bear with me. Link to comment Share on other sites More sharing options...
Saragani Posted January 9, 2015 Report Share Posted January 9, 2015 You can also write directly to the data table, without using the sdI will look into the code on the next working day Link to comment Share on other sites More sharing options...
Saragani Posted January 11, 2015 Report Share Posted January 11, 2015 Hi, you are correct. Because the file was originally created from the PLC and might contain several tables, we don't allow creating a UDT file. You can save it as FDT (Use the Save function, which accepts path and file type). If you want to directly write to the PLC, then why do you use a file? You can do: table = dt.Tables("verzenden") table.Write(); (which will write the whole table back top the PLC). Link to comment Share on other sites More sharing options...
Marco G Posted January 14, 2015 Author Report Share Posted January 14, 2015 Hi, you are correct. Because the file was originally created from the PLC and might contain several tables, we don't allow creating a UDT file. You can save it as FDT (Use the Save function, which accepts path and file type). If you want to directly write to the PLC, then why do you use a file? You can do: table = dt.Tables("verzenden") table.Write(); (which will write the whole table back top the PLC). Thanks. I will look into it, the using of a file is prefered, but just to make it easier to look back at the settings previously used. I believe a collegue of mine already has some experience with the Unitronics datatables so he can help me set up a checker so that tasks are executed at a by the user specified date and time. I'm also busy with some other things, but if it worked i'll report it to you. Link to comment Share on other sites More sharing options...
Marco G Posted January 15, 2015 Author Report Share Posted January 15, 2015 Okay, savetoUDT(filepath .FDT) gives the same "cannot save into UDT from xml or FDT files" error Will try the table.write() and mess around a bit. Link to comment Share on other sites More sharing options...
Saragani Posted January 15, 2015 Report Share Posted January 15, 2015 No, SaveToUDT saves the file as UDT (it won't save the file to other formats). You can use the Save function (rather than SaveToUDT) This function accepts a filename and file type (an enum), which can be either XML, FDT or UDT. (If UDT is chosen, then SaveToUDT is being called). As much as I remember, the PLC doesn't let you load an FDT file from the ladder (but rather than from the INFO), but in your case, you can save the file as FDT for later use (if you want to save the data, and load it few hours later and only then write it to PLC). If you intend to write the data immediately then table.Write looks like a good choice. Link to comment Share on other sites More sharing options...
Marco G Posted January 15, 2015 Author Report Share Posted January 15, 2015 No, SaveToUDT saves the file as UDT (it won't save the file to other formats). You can use the Save function (rather than SaveToUDT) This function accepts a filename and file type (an enum), which can be either XML, FDT or UDT. (If UDT is chosen, then SaveToUDT is being called). As much as I remember, the PLC doesn't let you load an FDT file from the ladder (but rather than from the INFO), but in your case, you can save the file as FDT for later use (if you want to save the data, and load it few hours later and only then write it to PLC). If you intend to write the data immediately then table.Write looks like a good choice. Hmm, then saving to FDT isn't of much use(except the future reference). If i use the table.write() function, do i need to specify only the tablename in it or also the textbox.text values that will fill the table? Because if i use the code i got sofar it won't give me any errors but i have the feeling that it's not doing much either because visilogic shows no data in the datatable. On the plus side, i resolved all the earlier errors. Dim dt As Unitronics.DataTables.DataTables dt = New DataTables(plc, DataTablesReadOptions.StructureAndValues) ' You can also read just the structure. depending on your needs ' we are working with unitronics data tables, not the .net data tables. those are 2 different objects Dim table As Unitronics.DataTables.Table table = dt.Tables("verzenden") table.Write() ' alter the data on the tables, for example: (zelf al wat extra velden toegevoegd!) table.Rows(0).Cells(2).Fields(0).Value = lblvoerbaknr.Text table.Rows(0).Cells(0).Fields(0).Value = lblVoerzend.Text table.Rows(0).Cells(1).Fields(0).Value = lblzendgewicht.Text Link to comment Share on other sites More sharing options...
Saragani Posted January 15, 2015 Report Share Posted January 15, 2015 Off course you need to put the data in the table first... how else would the PC know what you want to write? Dim dt As Unitronics.DataTables.DataTables dt = New DataTables(plc, DataTablesReadOptions.StructureAndValues) ' You can also read just the structure. depending on your needs ' we are working with unitronics data tables, not the .net data tables. those are 2 different objects Dim table As Unitronics.DataTables.Table table = dt.Tables("verzenden") ' alter the data on the tables, for example: (zelf al wat extra velden toegevoegd!) table.Rows(0).Cells(2).Fields(0).Value = lblvoerbaknr.Text table.Rows(0).Cells(0).Fields(0).Value = lblVoerzend.Text table.Rows(0).Cells(1).Fields(0).Value = lblzendgewicht.Text table.Write() Link to comment Share on other sites More sharing options...
Marco G Posted January 21, 2015 Author Report Share Posted January 21, 2015 facepalm.. turns out i had the table.write on the wrong place... I had it before the table.rows. Now i can advance, add the other items as new rows in the table and at the date and time at which the row has to be executed. THANKS! Link to comment Share on other sites More sharing options...
Marco G Posted January 21, 2015 Author Report Share Posted January 21, 2015 Before you close this, i was doing some tests and noticed that it will overwrite row 0 in the plc every time i transfer data to it. Is it possible to have it automatically add a new row every time i want to transfer data to it? Link to comment Share on other sites More sharing options...
Saragani Posted January 22, 2015 Report Share Posted January 22, 2015 This is a real-time system, so every variable must have a fixed position in RAM, meaning, the table must be predefined and must have a fixed or max size (else, if it keeps growing, then it will need to be reallocated). You can define the number of rows you want in teh project itself. The use an MI for pointing to the next free row. (So the MI will be 0 when the project is first downloaded to the PLC). Now, each time you want to write the rows to the table, then read the MI (for example, now it is 15), In your table, start writing to row 15 (instead of row 0), write the data to the table, and then increase the value of the MI to 16. Link to comment Share on other sites More sharing options...
Marco G Posted January 22, 2015 Author Report Share Posted January 22, 2015 Hello, If i understand you correctly, i have to keep the pc software the same ( table.rows(0).cells(0).fields(0)) and write the ladder in such a way that when it sees that i want to add a entry to the table, it automatically writes it to a new line? Cool. thought it was just me because i couldn't find a solution in vb.net. Link to comment Share on other sites More sharing options...
Saragani Posted January 22, 2015 Report Share Posted January 22, 2015 No, if you want to change the start row, then you will need to change your PC software as well. Your PC software will read some MI, use it as a row number, change the values on the Data Tables on the PC (in the correct rows, not from row 0), and Write (or use Update command), and then increase the value of the MI by one by sending a command from the PC. Link to comment Share on other sites More sharing options...
Marco G Posted January 26, 2015 Author Report Share Posted January 26, 2015 Okay... and how can i do that? I thought i already got the pc part working and just needed to change some things in the ladder to make it working like i wanted. Row 0 doesnt have to be renewed, all it has to do is add a extra entry to the plc datatable every time i send 1(or multiple) rows to the plc. Link to comment Share on other sites More sharing options...
Saragani Posted January 28, 2015 Report Share Posted January 28, 2015 Use plc.ReadWrite ReadWriteRequest[] rw = new ReadWriteRequest[1]; rw[0] = new ReadOperands() { OperandType = OperandTypes.MI, StartAddress = 100, NumberOfOperands = 1, }; plc.ReadWrite(ref rw); var startRowIndex = Convert.ToInt16(((rw[0] as ReadOperands).ResponseValues as object[])[0]); // Your code here... but instead of start putting data to row 0, start with row startRowIndex, for example: table.Rows(startRowIndex).Cells(2).Fields(0).Value = lblvoerbaknr.Texttable.Rows(startRowIndex).Cells(0).Fields(0).Value = lblVoerzend.Texttable.Rows(startRowIndex).Cells(1).Fields(0).Value = lblzendgewicht.Text // Now you increment startRowIndex by the number of rows you intend to write (in this example, only 1 row): startRowIndex++; // Now you write the table (You can also use Update, which will only update the cells that you have altered) table.Write() // or table.Update() // Now we need to update the value of MI100 in the PLC. rw[0] = new WriteOperands() { OperandType = OperandTypes.MI, StartAddress = 100, NumberOfOperands = 1, Values = new object[] { startRowIndex } }; plc.ReadWrite(ref rw); Link to comment Share on other sites More sharing options...
Marco G Posted January 29, 2015 Author Report Share Posted January 29, 2015 Aah, so i do have to do something with read and writeoperands. I read about it in the PLC .net documentation but thought it was for writing directly to the application. Thanks. I will convert it to .net and see if it works. Link to comment Share on other sites More sharing options...
Marco G Posted January 29, 2015 Author Report Share Posted January 29, 2015 Hey, I adjusted the code(see below) Right now, it compiles without error but it gives the error: "The number of Operands to read cannot be less than 1" on rw(0) = New ReadOperands plc.ReadWrite(rw) The complete code: Dim rw() As ReadWriteRequest = New ReadWriteRequest((1) - 1) {} rw(0) = New ReadOperands plc.ReadWrite(rw) Dim startRowIndex = Convert.ToInt16(CType(CType(rw(0), ReadOperands).ResponseValues, Object())(0)) table.Rows(startRowIndex).Cells(3).Fields(0).Value = DateTimePicker1.Text 'datum en tijd table.Rows(startRowIndex).Cells(2).Fields(0).Value = lblvoerbaknr.Text table.Rows(startRowIndex).Cells(0).Fields(0).Value = lblVoerzend.Text table.Rows(startRowIndex).Cells(1).Fields(0).Value = lblzendgewicht.Text ' Now you increment startRowIndex by the number of rows you intend to write (in this example, only 1 row): startRowIndex = (startRowIndex + 1) ' Now you write the table (You can also use Update, which will only update the cells that you have altered) table.Write() ' or table.Update() ' Now we need to update the value of MI100 in the PLC. '30-1-15 ANDERS dan bron! aangepast naar .net en code lichtelijk veranderd! Broncode: Dim Write As WriteOperands = New WriteOperands() rw(0) = Write With Write .NumberOfOperands = 1 .OperandType = OperandTypes.MI .StartAddress = 100 .NumberOfOperands = 1 .Values = New Object() {startRowIndex} End With plc.ReadWrite(rw) Link to comment Share on other sites More sharing options...
Saragani Posted January 29, 2015 Report Share Posted January 29, 2015 Off course it gives you that... On the read request you don't tell it what you want to read (what type, what address and how much) Dim rw() As ReadWriteRequest = New ReadWriteRequest((1) - 1) {} Dim Read As WriteOperands = New ReadOperands() rw(0) = Read With Read .NumberOfOperands = 1 .OperandType = OperandTypes.MI .StartAddress = 100 .NumberOfOperands = 1 End With plc.ReadWrite(rw) Dim startRowIndex = Convert.ToInt16(CType(CType(rw(0), ReadOperands).ResponseValues, Object())(0)) table.Rows(startRowIndex).Cells(3).Fields(0).Value = DateTimePicker1.Text 'datum en tijd table.Rows(startRowIndex).Cells(2).Fields(0).Value = lblvoerbaknr.Text table.Rows(startRowIndex).Cells(0).Fields(0).Value = lblVoerzend.Text table.Rows(startRowIndex).Cells(1).Fields(0).Value = lblzendgewicht.Text ' Now you increment startRowIndex by the number of rows you intend to write (in this example, only 1 row): startRowIndex = (startRowIndex + 1) ' Now you write the table (You can also use Update, which will only update the cells that you have altered) table.Write() ' or table.Update() ' Now we need to update the value of MI100 in the PLC. '30-1-15 ANDERS dan bron! aangepast naar .net en code lichtelijk veranderd! Broncode: Dim Write As WriteOperands = New WriteOperands() rw(0) = Write With Write .NumberOfOperands = 1 .OperandType = OperandTypes.MI .StartAddress = 100 .NumberOfOperands = 1 .Values = New Object() {startRowIndex} End With plc.ReadWrite(rw) Link to comment Share on other sites More sharing options...
Marco G Posted February 2, 2015 Author Report Share Posted February 2, 2015 Ah right. That makes sense. Sorry, completely new to using operands and PLC's in general, just fresh out of college(well not even, learning a second degree in Business IT on the side) Link to comment Share on other sites More sharing options...
Marco G Posted February 2, 2015 Author Report Share Posted February 2, 2015 Hey, Thanks. I think there a error though. Dim rw() As ReadWriteRequest = New ReadWriteRequest((1) - 1) {} Dim Read As WriteOperands = New ReadOperands() rw(0) = Read With Read It says writeoperand AND readoperand so that gives a error. When i change the readoperand to writeoperand i get the ComDriveException "Values cannot be Null in a Write Operands request" And if i switch it all to read: "'index' must be non-negative and less than the number of rows in table. I checked the fields, removed fields and tested some things but the fields do have a value(default value = 0, but it also doesnt work if i enter a value like 24) I suspect that the error comes from the PLC. I havn't figured out how to program the plc to make it store the newest empty row in a MI, i think i will ask a collegue for help. Parameternaam: index " Link to comment Share on other sites More sharing options...
Saragani Posted February 3, 2015 Report Share Posted February 3, 2015 Yes, I've copy pasted it from your code and forgot to change a small part of it. It is supposed to be ReadOperands (You want to first read the value of the MI, which is the start row) My example uses MI 100. This MI might be in use by your ladder program... If not, it might also have a value from previously downloaded project since those registers are retained. So, assuming your Data Table on the PLC contains a total of 50 rows, and the value of MI 100 is either smaller than 0 or greater than 49, then you will get the exception: 'index' must be non-negative and less than the number of rows in table Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now